changeset 554:3328189786e7

Added external ADC interface functionality (MCP3424): Added communication protocoll to read data from external ADC. At the moment 16bit and 18bit resolutions are supported. External data will be read and forwarded depending on the conversion time of the ADC.
author Ideenmodellierer
date Thu, 12 Nov 2020 19:46:03 +0100
parents 43a2dd4ba30f
children 573a2bc796c8
files Small_CPU/Inc/externalInterface.h Small_CPU/Inc/i2c.h Small_CPU/Src/baseCPU2.c Small_CPU/Src/externalInterface.c Small_CPU/Src/scheduler.c
diffstat 5 files changed, 235 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Small_CPU/Inc/externalInterface.h	Thu Nov 12 19:46:03 2020 +0100
@@ -0,0 +1,41 @@
+/**
+  ******************************************************************************
+  * @file    externalInterface.h
+  * @author  heinrichs weikamp gmbh
+  * @version V0.0.1
+  * @date    07-Nov-2020
+  * @brief	 Interface functionality to proceed external analog signal via i2c connection
+  *
+  @verbatim
+  ==============================================================================
+                        ##### How to use #####
+  ==============================================================================
+  @endverbatim
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2014 heinrichs weikamp</center></h2>
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef EXTERNAL_INTERFACE_H
+#define EXTERNAL_INTERFACE_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+
+#define MAX_ADC_CHANNEL		(3u)		/* number of channels to be read */
+#define EXTERNAL_ADC_NO_DATA	0xFF
+
+void externalInterface_Init(void);
+uint8_t externalInterface_StartConversion(uint8_t channel);
+uint8_t externalInterface_ReadAndSwitch();
+float externalInterface_CalculateADCValue(uint8_t channel);
+float getExternalInterfaceChannel(uint8_t channel);
+
+#endif /* EXTERNAL_INTERFACE_H */
--- a/Small_CPU/Inc/i2c.h	Sun Nov 08 18:49:54 2020 +0100
+++ b/Small_CPU/Inc/i2c.h	Thu Nov 12 19:46:03 2020 +0100
@@ -27,7 +27,7 @@
 #define DEVICE_BATTERYGAUGE 			0xC8 	// LTC2941 battery gauge
 
 /* ADC for external bulkhead */
-#define DEVICE_EXTERNAL_ADC				0x68	// MCP3424 with Adr0=GND and Adr1=GND (Hardware gen 3 only)
+#define DEVICE_EXTERNAL_ADC				0xD0	// MCP3424 with Adr0=GND and Adr1=GND (Hardware gen 3 only)
 
 
 /* Includes ------------------------------------------------------------------*/
--- a/Small_CPU/Src/baseCPU2.c	Sun Nov 08 18:49:54 2020 +0100
+++ b/Small_CPU/Src/baseCPU2.c	Thu Nov 12 19:46:03 2020 +0100
@@ -141,6 +141,7 @@
 #include "batteryCharger.h"
 #include "scheduler.h"
 #include "tm_stm32f4_otp.h"
+#include "externalInterface.h"
 
 // From Common/Inc:
 #include "calc_crush.h"
@@ -397,6 +398,7 @@
 			//				ReInit_battery_charger_status_pins();
 			compass_init(0, 7);
 			accelerator_init();
