From cb939acc4d24736a13defca57f142a47f1da6c5f Mon Sep 17 00:00:00 2001 From: cfif Date: Fri, 8 May 2026 12:50:13 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=BB=D0=B0=D1=82=D1=8B=20=D0=BD?= =?UTF-8?q?=D0=B0=20V2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AdcFilter.c | 339 ++++++++++++++++++++++++++++++++++++++++++++++++++++ AdcFilter.h | 27 +++++ AdcTasks.c | 190 +++++++++++++++++++++++++---- AdcTasks.h | 126 +++++++++++++++++-- 4 files changed, 654 insertions(+), 28 deletions(-) create mode 100644 AdcFilter.c create mode 100644 AdcFilter.h diff --git a/AdcFilter.c b/AdcFilter.c new file mode 100644 index 0000000..c9ec4c7 --- /dev/null +++ b/AdcFilter.c @@ -0,0 +1,339 @@ +// +// Created by cfif on 08.05.2026. +// +#include "AdcFilter.h" +#include "stdbool.h" +#include "stddef.h" + +bool ADC_Filter_Init(ADC_Filter* filter, uint8_t size) { + if (filter == NULL || size == 0 || size > MAX_ADC_FILTER_SIZE) { + return false; + } + + // Обнуляем буфер + for (uint8_t i = 0; i < MAX_ADC_FILTER_SIZE; i++) { + filter->buffer[i] = 0; + } + + filter->sum = 0; + filter->size = size; + filter->index = 0; + filter->count = 0; + + return true; +} + +/** + * Сброс фильтра в начальное состояние + */ +void ADC_Filter_Reset(ADC_Filter* filter) { + if (filter == NULL) return; + + for (uint8_t i = 0; i < filter->size; i++) { + filter->buffer[i] = 0; + } + + filter->sum = 0; + filter->index = 0; + filter->count = 0; +} + +/** + * Обновление фильтра новым значением АЦП + * @param filter указатель на фильтр + * @param adc_value новое значение АЦП (0-65535) + * @return отфильтрованное значение + */ +uint16_t ADC_Filter_Update(ADC_Filter* filter, uint16_t adc_value) { + if (filter == NULL) return 0; + + // Переходный период (буфер не заполнен) + if (filter->count < filter->size) { + filter->buffer[filter->index] = adc_value; + filter->sum += adc_value; + filter->count++; + filter->index = (filter->index + 1) % filter->size; + + // Целочисленное деление (округляем вниз) + return (uint16_t)(filter->sum / filter->count); + } + + // Нормальный режим работы + uint16_t old_value = filter->buffer[filter->index]; + filter->buffer[filter->index] = adc_value; + filter->sum = filter->sum - old_value + adc_value; + filter->index = (filter->index + 1) % filter->size; + + // Деление с округлением для большей точности + // (сумма + половина размера) / размер + return (uint16_t)((filter->sum + (filter->size >> 1)) / filter->size); +} + +/** + * Получение текущего значения без обновления + */ +uint16_t ADC_Filter_GetCurrent(const ADC_Filter* filter) { + if (filter == NULL || filter->count == 0) return 0; + return (uint16_t)((filter->sum + (filter->count >> 1)) / filter->count); +} + +/** + * Проверка, заполнен ли буфер полностью + */ +bool ADC_Filter_IsReady(const ADC_Filter* filter) { + return (filter != NULL && filter->count == filter->size); +} + +/** + * Получение дисперсии (отклонения от среднего) + * Полезно для обнаружения шумов + */ +uint16_t ADC_Filter_GetVariance(const ADC_Filter* filter) { + if (filter == NULL || filter->count == 0) return 0; + + uint16_t mean = ADC_Filter_GetCurrent(filter); + uint32_t variance_sum = 0; + + for (uint8_t i = 0; i < filter->count; i++) { + int32_t diff = (int32_t)filter->buffer[i] - mean; + variance_sum += (diff * diff); + } + + return (uint16_t)(variance_sum / filter->count); +} + +/* ======================================================== + * ОПТИМИЗИРОВАННАЯ ВЕРСИЯ (размер = степень двойки) + * Быстрее, так как использует сдвиги вместо деления + * ======================================================== */ +/* +typedef struct { + uint16_t buffer[16]; // максимальный размер 16 + uint32_t sum; + uint8_t shift; // сдвиг для деления (log2 размера) + uint8_t index; + uint8_t count; +} ADC_FilterFast; + +// Инициализация (размер должен быть степенью двойки: 1,2,4,8,16) +bool ADC_FastFilter_Init(ADC_FilterFast* filter, uint8_t size) { + if (filter == NULL || size == 0 || size > 16) return false; + + // Проверка, что размер является степенью двойки + if ((size & (size - 1)) != 0) return false; + + for (uint8_t i = 0; i < size; i++) { + filter->buffer[i] = 0; + } + + filter->sum = 0; + filter->shift = 0; + filter->index = 0; + filter->count = 0; + + // Вычисляем сдвиг: log2(size) + uint8_t temp = size; + while (temp > 1) { + temp >>= 1; + filter->shift++; + } + + return true; +} + +// Быстрое обновление (без деления, только сдвиги) +uint16_t ADC_FastFilter_Update(ADC_FilterFast* filter, uint16_t adc_value) { + if (filter == NULL) return 0; + + uint8_t size = 1 << filter->shift; + + if (filter->count < size) { + filter->buffer[filter->index] = adc_value; + filter->sum += adc_value; + filter->count++; + filter->index = (filter->index + 1) & (size - 1); // быстрый modulo + return (uint16_t)(filter->sum / filter->count); + } + + uint16_t old_value = filter->buffer[filter->index]; + filter->buffer[filter->index] = adc_value; + filter->sum = filter->sum - old_value + adc_value; + filter->index = (filter->index + 1) & (size - 1); + + // Быстрое деление через сдвиг + return (uint16_t)(filter->sum >> filter->shift); +} +*/ +/* ======================================================== + * МЕДИАННЫЙ ФИЛЬТР (для подавления импульсных помех) + * Полезен, когда есть выбросы АЦП + * ======================================================== */ +/* +typedef struct { + uint16_t buffer[16]; + uint16_t sorted[16]; // отсортированная копия + uint8_t size; + uint8_t index; + uint8_t count; +} ADC_MedianFilter; + +bool ADC_MedianFilter_Init(ADC_MedianFilter* filter, uint8_t size) { + if (filter == NULL || size == 0 || size > 16) return false; + + for (uint8_t i = 0; i < size; i++) { + filter->buffer[i] = 0; + filter->sorted[i] = 0; + } + + filter->size = size; + filter->index = 0; + filter->count = 0; + + return true; +} + +// Простая сортировка вставками для маленького массива +static void sort_uint16(uint16_t* arr, uint8_t n) { + for (uint8_t i = 1; i < n; i++) { + uint16_t key = arr[i]; + int8_t j = i - 1; + + while (j >= 0 && arr[j] > key) { + arr[j + 1] = arr[j]; + j--; + } + arr[j + 1] = key; + } +} + +uint16_t ADC_MedianFilter_Update(ADC_MedianFilter* filter, uint16_t adc_value) { + if (filter == NULL) return 0; + + // Сохраняем новое значение + filter->buffer[filter->index] = adc_value; + filter->index = (filter->index + 1) % filter->size; + + if (filter->count < filter->size) { + filter->count++; + } + + // Копируем в сортированный массив + for (uint8_t i = 0; i < filter->count; i++) { + filter->sorted[i] = filter->buffer[i]; + } + + // Сортируем + sort_uint16(filter->sorted, filter->count); + + // Возвращаем медиану + return filter->sorted[filter->count / 2]; +} +*/ +/* ======================================================== + * ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ + * ======================================================== */ + +#ifdef TEST_MAIN +#include + +// Пример 1: Фильтрация зашумленного сигнала АЦП +void example_basic_filter(void) { + printf("=== Базовый фильтр АЦП (окно 8) ===\n"); + + ADC_Filter filter; + ADC_Filter_Init(&filter, 8); + + // Симулируем зашумленные показания АЦП (например, датчик температуры) + uint16_t adc_values[] = { + 512, 515, 508, 1024, // выброс! + 510, 513, 509, 511, 507, 514, 508, 512 + }; + + for (int i = 0; i < 12; i++) { + uint16_t filtered = ADC_Filter_Update(&filter, adc_values[i]); + printf("ADC: %4u -> Фильтр: %4u", adc_values[i], filtered); + + if (ADC_Filter_IsReady(&filter)) { + printf(" (стабильно)"); + } + printf("\n"); + } +} + +// Пример 2: Оптимизированный фильтр со сдвигами +void example_fast_filter(void) { + printf("\n=== Быстрый фильтр (окно 16) ===\n"); + + ADC_FilterFast filter; + ADC_FastFilter_Init(&filter, 16); + + // Генерируем тестовые данные + for (int i = 0; i < 20; i++) { + uint16_t adc = 2048 + (i * 10) + (rand() % 50); // тренд + шум + uint16_t filtered = ADC_FastFilter_Update(&filter, adc); + printf("ADC: %4u -> Фильтр: %4u\n", adc, filtered); + } +} + +// Пример 3: Медианный фильтр для подавления выбросов +void example_median_filter(void) { + printf("\n=== Медианный фильтр (окно 5) ===\n"); + + ADC_MedianFilter filter; + ADC_MedianFilter_Init(&filter, 5); + + // Данные с сильными выбросами + uint16_t adc_data[] = { + 500, 502, 498, 1000, // сильный выброс + 501, 503, 497, 2000, // ещё выброс + 502, 499, 501, 503 + }; + + for (int i = 0; i < 12; i++) { + uint16_t filtered = ADC_MedianFilter_Update(&filter, adc_data[i]); + printf("ADC: %4u -> Медиана: %4u\n", adc_data[i], filtered); + } +} + +// Пример 4: Реальный сценарий - сглаживание АЦП для измерения температуры +void example_temperature_sensor(void) { + printf("\n=== Фильтрация температуры (NTC термистор) ===\n"); + + ADC_Filter temp_filter; + ADC_Filter_Init(&temp_filter, 10); + + // Симуляция 50 измерений температуры с шумом + float base_temp = 25.0; // базовая температура + + for (int i = 0; i < 50; i++) { + // Симуляция АЦП (10 бит = 0-1023) + // Предполагаем, что 512 = 25°C, 1 LSB = 0.1°C + int adc_noise = (rand() % 100) - 50; // шум ±5 LSB + uint16_t adc_raw = 512 + adc_noise; + + if (i > 20 && i < 30) { + adc_raw += 100; // резкое изменение температуры + } + + uint16_t adc_filtered = ADC_Filter_Update(&temp_filter, adc_raw); + + // Конвертируем в температуру + float temp_raw = 25.0 + (adc_raw - 512) * 0.1; + float temp_filtered = 25.0 + (adc_filtered - 512) * 0.1; + + if (i % 5 == 0 || (i > 20 && i < 30)) { + printf("Измерение %2d: сырая=%.1f°C, фильтрованная=%.1f°C\n", + i, temp_raw, temp_filtered); + } + } +} + +int main(void) { + example_basic_filter(); + example_fast_filter(); + example_median_filter(); + example_temperature_sensor(); + + return 0; +} +#endif \ No newline at end of file diff --git a/AdcFilter.h b/AdcFilter.h new file mode 100644 index 0000000..cfea4a0 --- /dev/null +++ b/AdcFilter.h @@ -0,0 +1,27 @@ +// +// Created by cfif on 08.05.2026. +// + +#ifndef HVAC_M7_ADCFILTER_H +#define HVAC_M7_ADCFILTER_H + +#include "stdint.h" +#include "stdbool.h" + +// Максимальный размер фильтра (измените под свои нужды) +// Рекомендации: 4, 8, 16, 32 (степень двойки для оптимизации) +#define MAX_ADC_FILTER_SIZE 16 + +// Структура фильтра АЦП +typedef struct { + uint16_t buffer[MAX_ADC_FILTER_SIZE]; // кольцевой буфер + uint32_t sum; // сумма элементов (32 бита достаточно) + uint8_t size; // размер окна (<= MAX_ADC_FILTER_SIZE) + uint8_t index; // текущий индекс + uint8_t count; // количество накопленных данных +} ADC_Filter; + +bool ADC_Filter_Init(ADC_Filter* filter, uint8_t size); +uint16_t ADC_Filter_Update(ADC_Filter* filter, uint16_t adc_value); + +#endif //HVAC_M7_ADCFILTER_H diff --git a/AdcTasks.c b/AdcTasks.c index 3650180..0ccf30a 100644 --- a/AdcTasks.c +++ b/AdcTasks.c @@ -12,7 +12,7 @@ #define LOG_SIGN "ADC" #define LOGGER env->logger -void Adc_0_Init(tAdcTask *env, +void Adc_0_Init(tAdc0Task *env, osMutexId_t modelTaskAccess, tAdcIO *adcIO, tGpios *gpios, @@ -27,11 +27,52 @@ void Adc_0_Init(tAdcTask *env, env->queueRandom = osMessageQueueNew(10, 4, NULL); + + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_Ambient_Temp, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.IGN_ANS, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_AC_Pressure, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_Incar_Temp_FL, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_Incar_Temp_RL, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_Rear_Evap_Temp, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_Rear_Duct1, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_Rear_Duct2, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_Front_Duct1, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_Front_Duct2, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_Front_Duct3, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_Front_Duct4, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_Rear_Duct3, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_Rear_Duct4, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_Incar_Temp_FR, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_Incar_Temp_RR, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_Rear_Duct5, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_Rear_Duct6, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Reserve_Sensor_Duct_Temp_1, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_Front_Duct5, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_Front_Duct6, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Pressure_DIAG, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Reserve_Sensor_Duct_Temp_2, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_PT_rHVAC_P, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.Sensor_A_T_reserve, MAX_ADC_FILTER_SIZE); + + + ADC_Filter_Init(&env->ADC0_Filter_data.BTS5120_2EKA_ShutoffValvePowerTXV1, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.BTS5180_2EKA_ShutOFFValveFront, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.BTS5180_2EKA_TwoWayValve, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.BTS5180_2EKA_FrontIncarMotor, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.BTS5180_2EKA_ChannelPTCPower1, MAX_ADC_FILTER_SIZE); + + ADC_Filter_Init(&env->ADC0_Filter_data.BTS5120_2EKA_ShutoffValvePowerTXV2, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.BTS5180_2EKA_ShutOFFValveRear, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.BTS5180_2EKA_ReservePowerSupply, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.BTS5180_2EKA_RearIncarMotor, MAX_ADC_FILTER_SIZE); + ADC_Filter_Init(&env->ADC0_Filter_data.BTS5180_2EKA_ChannelPTCPower2, MAX_ADC_FILTER_SIZE); + + InitThreadAtrStatic(&env->thread.attr, "Adc0", env->thread.controlBlock, env->thread.stack, osPriorityNormal); } -void BTS5180_120(tAdcTask *env, char *desc, uint16_t adc_value) { +void BTS5180_120(tAdc0Task *env, char *desc, uint16_t adc_value) { float kILIS = 550.0f; float ERROR_THRESHOLD_HIGH_V = 4.9f; @@ -39,7 +80,7 @@ void BTS5180_120(tAdcTask *env, char *desc, uint16_t adc_value) { uint16_t ERROR_THRESHOLD_HIGH_CODE = (uint16_t) (ERROR_THRESHOLD_HIGH_V * 4095.0f / 5.0f); // uint16_t ERROR_THRESHOLD_LOW_CODE = (uint16_t) (ERROR_THRESHOLD_LOW_V * 4095.0f / 5.0f); - if (adc_value >= ERROR_THRESHOLD_HIGH_CODE /*|| adc_value <= ERROR_THRESHOLD_LOW_CODE*/) { + if (adc_value >= ERROR_THRESHOLD_HIGH_CODE) { LoggerFormatInfo(LOGGER, LOG_SIGN, "%s: Error !!! (adc = %d)", desc, adc_value) } else { // Преобразование в напряжение @@ -53,7 +94,7 @@ void BTS5180_120(tAdcTask *env, char *desc, uint16_t adc_value) { } -void VN7008AJ(tAdcTask *env, char *desc, uint16_t adc_value) { +void VN7008AJ(tAdc0Task *env, char *desc, uint16_t adc_value) { float RSENSE = 2490.0f; // Сопротивление датчика, Ом (На схеме) float K_TYPICAL = 5890.0f; // Типичный коэффициент из даташита на микросхему @@ -64,7 +105,7 @@ void VN7008AJ(tAdcTask *env, char *desc, uint16_t adc_value) { // uint16_t ERROR_THRESHOLD_LOW_CODE = (uint16_t) (ERROR_THRESHOLD_LOW_V * 4095.0f / 5.0f); // 1. Проверка на ошибку - if (adc_value >= ERROR_THRESHOLD_HIGH_CODE/* || adc_value <= ERROR_THRESHOLD_LOW_CODE*/) { + if (adc_value >= ERROR_THRESHOLD_HIGH_CODE) { LoggerFormatInfo(LOGGER, LOG_SIGN, "%s: Error !!! (adc = %d)", desc, adc_value) } else { @@ -82,7 +123,7 @@ void VN7008AJ(tAdcTask *env, char *desc, uint16_t adc_value) { } -void ANALOG_SENSOR(tAdcTask *env, char *desc, uint16_t adc_value, eNtcTable NtcTable, float R) { +void ANALOG_SENSOR(tAdc0Task *env, char *desc, uint16_t adc_value, eNtcTable NtcTable, float R) { float ERROR_THRESHOLD_HIGH_V = 4.9f; float ERROR_THRESHOLD_LOW_V = 0.1f; uint16_t ERROR_THRESHOLD_HIGH_CODE = (uint16_t) (ERROR_THRESHOLD_HIGH_V * 4095.0f / 5.0f); @@ -125,7 +166,30 @@ void ANALOG_SENSOR(tAdcTask *env, char *desc, uint16_t adc_value, eNtcTable NtcT } -static _Noreturn void Adc0_Thread(tAdcTask *env) { +float calculate_ntc_resistance_case_a(uint16_t adc_value, + float R_series, + float V_ref, + uint16_t adc_max) { + // Защита от деления на ноль и выхода за пределы + if (adc_value == 0) { + return 0.0f; // Rntc = 0 (короткое замыкание на GND) + } + if (adc_value >= adc_max) { + return 0.0f; // Rntc стремится к бесконечности (обрыв) + } + + // Напряжение на NTC, измеренное АЦП + float V_ntc = (float) adc_value / adc_max * V_ref; + + // Формула: V_ntc / V_ref = Rntc / (Rntc + R_series) + // Rntc = R_series * V_ntc / (V_ref - V_ntc) + float Rntc = R_series * V_ntc / (V_ref - V_ntc); + + return Rntc; +} + + +static _Noreturn void Adc0_Thread(tAdc0Task *env) { uint32_t ADC_Pointer_Data; @@ -155,6 +219,57 @@ static _Noreturn void Adc0_Thread(tAdcTask *env) { if (osMutexAcquire(env->modelTaskAccess, 5000) == osOK) { + tADC0_data *ADC0_data = (tADC0_data *) ADC_Pointer_Data; + + rtDW.ADC_Data_Model.Sensor_Ambient_Temp = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_Ambient_Temp, + ADC0_data->Sensor_Ambient_Temp); + rtDW.ADC_Data_Model.IGN_ANS = ADC_Filter_Update(&env->ADC0_Filter_data.IGN_ANS, ADC0_data->IGN_ANS); + rtDW.ADC_Data_Model.Sensor_AC_Pressure = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_AC_Pressure, + ADC0_data->Sensor_AC_Pressure); + rtDW.ADC_Data_Model.Sensor_Incar_Temp_FL = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_Incar_Temp_FL, + ADC0_data->Sensor_Incar_Temp_FL); + rtDW.ADC_Data_Model.Sensor_Incar_Temp_RL = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_Incar_Temp_RL, + ADC0_data->Sensor_Incar_Temp_RL); + rtDW.ADC_Data_Model.Sensor_Rear_Evap_Temp = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_Rear_Evap_Temp, + ADC0_data->Sensor_Rear_Evap_Temp); + rtDW.ADC_Data_Model.Sensor_Rear_Duct1 = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_Rear_Duct1, + ADC0_data->Sensor_Rear_Duct1); + rtDW.ADC_Data_Model.Sensor_Rear_Duct2 = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_Rear_Duct2, + ADC0_data->Sensor_Rear_Duct2); + rtDW.ADC_Data_Model.Sensor_Front_Duct1 = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_Front_Duct1, + ADC0_data->Sensor_Front_Duct1); + rtDW.ADC_Data_Model.Sensor_Front_Duct2 = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_Front_Duct2, + ADC0_data->Sensor_Front_Duct2); + rtDW.ADC_Data_Model.Sensor_Front_Duct3 = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_Front_Duct3, + ADC0_data->Sensor_Front_Duct3); + rtDW.ADC_Data_Model.Sensor_Front_Duct4 = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_Front_Duct4, + ADC0_data->Sensor_Front_Duct4); + rtDW.ADC_Data_Model.Sensor_Rear_Duct3 = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_Rear_Duct3, + ADC0_data->Sensor_Rear_Duct3); + rtDW.ADC_Data_Model.Sensor_Rear_Duct4 = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_Rear_Duct4, + ADC0_data->Sensor_Rear_Duct4); + rtDW.ADC_Data_Model.Sensor_Incar_Temp_FR = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_Incar_Temp_FR, + ADC0_data->Sensor_Incar_Temp_FR); + rtDW.ADC_Data_Model.Sensor_Incar_Temp_RR = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_Incar_Temp_RR, + ADC0_data->Sensor_Incar_Temp_RR); + rtDW.ADC_Data_Model.Sensor_Rear_Duct5 = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_Rear_Duct5, + ADC0_data->Sensor_Rear_Duct5); + rtDW.ADC_Data_Model.Sensor_Rear_Duct6 = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_Rear_Duct6, + ADC0_data->Sensor_Rear_Duct6); + rtDW.ADC_Data_Model.Reserve_Sensor_Duct_Temp_1 = ADC_Filter_Update( + &env->ADC0_Filter_data.Reserve_Sensor_Duct_Temp_1, ADC0_data->Reserve_Sensor_Duct_Temp_1); + rtDW.ADC_Data_Model.Sensor_Front_Duct5 = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_Front_Duct5, + ADC0_data->Sensor_Front_Duct5); + rtDW.ADC_Data_Model.Sensor_Front_Duct6 = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_Front_Duct6, + ADC0_data->Sensor_Front_Duct6); + rtDW.ADC_Data_Model.Pressure_DIAG = ADC_Filter_Update(&env->ADC0_Filter_data.Pressure_DIAG, + ADC0_data->Pressure_DIAG); + rtDW.ADC_Data_Model.Reserve_Sensor_Duct_Temp_2 = ADC_Filter_Update( + &env->ADC0_Filter_data.Reserve_Sensor_Duct_Temp_2, ADC0_data->Reserve_Sensor_Duct_Temp_2); +// rtDW.ADC_Data_Model.Sensor_PT_rHVAC_P = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_PT_rHVAC_P, ADC0_data->Sensor_PT_rHVAC_P); +// rtDW.ADC_Data_Model.Sensor_A_T_reserve = ADC_Filter_Update(&env->ADC0_Filter_data.Sensor_A_T_reserve, ADC0_data->Sensor_A_T_reserve); + +/* rtDW.ADC_Data_Model.Sensor_Ambient_Temp = pData[0]; rtDW.ADC_Data_Model.IGN_ANS = pData[1]; rtDW.ADC_Data_Model.Sensor_AC_Pressure = pData[2]; @@ -180,10 +295,10 @@ static _Noreturn void Adc0_Thread(tAdcTask *env) { rtDW.ADC_Data_Model.Pressure_DIAG = pData[23]; rtDW.ADC_Data_Model.Reserve_Sensor_Duct_Temp_2 = pData[28]; -/* - rtDW.ADC_Data_Model.Sensor_PT_rHVAC_P = pData[29]; - rtDW.ADC_Data_Model.Sensor_A_T_reserve = pData[30]; */ +// rtDW.ADC_Data_Model.Sensor_PT_rHVAC_P = pData[29]; +// rtDW.ADC_Data_Model.Sensor_A_T_reserve = pData[30]; + if (env->ADC0_BTS5120_2EKA_Channel == 0) { env->ADC0_BTS5120_2EKA_Channel = 1; @@ -193,12 +308,25 @@ static _Noreturn void Adc0_Thread(tAdcTask *env) { GpioPinSet(&env->gpios->power.BTS5180_2EKA_FrontRearIncarMotor.Incar_SEL_Diag, true); GpioPinSet(&env->gpios->power.BTS5180_2EKA_2xChannelPTCPower.PtcRelayDriver_SEL_Diag, true); - + rtDW.ADC_Data_Model.BTS5120_2EKA_ShutoffValvePowerTXV1 = ADC_Filter_Update( + &env->ADC0_Filter_data.BTS5120_2EKA_ShutoffValvePowerTXV1, + ADC0_data->BTS5120_2EKA_ShutoffValvePowerTXV1); + rtDW.ADC_Data_Model.BTS5180_2EKA_ShutOFFValveFront = ADC_Filter_Update( + &env->ADC0_Filter_data.BTS5180_2EKA_ShutOFFValveFront, + ADC0_data->BTS5180_2EKA_ShutOFFValveFront); + rtDW.ADC_Data_Model.BTS5180_2EKA_TwoWayValve = ADC_Filter_Update( + &env->ADC0_Filter_data.BTS5180_2EKA_TwoWayValve, ADC0_data->BTS5180_2EKA_TwoWayValve); + rtDW.ADC_Data_Model.BTS5180_2EKA_FrontIncarMotor = ADC_Filter_Update( + &env->ADC0_Filter_data.BTS5180_2EKA_FrontIncarMotor, ADC0_data->BTS5180_2EKA_FrontIncarMotor); + rtDW.ADC_Data_Model.BTS5180_2EKA_ChannelPTCPower1 = ADC_Filter_Update( + &env->ADC0_Filter_data.BTS5180_2EKA_ChannelPTCPower1, ADC0_data->BTS5180_2EKA_ChannelPTCPower1); +/* rtDW.ADC_Data_Model.BTS5120_2EKA_ShutoffValvePowerTXV1 = pData[22]; // rtDW.ADC_Data_Model.BTS5180_2EKA_ShutOFFValveFront = pData[24]; // rtDW.ADC_Data_Model.BTS5180_2EKA_TwoWayValve = pData[25]; // rtDW.ADC_Data_Model.BTS5180_2EKA_FrontIncarMotor = pData[26]; // rtDW.ADC_Data_Model.BTS5180_2EKA_ChannelPTCPower1 = pData[27]; // +*/ } else { env->ADC0_BTS5120_2EKA_Channel = 0; @@ -209,17 +337,31 @@ static _Noreturn void Adc0_Thread(tAdcTask *env) { GpioPinSet(&env->gpios->power.BTS5180_2EKA_FrontRearIncarMotor.Incar_SEL_Diag, false); GpioPinSet(&env->gpios->power.BTS5180_2EKA_2xChannelPTCPower.PtcRelayDriver_SEL_Diag, false); + rtDW.ADC_Data_Model.BTS5120_2EKA_ShutoffValvePowerTXV2 = ADC_Filter_Update( + &env->ADC0_Filter_data.BTS5120_2EKA_ShutoffValvePowerTXV2, + ADC0_data->BTS5120_2EKA_ShutoffValvePowerTXV2); + rtDW.ADC_Data_Model.BTS5180_2EKA_ShutOFFValveRear = ADC_Filter_Update( + &env->ADC0_Filter_data.BTS5180_2EKA_ShutOFFValveRear, ADC0_data->BTS5180_2EKA_ShutOFFValveRear); + rtDW.ADC_Data_Model.BTS5180_2EKA_ReservePowerSupply = ADC_Filter_Update( + &env->ADC0_Filter_data.BTS5180_2EKA_ReservePowerSupply, + ADC0_data->BTS5180_2EKA_ReservePowerSupply); + rtDW.ADC_Data_Model.BTS5180_2EKA_RearIncarMotor = ADC_Filter_Update( + &env->ADC0_Filter_data.BTS5180_2EKA_RearIncarMotor, ADC0_data->BTS5180_2EKA_RearIncarMotor); + rtDW.ADC_Data_Model.BTS5180_2EKA_ChannelPTCPower2 = ADC_Filter_Update( + &env->ADC0_Filter_data.BTS5180_2EKA_ChannelPTCPower2, ADC0_data->BTS5180_2EKA_ChannelPTCPower2); + +/* rtDW.ADC_Data_Model.BTS5120_2EKA_ShutoffValvePowerTXV2 = pData[22]; // rtDW.ADC_Data_Model.BTS5180_2EKA_ShutOFFValveRear = pData[24]; // rtDW.ADC_Data_Model.BTS5180_2EKA_ReservePowerSupply = pData[25]; // rtDW.ADC_Data_Model.BTS5180_2EKA_RearIncarMotor = pData[26]; // rtDW.ADC_Data_Model.BTS5180_2EKA_ChannelPTCPower2 = pData[27]; // - +*/ } //////////////////////////////////////----DEBUG----//////////////////////////////////////////////////////////////////// - +/* BTS5180_120(env, "BTS5120_2EKA_ShutoffValvePowerTXV1", rtDW.ADC_Data_Model.BTS5120_2EKA_ShutoffValvePowerTXV1); BTS5180_120(env, "BTS5120_2EKA_ShutoffValvePowerTXV2", @@ -259,10 +401,17 @@ static _Noreturn void Adc0_Thread(tAdcTask *env) { ANALOG_SENSOR(env, "Sensor_Rear_Duct6", rtDW.ADC_Data_Model.Sensor_Rear_Duct6, TABLE_DUCT, 3000); ANALOG_SENSOR(env, "Reserve_Sensor_Duct_Temp_1", rtDW.ADC_Data_Model.Reserve_Sensor_Duct_Temp_1, TABLE_DUCT, 20000); +*/ + ANALOG_SENSOR(env, "Sensor_Front_Duct5", rtDW.ADC_Data_Model.Sensor_Front_Duct5, TABLE_DUCT, 3000); + +// ANALOG_SENSOR(env, "Sensor_Front_Duct6", rtDW.ADC_Data_Model.Sensor_Front_Duct6, TABLE_DUCT, 3000); + +// float Rntc = calculate_ntc_resistance_case_a(rtDW.ADC_Data_Model.Sensor_Front_Duct6,3000,5,4095); +// LoggerFormatInfo(LOGGER, LOG_SIGN, "Rntc = %f", Rntc) + + -// ANALOG_SENSOR(env, "Sensor_Front_Duct5", rtDW.ADC_Data_Model.Sensor_Front_Duct5, TABLE_DUCT, 3000); - ANALOG_SENSOR(env, "Sensor_Front_Duct6", rtDW.ADC_Data_Model.Sensor_Front_Duct6, TABLE_DUCT, 3000); /* ANALOG_SENSOR(env, "Pressure_DIAG", rtDW.ADC_Data_Model.Pressure_DIAG, TABLE_NONE, 0); @@ -298,7 +447,7 @@ static _Noreturn void Adc0_Thread(tAdcTask *env) { } -uint32_t getRandom32(tAdcTask *env) { +uint32_t getRandom32(tAdc0Task *env) { uint32_t random = 0; @@ -311,14 +460,14 @@ uint32_t getRandom32(tAdcTask *env) { return 0; } -void Adc_0_StartThread(tAdcTask *env) { +void Adc_0_StartThread(tAdc0Task *env) { if (!env->thread.id) { env->thread.id = osThreadNew((osThreadFunc_t) (Adc0_Thread), (void *) (env), &env->thread.attr); } } -void Adc_1_Init(tAdcTask *env, +void Adc_1_Init(tAdc1Task *env, osMutexId_t modelTaskAccess, tAdcIO *adcIO, tGpios *gpios, @@ -335,12 +484,11 @@ void Adc_1_Init(tAdcTask *env, } -static _Noreturn void Adc1_Thread(tAdcTask *env) { +static _Noreturn void Adc1_Thread(tAdc1Task *env) { uint32_t ADC_Pointer_Data; for (;;) { - env->ADC_ChannelCount = env->adcIO->get(env->adcIO->env, &ADC_Pointer_Data, 5000); if (osMutexAcquire(env->modelTaskAccess, 5000) == osOK) { @@ -404,7 +552,7 @@ static _Noreturn void Adc1_Thread(tAdcTask *env) { } } -void Adc_1_StartThread(tAdcTask *env) { +void Adc_1_StartThread(tAdc1Task *env) { if (!env->thread.id) { env->thread.id = osThreadNew((osThreadFunc_t) (Adc1_Thread), (void *) (env), &env->thread.attr); } diff --git a/AdcTasks.h b/AdcTasks.h index d8185a9..96da7f0 100644 --- a/AdcTasks.h +++ b/AdcTasks.h @@ -10,6 +10,7 @@ #include #include "Gpios.h" #include "LoggerInterface.h" +#include "AdcFilter.h" typedef struct { uint16_t Sensor_Ambient_Temp; @@ -53,6 +54,10 @@ typedef struct { uint16_t BTS5180_2EKA_ChannelPTCPower2; // uint16_t Reserve_Sensor_Duct_Temp_2; + + uint16_t Sensor_PT_rHVAC_P; + uint16_t Sensor_A_T_reserve; + } tADC0_data; typedef struct { @@ -61,8 +66,90 @@ typedef struct { uint16_t PBATT_CHECK; uint16_t VN7008AJ_FrontLINActuatorPowerDriverAB; uint16_t VN7008AJ_RearLINActuatorPowerDriverC; + + uint16_t PT_F_HVAC_VCC_DIAG; + uint16_t PT_HVBchiller_VCC_DIAG; + uint16_t PT_R_HVAC_VCC_DIAG; + uint16_t Sensor_PT_fHVAC_P; + uint16_t Sensor_PT_fHVAC_T; + uint16_t Sensor_PT_rHVAC_T; + uint16_t Sensor_HVBchiller_P; + uint16_t Sensor_HVBchiller_T; + uint16_t Sensor_PT_P_reserve; + uint16_t Sensor_PT_T_reserve; + uint16_t Sensor_B_T_reserve; + } tADC1_data; +typedef struct { + ADC_Filter Sensor_Ambient_Temp; + ADC_Filter IGN_ANS; + ADC_Filter Sensor_AC_Pressure; + ADC_Filter Sensor_Incar_Temp_FL; + ADC_Filter Sensor_Incar_Temp_RL; + ADC_Filter Sensor_Rear_Evap_Temp; + ADC_Filter Sensor_Evap_Temp; + ADC_Filter Sensor_Rear_Duct1; + ADC_Filter Sensor_Rear_Duct2; + ADC_Filter Sensor_Front_Duct1; + ADC_Filter Sensor_Front_Duct2; + ADC_Filter Sensor_Front_Duct3; + ADC_Filter Sensor_Front_Duct4; + ADC_Filter Sensor_Rear_Duct3; + ADC_Filter Sensor_Rear_Duct4; + ADC_Filter Sensor_Incar_Temp_FR; + ADC_Filter Sensor_Incar_Temp_RR; + ADC_Filter Sensor_Rear_Duct5; + ADC_Filter Sensor_Rear_Duct6; + ADC_Filter Reserve_Sensor_Duct_Temp_1; + ADC_Filter Sensor_Front_Duct5; + ADC_Filter Sensor_Front_Duct6; + + ADC_Filter BTS5120_2EKA_ShutoffValvePowerTXV1; // + ADC_Filter BTS5120_2EKA_ShutoffValvePowerTXV2; // + + ADC_Filter Pressure_DIAG; + + ADC_Filter BTS5180_2EKA_ShutOFFValveFront; // + ADC_Filter BTS5180_2EKA_ShutOFFValveRear; // + + ADC_Filter BTS5180_2EKA_TwoWayValve; // + ADC_Filter BTS5180_2EKA_ReservePowerSupply; // + + ADC_Filter BTS5180_2EKA_FrontIncarMotor; // + ADC_Filter BTS5180_2EKA_RearIncarMotor; // + + ADC_Filter BTS5180_2EKA_ChannelPTCPower1; // + ADC_Filter BTS5180_2EKA_ChannelPTCPower2; // + + ADC_Filter Reserve_Sensor_Duct_Temp_2; + + ADC_Filter Sensor_PT_rHVAC_P; + ADC_Filter Sensor_A_T_reserve; + +} tADC0_Filter_data; + +typedef struct { + ADC_Filter VN7008AJ_DIAG_FrontLINActuatorPowerDriverAB; + ADC_Filter VN7008AJ_DIAG_RearLINActuatorPowerDriverC; + ADC_Filter PBATT_CHECK; + ADC_Filter VN7008AJ_FrontLINActuatorPowerDriverAB; + ADC_Filter VN7008AJ_RearLINActuatorPowerDriverC; + + ADC_Filter PT_F_HVAC_VCC_DIAG; + ADC_Filter PT_HVBchiller_VCC_DIAG; + ADC_Filter PT_R_HVAC_VCC_DIAG; + ADC_Filter Sensor_PT_fHVAC_P; + ADC_Filter Sensor_PT_fHVAC_T; + ADC_Filter Sensor_PT_rHVAC_T; + ADC_Filter Sensor_HVBchiller_P; + ADC_Filter Sensor_HVBchiller_T; + ADC_Filter Sensor_PT_P_reserve; + ADC_Filter Sensor_PT_T_reserve; + ADC_Filter Sensor_B_T_reserve; + +} tADC1_Filter_data; + typedef struct { @@ -70,7 +157,7 @@ typedef struct { osMutexId_t access; tADC0_data ADC0_Data; - tADC1_data ADC1_Data; + tADC0_Filter_data ADC0_Filter_data; osMutexId_t modelTaskAccess; @@ -91,24 +178,49 @@ typedef struct { osThreadAttr_t attr; } thread; -} tAdcTask; +} tAdc0Task; -uint32_t getRandom32(tAdcTask *env); +typedef struct { -void Adc_0_Init(tAdcTask *env, + tAdcIO *adcIO; + osMutexId_t access; + + tADC1_data ADC1_Data; + tADC1_Filter_data ADC1_Filter_data; + + osMutexId_t modelTaskAccess; + + uint8_t ADC_ChannelCount; + + tGpios *gpios; + + tLoggerInterface *logger; + + struct { + osThreadId_t id; + uint32_t stack[384]; + StaticTask_t controlBlock; + osThreadAttr_t attr; + } thread; + +} tAdc1Task; + +uint32_t getRandom32(tAdc0Task *env); + +void Adc_0_Init(tAdc0Task *env, osMutexId_t modelTaskAccess, tAdcIO *adcIO, tGpios *gpios, tLoggerInterface *logger); -void Adc_0_StartThread(tAdcTask *env); +void Adc_0_StartThread(tAdc0Task *env); -void Adc_1_Init(tAdcTask *env, +void Adc_1_Init(tAdc1Task *env, osMutexId_t modelTaskAccess, tAdcIO *adcIO, tGpios *gpios, tLoggerInterface *logger); -void Adc_1_StartThread(tAdcTask *env); +void Adc_1_StartThread(tAdc1Task *env); #endif //HVAC_M7_ADCTASKS_H