1207 lines
36 KiB
C
1207 lines
36 KiB
C
/*
|
|
* 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 "measure.h"
|
|
#include "utils.h"
|
|
#include "hwFixes.h"
|
|
|
|
#include "adc.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;
|
|
|
|
/*******************************************************************************
|
|
* Variables
|
|
******************************************************************************/
|
|
|
|
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;
|
|
|
|
#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);
|
|
}
|
|
|
|
//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;
|
|
|
|
#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);
|
|
}
|
|
|
|
//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;
|
|
|
|
#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);
|
|
}
|
|
|
|
//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;
|
|
|
|
#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);
|
|
}
|
|
|
|
//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;
|
|
|
|
#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);
|
|
}
|
|
|
|
//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;
|
|
|
|
#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);
|
|
}
|
|
|
|
//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;
|
|
|
|
#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);
|
|
}
|
|
|
|
//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;
|
|
|
|
#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);
|
|
}
|
|
|
|
//Update adc.currentClipping
|
|
adc.currentClipping = (input > ADC_HIGH_GAIN_CURR_CLIP_THRESH);
|
|
|
|
return ((input * scale) + offset);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Public Functions
|
|
******************************************************************************/
|
|
|
|
/*!
|
|
* @brief Main function
|
|
*/
|
|
void ADC_Init2(void)
|
|
{
|
|
/* 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)
|
|
adc.measure = true;
|
|
}
|
|
|
|
//Measure offset for current measurement channel
|
|
//Also output voltage channel
|
|
void ADC_MeasureCurrentOffset(void)
|
|
{
|
|
//Measure current 8x and average
|
|
//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
|
|
|
|
currentOffsetSum += adc.rawCurrent;
|
|
voltageOffsetSum += adc.rawVoltage;
|
|
|
|
test[i] = adc.rawVoltage; //collect samples for testing
|
|
}
|
|
|
|
adc.I_OffsetAdc = currentOffsetSum >> 3; //average of 8 samples
|
|
|
|
#if ADC_USE_NOISE_OFFSET
|
|
adc.I_OffsetAdc -= ADC_NOISE_OFFSET_COUNTS;
|
|
#endif
|
|
|
|
#if 0 //TESTING: Allow larger offset
|
|
if(abs((int32_t)(adc.I_OffsetAdc) - ADC_HALF_COUNTS) <= 50)
|
|
#else
|
|
if(abs((int32_t)(adc.I_OffsetAdc) - ADC_HALF_COUNTS) <= ADC_OFFSET_MAX_ERROR) //offset within 30 counts of mid scale
|
|
#endif
|
|
{
|
|
adc.iosOK = true;
|
|
}
|
|
else
|
|
{
|
|
adc.iosOK = false; //This will NOT be needed after keith removes the restart when USB is disconnected
|
|
}
|
|
|
|
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
|
|
{
|
|
adc.vosOK = true;
|
|
}
|
|
else
|
|
{
|
|
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
|
|
adc.V_BID_RAW += adcResultInfoStruct.result; //ch10
|
|
|
|
|
|
//CURRENT
|
|
ADC_GetChannelConversionResult(DEMO_ADC_BASE, 0, &adcResultInfoStruct);
|
|
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
|
|
adc.I_OUT -= ADC_HALF_COUNTS;
|
|
#else
|
|
if(adc.iosOK) {adc.I_OUT -= adc.I_OffsetAdc; }
|
|
else {adc.I_OUT -= ADC_HALF_COUNTS; }
|
|
#endif
|
|
|
|
|
|
#if 1 //Testing filtered raw value
|
|
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)
|
|
if(adc.I_OUT > ADC_NOISE_OFFSET_COUNTS) //avoid sqrt(negative number)
|
|
{
|
|
adc.I_OUT = sqrtf(adc.I_OUT * adc.I_OUT - ADC_NOISE_OFFSET_COUNTS * ADC_NOISE_OFFSET_COUNTS);
|
|
}
|
|
else
|
|
{
|
|
adc.I_OUT = 0;
|
|
}
|
|
|
|
#endif
|
|
|
|
//Current Scaling
|
|
if((Port_State[MID_SR] & I_GAIN) > 0) //High Current Gain
|
|
{
|
|
if(hwf.mainPcbaPN >= 208025)
|
|
{
|
|
adc.I_OUT = ScaleHighGainCurrent208025(adc.I_OUT);
|
|
}
|
|
else if(hwf.mainPcbaPN == 208023)
|
|
{
|
|
adc.I_OUT = ScaleHighGainCurrent208023(adc.I_OUT);
|
|
}
|
|
else
|
|
{
|
|
adc.I_OUT = ScaleHighGainCurrent(adc.I_OUT);
|
|
}
|
|
}
|
|
else //Low Current Gain
|
|
{
|
|
if(hwf.mainPcbaPN >= 208025)
|
|
{
|
|
adc.I_OUT = ScaleLowGainCurrent208025(adc.I_OUT);
|
|
}
|
|
else if(hwf.mainPcbaPN == 208023)
|
|
{
|
|
adc.I_OUT = ScaleLowGainCurrent208025(adc.I_OUT);
|
|
}
|
|
else
|
|
{
|
|
adc.I_OUT = ScaleLowGainCurrent(adc.I_OUT);
|
|
}
|
|
}
|
|
|
|
|
|
//VOLTAGE
|
|
ADC_GetChannelConversionResult(DEMO_ADC_BASE, 1, &adcResultInfoStruct);
|
|
adc.rawVoltage = adcResultInfoStruct.result;
|
|
adc.V_OUT_RAW = adc.rawVoltage;
|
|
adc.V_OUT = adc.rawVoltage;
|
|
|
|
#if 0 //TESTING: Don't use offset
|
|
adc.V_OUT -= ADC_HALF_COUNTS;
|
|
#else
|
|
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
|
|
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
|
|
//adc.V_OUT = MeasureHighGainVoltage(adc.V_OUT);
|
|
}
|
|
else //Low Current Gain
|
|
{
|
|
if(hwf.mainPcbaPN >= 208023) //208023 and 208025 use the same table
|
|
{
|
|
adc.V_OUT = ScaleLowGainVoltage208023(adc.V_OUT);
|
|
}
|
|
else
|
|
{
|
|
adc.V_OUT = ScaleLowGainVoltage(adc.V_OUT);
|
|
}
|
|
}
|
|
|
|
#else
|
|
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
|
|
|
|
adc.V_OUT = CompensateVout(adc.V_OUT); //divider scaling sucked because AC...
|
|
|
|
Measure_Volts();
|
|
#endif
|
|
|
|
|
|
|
|
ADC_GetChannelConversionResult(DEMO_ADC_BASE, 3, &adcResultInfoStruct);
|
|
adc.V_PSU_RAW += adcResultInfoStruct.result;
|
|
|
|
ADC_GetChannelConversionResult(DEMO_ADC_BASE, 4, &adcResultInfoStruct);
|
|
adc.V_BAT_RAW += adcResultInfoStruct.result;
|
|
|
|
while(!ADC_GetChannelConversionResult(DEMO_ADC_BASE, 5, &adcResultInfoStruct));
|
|
adc.V_ID2_RAW += adcResultInfoStruct.result;
|
|
what_val2 = adcResultInfoStruct.result;
|
|
|
|
while(!ADC_GetChannelConversionResult(DEMO_ADC_BASE, 6, &adcResultInfoStruct));
|
|
adc.V_ID1_RAW += adcResultInfoStruct.result;
|
|
what_val1 = adcResultInfoStruct.result;
|
|
|
|
ADC_GetChannelConversionResult(DEMO_ADC_BASE, 7, &adcResultInfoStruct);
|
|
adc.V_CHK_RAW += adcResultInfoStruct.result;
|
|
|
|
ADC_GetChannelConversionResult(DEMO_ADC_BASE, 8, &adcResultInfoStruct);
|
|
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
|
|
adc.V_ID1 = adc.V_ID1_RAW / ADC_NUM_AVERAGES; //average
|
|
adc.V_ID1 = adc.V_ID1 / 4096.0 * ADC_VREF; //scaling
|
|
|
|
//CHANNEL 6
|
|
adc.V_ID2 = adc.V_ID2_RAW / ADC_NUM_AVERAGES; //average
|
|
adc.V_ID2 = adc.V_ID2 / 4096.0 * ADC_VREF; //scaling
|
|
|
|
//CHANNEL 4
|
|
adc.V_BAT = adc.V_BAT_RAW / ADC_NUM_AVERAGES; //average
|
|
adc.diag_bat = (adc.V_BAT);
|
|
|
|
adc.V_BAT = adc.V_BAT / 4096.0 * 3.3;//ADC_VREF; //scaling
|
|
float temp;
|
|
|
|
temp = 10000.0/59900.0;
|
|
adc.V_BAT = adc.V_BAT / temp;
|
|
|
|
|
|
//CHANNEL 3
|
|
adc.V_PSU = adc.V_PSU_RAW / ADC_NUM_AVERAGES; //average
|
|
adc.V_PSU = adc.V_PSU / 4096.0 * ADC_VREF; //scaling
|
|
|
|
//CHANNEL 8
|
|
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
|
|
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
|
|
// adc.V_BID = adc.V_BID * 1.09; // additional scaling factor
|
|
|
|
temp = 10000.0/59900.0;
|
|
adc.V_BID = adc.V_BID / temp;
|
|
//##############
|
|
|
|
|
|
//CHANNEL 7
|
|
adc.V_CHK = adc.V_CHK_RAW / ADC_NUM_AVERAGES; //average
|
|
volts_check = adc.V_CHK;
|
|
|
|
//scaling
|
|
|
|
adc.V_PSU = adc.V_PSU * (1000+47.5)/47.5; // vratio;
|
|
|
|
adc.V_CHK = adc.V_CHK / 4096.0 * ADC_VREF; //ADC bits & ref voltage
|
|
#if 1 //HV scaling
|
|
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
|
|
adc.V_CHK *= 599.0 / 100.0; // Vin = Vadc* (R1+R2) / R2
|
|
|
|
adc.V_CHK *= 100; //rough scale factor needs to be re done later
|
|
#endif
|
|
//clear raw sums
|
|
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;
|
|
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
if(adc.I_OUT_FastFilt > 0)
|
|
{
|
|
adc.Ohms_slowfilt = FILT_ExpAvgF32(adc.V_OUT_FastFilt/adc.I_OUT_FastFilt,&adc.Ohms_SlowDelay,k);
|
|
|
|
if(isnanf(adc.Ohms_SlowDelay)) //Fix nan delay line
|
|
{
|
|
adc.Ohms_SlowDelay = 0.00001;
|
|
}
|
|
}
|
|
|
|
|
|
//##########################################################################
|
|
Watts_Filt = adc.V_OUT_FastFilt * (adc.I_OUT_FastFilt);
|
|
// Ohms_filt = adc.V_OUT_Filt/adc.I_OUT_Filt;
|
|
|
|
|
|
#if ADC_MEASUREMENT_TEST
|
|
//USAGE: Set adc.testCollectData = 1; to start data collection
|
|
|
|
|
|
//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;
|
|
|
|
if(adc.testCollectData && measure)
|
|
{
|
|
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)
|
|
{
|
|
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;
|
|
}
|
|
|
|
|