Files
TX/source/adc.c

1218 lines
37 KiB
C
Raw Normal View History

/*
2025-06-11 10:55:00 -05:00
* _adc->c
*
* Created on: Mar 31, 2023
* Author: Keith.Lloyd
*/
#include <stdbool.h>
#include <math.h>
#include "fsl_device_registers.h"
#include "fsl_debug_console.h"
#include "pin_mux.h"
#include "board.h"
#include "fsl_adc.h"
#include "fsl_clock.h"
#include "fsl_power.h"
//Application includes
#include "timer.h"
#include "adc.h"
//#include "frq.h"
#include "ports.h"
#include "utils.h"
#include "hwFixes.h"
2025-06-11 10:55:00 -05:00
#include "System/system.h"
#include "driver.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define DEMO_ADC_BASE ADC0
#define DEMO_ADC_SAMPLE_CHANNEL_NUMBER 7U
#define DEMO_ADC_CLOCK_DIVIDER 1U
/*******************************************************************************
* Prototypes
******************************************************************************/
static void ADC_Configuration(void);
extern uint8_t Port_State[];
uint32_t what_val1,what_val2;
extern uint8_t frequency;
extern FREQUENCY_t freqArray[FREQ_MAX_NUM];
float32_t volts_check;
extern float32_t Watts_Filt;
extern HARDWARE_FIX_t hwf;
2025-06-11 10:55:00 -05:00
extern SYSTEM_DATA_t sys;
/*******************************************************************************
* Variables
******************************************************************************/
2025-06-11 10:55:00 -05:00
static ADC_t *_adc;
adc_result_info_t adcResultInfoStruct;
/*
* Current measurement scaling vs frequency for LOW gain
* This is used to look up and interpolate current scaling
* Number of rows is not specified and can be any length
* Number of columns hard coded at 2: frequency, scale
*/
//Values from SN ONION using offset compensated single point @ 1000mA
float32_t currentTableLowGain[][ADC_TABLE_COLUMNS] = {
{ 256 , 0.002118644 } ,
{ 360 , 0.001926782 } ,
{ 512 , 0.001858736 } ,
{ 640 , 0.001821494 } ,
{ 1170 , 0.001785714 } ,
{ 3140 , 0.001769912 } ,
{ 8192 , 0.00177305 } ,
{ 14000 , 0.001778726 } ,
{ 20000 , 0.001786991 } ,
{ 29430 , 0.001801802 } ,
{ 32800 , 0.001806685 } ,
{ 44500 , 0.001828154 } ,
#if 1 //temporary change
{ 66100 , 0.001874414 * 1.28} ,//1.28
{ 88800 , 0.001931621 * 1.84} ,//1.84
{ 99000 , 0.001960784 * 1.58} ,//1.58
{ 150000 , 0.00213858 } ,
{ 200000 , 0.002364066 } ,
#else //original values
{ 66100 , 0.001874414 } ,
{ 88800 , 0.001931621 } ,
{ 99000 , 0.001960784 } ,
{ 150000 , 0.00213858 } ,
{ 200000 , 0.002364066 } ,
#endif
};
//High gain current table - Works same as low gain table. Values from SN ONION
float32_t currentTableHighGain[][ADC_TABLE_COLUMNS] = {
{ 256 , 5.27426E-05 } ,
{ 360 , 4.92126E-05 } ,
{ 512 , 4.64684E-05 } ,
{ 640 , 4.54959E-05 } ,
{ 1170 , 4.44444E-05 } ,
{ 3140 , 4.42087E-05 } ,
{ 8192 , 4.53309E-05 } ,
{ 14000 , 4.77464E-05 } ,
{ 20000 , 5.13663E-05 } ,
{ 29430 , 5.9004E-05 } ,
{ 32800 , 6.21891E-05 } ,
{ 44500 , 7.47831E-05 } ,
{ 66100 , 0.000103907 } ,
{ 88800 , 0.000143349 } ,
{ 99000 , 0.000165017 } ,
{ 150000 , 0.000340136 } ,
{ 200000 , 0.000702247 } ,
};
/*
* Voltage measurement scaling vs frequency for LOW gain
* This is used to look up and interpolate current scaling
* Number of rows is not specified and can be any length
* Number of columns hard coded at 2: frequency, scale
*/
float32_t voltageTableLowGain[][ADC_TABLE_COLUMNS] = {
{ 256 , 0.182338205 } ,
{ 360 , 0.165825101 } ,
{ 512 , 0.159240069 } ,
{ 640 , 0.155824916 } ,
{ 870 , 0.147733711 } ,
{ 1170 , 0.14674221 } ,
{ 3140 , 0.146165644 } ,
{ 5600 , 0.146347826 } ,
{ 8192 , 0.146907216 } ,
{ 14000 , 0.148426509 } ,
{ 20000 , 0.148590381 } ,
{ 29430 , 0.147376717 } ,
{ 32800 , 0.152678378 } ,
{ 44500 , 0.149038462 } ,
{ 66100 , 0.179871383 } ,
{ 88800 , 0.19462585 } ,
{ 99000 , 0.202585604 } ,
{ 150000 , 0.252818035 } ,
{ 200000 , 0.312444837 } ,
};
//Values from SN ONION (208023) using offset compensated single point @ 500mA
float32_t currentTableLowGain208023[][ADC_TABLE_COLUMNS] = {
{ 256 , 0.00203666 } ,
{ 360 , 0.00187970 } ,
{ 512 , 0.00181818 } ,
{ 640 , 0.00179856 } ,
{ 1170 , 0.00175747 } ,
{ 3140 , 0.00174459 } ,
{ 8192 , 0.00174825 } ,
{ 14000 , 0.00176056 } ,
{ 20000 , 0.00177431 } ,
{ 29430 , 0.00179856 } ,
{ 32800 , 0.00180897 } ,
{ 44500 , 0.00184502 } ,
{ 66100 , 0.00192678 } ,
{ 88800 , 0.00202840 } ,
{ 99000 , 0.00208333 } ,
{ 150000 , 0.00241313 } ,
{ 200000 , 0.00286862 } ,
};
//High gain current table - Works same as low gain table. Values from SN ONION
float32_t currentTableHighGain208023[][ADC_TABLE_COLUMNS] = {
{ 256 , 0.00005171 } ,
{ 360 , 0.00004817 } ,
{ 512 , 0.00004695 } ,
{ 640 , 0.00004600 } ,
{ 1170 , 0.00004505 } ,
{ 3140 , 0.00004464 } ,
{ 8192 , 0.00004452 } ,
{ 14000 , 0.00004460 } ,
{ 20000 , 0.00004468 } ,
{ 29430 , 0.00004492 } ,
{ 32800 , 0.00004500 } ,
{ 44500 , 0.00004533 } ,
{ 66100 , 0.00004610 } ,
{ 88800 , 0.00004707 } ,
{ 99000 , 0.00004762 } ,
{ 150000 , 0.00005086 } ,
{ 200000 , 0.00005513 } ,
};
/*
* Voltage measurement scaling vs frequency for LOW gain
* This is used to look up and interpolate current scaling
* Number of rows is not specified and can be any length
* Number of columns hard coded at 2: frequency, scale
*/
float32_t voltageTableLowGain208023[][ADC_TABLE_COLUMNS] = {
{ 98 , 0.155877863 } ,
{ 256 , 0.155877863 } ,
{ 360 , 0.151178571 } ,
{ 512 , 0.148143054 } ,
{ 640 , 0.147208986 } ,
{ 870 , 0.146820809 } ,
{ 1170 , 0.14350365 } ,
{ 3140 , 0.145137645 } ,
{ 5600 , 0.146038095 } ,
{ 8192 , 0.146697229 } ,
{ 14000 , 0.146918994 } ,
{ 20000 , 0.147096457 } ,
{ 29430 , 0.145183742 } ,
{ 32800 , 0.14886061 } ,
{ 44500 , 0.150783939 } ,
{ 66100 , 0.157547751 } ,
{ 88800 , 0.163411541 } ,
{ 99000 , 0.166688103 } ,
{ 150000 , 0.187197232 } ,
{ 200000 , 0.21567892 } ,
};
//Values from SN 2060-00424 (208025) using offset compensated single point @ 500mA
float32_t currentTableLowGain208025[][ADC_TABLE_COLUMNS2] = {
{ 98 , 0.00124072 , 0.000 } ,
{ 256 , 0.00124072 , 0.000 } ,
{ 360 , 0.00116692 , 0.000 } ,
{ 512 , 0.00112509 , 0.000 } ,
{ 640 , 0.00110724 , 0.000 } ,
{ 1170 , 0.00108541 , 0.000 } ,
{ 3140 , 0.00107574 , 0.000 } ,
{ 8192 , 0.00107574 , 0.000 } ,
{ 14000 , 0.00107870 , 0.000 } ,
{ 20000 , 0.00108242 , 0.000 } ,
{ 29430 , 0.00108918 , 0.000 } ,
{ 32800 , 0.00109183 , 0.000 } ,
{ 44500 , 0.00110334 , 0.000 } ,
{ 66100 , 0.00112671 * 1.1052 , 0.000 } ,
{ 88800 , 0.00115831 * 1.1052, 0.000 } ,
{ 99000 , 0.00117346 * 1.2413, 0.000 } ,
{ 150000 , 0.00127086 * 1.6322 , 0.000 } , //1.327
{ 200000 , 0.00140135 * 2.4123 , 0.000 } ,//2.805
};
//High gain current table. Values from SN 2060-00424 (208025)
//Scale values are Amps/count, offsets are in Amps
float32_t currentTableHighGain208025[][ADC_TABLE_COLUMNS2] = {
{ 98 , 0.00004951 , 0.000 } ,
{ 256 , 0.00004951 , 0.000 } ,
{ 360 , 0.00004662 , 0.000 } ,
{ 512 , 0.00004499 , 0.000 } ,
{ 640 , 0.00004437 , 0.000 } ,
{ 1170 , 0.00004342 , 0.000 } ,
{ 3140 , 0.00004296 , 0.000 } ,
{ 8192 , 0.00004289 , 0.000 } ,
{ 14000 , 0.00004289 , 0.000 } ,
{ 20000 , 0.00004293 , 0.000 } ,
{ 29430 , 0.00004304 , 0.000 } ,
{ 32800 , 0.00004308 , 0.000 } ,
{ 44500 , 0.00004327 , 0.000 } ,
{ 66100 , 0.00004374 , 0.000 } ,
{ 88800 , 0.00004437 , 0.000 } ,
{ 99000 , 0.00004470 , 0.000 } ,
{ 150000 , 0.00004685 , 0.000 } ,
{ 200000 , 0.00004967 , 0.000 } ,
};
/*******************************************************************************
* Static Functions
******************************************************************************/
static void ADC_ClockPower_Configuration(void)
{
/* SYSCON power. */
POWER_DisablePD(kPDRUNCFG_PD_ADC0); /* Power on the ADC converter. */
POWER_DisablePD(kPDRUNCFG_PD_VD7_ENA); /* Power on the analog power supply. */
POWER_DisablePD(kPDRUNCFG_PD_VREFP_SW); /* Power on the reference voltage source. */
POWER_DisablePD(kPDRUNCFG_PD_TEMPS); /* Power on the temperature sensor. */
CLOCK_EnableClock(kCLOCK_Adc0); /* SYSCON->AHBCLKCTRL[0] |= SYSCON_AHBCLKCTRL_ADC0_MASK; */
}
static void ADC_Configuration(void)
{
adc_config_t adcConfigStruct;
adc_conv_seq_config_t adcConvSeqConfigStruct;
/* Configure the converter. */
adcConfigStruct.clockMode = kADC_ClockSynchronousMode; /* Using sync clock source. */
adcConfigStruct.clockDividerNumber = DEMO_ADC_CLOCK_DIVIDER;
adcConfigStruct.resolution = kADC_Resolution12bit;
adcConfigStruct.enableBypassCalibration = false;
adcConfigStruct.sampleTimeNumber = 0U;
ADC_Init(DEMO_ADC_BASE, &adcConfigStruct);
/* Use the temperature sensor input to channel 0. */
ADC_EnableTemperatureSensor(DEMO_ADC_BASE, false); //was true
/* Enable channel DEMO_ADC_SAMPLE_CHANNEL_NUMBER's conversion in Sequence A. */
adcConvSeqConfigStruct.channelMask =
(1U << 7) | (1 << 5) | (1 << 6) | ( 1 << 10 ) | (1 << 9) | ( 1 << 8) | (1 << 4) | (1 << 3) | ( 1 << 1) | (1 << 0); // added ID1 and 2
//adcConvSeqConfigStruct.channelMask =
// (1 << 5) |(1 << 6); // ACCY1 and 2 only
adcConvSeqConfigStruct.triggerMask = 0U;
adcConvSeqConfigStruct.triggerPolarity = kADC_TriggerPolarityPositiveEdge;
adcConvSeqConfigStruct.enableSingleStep = false;
adcConvSeqConfigStruct.enableSyncBypass = false;
adcConvSeqConfigStruct.interruptMode = kADC_InterruptForEachSequence;
ADC_SetConvSeqAConfig(DEMO_ADC_BASE, &adcConvSeqConfigStruct);
ADC_EnableConvSeqA(DEMO_ADC_BASE, true); /* Enable the conversion sequence A. */
/* Clear the result register. */
ADC_DoSoftwareTriggerConvSeqA(DEMO_ADC_BASE);
while (!ADC_GetChannelConversionResult(DEMO_ADC_BASE, 6, &adcResultInfoStruct)) //MAKE SURE THIS CHANNEL IS USED!
{
}
ADC_GetConvSeqAGlobalConversionResult(DEMO_ADC_BASE, &adcResultInfoStruct);
}
/*
* Get Current for LOW gain
* @arg input raw ADC counts
* @return
*/
static float32_t ScaleLowGainCurrent(float32_t input)
{
uint32_t lowIndex; //index of the closest table frequency below the target frequency
uint32_t highIndex; //index of the closest table frequency above the target frequency
float32_t scale = 0;//scale factor for the frequency. input * scale = current
//Get number of entries in table
uint32_t numEntries = sizeof(currentTableLowGain) / sizeof(float32_t) / 2;
//Get target frequency
//float32_t targetFreq = FREQ_GetFreqByIndex(frequency).frequency1;
float32_t targetFreq = sys.driver->frequency->frequency;
#if 0 //TESTING - Use a specific frequency
targetFreq = 384;
#endif
//Find the first index in currentTableLowGain that is greater than or equal to targetFreq. This will be highIndex
highIndex = 0;
while((currentTableLowGain[highIndex][ADC_TABLE_FREQ] < targetFreq) && (highIndex < numEntries))
{
highIndex++;
}
if(currentTableLowGain[highIndex][ADC_TABLE_FREQ] < targetFreq)//If targetFreq is too large, use the highest table value
{
scale = currentTableLowGain[numEntries][ADC_TABLE_SCALE];
}
else if(currentTableLowGain[highIndex][ADC_TABLE_FREQ] == targetFreq) //If it's equal, use the value in the table
{
scale = currentTableLowGain[highIndex][ADC_TABLE_SCALE];
}
else //else interpolate
{
lowIndex = highIndex-1;
float32_t x = targetFreq;
float32_t x1 = currentTableLowGain[lowIndex][ADC_TABLE_FREQ];
float32_t x2 = currentTableLowGain[highIndex][ADC_TABLE_FREQ];
float32_t y1 = currentTableLowGain[lowIndex][ADC_TABLE_SCALE];
float32_t y2 = currentTableLowGain[highIndex][ADC_TABLE_SCALE];
scale = y1 + (x - x1) * (y2 - y1) / (x2 - x1);
}
2025-06-11 10:55:00 -05:00
//Update _adc->currentClipping
_adc->currentClipping = (input > ADC_LOW_GAIN_CURR_CLIP_THRESH);
return (input * scale);
}
/*
* Get Current for HIGH gain
* @arg input raw ADC counts
* @return
*/
static float32_t ScaleHighGainCurrent(float32_t input)
{
uint32_t lowIndex; //index of the closest table frequency below the target frequency
uint32_t highIndex; //index of the closest table frequency above the target frequency
float32_t scale = 0;//scale factor for the frequency. input * scale = current
//Get number of entries in table
uint32_t numEntries = sizeof(currentTableHighGain) / sizeof(float32_t) / 2;
//Get target frequency
//float32_t targetFreq = FREQ_GetFreqByIndex(frequency).frequency1;
float32_t targetFreq = sys.driver->frequency->frequency;
#if 0 //TESTING - Use a specific frequency
targetFreq = 384;
#endif
//Find the first index in currentTableHighGain that is greater than or equal to targetFreq. This will be highIndex
highIndex = 0;
while((currentTableHighGain[highIndex][ADC_TABLE_FREQ] < targetFreq) && (highIndex < numEntries))
{
highIndex++;
}
if(currentTableHighGain[highIndex][ADC_TABLE_FREQ] < targetFreq)//If targetFreq is too large, use the highest table value
{
scale = currentTableHighGain[numEntries][ADC_TABLE_SCALE];
}
else if(currentTableHighGain[highIndex][ADC_TABLE_FREQ] == targetFreq) //If it's equal, use the value in the table
{
scale = currentTableHighGain[highIndex][ADC_TABLE_SCALE];
}
else //else interpolate
{
lowIndex = highIndex-1;
float32_t x = targetFreq;
float32_t x1 = currentTableHighGain[lowIndex][ADC_TABLE_FREQ];
float32_t x2 = currentTableHighGain[highIndex][ADC_TABLE_FREQ];
float32_t y1 = currentTableHighGain[lowIndex][ADC_TABLE_SCALE];
float32_t y2 = currentTableHighGain[highIndex][ADC_TABLE_SCALE];
scale = y1 + (x - x1) * (y2 - y1) / (x2 - x1);
}
2025-06-11 10:55:00 -05:00
//Update _adc->currentClipping
_adc->currentClipping = (input > ADC_HIGH_GAIN_CURR_CLIP_THRESH);
return (input * scale);
}
/*
* Get Voltage for LOW gain
* @arg input raw ADC counts
* @return
*/
static float32_t ScaleLowGainVoltage(float32_t input)
{
uint32_t lowIndex; //index of the closest table frequency below the target frequency
uint32_t highIndex; //index of the closest table frequency above the target frequency
float32_t scale = 0;//scale factor for the frequency. input * scale = current
//Get number of entries in table
uint32_t numEntries = sizeof(voltageTableLowGain) / sizeof(float32_t) / 2;
//Get target frequency
//float32_t targetFreq = FREQ_GetFreqByIndex(frequency).frequency1;
float32_t targetFreq = sys.driver->frequency->frequency;
#if 0 //TESTING - Use a specific frequency
targetFreq = 384;
#endif
//Find the first index in voltageTableLowGain that is greater than or equal to targetFreq. This will be highIndex
highIndex = 0;
while((voltageTableLowGain[highIndex][ADC_TABLE_FREQ] < targetFreq) && (highIndex < numEntries))
{
highIndex++;
}
if(voltageTableLowGain[highIndex][ADC_TABLE_FREQ] < targetFreq)//If targetFreq is too large, use the highest table value
{
scale = voltageTableLowGain[numEntries][ADC_TABLE_SCALE];
}
else if(voltageTableLowGain[highIndex][ADC_TABLE_FREQ] == targetFreq) //If it's equal, use the value in the table
{
scale = voltageTableLowGain[highIndex][ADC_TABLE_SCALE];
}
else //else interpolate
{
lowIndex = highIndex-1;
float32_t x = targetFreq;
float32_t x1 = voltageTableLowGain[lowIndex][ADC_TABLE_FREQ];
float32_t x2 = voltageTableLowGain[highIndex][ADC_TABLE_FREQ];
float32_t y1 = voltageTableLowGain[lowIndex][ADC_TABLE_SCALE];
float32_t y2 = voltageTableLowGain[highIndex][ADC_TABLE_SCALE];
scale = y1 + (x - x1) * (y2 - y1) / (x2 - x1);
}
2025-06-11 10:55:00 -05:00
//Update _adc->votageClipping
_adc->voltageClipping = (input > ADC_LOW_GAIN_VOLT_CLIP_THRESH);
return (input * scale);
}
/*
* Get Current for LOW gain
* @arg input raw ADC counts
* @return corrected current
*/
static float32_t ScaleLowGainCurrent208023(float32_t input)
{
uint32_t lowIndex; //index of the closest table frequency below the target frequency
uint32_t highIndex; //index of the closest table frequency above the target frequency
float32_t scale = 0;//scale factor for the frequency. input * scale = current
//Get number of entries in table
uint32_t numEntries = sizeof(currentTableLowGain208023) / sizeof(float32_t) / 2;
//Get target frequency
//float32_t targetFreq = FREQ_GetFreqByIndex(frequency).frequency1;
float32_t targetFreq = sys.driver->frequency->frequency;
#if 0 //TESTING - Use a specific frequency
targetFreq = 384;
#endif
//Find the first index in currentTableLowGain208023 that is greater than or equal to targetFreq. This will be highIndex
highIndex = 0;
while((currentTableLowGain208023[highIndex][ADC_TABLE_FREQ] < targetFreq) && (highIndex < numEntries))
{
highIndex++;
}
if(currentTableLowGain208023[highIndex][ADC_TABLE_FREQ] < targetFreq)//If targetFreq is too large, use the highest table value
{
scale = currentTableLowGain208023[numEntries][ADC_TABLE_SCALE];
}
else if(currentTableLowGain208023[highIndex][ADC_TABLE_FREQ] == targetFreq) //If it's equal, use the value in the table
{
scale = currentTableLowGain208023[highIndex][ADC_TABLE_SCALE];
}
else //else interpolate
{
lowIndex = highIndex-1;
float32_t x = targetFreq;
float32_t x1 = currentTableLowGain208023[lowIndex][ADC_TABLE_FREQ];
float32_t x2 = currentTableLowGain208023[highIndex][ADC_TABLE_FREQ];
float32_t y1 = currentTableLowGain208023[lowIndex][ADC_TABLE_SCALE];
float32_t y2 = currentTableLowGain208023[highIndex][ADC_TABLE_SCALE];
scale = y1 + (x - x1) * (y2 - y1) / (x2 - x1);
}
2025-06-11 10:55:00 -05:00
//Update _adc->currentClipping
_adc->currentClipping = (input > ADC_LOW_GAIN_CURR_CLIP_THRESH);
return (input * scale);
}
/*
* Get Current for HIGH gain
* @arg input raw ADC counts
* @return corrected current
*/
static float32_t ScaleHighGainCurrent208023(float32_t input)
{
uint32_t lowIndex; //index of the closest table frequency below the target frequency
uint32_t highIndex; //index of the closest table frequency above the target frequency
float32_t scale = 0;//scale factor for the frequency. input * scale = current
//Get number of entries in table
uint32_t numEntries = sizeof(currentTableHighGain208023) / sizeof(float32_t) / 2;
//Get target frequency
//float32_t targetFreq = FREQ_GetFreqByIndex(frequency).frequency1;
float32_t targetFreq = sys.driver->frequency->frequency;
#if 0 //TESTING - Use a specific frequency
targetFreq = 384;
#endif
//Find the first index in currentTableHighGain208023 that is greater than or equal to targetFreq. This will be highIndex
highIndex = 0;
while((currentTableHighGain208023[highIndex][ADC_TABLE_FREQ] < targetFreq) && (highIndex < numEntries))
{
highIndex++;
}
if(currentTableHighGain208023[highIndex][ADC_TABLE_FREQ] < targetFreq)//If targetFreq is too large, use the highest table value
{
scale = currentTableHighGain208023[numEntries][ADC_TABLE_FREQ];
}
else if(currentTableHighGain208023[highIndex][ADC_TABLE_FREQ] == targetFreq) //If it's equal, use the value in the table
{
scale = currentTableHighGain208023[highIndex][ADC_TABLE_SCALE];
}
else //else interpolate
{
lowIndex = highIndex-1;
float32_t x = targetFreq;
float32_t x1 = currentTableHighGain208023[lowIndex][ADC_TABLE_FREQ];
float32_t x2 = currentTableHighGain208023[highIndex][ADC_TABLE_FREQ];
float32_t y1 = currentTableHighGain208023[lowIndex][ADC_TABLE_SCALE];
float32_t y2 = currentTableHighGain208023[highIndex][ADC_TABLE_SCALE];
scale = y1 + (x - x1) * (y2 - y1) / (x2 - x1);
}
2025-06-11 10:55:00 -05:00
//Update _adc->currentClipping
_adc->currentClipping = (input > ADC_HIGH_GAIN_CURR_CLIP_THRESH);
return (input * scale);
}
/*
* Get Voltage for LOW gain 208023. Also used for 208025
* @arg input raw ADC counts
* @return corrected voltage
*/
static float32_t ScaleLowGainVoltage208023(float32_t input)
{
uint32_t lowIndex; //index of the closest table frequency below the target frequency
uint32_t highIndex; //index of the closest table frequency above the target frequency
float32_t scale = 0;//scale factor for the frequency. input * scale = current
//Get number of entries in table
uint32_t numEntries = sizeof(voltageTableLowGain208023) / sizeof(float32_t) / 2;
//Get target frequency
//float32_t targetFreq = FREQ_GetFreqByIndex(frequency).frequency1;
float32_t targetFreq = sys.driver->frequency->frequency;
#if 0 //TESTING - Use a specific frequency
targetFreq = 384;
#endif
//Find the first index in voltageTableLowGain208023 that is greater than or equal to targetFreq. This will be highIndex
highIndex = 0;
while((voltageTableLowGain208023[highIndex][ADC_TABLE_FREQ] < targetFreq) && (highIndex < numEntries))
{
highIndex++;
}
if(voltageTableLowGain208023[highIndex][ADC_TABLE_FREQ] < targetFreq)//If targetFreq is too large, use the highest table value
{
scale = voltageTableLowGain208023[numEntries][ADC_TABLE_SCALE];
}
else if(voltageTableLowGain208023[highIndex][ADC_TABLE_FREQ] == targetFreq) //If it's equal, use the value in the table
{
scale = voltageTableLowGain208023[highIndex][ADC_TABLE_SCALE];
}
else //else interpolate
{
lowIndex = highIndex-1;
float32_t x = targetFreq;
float32_t x1 = voltageTableLowGain208023[lowIndex][ADC_TABLE_FREQ];
float32_t x2 = voltageTableLowGain208023[highIndex][ADC_TABLE_FREQ];
float32_t y1 = voltageTableLowGain208023[lowIndex][ADC_TABLE_SCALE];
float32_t y2 = voltageTableLowGain208023[highIndex][ADC_TABLE_SCALE];
scale = y1 + (x - x1) * (y2 - y1) / (x2 - x1);
}
2025-06-11 10:55:00 -05:00
//Update _adc->votageClipping
_adc->voltageClipping = (input > ADC_LOW_GAIN_VOLT_CLIP_THRESH);
return (input * scale);
}
/*
* Get Current for LOW gain
* Apply scaling and offset from table
* @arg input raw ADC counts
* @return corrected current
*/
static float32_t ScaleLowGainCurrent208025(float32_t input)
{
uint32_t lowIndex; //index of the closest table frequency below the target frequency
uint32_t highIndex; //index of the closest table frequency above the target frequency
float32_t scale = 0; //scale factor for the frequency. input * scale = current
float32_t offset = 0; //offset for the frequency in Amps
//Get number of entries in table
uint32_t numEntries = sizeof(currentTableLowGain208025) / sizeof(float32_t) / 3;
//Get target frequency
//float32_t targetFreq = FREQ_GetFreqByIndex(frequency).frequency1;
float32_t targetFreq = sys.driver->frequency->frequency;
#if 0 //TESTING - Use a specific frequency
targetFreq = 384;
#endif
//Find the first index in currentTableLowGain208025 that is greater than or equal to targetFreq. This will be highIndex
highIndex = 0;
while((currentTableLowGain208025[highIndex][ADC_TABLE_FREQ] < targetFreq) && (highIndex < numEntries))
{
highIndex++;
}
if(currentTableLowGain208025[highIndex][ADC_TABLE_FREQ] < targetFreq) //If targetFreq is too large, use the highest table value
{
scale = currentTableLowGain208025[numEntries][ADC_TABLE_SCALE];
offset = currentTableLowGain208025[numEntries][ADC_TABLE_OFFSET];
}
else if(currentTableLowGain208025[highIndex][ADC_TABLE_FREQ] == targetFreq) //If it's equal, use the value in the table
{
scale = currentTableLowGain208025[highIndex][ADC_TABLE_SCALE];
offset = currentTableLowGain208025[highIndex][ADC_TABLE_OFFSET];
}
else //else interpolate
{
lowIndex = highIndex-1;
//scale
float32_t x = targetFreq;
float32_t x1 = currentTableLowGain208025[lowIndex][ADC_TABLE_FREQ];
float32_t x2 = currentTableLowGain208025[highIndex][ADC_TABLE_FREQ];
float32_t y1 = currentTableLowGain208025[lowIndex][ADC_TABLE_SCALE];
float32_t y2 = currentTableLowGain208025[highIndex][ADC_TABLE_SCALE];
scale = y1 + (x - x1) * (y2 - y1) / (x2 - x1);
//OFFSET
y1 = currentTableLowGain208025[lowIndex][ADC_TABLE_OFFSET];
y2 = currentTableLowGain208025[highIndex][ADC_TABLE_OFFSET];
offset = y1 + (x - x1) * (y2 - y1) / (x2 - x1);
}
2025-06-11 10:55:00 -05:00
//Update _adc->currentClipping
_adc->currentClipping = (input > ADC_LOW_GAIN_CURR_CLIP_THRESH);
return ((input * scale) + offset);
}
/*
* Get Current for HIGH gain
* Apply scaling and offset from table
* @arg input raw ADC counts
* @return corrected current
*/
static float32_t ScaleHighGainCurrent208025(float32_t input)
{
uint32_t lowIndex; //index of the closest table frequency below the target frequency
uint32_t highIndex; //index of the closest table frequency above the target frequency
float32_t scale = 0; //scale factor for the frequency. input * scale = current
float32_t offset = 0; //offset for the frequency in Amps
//Get number of entries in table
uint32_t numEntries = sizeof(currentTableHighGain208025) / sizeof(float32_t) / 3;
//Get target frequency
//float32_t targetFreq = FREQ_GetFreqByIndex(frequency).frequency1;
float32_t targetFreq = sys.driver->frequency->frequency;
#if 1 //TESTING - Use a specific frequency
targetFreq = 5666;
#endif
//Find the first index in currentTableHighGain208025 that is greater than or equal to targetFreq. This will be highIndex
highIndex = 0;
while((currentTableHighGain208025[highIndex][ADC_TABLE_FREQ] < targetFreq) && (highIndex < numEntries))
{
highIndex++;
}
if(currentTableHighGain208025[highIndex][ADC_TABLE_FREQ] < targetFreq) //If targetFreq is too large, use the highest table value
{
scale = currentTableHighGain208025[numEntries][ADC_TABLE_SCALE];
offset = currentTableHighGain208025[numEntries][ADC_TABLE_OFFSET];
}
else if(currentTableHighGain208025[highIndex][ADC_TABLE_FREQ] == targetFreq) //If it's equal, use the value in the table
{
scale = currentTableHighGain208025[highIndex][ADC_TABLE_SCALE];
offset = currentTableHighGain208025[highIndex][ADC_TABLE_OFFSET];
}
else //else interpolate
{
lowIndex = highIndex-1;
//scale
float32_t x = targetFreq;
float32_t x1 = currentTableHighGain208025[lowIndex][ADC_TABLE_FREQ];
float32_t x2 = currentTableHighGain208025[highIndex][ADC_TABLE_FREQ];
float32_t y1 = currentTableHighGain208025[lowIndex][ADC_TABLE_SCALE];
float32_t y2 = currentTableHighGain208025[highIndex][ADC_TABLE_SCALE];
scale = y1 + (x - x1) * (y2 - y1) / (x2 - x1);
//OFFSET
y1 = currentTableHighGain208025[lowIndex][ADC_TABLE_OFFSET];
y2 = currentTableHighGain208025[highIndex][ADC_TABLE_OFFSET];
offset = y1 + (x - x1) * (y2 - y1) / (x2 - x1);
}
2025-06-11 10:55:00 -05:00
//Update _adc->currentClipping
_adc->currentClipping = (input > ADC_HIGH_GAIN_CURR_CLIP_THRESH);
return ((input * scale) + offset);
}
/*******************************************************************************
* Public Functions
******************************************************************************/
/*!
* @brief Main function
*/
2025-06-11 10:55:00 -05:00
void ADC_SysInit(void)
{
2025-06-11 10:55:00 -05:00
_adc = &sys.adc;
/* Enable the power and clock for ADC. */
ADC_ClockPower_Configuration();
uint32_t adcClockFreq = 0U;
/* Calibration after power up. */
//DEMO_ADC_BASE->CTRL |= ADC_CTRL_BYPASSCAL_MASK; //This line skips adc offset calibration
adcClockFreq = CLOCK_GetFreq(kCLOCK_BusClk);
if (true == ADC_DoOffsetCalibration(DEMO_ADC_BASE, adcClockFreq)) //Also fixes ADCCLK (30MHZ max)
{
//PRINTF("ADC Calibration Done.\r\n");
}
else
{
//PRINTF("ADC Calibration Failed.\r\n");
while(1);
}
/* Configure the converter and work mode. */
ADC_Configuration();
ADC_MeasureCurrentOffset();
//Start automatic ADC measurements (ctimer callback)
2025-06-11 10:55:00 -05:00
_adc->measure = true;
}
//Measure offset for current measurement channel
//Also output voltage channel
void ADC_MeasureCurrentOffset(void)
{
//Measure current 8x and average
2025-06-11 10:55:00 -05:00
//Store as _adc->I_Offset
Delay_Ticks(7); //70mS for current signal to stabilize
uint32_t currentOffsetSum = 0;
uint32_t voltageOffsetSum = 0;
uint32_t test[8];
for(uint32_t i = 0; i < 8; i++) //8 samples
{
ADC_Update();
Delay_Ticks(2); //20mS
2025-06-11 10:55:00 -05:00
currentOffsetSum += _adc->rawCurrent;
voltageOffsetSum += _adc->rawVoltage;
2025-06-11 10:55:00 -05:00
test[i] = _adc->rawVoltage; //collect samples for testing
}
2025-06-11 10:55:00 -05:00
_adc->I_OffsetAdc = currentOffsetSum >> 3; //average of 8 samples
#if ADC_USE_NOISE_OFFSET
2025-06-11 10:55:00 -05:00
_adc->I_OffsetAdc -= ADC_NOISE_OFFSET_COUNTS;
#endif
#if 0 //TESTING: Allow larger offset
2025-06-11 10:55:00 -05:00
if(abs((int32_t)(_adc->I_OffsetAdc) - ADC_HALF_COUNTS) <= 50)
#else
2025-06-11 10:55:00 -05:00
if(abs((int32_t)(_adc->I_OffsetAdc) - ADC_HALF_COUNTS) <= ADC_OFFSET_MAX_ERROR) //offset within 30 counts of mid scale
#endif
{
2025-06-11 10:55:00 -05:00
_adc->iosOK = true;
}
else
{
2025-06-11 10:55:00 -05:00
_adc->iosOK = false; //This will NOT be needed after keith removes the restart when USB is disconnected
}
2025-06-11 10:55:00 -05:00
_adc->V_OffsetAdc = voltageOffsetSum >> 3; //average of 8 samples
if(abs((int32_t)(_adc->V_OffsetAdc) - ADC_HALF_COUNTS) <= ADC_OFFSET_MAX_ERROR) //offset within 30 counts of mid scale
{
2025-06-11 10:55:00 -05:00
_adc->vosOK = true;
}
else
{
2025-06-11 10:55:00 -05:00
_adc->vosOK = false;
}
}
/*
* Measure analog voltages and convert to quantities
* 100Hz sample rate
* Voltage and current are sampled and filtered at 100Hz
* All others are averages of 10 samples, so output at 10Hz
*/
void ADC_Update(void)
{
//start conversion
ADC_DoSoftwareTriggerConvSeqA(DEMO_ADC_BASE);
// Wait for the converter to be done with the LAST channel (10)
while(!ADC_GetChannelConversionResult(DEMO_ADC_BASE, 10, &adcResultInfoStruct));
//Add measurement to adc struct
2025-06-11 10:55:00 -05:00
_adc->V_BID_RAW += adcResultInfoStruct.result; //ch10
//CURRENT
ADC_GetChannelConversionResult(DEMO_ADC_BASE, 0, &adcResultInfoStruct);
2025-06-11 10:55:00 -05:00
_adc->rawCurrent = adcResultInfoStruct.result;
_adc->I_OUT_RAW = _adc->rawCurrent;
_adc->I_OUT = _adc->rawCurrent; //route raw current measurement to testIout
#if 0 //TESTING: Don't use offset
2025-06-11 10:55:00 -05:00
_adc->I_OUT -= ADC_HALF_COUNTS;
#else
2025-06-11 10:55:00 -05:00
if(_adc->iosOK) {_adc->I_OUT -= _adc->I_OffsetAdc; }
else {_adc->I_OUT -= ADC_HALF_COUNTS; }
#endif
#if 1 //Testing filtered raw value
2025-06-11 10:55:00 -05:00
_adc->IRaw = _adc->I_OUT; //ADC value with offset applied
_adc->IRawFilt = _adc->I_OUT; //filtered ADC counts w/ offset
_adc->IRawFilt = FILT_ExpAvgF32(_adc->IRawFilt,&_adc->IRawDelay,0.02);
#endif
#if ADC_CORRECT_FOR_CURRENT_NOISE
//signal = SQRT( measurement^2 - noise^2)
2025-06-11 10:55:00 -05:00
if(_adc->I_OUT > ADC_NOISE_OFFSET_COUNTS) //avoid sqrt(negative number)
{
2025-06-11 10:55:00 -05:00
_adc->I_OUT = sqrtf(_adc->I_OUT * _adc->I_OUT - ADC_NOISE_OFFSET_COUNTS * ADC_NOISE_OFFSET_COUNTS);
}
else
{
2025-06-11 10:55:00 -05:00
_adc->I_OUT = 0;
}
#endif
//Current Scaling
if((Port_State[MID_SR] & I_GAIN) > 0) //High Current Gain
{
if(hwf.mainPcbaPN >= 208025)
{
2025-06-11 10:55:00 -05:00
_adc->I_OUT = ScaleHighGainCurrent208025(_adc->I_OUT);
}
else if(hwf.mainPcbaPN == 208023)
{
2025-06-11 10:55:00 -05:00
_adc->I_OUT = ScaleHighGainCurrent208023(_adc->I_OUT);
}
else
{
2025-06-11 10:55:00 -05:00
_adc->I_OUT = ScaleHighGainCurrent(_adc->I_OUT);
}
}
else //Low Current Gain
{
if(hwf.mainPcbaPN >= 208025)
{
2025-06-11 10:55:00 -05:00
_adc->I_OUT = ScaleLowGainCurrent208025(_adc->I_OUT);
}
else if(hwf.mainPcbaPN == 208023)
{
2025-06-11 10:55:00 -05:00
_adc->I_OUT = ScaleLowGainCurrent208025(_adc->I_OUT);
}
else
{
2025-06-11 10:55:00 -05:00
_adc->I_OUT = ScaleLowGainCurrent(_adc->I_OUT);
}
}
//VOLTAGE
ADC_GetChannelConversionResult(DEMO_ADC_BASE, 1, &adcResultInfoStruct);
2025-06-11 10:55:00 -05:00
_adc->rawVoltage = adcResultInfoStruct.result;
_adc->V_OUT_RAW = _adc->rawVoltage;
_adc->V_OUT = _adc->rawVoltage;
#if 0 //TESTING: Don't use offset
2025-06-11 10:55:00 -05:00
_adc->V_OUT -= ADC_HALF_COUNTS;
#else
2025-06-11 10:55:00 -05:00
if(_adc->vosOK) {_adc->V_OUT -= _adc->V_OffsetAdc; } //use offset if in range
else {_adc->V_OUT -= ADC_HALF_COUNTS; } //otherwise, use ADC_HALF_COUNTS
#endif
#if 1 //Testing filtered raw value
2025-06-11 10:55:00 -05:00
_adc->VRaw = _adc->V_OUT; //ADC value with offset applied. Snapshot since V_OUT gets modified later
_adc->VRawFilt = FILT_ExpAvgF32(_adc->VRaw,&_adc->VRawDelay,0.02); //filtered ADC counts w/ offset
#endif
#if 1
//Voltage Scaling
if((Port_State[BOTTOM_SR] & 0x80) > 0) //High Voltage Gain
{
//Not implemented
2025-06-11 10:55:00 -05:00
//_adc->V_OUT = MeasureHighGainVoltage(_adc->V_OUT);
}
else //Low Current Gain
{
if(hwf.mainPcbaPN >= 208023) //208023 and 208025 use the same table
{
2025-06-11 10:55:00 -05:00
_adc->V_OUT = ScaleLowGainVoltage208023(_adc->V_OUT);
}
else
{
2025-06-11 10:55:00 -05:00
_adc->V_OUT = ScaleLowGainVoltage(_adc->V_OUT);
}
}
#else
2025-06-11 10:55:00 -05:00
_adc->V_OUT = _adc->V_OUT / 4096.0 * ADC_VREF; //scale to input voltage
//_adc->V_OUT = _adc->V_OUT * (804.0 + 10.0) / 10.0; //Scale for external voltage divider
2025-06-11 10:55:00 -05:00
_adc->V_OUT = CompensateVout(_adc->V_OUT); //divider scaling sucked because AC...
Measure_Volts();
#endif
ADC_GetChannelConversionResult(DEMO_ADC_BASE, 3, &adcResultInfoStruct);
2025-06-11 10:55:00 -05:00
_adc->V_PSU_RAW += adcResultInfoStruct.result;
ADC_GetChannelConversionResult(DEMO_ADC_BASE, 4, &adcResultInfoStruct);
2025-06-11 10:55:00 -05:00
_adc->V_BAT_RAW += adcResultInfoStruct.result;
while(!ADC_GetChannelConversionResult(DEMO_ADC_BASE, 5, &adcResultInfoStruct));
2025-06-11 10:55:00 -05:00
_adc->V_ID2_RAW += adcResultInfoStruct.result;
what_val2 = adcResultInfoStruct.result;
while(!ADC_GetChannelConversionResult(DEMO_ADC_BASE, 6, &adcResultInfoStruct));
2025-06-11 10:55:00 -05:00
_adc->V_ID1_RAW += adcResultInfoStruct.result;
what_val1 = adcResultInfoStruct.result;
ADC_GetChannelConversionResult(DEMO_ADC_BASE, 7, &adcResultInfoStruct);
2025-06-11 10:55:00 -05:00
_adc->V_CHK_RAW += adcResultInfoStruct.result;
ADC_GetChannelConversionResult(DEMO_ADC_BASE, 8, &adcResultInfoStruct);
2025-06-11 10:55:00 -05:00
_adc->V_TMP_RAW += adcResultInfoStruct.result;
static uint32_t index = 0;
//On nth measurement, calculate final variable and store in adc struct
if(++index >= ADC_NUM_AVERAGES)
{
index = 0;
//CHANNEL 5
2025-06-11 10:55:00 -05:00
_adc->V_ID1 = _adc->V_ID1_RAW / ADC_NUM_AVERAGES; //average
_adc->V_ID1 = _adc->V_ID1 / 4096.0 * ADC_VREF; //scaling
//CHANNEL 6
2025-06-11 10:55:00 -05:00
_adc->V_ID2 = _adc->V_ID2_RAW / ADC_NUM_AVERAGES; //average
_adc->V_ID2 = _adc->V_ID2 / 4096.0 * ADC_VREF; //scaling
//CHANNEL 4
2025-06-11 10:55:00 -05:00
_adc->V_BAT = _adc->V_BAT_RAW / ADC_NUM_AVERAGES; //average
_adc->diag_bat = (_adc->V_BAT);
2025-06-11 10:55:00 -05:00
_adc->V_BAT = _adc->V_BAT / 4096.0 * 3.3;//ADC_VREF; //scaling
float temp;
temp = 10000.0/59900.0;
2025-06-11 10:55:00 -05:00
_adc->V_BAT = _adc->V_BAT / temp;
//CHANNEL 3
2025-06-11 10:55:00 -05:00
_adc->V_PSU = _adc->V_PSU_RAW / ADC_NUM_AVERAGES; //average
_adc->V_PSU = _adc->V_PSU / 4096.0 * ADC_VREF; //scaling
//CHANNEL 8
2025-06-11 10:55:00 -05:00
_adc->V_TMP = _adc->V_TMP_RAW / ADC_NUM_AVERAGES; //average
_adc->V_TMP = _adc->V_TMP / 4096.0 * ADC_VREF; //scaling
//CHANNEL 10 - Battery ID
2025-06-11 10:55:00 -05:00
_adc->V_BID = _adc->V_BID_RAW / ADC_NUM_AVERAGES; //average
_adc->V_BID = _adc->V_BID / 4096.0 * 3.3;//ADC_VREF; //scaling
//############# Added 2/5/24
2025-06-11 10:55:00 -05:00
// _adc->V_BID = _adc->V_BID * 1.09; // additional scaling factor
temp = 10000.0/59900.0;
2025-06-11 10:55:00 -05:00
_adc->V_BID = _adc->V_BID / temp;
//##############
//CHANNEL 7
2025-06-11 10:55:00 -05:00
_adc->V_CHK = _adc->V_CHK_RAW / ADC_NUM_AVERAGES; //average
volts_check = _adc->V_CHK;
//scaling
2025-06-11 10:55:00 -05:00
_adc->V_PSU = _adc->V_PSU * (1000+47.5)/47.5; // vratio;
2025-06-11 10:55:00 -05:00
_adc->V_CHK = _adc->V_CHK / 4096.0 * ADC_VREF; //ADC bits & ref voltage
#if 1 //HV scaling
2025-06-11 10:55:00 -05:00
_adc->V_CHK *= 2.0; //Divider in the LPF
_adc->V_CHK += 0.7; //diode drop from rectifier
_adc->V_CHK = _adc->V_CHK * (402.0 + 3.92) / 3.92; //voltage divider
#else
2025-06-11 10:55:00 -05:00
_adc->V_CHK *= 599.0 / 100.0; // Vin = Vadc* (R1+R2) / R2
2025-06-11 10:55:00 -05:00
_adc->V_CHK *= 100; //rough scale factor needs to be re done later
#endif
//clear raw sums
2025-06-11 10:55:00 -05:00
_adc->V_ID1_RAW = 0;
_adc->V_ID2_RAW = 0;
_adc->V_CHK_RAW = 0;
_adc->V_PSU_RAW = 0;
_adc->V_BAT_RAW = 0;
_adc->V_TMP_RAW = 0;
_adc->V_BID_RAW = 0;
}
// #########################################################################
// New Filter Section
// float32_t FILT_ExpAvgF32(float32_t input, float32_t *temp, float32_t k)
float32_t k=0.02;
float32_t fast_k=0.0951;
2025-06-11 10:55:00 -05:00
_adc->V_OUT_SlowFilt = FILT_ExpAvgF32(_adc->V_OUT,&_adc->V_OUT_Delay,k);
_adc->I_OUT_SlowFilt = FILT_ExpAvgF32(_adc->I_OUT,&_adc->I_OUT_Delay,k);
2025-06-11 10:55:00 -05:00
_adc->V_OUT_FastFilt = FILT_ExpAvgF32(_adc->V_OUT,&_adc->V_OUT_FastDelay,fast_k);
_adc->I_OUT_FastFilt = FILT_ExpAvgF32(_adc->I_OUT,&_adc->I_OUT_FastDelay,fast_k);
2025-06-11 10:55:00 -05:00
if(_adc->I_OUT_FastFilt > 0)
{
2025-06-11 10:55:00 -05:00
_adc->Ohms_slowfilt = FILT_ExpAvgF32(_adc->V_OUT_FastFilt/_adc->I_OUT_FastFilt,&_adc->Ohms_SlowDelay,k);
2025-06-11 10:55:00 -05:00
if(isnanf(_adc->Ohms_SlowDelay)) //Fix nan delay line
{
2025-06-11 10:55:00 -05:00
_adc->Ohms_SlowDelay = 0.00001;
}
}
//##########################################################################
2025-06-11 10:55:00 -05:00
Watts_Filt = _adc->V_OUT_FastFilt * (_adc->I_OUT_FastFilt);
// Ohms_filt = _adc->V_OUT_Filt/_adc->I_OUT_Filt;
#if ADC_MEASUREMENT_TEST
2025-06-11 10:55:00 -05:00
//USAGE: Set _adc->testCollectData = 1; to start data collection
2025-06-11 10:55:00 -05:00
//_adc->testIout = FILT_ExpAvgF32(_adc->testIout,&_adc->testIoutDelay,fast_k);
//_adc->testVout = FILT_ExpAvgF32(_adc->testVout,&_adc->testVoutDelay,fast_k);
//Test data collection for measuring filter responses
static uint32_t idx = 0;
static bool measure = 1;
2025-06-11 10:55:00 -05:00
if(_adc->testCollectData && measure)
{
2025-06-11 10:55:00 -05:00
_adc->testData1[idx] = _adc->V_OUT_FastFilt;
_adc->testData2[idx] = _adc->I_OUT_FastFilt * 1000.0; //convert to mA
idx++;
if(idx >= ADC_NUM_TEST)
{
2025-06-11 10:55:00 -05:00
_adc->testCollectData = 0; //stop data collection
idx = 0; //reset idx
measure = 0; //DO NOT take another measurement (Don't clear and it'll measure again)
}
}
#endif
}
/* Exponential averaging filter
* @input float32_t input
* @*temp float32_t storage for temporary variable
* @k float32_t filter constant k = 1 - exp(-1/T*Fs)
*/
float32_t FILT_ExpAvgF32(float32_t input, float32_t *temp, float32_t k)
{
return *temp += (input - *temp) * k;
}