/** ****************************************************************************** * @file meas.c * @author ECS, Zed Kazharov * @version V1.0.0 * @date 15-Jan-2023 * @brief Measurement Modul * Beschreibung in Header ****************************************************************************** */ // --- INCLUDES ---------------------------------------------------------------- #include "meas.h" #include "main.h" #include "adc.h" #include "stdio.h" #include "sysdata.h" //--- GGF. EXTERNE VARIABLEN --------------------------------------------------- //--- LOKALE DEFINES - bitte hier dokumentieren -------------------------------- #define ADC_CONVERTED_DATA_BUFFER_SIZE 4 #define VREF 2500 //in mV #define CELL_VOLTAGE_DIVIDER 2 #define ADC_RESOLUTION 65536 //16 bit AD Wandler durch Oversampling #define CELL_VOLTAGE_FILTER 8 // Filterlängen in 2er-Potenzen --> Compiler optimiert #define CELL_TEMPERATURE_FILTER 8 #define BALANCER_CURRENT_FILTER 8 //--- LOKALE TYPE DEFS - bitte hier dokumentieren------------------------------- //--- DEFINATIONEN GLOBALER VARIABLEN - Bitte in Header dokumentieren ---------- //--- LOKALE VARIABLEN - bitte hier dokumentieren ------------------------------ __IO uint16_t aADCxConvertedData[ADC_CONVERTED_DATA_BUFFER_SIZE]; /* ADC group regular conversion data (array of data) */ __IO uint32_t newADCDataFlag; uint32_t currentOffset; uint32_t totalMeas; //--- LOKALE FUNKTIONS PROTOTYPEN ---------------------------------------------- uint32_t calcCellVoltageFiltered(void); uint32_t calcCellVoltageUnfiltered(void); int32_t calcCellTemperature(void); uint32_t calcBalancerCurrent(void); extern uint32_t initRefresh; //--- LOKALE FUNKTIONEN - bitte hier dokumentieren ----------------------------- //--- GLOBALE FUNKTIONEN - bitte in Header dokumentieren------------------------ void MEAS_Init() { if (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK) { printf("HAL_ADCEx_Calibration_Start: ERROR\n"); return; } printf("HAL_ADCEx_Calibration_Start: OK\n"); if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *)aADCxConvertedData, ADC_CONVERTED_DATA_BUFFER_SIZE ) != HAL_OK) { /* ADC conversion start error */ printf("Error HAL_ADC_Start_DMA\n"); return; } printf("HAL_ADC_Start_DMA: OK\n"); //---- Offset calibrierung --- //Warte bis Mittelwert gebildet while (totalMeas < 100) { MEAS_Exec(); initRefresh = 1; } currentOffset = calcBalancerCurrent(); } void MEAS_Exec() { if (newADCDataFlag) { totalMeas++; sysData.s.cellVoltage = calcCellVoltageFiltered(); sysData.s.cellVoltageUnfiltered = calcCellVoltageUnfiltered(); sysData.s.cellTemperature = calcCellTemperature(); sysData.s.balancerCurrent = calcBalancerCurrent() - currentOffset; newADCDataFlag=0; } } /** * @brief Conversion complete callback in non blocking mode * @param hadc: ADC handle * @note This example shows a simple way to report end of conversion * and get conversion result. You can add your own implementation. * @retval None */ void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) { newADCDataFlag = 1; } uint32_t calcCellVoltageFiltered() { static unsigned long avgsum = 0; //ADC Wert gefiltert uint32_t adcValue; //Wert umgerechnet in Spannung [mV] uint32_t u; //Filter avgsum -= avgsum / CELL_VOLTAGE_FILTER; avgsum += aADCxConvertedData[1];; adcValue = avgsum / CELL_VOLTAGE_FILTER; //Umrechnung in Spannung u = (adcValue * VREF * CELL_VOLTAGE_DIVIDER) / ADC_RESOLUTION; return u; } uint32_t calcCellVoltageUnfiltered() { static unsigned long avgsum = 0; //ADC Wert gefiltert uint32_t adcValue; //Wert umgerechnet in Spannung [mV] uint32_t u; adcValue = aADCxConvertedData[1];; //Umrechnung in Spannung u = (adcValue * VREF * CELL_VOLTAGE_DIVIDER) / ADC_RESOLUTION; return u; } int32_t calcCellTemperature() { static unsigned long avgsum = 0; //ADC Wert gefiltert uint32_t adcValue; //Wert umgerechnet in Spannung [mV] uint32_t u; //Wert umgerechnet in [°C ] int32_t temp; //Filter avgsum -= avgsum / CELL_TEMPERATURE_FILTER; avgsum += aADCxConvertedData[2]; adcValue = avgsum / CELL_TEMPERATURE_FILTER; //Umrechnung in Spannung u = (adcValue * VREF ) / ADC_RESOLUTION; //Umrechnung in Grade C temp = u; temp = temp - 600; temp = temp * 100; temp = temp / 100; //Von Milligrad in Grad * 10 return temp; } uint32_t calcBalancerCurrent() { static unsigned long avgsum = 0; //ADC Wert gefiltert uint32_t adcValue; //Wert umgerechnet in Spannung [mV] uint32_t u; //Wert umgerechnet in mA int32_t i; //Filter avgsum -= avgsum / BALANCER_CURRENT_FILTER; avgsum += aADCxConvertedData[0]; adcValue = avgsum / BALANCER_CURRENT_FILTER; //Umrechnung in Spannung u = (adcValue * VREF ) / ADC_RESOLUTION; //Umrechnung in Strom //u = u / 100; //Verstärkunsfaktor INA180A3 //i = u / 0.001; Shunt Widerstand //Die beiden letzten Zeilen wurden zusammengefasst in i = u * 10; return i; }