Hi, I need help regarding ADC Automatic Comparision, if there is any SDK example code, it will be helpful to work with. I have attached my ADC configuration and function
/*
* adc_driver.c
*
* Created on: 21-Jul-2023
* Author: DELL
*/
#include "adc_driver.h"
uint16_t adc_channel0_measuremnt[NO_ADC0_CHANNEL];
uint16_t adc_channel1_measuremnt[NO_ADC1_CHANNEL];
bool adc0_conversion_complete, adc1_conversion_complete;
void ADC0_IRQHandler(){
for (uint8_t i=0; i < NO_ADC0_CHANNEL ;i++){
ADC_DRV_GetChanResult(INST_ADCONV1, i, &adc_channel0_measuremnt[i]);
}
adc0_conversion_complete = true;
return;
}
void ADC1_IRQHandler(){
for (uint8_t i=0; i<NO_ADC1_CHANNEL; i++) {
ADC_DRV_GetChanResult(INST_ADCONV2, i, &adc_channel1_measuremnt[i]);
}
adc1_conversion_complete = true;
return;
}
void ADC0_init(void){
ADC_DRV_ConfigConverter(INST_ADCONV1, &adConv1_ConvConfig0);
ADC_DRV_AutoCalibration(INST_ADCONV1);
ADC_DRV_ConfigChan(INST_ADCONV1,0U, &adConv1_ChnConfig0);
ADC_DRV_ConfigChan(INST_ADCONV1,1U, &adConv1_ChnConfig1);
ADC_DRV_ConfigChan(INST_ADCONV1,2U, &adConv1_ChnConfig2);
ADC_DRV_ConfigChan(INST_ADCONV1,3U, &adConv1_ChnConfig3);
ADC_DRV_ConfigChan(INST_ADCONV1,4U, &adConv1_ChnConfig4);
ADC_DRV_ConfigChan(INST_ADCONV1,5U, &adConv1_ChnConfig5);
return;
}
void ADC1_init(void){
ADC_DRV_ConfigConverter(INST_ADCONV2, &adConv2_ConvConfig0);
ADC_DRV_AutoCalibration(INST_ADCONV2);
ADC_DRV_ConfigChan(INST_ADCONV2, ADC1_CHANNEL_NTC_TEMP_SENSE, &adConv2_ChnConfig0);
ADC_DRV_ConfigChan(INST_ADCONV2, ADC1_CHANNEL_PCB_THERMISITOR_SENSE, &adConv2_ChnConfig1);
return;
}
void PDB0_config(void){
PDB_DRV_Init(INST_PDB1, &pdb1_InitConfig0);
PDB_DRV_Enable(INST_PDB1);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB1, 0U, &pdb1_AdcTrigInitConfig0);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB1, 0U, &pdb1_AdcTrigInitConfig1);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB1, 0U, &pdb1_AdcTrigInitConfig2);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB1, 0U, &pdb1_AdcTrigInitConfig3);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB1, 0U, &pdb1_AdcTrigInitConfig4);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB1, 0U, &pdb1_AdcTrigInitConfig5);
PDB_DRV_SetTimerModulusValue(INST_PDB1, 15U);
PDB_DRV_SetAdcPreTriggerDelayValue(INST_PDB1, 0U, 0U, 10U);
PDB_DRV_LoadValuesCmd(INST_PDB1);
return;
}
void PDB1_config(void){
PDB_DRV_Init(INST_PDB2, &pdb2_InitConfig0);
PDB_DRV_Enable(INST_PDB2);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB2, 0U, &pdb2_AdcTrigInitConfig0);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB2, 0U, &pdb2_AdcTrigInitConfig1);
PDB_DRV_SetTimerModulusValue(INST_PDB2, 15U);
PDB_DRV_SetAdcPreTriggerDelayValue(INST_PDB2, 0U, 0U, 10U);
PDB_DRV_LoadValuesCmd(INST_PDB2);
return;
}
/*
* adc.c
* Refactored for clarity, efficiency, and readability.
*/
#include "adc.h"
#include "main.h"
// Constants
#define NUM_MEASUREMENTS 3
#define ADC_MAX_VALUE 4096.0
#define ADC_VOLTAGE_REF 3.3
#define VOLTAGE_SCALE_FACTOR 100.0
#define PACK_VOLTAGE_SCALE 22
#define PACK_VOLTAGE_OFFSET -55550.0
// Static function declarations
static void ADC_start(void);
static double calculate_average(uint16_t *values, uint8_t size);
static uint8_t ADC_calculate_ntc_temperature(void);
// Function to calculate battery pack voltage
void ADC_calculate_voltage(void) {
ADC_start();
double battsense_adc = adc_channel0_measuremnt[0];
packvoltage = ((battsense_adc * ADC_VOLTAGE_REF) / ADC_MAX_VALUE) * VOLTAGE_SCALE_FACTOR;
packvoltage = (packvoltage * PACK_VOLTAGE_SCALE * VOLTAGE_SCALE_FACTOR) + PACK_VOLTAGE_OFFSET;
battery_param[5] = (uint8_t)(packvoltage / VOLTAGE_SCALE_FACTOR) >> 8;
battery_param[4] = (uint8_t)(packvoltage / VOLTAGE_SCALE_FACTOR);
}
// Function to calculate load voltage
double adc_calculate_loadvoltage(void) {
ADC_start();
return adc_channel0_measuremnt[3];
}
// Function to determine precharge status based on load/batt ratio
bool precharge_status(void) {
ADC_start();
double battsense_adc = adc_channel0_measuremnt[0];
double loadsense_adc = adc_channel0_measuremnt[3];
double percentage = (loadsense_adc / battsense_adc) * 100.0;
return (percentage > 85.0);
}
//// Function to calculate current, using an averaging buffer and direction detection
//void ADC_calculate_current(void) {
// ADC_start();
//
// static uint16_t adc_measurements[NUM_MEASUREMENTS] = {0};
// static int measurement_index = 0;
// static bool buffer_full = false;
// static double prev_avg_adc = 0.0;
//
// const double ADC_DISCHARGE_THRESHOLD = 2.2;
//#if BAT_POOL
// const double ADC_CHARGE_THRESHOLD = -0.1;
//#endif
//
// uint16_t current_adc = adc_channel0_measuremnt[ADC0_CHANNEL_BATTERY_CURRENT_SENSE];
// adc_measurements[measurement_index++] = current_adc;
// measurement_index %= NUM_MEASUREMENTS;
// buffer_full = (measurement_index == 0);
//
// if (buffer_full) {
// double current_avg_adc = calculate_average(adc_measurements, NUM_MEASUREMENTS);
// double delta_avg_adc = current_avg_adc - prev_avg_adc;
//
// if (delta_avg_adc > ADC_DISCHARGE_THRESHOLD) {
// discharge_T = true;
// charge_T = false;
// idle_T = false;
// }
// #if BAT_POOL
// else if (delta_avg_adc < ADC_CHARGE_THRESHOLD) {
// charge_T = true;
// discharge_T = false;
// idle_T = false;
// }
// #endif
// else {
// charge_T = false;
// discharge_T = false;
// idle_T = true;
// }
//
// buffer_full = false;
// prev_avg_adc = current_avg_adc;
// } else {
// prev_avg_adc = calculate_average(adc_measurements, measurement_index);
// }
//
//#if V4
// double current = (0.7376 * current_adc) - 239.04;
//#elif V3
// double current = (0.1127 * prev_avg_adc) - 232.46;
//#endif
//
// if (bms_sm_T == init || bms_sm_T == calculate_load) {
// current = 0;
// }
//
// pack_current = (uint32_t)(current * 10); // Scale as needed
// battery_param[3] = pack_current >> 8;
// battery_param[2] = pack_current;
//}
void ADC_calculate_current(void) {
ADC_start();
const double ADC_DISCHARGE_THRESHOLD = 2.2;
#if BAT_POOL
const double ADC_CHARGE_THRESHOLD = -0.1;
#endif
// Static variables to maintain state across function calls
static uint16_t adc_measurements[NUM_MEASUREMENTS] = {0};
static int measurement_index = 0;
static bool buffer_full = false;
static double prev_avg_adc = 0.0;
uint16_t current_adc = adc_channel0_measuremnt[ADC0_CHANNEL_BATTERY_CURRENT_SENSE];
double current_avg_adc = 0.0;
double delta_avg_adc = 0.0;
double current = 0.0;
// Store the current ADC reading in the buffer
adc_measurements[measurement_index] = current_adc;
measurement_index = (measurement_index + 1) % NUM_MEASUREMENTS;
// Check if the buffer is full
if (measurement_index == 0) {
buffer_full = true;
}
// Only proceed if we have enough measurements
if (buffer_full) {
// Calculate the average of the ADC measurements
uint32_t sum_adc = 0;
for (int i = 0; i < NUM_MEASUREMENTS; i++) {
sum_adc += adc_measurements[i];
}
current_avg_adc = (double)sum_adc / NUM_MEASUREMENTS;
// Calculate the change in average ADC value
delta_avg_adc = current_avg_adc - prev_avg_adc;
// Determine the direction of current flow based on delta_avg_adc
if (delta_avg_adc > ADC_DISCHARGE_THRESHOLD) {
// Average ADC value increased, indicating possible discharging
discharge_T = true;
charge_T = false;
idle_T = false;
}
#if BAT_POOL
else if (delta_avg_adc < ADC_CHARGE_THRESHOLD) {
// Average ADC value decreased, indicating possible charging
charge_T = true;
discharge_T = false;
idle_T = false;
}
#endif
else {
// Change is within the threshold, consider it idle
charge_T = false;
discharge_T = false;
idle_T = true;
}
// Update the current based on the averaged ADC value
if (charge_T) {
#if V4
current = (-0.7305 * current_avg_adc) + 236.53;
#elif V3
current = (-0.7305 * current_avg_adc) + 236.53;
#endif
} else if (discharge_T) {
#if V4
current = (0.7376 * current_avg_adc) - 239.04;
#elif V3
current = (0.1127 * current_avg_adc) - 232.46;
#endif
} else if (idle_T) {
current = 0;
}
// Update the pack_current and battery parameters
pack_current = (uint32_t)(current * 10); // Adjust as per your scaling
battery_param[3] = pack_current >> 8;
battery_param[2] = pack_current;
// Update prev_avg_adc for the next iteration
prev_avg_adc = current_avg_adc;
buffer_full = false;
} else {
// Buffer not full yet, initialize prev_avg_adc
uint32_t sum_adc = 0;
for (int i = 0; i < measurement_index; i++) {
sum_adc += adc_measurements[i];
}
prev_avg_adc = (double)sum_adc / measurement_index;
// Do not update pack_current or states until buffer is full
}
return;
}
uint8_t ADC_get_filtered_ntc_temperature(void) {
static int16_t temp_buffer[NUM_TEMP_SAMPLES] = { 0 };
static uint8_t buffer_index = 0;
int32_t sum = 0;
int8_t current_temp = ADC_calculate_ntc_temperature();
// Add current reading to buffer
temp_buffer[buffer_index] = current_temp;
buffer_index = (buffer_index + 1) % NUM_TEMP_SAMPLES;
// Calculate average
for (uint8_t i = 0; i < NUM_TEMP_SAMPLES; i++) {
sum += temp_buffer[i];
}
return (int8_t) (sum / NUM_TEMP_SAMPLES);
}
// Helper function to calculate the average of ADC values in the buffer
static double calculate_average(uint16_t *values, uint8_t size) {
uint32_t sum_adc = 0;
for (uint8_t i = 0; i < size; i++) {
sum_adc += values[i];
}
return (double)sum_adc / size;
}
static uint8_t ADC_calculate_ntc_temperature(void) {
ADC_start();
uint16_t adc_value =
adc_channel1_measuremnt[ADC1_CHANNEL_PCB_THERMISITOR_SENSE];
// Convert ADC value to voltage
float vcc = 3.3f; // Supply voltage
float adc_max = 4095.0f;
float voltage = (adc_value / adc_max) * vcc;
// Convert voltage to millivolts
float mV = voltage * 1000.0f;
// Calculate temperature
float temperature;
if (mV < 1500.0f) {
// For temperatures below 100°C
temperature = (mV - TMP235_OFFSET) / TMP235_TEMP_COEFF;
} else if (mV < 1752.5f) {
// For temperatures between 100°C and 125°C
temperature = (mV - 1500.0f) / 10.1f + 100.0f;
} else {
// For temperatures above 125°C
temperature = (mV - 1752.5f) / 10.6f + 125.0f;
}
// Round to nearest integer
return (int8_t) (temperature + 0.5f);
}
/* STATIC FUNCTIONS */
static void ADC_start(void) {
adc0_conversion_complete = false;
adc1_conversion_complete = false;
LPIT_DRV_StartTimerChannels(INST_LPIT1, 1);
while (!adc1_conversion_complete);
while (!adc0_conversion_complete);
LPIT_DRV_StopTimerChannels(INST_LPIT1, 1);
return;
}
void peripheral_init(void) {
//// // Initialize system clocks and update configuration to a predefined setup.
CLOCK_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT, g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT);
CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_AGREEMENT);
// Initialize power modes and set the system to run mode.
POWER_SYS_Init(&powerConfigsArr, POWER_MANAGER_CONFIG_CNT, &powerStaticCallbacksConfigsArr, POWER_MANAGER_CALLBACK_CNT);
POWER_SYS_SetMode(RUN_Mode, POWER_MANAGER_POLICY_AGREEMENT);
// Initialize and configure all system pins.
PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_pin_mux_InitConfigArr);
// Initialize SPI for AFE, SD card, and MOSFET driver modules.
LPSPI_DRV_MasterInit(LPSPICOM1, &lpspiCom1State, &lpspiCom1_MasterConfig0);
LPSPI_DRV_MasterSetDelay(LPSPICOM1, 1, 1, 1);
LPSPI_DRV_MasterInit(LPSPICOM2, &lpspiCom2State, &lpspiCom2_MasterConfig0);
LPSPI_DRV_MasterSetDelay(LPSPICOM2, 10, 10, 10);
LPSPI_DRV_MasterInit(LPSPICOM3, &lpspiCom3State, &lpspiCom3_MasterConfig0);
LPSPI_DRV_MasterSetDelay(LPSPICOM3, 1, 1, 1);
// Initialize the DMA for the UART Communication
EDMA_DRV_Init(&dmaController1_State, &dmaController1_InitConfig0, edmaChnStateArray, edmaChnConfigArray, EDMA_CONFIGURED_CHANNELS_COUNT);
// Initialize UART for IoT communication.
LPUART_DRV_Init(INST_LPUART1, &lpuart1_State, &lpuart1_InitConfig0);
UART_BAURDRATE_CONFIG();
LPUART_DRV_InstallRxCallback(INST_LPUART1, iotcard_irq, NULL);
LPUART_DRV_SetRxBuffer(INST_LPUART1, &iotcrd_rxbuff, 1U);
LPUART_DRV_ReceiveData(INST_LPUART1, &iotcrd_rxbuff, 1U);
// Initialize the Real Time Clock.
RTC_DRV_Init(RTCTIMER1, &rtcTimer1_Config0);
RTC_DRV_SetTimeDate(RTCTIMER1, &rtcTimer1_StartTime0);
RTC_DRV_StartCounter(RTCTIMER1);
// Initialize CAN communication.
FLEXCAN_DRV_Init(INST_CANCOM1, &canCom1_State, &canCom1_InitConfig0);
CAN_BIT_CONFIG();
// Initialize onboard flash memory.
FLASH_DRV_Init(&Flash1_InitConfig0, &flash_ssd_config_T);
// Initialize low power timer for delays.
LPTMR_DRV_Init(INST_LPTMR1, &lpTmr1_config0, 0U);
INT_SYS_InstallHandler(LPTMR0_IRQn, &delay_irq, (isr_t*) 0);
INT_SYS_EnableIRQ(LPTMR0_IRQn);
// Setup ignition key handler.
INT_SYS_InstallHandler(PORTE_IRQn, &ignition_key_handler, (isr_t*) 0);
// INT_SYS_EnableIRQ(PORTE_IRQn);
// Initialize ADC modules.
ADC0_init();
ADC1_init();
INT_SYS_InstallHandler(ADC0_IRQn, &ADC0_IRQHandler, (isr_t*) 0);
INT_SYS_InstallHandler(ADC1_IRQn, &ADC1_IRQHandler, (isr_t*) 0);
INT_SYS_EnableIRQ(ADC0_IRQn);
INT_SYS_EnableIRQ(ADC1_IRQn);
// Configure Programmable Delay Blocks.
PDB0_config();
PDB1_config();
// Initialize Trigger Multiplexer.
TRGMUX_DRV_Init(INST_TRGMUX1, &trgmux1_InitConfig0);
// Initialize LPIT timers for system timing tasks.
LPIT_DRV_Init(INST_LPIT1, &lpit1_InitConfig);
LPIT_DRV_InitChannel(INST_LPIT1, 0U, &lpit1_ChnConfig0);
// Initialize PWM for buzzer control and set duty cycle.
FTM_DRV_Init(INST_FLEXTIMER_PWM1, &flexTimer_pwm1_InitConfig, &state_pwm);
FTM_DRV_InitPwm(INST_FLEXTIMER_PWM1, &flexTimer_pwm1_PwmConfig);
FTM_DRV_UpdatePwmChannel(INST_FLEXTIMER_PWM1, 2U, FTM_PWM_UPDATE_IN_DUTY_CYCLE, 0x4000, 0U, true);
LL_mDelay(100);
FTM_DRV_UpdatePwmChannel(INST_FLEXTIMER_PWM1, 2U, FTM_PWM_UPDATE_IN_DUTY_CYCLE, 0x8000, 0U, true);
LL_mDelay(100);
// Initialize and configure SOC dt Timer for time-sensitive tasks.
FTM_DRV_Init(INST_FLEXTIMER_MC1, &flexTimer_mc1_InitConfig, &ftmStateStruct_soc);
INT_SYS_InstallHandler(FTM4_Ovf_Reload_IRQn, &ftmTimer_soc_ISR, (isr_t*) 0U);
INT_SYS_EnableIRQ(FTM4_Ovf_Reload_IRQn);
FTM_DRV_InitCounter(INST_FLEXTIMER_MC1, &flexTimer_mc1_TimerConfig);
INT_SYS_SetPriority(LPTMR0_IRQn, 0U);
INT_SYS_SetPriority(FTM4_Ovf_Reload_IRQn, 1U);
// Initialize I2C communication
LPI2C_DRV_MasterInit(INST_LPI2C1, &lpi2c1_MasterConfig0, &lpi2c1MasterState);
}