Need help regarding ADC Automatic Comparision

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

Need help regarding ADC Automatic Comparision

282 次查看
KKB
Contributor I

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);
}
0 项奖励
回复
0 回复数