+			externalInterface_Init();
 
 			if (global.mode == MODE_BOOT) {
 				GPIO_Power_MainCPU_OFF();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Small_CPU/Src/externalInterface.c	Thu Nov 12 19:46:03 2020 +0100
@@ -0,0 +1,161 @@
+/**
+  ******************************************************************************
+  * @file    externalInterface.c
+  * @author  heinrichs weikamp gmbh
+  * @version V0.0.1
+  * @date    07-Nov-2020
+  * @brief   Interface functionality to proceed external analog signal via i2c connection
+  *
+  @verbatim
+  ==============================================================================
+                ##### stm32f4xx_hal_i2c.c modification #####
+  ==============================================================================
+	The LTC2942 requires an repeated start condition without stop condition
+	for data reception.
+
+  @endverbatim
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2014 heinrichs weikamp</center></h2>
+  *
+  ******************************************************************************
+  */
+/* Includes ------------------------------------------------------------------*/
+
+#include <math.h>
+#include "i2c.h"
+#include "externalInterface.h"
+#include "scheduler.h"
+
+extern SGlobal global;
+
+#define ADC_ANSWER_LENGTH	(5u)		/* 3424 will provide addr + 4 data bytes */
+#define ADC_TIMEOUT			(10u)		/* conversion stuck for unknown reason => restart */
+#define ADC_REF_VOLTAGE_MV	(2048.0f)	/* reference voltage of MPC3424*/
+
+#define ADC_START_CONVERSION		(0x80)
+#define ADC_GAIN_4					(0x02)
+#define ADC_GAIN_4_VALUE			(4.0f)
+#define ADC_GAIN_8					(0x03)
+#define ADC_GAIN_8_VALUE			(8.0f)
+#define ADC_RESOLUTION_16BIT		(0x08)
+#define ADC_RESOLUTION_16BIT_VALUE	(16u)
+#define ADC_RESOLUTION_18BIT		(0x0C)
+#define ADC_RESOLUTION_18BIT_VALUE	(18u)
+
+#define ANSWER_CONFBYTE_INDEX		(4u)
+
+static uint8_t activeChannel = 0;			/* channel which is in request */
+static uint8_t recBuf[ADC_ANSWER_LENGTH];
+static uint8_t timeoutCnt = 0;
+static uint8_t externalInterfacePresent = 0;
+
+float externalChannel_mV[MAX_ADC_CHANNEL];
+
+
+void externalInterface_Init(void)
+{
+	activeChannel = 0;
+	timeoutCnt = 0;
+	externalInterfacePresent = 0;
+	if(externalInterface_StartConversion(activeChannel) == HAL_OK)
+	{
+		externalInterfacePresent = 1;
+		global.deviceDataSendToMaster.hw_Info.extADC = 1;
+	}
+}
+
+
+uint8_t externalInterface_StartConversion(uint8_t channel)
+{
+	uint8_t retval = 0;
+	uint8_t confByte = 0;
+
+	if(channel < MAX_ADC_CHANNEL)
+	{
+		confByte = ADC_START_CONVERSION | ADC_RESOLUTION_16BIT | ADC_GAIN_8;
+		confByte |= channel << 5;
+		retval = I2C_Master_Transmit(DEVICE_EXTERNAL_ADC, &confByte, 1);
+	}
+	return retval;
+}
+
+/* Check if conversion is done and trigger measurement of next channel */
+uint8_t externalInterface_ReadAndSwitch()
+{
+	uint8_t retval = EXTERNAL_ADC_NO_DATA;
+
+	if(externalInterfacePresent)
+	{
+		if(I2C_Master_Receive(DEVICE_EXTERNAL_ADC, recBuf, ADC_ANSWER_LENGTH) == HAL_OK)
+		{
+			if((recBuf[ANSWER_CONFBYTE_INDEX] & ADC_START_CONVERSION) == 0)		/* !ready set => received data contains new value */
+			{
+				retval = activeChannel;										/* return channel number providing new data */
+				activeChannel++;
+				if(activeChannel == MAX_ADC_CHANNEL)
+				{
+					activeChannel = 0;
+				}
+				externalInterface_StartConversion(activeChannel);
+				timeoutCnt = 0;
+			}
+			else
+			{
+				if(timeoutCnt++ >= ADC_TIMEOUT)
+				{
+					externalInterface_StartConversion(activeChannel);
+					timeoutCnt = 0;
+				}
+			}
+		}
+	}
+	return retval;
+}
+float externalInterface_CalculateADCValue(uint8_t channel)
+{
+	int32_t rawvalue = 0;
+	float retValue = 0.0;
+	if(channel < MAX_ADC_CHANNEL)
+	{
+
+		rawvalue = ((recBuf[0] << 16) | (recBuf[1] << 8) | (recBuf[2]));
+
+		switch(recBuf[3] & 0x0C)			/* confbyte => Resolution bits*/
+		{
+			case ADC_RESOLUTION_16BIT:		rawvalue = rawvalue >> 8;										/* only 2 databytes received shift out confbyte*/
+											if(rawvalue & (0x1 << (ADC_RESOLUTION_16BIT_VALUE-1)))			/* MSB set => negative number */
+											{
+												rawvalue |= 0xFFFF0000; 	/* set MSB for int32 */
+											}
+											else
+											{
+												rawvalue &= 0x0000FFFF;
+											}
+											externalChannel_mV[channel] = ADC_REF_VOLTAGE_MV * 2.0 / (float) pow(2,ADC_RESOLUTION_16BIT_VALUE);	/* calculate bit resolution */
+				break;
+			case ADC_RESOLUTION_18BIT:		if(rawvalue & (0x1 << (ADC_RESOLUTION_18BIT_VALUE-1)))			/* MSB set => negative number */
+											{
+												rawvalue |= 0xFFFE0000; 	/* set MSB for int32 */
+											}
+											externalChannel_mV[channel] = ADC_REF_VOLTAGE_MV * 2.0 / (float) pow(2,ADC_RESOLUTION_18BIT_VALUE);	/* calculate bit resolution */
+							break;
+			default: rawvalue = 0;
+				break;
+		}
+		externalChannel_mV[channel] = externalChannel_mV[channel] * rawvalue / ADC_GAIN_8_VALUE;
+		retValue = externalChannel_mV[channel];
+	}
+	return retValue;
+}
+float getExternalInterfaceChannel(uint8_t channel)
+{
+	float retval = 0;
+
+	if(channel < MAX_ADC_CHANNEL)
+	{
+		retval = externalChannel_mV[channel];
+	}
+	return retval;
+}
--- a/Small_CPU/Src/scheduler.c	Sun Nov 08 18:49:54 2020 +0100
+++ b/Small_CPU/Src/scheduler.c	Thu Nov 12 19:46:03 2020 +0100
@@ -41,6 +41,7 @@
 #include "stm32f4xx_hal_rtc_ex.h"
 #include "decom.h"
 #include "tm_stm32f4_otp.h"
+#include "externalInterface.h"
 
 /* uncomment to enable restoting of last known date in case of a power loss (RTC looses timing data) */
 /* #define RESTORE_LAST_KNOWN_DATE */
@@ -88,6 +89,7 @@
 void copyVpmCrushingData(void);
 void copyDeviceData(void);
 void copyPICdata(void);
+void copyExtADCdata();
 static void schedule_update_timer_helper(int8_t thisSeconds);
 uint32_t time_elapsed_ms(uint32_t ticksstart,uint32_t ticksnow);
 
@@ -454,6 +456,7 @@
 {
 	uint32_t ticksdiff = 0; 
 	uint32_t lasttick = 0;
+	uint8_t extAdcChannel = 0;
 	uint8_t counterAscentRate = 0;
 	float lastPressure_bar = 0.0f;
 	global.dataSendToMaster.mode = MODE_DIVE;
@@ -491,6 +494,13 @@
 				Scheduler.counterSPIdata100msec++;
 			}
 			schedule_check_resync();
+
+			extAdcChannel = externalInterface_ReadAndSwitch();
+			if(extAdcChannel != EXTERNAL_ADC_NO_DATA)
+			{
+				externalInterface_CalculateADCValue(extAdcChannel);
+				copyExtADCdata();
+			}
 		}
 
 		//Evaluate pressure at 20 ms, 120 ms, 220 ms,....
