diff --git a/APP/inc/ADC_Temp.h b/APP/inc/ADC_Temp.h index 5825892..02d13fa 100644 --- a/APP/inc/ADC_Temp.h +++ b/APP/inc/ADC_Temp.h @@ -37,15 +37,9 @@ typedef enum { // Алгоритмы расчёта температуры typedef enum { ALG_STEINHART = 0, - ALG_STEINHART_FULL = 1, - ALG_LINEAR = 2 + ALG_LINEAR = 1 } eAlg; -// Параметры Steinhart-Hart для термистора (общие для всех таблиц) -#define koef_A 0.001741624168166423 -#define koef_B 0.00017003940268680147 -#define koef_C 0.0000004890545443703666 - // Размеры таблиц #define TABLE_SIZE_DUCT 26 #define TABLE_SIZE_INCAR 38 @@ -63,17 +57,6 @@ typedef struct { eNtcTable table_type; // Тип таблицы, для которой вычислены данные } adc_temp_lookup; -// Структура конфигурации для NTC -typedef struct { - eNtcTable table_type; // Тип используемой таблицы - float r1; // Сопротивление делителя напряжения (Ом) - float vcc_mv; // Напряжение питания делителя (мВ) - float vref_mv; // Опорное напряжение АЦП (мВ) - int16_t start_temp; // Начальная температура таблицы (°C) - int16_t end_temp; // Конечная температура таблицы (°C) - uint16_t table_size; // Размер таблицы -} ntc_config_t; - // Структура для хранения таблиц быстрого доступа для каждой конфигурации typedef struct { adc_temp_lookup duct[TABLE_SIZE_LOOKUP]; @@ -98,8 +81,6 @@ void init_duct_table(float r1, eAlg use_alg); void init_incar_table(float r1, eAlg use_alg); void init_ambient_table(float r1, eAlg use_alg); void init_all_tables(float r1_duct, float r1_incar, float r1_ambient, eAlg use_alg); -void set_active_config(eNtcTable table_type, float r1); -const ntc_config_t* get_active_config(void); const fast_lookup_tables_t* get_fast_tables(void); // Вспомогательные функции для преобразований @@ -126,10 +107,8 @@ float get_resistance_from_adc_with_table(uint16_t adc_value, eNtcTable table_typ // Быстрые функции с использованием предварительно вычисленной таблицы int16_t get_temperature_log_fast(uint16_t adc_value); int16_t get_temperature_log_fast_for_table(uint16_t adc_value, eNtcTable table_type); -int16_t get_temperature_linear_fast(uint16_t adc_value); float get_resistance_log_fast(int16_t temperature_c10); float get_resistance_log_fast_for_table(int16_t temperature_c10, eNtcTable table_type); -float get_resistance_fast_simple(int16_t temperature_c10); // Новые функции для получения напряжений uint16_t get_voltage_from_adc(uint16_t adc_value); diff --git a/APP/main.c b/APP/main.c index 865c62c..1a9d2d4 100644 --- a/APP/main.c +++ b/APP/main.c @@ -209,80 +209,29 @@ void save_all_tables_to_files(void) { save_table_to_c_file("duct_table_array.c", tables->duct, "DUCT", "duct_lookup_table"); save_table_to_csv("duct_table.csv", tables->duct, "DUCT"); save_table_to_txt("duct_table.txt", tables->duct, "DUCT"); -// save_temperature_int_one_line("duct_table.txt", tables->duct, "DUCT"); + save_temperature_int_one_line("duct_temperatures.txt", tables->duct, "DUCT"); // Сохраняем INCAR таблицу save_table_to_c_file("incar_table_array.c", tables->incar, "INCAR", "incar_lookup_table"); save_table_to_csv("incar_table.csv", tables->incar, "INCAR"); save_table_to_txt("incar_table.txt", tables->incar, "INCAR"); + save_temperature_int_one_line("incar_temperatures.txt", tables->incar, "INCAR"); // Сохраняем AMBIENT таблицу save_table_to_c_file("ambient_table_array.c", tables->ambient, "AMBIENT", "ambient_lookup_table"); save_table_to_csv("ambient_table.csv", tables->ambient, "AMBIENT"); save_table_to_txt("ambient_table.txt", tables->ambient, "AMBIENT"); + save_temperature_int_one_line("ambient_temperatures.txt", tables->ambient, "AMBIENT"); printf("\nВсе таблицы успешно сохранены!\n"); } -// Функция для проверки корректности таблицы -void validate_table(const adc_temp_lookup* table, const char* table_name, float r1) { - printf("\n=== Проверка таблицы: %s (R1=%.0fΩ) ===\n", table_name, r1); - - int monotonic_errors = 0; - int last_temp = table[0].temp_c; - float min_resistance = 999999999.0f; - float max_resistance = 0.0f; - - for (int i = 1; i < TABLE_SIZE_LOOKUP; i++) { - // Проверка монотонности температуры (должна убывать) - if (table[i].temp_c > last_temp) { - if (monotonic_errors < 5) { - printf("Ошибка монотонности: ADC=%u, Temp=%d > предыдущего %d\n", - table[i].adc_value, table[i].temp_c, last_temp); - } - monotonic_errors++; - } - last_temp = table[i].temp_c; - - // Поиск min/max сопротивления - if (table[i].resistance_ohm < min_resistance && table[i].resistance_ohm > 0) { - min_resistance = table[i].resistance_ohm; - } - if (table[i].resistance_ohm > max_resistance) { - max_resistance = table[i].resistance_ohm; - } - } - - if (monotonic_errors > 0) { - printf("Найдено %d ошибок монотонности\n", monotonic_errors); - } else { - printf("Монотонность: OK (температура монотонно убывает)\n"); - } - - printf("Диапазон сопротивлений: %.2f Ом ... %.2f Ом\n", max_resistance, min_resistance); - - // Вывод первых и последних записей - printf("\nПервые 10 записей:\n"); - for (int i = 0; i < 10 && i < TABLE_SIZE_LOOKUP; i++) { - printf(" ADC=%4u: Temp=%6.1f°C, R=%8.2fΩ\n", - table[i].adc_value, table[i].temp_c / 10.0f, table[i].resistance_ohm); - } - - printf("\nПоследние 10 записей:\n"); - for (int i = TABLE_SIZE_LOOKUP - 10; i < TABLE_SIZE_LOOKUP; i++) { - printf(" ADC=%4u: Temp=%6.1f°C, R=%8.2fΩ\n", - table[i].adc_value, table[i].temp_c / 10.0f, table[i].resistance_ohm); - } -} - int main() { printf("=== Генерация таблиц быстрого поиска для NTC термисторов ===\n"); printf("Конфигурация:\n"); printf(" VCC делителя = %.2f V\n", VCC_DIVIDER_MV / 1000.0f); printf(" VREF АЦП = %.2f V\n", VREF_MV / 1000.0f); printf(" ADC_MAX = %.0f\n", ADC_MAX); - printf(" Максимальное ADC при VCC=%.2fV: %.1f\n", - VCC_DIVIDER_MV / 1000.0f, (VCC_DIVIDER_MV * ADC_MAX) / VREF_MV); // Инициализируем все три таблицы printf("\n=== Инициализация таблиц ===\n"); @@ -293,38 +242,15 @@ int main() { printf("Таблицы успешно инициализированы\n"); - // Проверяем таблицы - const fast_lookup_tables_t* tables = get_fast_tables(); - validate_table(tables->duct, "DUCT", g_fast_tables.duct_r1); - validate_table(tables->incar, "INCAR", g_fast_tables.incar_r1); - validate_table(tables->ambient, "AMBIENT", g_fast_tables.ambient_r1); - // Сохраняем таблицы в файлы save_all_tables_to_files(); - // Пример использования - printf("\n=== Пример использования ===\n"); - uint16_t test_adcs[] = {0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000}; - - printf("ADC\tDUCT Temp\tINCAR Temp\tAMBIENT Temp\n"); - printf("------------------------------------------------\n"); - for (int i = 0; i < sizeof(test_adcs)/sizeof(test_adcs[0]); i++) { - uint16_t adc = test_adcs[i]; - int16_t temp_duct = get_temperature_log_fast_for_table(adc, TABLE_DUCT); - int16_t temp_incar = get_temperature_log_fast_for_table(adc, TABLE_INCAR); - int16_t temp_ambient = get_temperature_log_fast_for_table(adc, TABLE_AMBIENT); - - printf("%u\t%.1f°C\t\t%.1f°C\t\t%.1f°C\n", - adc, temp_duct / 10.0f, temp_incar / 10.0f, temp_ambient / 10.0f); - } - printf("\n=== Готово ===\n"); printf("Сгенерированы файлы:\n"); - printf(" - duct_table_array.c (статический массив)\n"); - printf(" - incar_table_array.c (статический массив)\n"); - printf(" - ambient_table_array.c (статический массив)\n"); + printf(" - duct_table_array.c, incar_table_array.c, ambient_table_array.c (статический массив)\n"); printf(" - duct_table.csv, incar_table.csv, ambient_table.csv (для Excel)\n"); printf(" - duct_table.txt, incar_table.txt, ambient_table.txt (для просмотра)\n"); + printf(" - duct_temperatures.txt, incar_temperatures.txt, ambient_temperatures.txt (температуры в одну строку)\n"); return 0; } \ No newline at end of file diff --git a/APP/src/ADC_Temp.c b/APP/src/ADC_Temp.c index bf601d5..6b7b25f 100644 --- a/APP/src/ADC_Temp.c +++ b/APP/src/ADC_Temp.c @@ -139,18 +139,6 @@ fast_lookup_tables_t g_fast_tables = { .vref_mv = VREF_MV }; -// Активная конфигурация -static ntc_config_t active_config = { - .table_type = TABLE_DUCT, - .r1 = 3300.0f, - .vcc_mv = VCC_DIVIDER_MV, - .vref_mv = VREF_MV, - .start_temp = -40, - .end_temp = 85, - .table_size = TABLE_SIZE_DUCT -}; - - // Вспомогательная функция для получения таблицы по типу static const ntc_table_entry* get_table_by_type(eNtcTable table_type, uint16_t* size, int16_t* start_temp, int16_t* end_temp) { const ntc_table_entry* table = NULL; @@ -268,7 +256,6 @@ static float calculate_resistance(uint16_t adc_value, float r1) { #endif } - // Бинарный поиск в таблице static int find_interval_index(float resistance, const ntc_table_entry* table, uint16_t table_size) { int left = 0; @@ -330,39 +317,6 @@ static float interpolate_log_linear(float resistance, int index, const ntc_table return t1 + (t2 - t1) * (log_r - log_r1) / (log_r2 - log_r1); } -// Более надежная версия с проверкой параметров -static float interpolate_steinhart_full(float resistance, int index, const ntc_table_entry* table) { - // Проверка корректности входных данных - if (resistance <= 0.0f) { - return -273.15f; // Абсолютный ноль при некорректном сопротивлении - } - - // Для повышения точности можно использовать таблицу как справочную, - // но основное вычисление - по уравнению с коэффициентами - double L = logf(resistance); - - // Для термисторов NTC коэффициент C обычно очень маленький (порядка 1e-7...1e-8) - // Убедимся, что кубический член вычислен корректно - double L3 = L * L * L; - double inv_T = koef_A + koef_B * L + koef_C * L3; - - // Проверка на физическую реализуемость (температура должна быть положительной в Кельвинах) - if (inv_T <= 0.0f || inv_T > 1.0f) { // 1/T не может быть <= 0 (T < 0K) или слишком большим - // В случае ошибки возвращаем температуру из таблицы по индексу - return (float) table[index].temp_c; - } - - double temp_K = 1.0f / inv_T; - - // Дополнительная проверка диапазона (например, для NTC обычно -50...+150°C) - if (temp_K < 223.15f || temp_K > 423.15f) { // -50°C...150°C в Кельвинах - // Возвращаем значение из таблицы как запасной вариант - return (float) table[index].temp_c; - } - - return (float) (temp_K - 273.15f); -} - // Основная функция для получения температуры с указанием таблицы и R1 float get_temperature_from_adc_with_table(uint16_t adc_value, eAlg alg, eNtcTable table_type, float r1) { float resistance = calculate_resistance(adc_value, r1); @@ -386,16 +340,14 @@ float get_temperature_from_adc_with_table(uint16_t adc_value, eAlg alg, eNtcTabl if (alg == ALG_STEINHART) { return interpolate_steinhart(resistance, index, table); - } else if (alg == ALG_STEINHART_FULL) { - return interpolate_steinhart_full(resistance, index, table); } else { return interpolate_log_linear(resistance, index, table); } } -// Функция для получения температуры с активной конфигурацией +// Функция для получения температуры float get_temperature_from_adc(uint16_t adc_value, eAlg alg) { - return get_temperature_from_adc_with_table(adc_value, alg, active_config.table_type, active_config.r1); + return get_temperature_from_adc_with_table(adc_value, alg, TABLE_DUCT, 3300.0f); } // Функция для получения сопротивления из значения АЦП с указанием таблицы @@ -403,9 +355,9 @@ float get_resistance_from_adc_with_table(uint16_t adc_value, eNtcTable table_typ return calculate_resistance(adc_value, r1); } -// Функция для получения сопротивления с активной конфигурацией +// Функция для получения сопротивления float get_resistance_from_adc(uint16_t adc_value) { - return calculate_resistance(adc_value, active_config.r1); + return calculate_resistance(adc_value, 3300.0f); } // Функция для получения напряжения из АЦП @@ -512,10 +464,6 @@ void init_fast_lookup_table(eNtcTable table_type, float r1, eAlg use_alg) { max_valid_adc = temp; } - printf("DEBUG: %s - min_temp_adc=%u (low temp), max_temp_adc=%u (high temp)\n", - table_type == TABLE_DUCT ? "DUCT" : (table_type == TABLE_INCAR ? "INCAR" : "AMBIENT"), - min_valid_adc, max_valid_adc); - // Заполняем таблицу - теперь ADC растет от 0 до MAX // При ADC=0: минимальное сопротивление, максимальная температура // При ADC=MAX: максимальное сопротивление, минимальная температура @@ -575,8 +523,6 @@ void init_fast_lookup_table(eNtcTable table_type, float r1, eAlg use_alg) { } else { if (use_alg == ALG_STEINHART) { temp = interpolate_steinhart(resistance, index, table); - } else if (use_alg == ALG_STEINHART_FULL) { - temp = interpolate_steinhart_full(resistance, index, table); } else { temp = interpolate_log_linear(resistance, index, table); } @@ -608,7 +554,6 @@ void init_fast_lookup_table(eNtcTable table_type, float r1, eAlg use_alg) { } } - // Инициализация таблицы Duct void init_duct_table(float r1, eAlg use_alg) { init_fast_lookup_table(TABLE_DUCT, r1, use_alg); @@ -631,23 +576,6 @@ void init_all_tables(float r1_duct, float r1_incar, float r1_ambient, eAlg use_a init_fast_lookup_table(TABLE_AMBIENT, r1_ambient, use_alg); } -// Установка активной конфигурации -void set_active_config(eNtcTable table_type, float r1) { - active_config.table_type = table_type; - active_config.r1 = r1; - active_config.vcc_mv = VCC_DIVIDER_MV; - active_config.vref_mv = VREF_MV; - - uint16_t table_size; - get_table_by_type(table_type, &table_size, &active_config.start_temp, &active_config.end_temp); - active_config.table_size = table_size; -} - -// Получение активной конфигурации -const ntc_config_t* get_active_config(void) { - return &active_config; -} - // Получение таблиц быстрого доступа const fast_lookup_tables_t* get_fast_tables(void) { return &g_fast_tables; @@ -710,12 +638,7 @@ int16_t get_temperature_log_fast_for_table(uint16_t adc_value, eNtcTable table_t // Быстрые функции с использованием активной таблицы int16_t get_temperature_log_fast(uint16_t adc_value) { - return get_temperature_log_fast_for_table(adc_value, active_config.table_type); -} - -// Альтернативная простая версия -int16_t get_temperature_linear_fast(uint16_t adc_value) { - return get_temperature_log_fast_for_table(adc_value, active_config.table_type); + return get_temperature_log_fast_for_table(adc_value, TABLE_DUCT); } // Функция для получения сопротивления из температуры для конкретной таблицы @@ -775,10 +698,5 @@ float get_resistance_log_fast_for_table(int16_t temperature_c10, eNtcTable table // Функция для получения сопротивления из температуры (обратное преобразование) float get_resistance_log_fast(int16_t temperature_c10) { - return get_resistance_log_fast_for_table(temperature_c10, active_config.table_type); -} - -// Упрощенная версия с линейным поиском -float get_resistance_fast_simple(int16_t temperature_c10) { - return get_resistance_log_fast_for_table(temperature_c10, active_config.table_type); + return get_resistance_log_fast_for_table(temperature_c10, TABLE_DUCT); } \ No newline at end of file