@@ -754,6 +764,7 @@
 
 	uint32_t ticksdiff = 0; 
 	uint32_t lasttick = 0;
+	uint8_t extAdcChannel = 0;
 	Scheduler.tickstart = HAL_GetTick();
 	Scheduler.counterSPIdata100msec = 0;
 	Scheduler.counterCompass100msec = 0;
@@ -784,6 +795,12 @@
 				Scheduler.counterSPIdata100msec++;
 			}
 			schedule_check_resync();
+			extAdcChannel = externalInterface_ReadAndSwitch();
+			if(extAdcChannel != EXTERNAL_ADC_NO_DATA)
+			{
+				externalInterface_CalculateADCValue(extAdcChannel);
+				copyExtADCdata();
+			}
 		}
 
 		/* Evaluate pressure at 20 ms, 120 ms, 220 ms,... duration ~22ms] */
@@ -1606,6 +1623,19 @@
 	global.dataSendToMaster.boolPICdata = boolPICdata;
 }
 
+void copyExtADCdata()
+{
+	float value;
+
+	uint8_t channel = 0;
+
+	for(channel = 0; channel < MAX_ADC_CHANNEL; channel++)
+	{
+		value = getExternalInterfaceChannel(channel);
+		global.dataSendToMaster.data[0].extADC_voltage[channel] = value;
+	}
+}
+
 
 typedef enum 
 {