diff --git a/ADC_Temp_AAS-920-141A.c b/ADC_Temp_AAS-920-141A.c deleted file mode 100644 index 89a1de5..0000000 --- a/ADC_Temp_AAS-920-141A.c +++ /dev/null @@ -1,234 +0,0 @@ -// -// Created by cfif on 02.12.2025. -// -#include "stdint.h" -#include - -// Константы -#define ADC_MAX 4095.0f // 12-битный АЦП -#define R1 2795.0f // Сопротивление делителя напряжения -#define TABLE_START_TEMP (-40) -#define TABLE_END_TEMP 105 -#define TABLE_SIZE 42 - -// Константы для датчика -#define R25 2795.0f // Сопротивление при 25°C -#define B 3930.0f // Коэффициент B25/50 -#define T25 298.15f // 25°C в Кельвинах - -// Структура для хранения табличных данных -typedef struct { - int temp_c; // Температура (°C) - float r_nom; // Номинальное сопротивление (Ω) -} ntc_table_entry; - -// Таблица из документа -static const ntc_table_entry ntc_table[] = { - {-40, 101000.0f}, - {-35, 72600.0f}, - {-30, 52720.0f}, - {-25, 38660.0f}, - {-20, 28620.0f}, - {-15, 21390.0f}, - {-10, 16120.0f}, - {-5, 12260.0f}, - {-4, 11620.0f}, - {-3, 11010.0f}, - {-2, 10440.0f}, - {-1, 9907.0f}, - {0, 9399.0f}, - {1, 8924.0f}, - {2, 8473.0f}, - {3, 8048.0f}, - {4, 7646.0f}, - {5, 7267.0f}, - {6, 6909.0f}, - {7, 6570.0f}, - {8, 6250.0f}, - {9, 5947.0f}, - {10, 5661.0f}, - {15, 4441.0f}, - {20, 3512.0f}, - {25, 2795.0f}, - {30, 2239.0f}, - {35, 1806.0f}, - {40, 1464.0f}, - {45, 1195.0f}, - {50, 980.0f}, - {55, 809.0f}, - {60, 670.0f}, - {65, 559.0f}, - {70, 468.0f}, - {75, 394.0f}, - {80, 333.0f}, - {85, 283.0f}, - {90, 241.0f}, - {95, 207.0f}, - {100, 178.0f}, - {105, 153.0f} -}; - -// Функция расчёта сопротивления NTC из значения АЦП -static float calculate_resistance(uint16_t adc_value) { - if (adc_value == 0 || adc_value >= (uint16_t) ADC_MAX) { - return 0.0f; - } - // Формула делителя напряжения: R_ntc = R1 * (ADC_MAX / adc_value - 1) - // float R_ntc = R1 * (ADC_MAX / (float)adc_value - 1.0f); - - float R_ntc = R1 * (float) adc_value / (ADC_MAX - (float) adc_value); - - return R_ntc; -} - - -// Бинарный поиск в таблице -static int find_interval_index(float resistance) { - int left = 0; - int right = TABLE_SIZE - 1; - - // Проверка границ - if (resistance >= ntc_table[0].r_nom) return 0; - if (resistance <= ntc_table[right].r_nom) return right - 1; - - // Бинарный поиск - while (left <= right) { - int mid = left + (right - left) / 2; - - if (mid < TABLE_SIZE - 1 && - resistance <= ntc_table[mid].r_nom && - resistance >= ntc_table[mid + 1].r_nom) { - return mid; - } - - if (resistance > ntc_table[mid].r_nom) { - right = mid - 1; - } else { - left = mid + 1; - } - } - - return -1; // Не найден -} - -// Интерполяция с использованием уравнения Стейнхарта-Харта между точками -static float interpolate_steinhart(float resistance, int index) { - // Берем две соседние точки из таблицы - float t1 = (float) ntc_table[index].temp_c + 273.15f; // в Кельвинах - float t2 = (float) ntc_table[index + 1].temp_c + 273.15f; - float r1 = ntc_table[index].r_nom; - float r2 = ntc_table[index + 1].r_nom; - - // Вычисляем коэффициент B для интервала - float BB = logf(r1 / r2) / (1.0f / t1 - 1.0f / t2); - - // Используем уравнение Стейнхарта-Харта для вычисления температуры - float steinhart = logf(resistance / r1) / BB + 1.0f / t1; - float temp_k = 1.0f / steinhart; - - return temp_k - 273.15f; // Конвертация в °C -} - -// Линейная интерполяция в логарифмическом масштабе -static float interpolate_log_linear(float resistance, int index) { - float t1 = (float) ntc_table[index].temp_c; - float t2 = (float) ntc_table[index + 1].temp_c; - float r1 = ntc_table[index].r_nom; - float r2 = ntc_table[index + 1].r_nom; - - float log_r1 = logf(r1); - float log_r2 = logf(r2); - float log_r = logf(resistance); - - return t1 + (t2 - t1) * (log_r - log_r1) / (log_r2 - log_r1); -} - -// Основная функция для получения температуры -float get_temperature_from_adc_AAS_920(uint16_t adc_value, int use_steinhart) { - float resistance = calculate_resistance(adc_value); - - if (resistance <= 0.0f) { - return -273.15f; // Ошибка - } - - int index = find_interval_index(resistance); - - if (index < 0 || index >= TABLE_SIZE - 1) { - // Вне диапазона таблицы - if (resistance >= ntc_table[0].r_nom) return TABLE_START_TEMP; - if (resistance <= ntc_table[TABLE_SIZE - 1].r_nom) return TABLE_END_TEMP; - return -273.15f; // Ошибка - } - - if (use_steinhart) { - return interpolate_steinhart(resistance, index); - } else { - return interpolate_log_linear(resistance, index); - } -} - -// Предварительно вычисленная таблица для быстрого доступа -typedef struct { - uint16_t adc_value; // Значение АЦП - int16_t temp_c; // Температура в °C * 10 (для фиксированной точки) -} adc_temp_lookup; - -static adc_temp_lookup fast_lookup[256]; // Таблица на 256 значений - -static void init_fast_lookup_table(void) { - // Создаем таблицу для быстрого преобразования АЦП->температура - for (int i = 0; i < 256; i++) { - uint16_t adc = i * 16; // Для 12-битного АЦП (0-4095) - float temp = get_temperature_from_adc_AAS_920(adc, 0); - fast_lookup[i].adc_value = adc; - fast_lookup[i].temp_c = (int16_t) (temp * 10.0f); // Храним с точностью 0.1°C - } -} - -int16_t get_temperature_fast_AAS_920(uint16_t adc_value) { - // Простой поиск в таблице с линейной интерполяцией - uint8_t index = adc_value >> 4; // Делим на 16 - if (index >= 255) return fast_lookup[255].temp_c; - - uint16_t adc1 = fast_lookup[index].adc_value; - uint16_t adc2 = fast_lookup[index + 1].adc_value; - int16_t temp1 = fast_lookup[index].temp_c; - int16_t temp2 = fast_lookup[index + 1].temp_c; - - // Линейная интерполяция - return temp1 + ((temp2 - temp1) * (adc_value - adc1)) / (adc2 - adc1); -} - -// Функция расчёта температуры из сопротивления -static float calculate_temperature(float resistance) { - - if (resistance <= 0) return -273.15f; // Абсолютный ноль - - // Расчёт по уравнению Стейнхарта-Харта - float t_kelvin = 1.0f / (1.0f / T25 + (1.0f / B) * logf(resistance / R25)); - - return t_kelvin - 273.15f; -} - -// Прямой расчёт температуры из значения АЦП -float calculate_temperature_direct_AAS_920(uint16_t adc_value) { - float resistance = calculate_resistance(adc_value); - return calculate_temperature(resistance); -} - -// сигнал АЦП, (R резистора / R термистора), B термистора, t термистора, разрешение АЦП -//static float NTC_computeRR(float analog, float baseDiv, uint16_t BB, uint8_t t, uint8_t res) { -// if (analog <= 0 || isnan(analog)) return INFINITY; -// analog = baseDiv / ((float) ((1 << res) - 1) / analog - 1.0f); -// analog = (logf(analog) / (float)BB) + 1.0f / ((float)t + 273.15f); -// return (1.0f / analog - 273.15f); -//} - -// сигнал АЦП, R резистора, B термистора, t термистора, R термистора, разрешение АЦП -//float NTC_compute_AAS_920(float analog, uint32_t R, uint16_t BB, uint8_t t, uint32_t Rt, uint8_t res) { -// return NTC_computeRR(analog, (float) R / (float)Rt, BB, t, res); -//} - -//void zz_AAS_920() { -// NTC_compute_AAS_920(0, R25, B, 25, (uint32_t)R25, 12); -//} \ No newline at end of file diff --git a/ADC_Temp_AAS-920-141A.h b/ADC_Temp_AAS-920-141A.h deleted file mode 100644 index d2ee223..0000000 --- a/ADC_Temp_AAS-920-141A.h +++ /dev/null @@ -1,8 +0,0 @@ -// -// Created by cfif on 02.12.2025. -// - -#ifndef HVAC_M7_ADC_TEMP_AAS_920_141A_H -#define HVAC_M7_ADC_TEMP_AAS_920_141A_H - -#endif //HVAC_M7_ADC_TEMP_AAS_920_141A_H diff --git a/ADC_Temp_KST45-14-2.c b/ADC_Temp_KST45-14-2.c index c92e063..64a757a 100644 --- a/ADC_Temp_KST45-14-2.c +++ b/ADC_Temp_KST45-14-2.c @@ -2,6 +2,7 @@ // Created by cfif on 02.12.2025. // #include "stdint.h" +#include "ADC_Temp_KST45-14-2.h" #include // Константы @@ -11,10 +12,12 @@ #define TABLE_END_TEMP 85 #define TABLE_SIZE 26 -// Константы для датчика -#define R25 3000.0f // Сопротивление при 25°C -#define B 3917.0f // Коэффициент B25/50 -#define T25 298.15f // 25°C в Кельвинах +// Параметры Steinhart-Hart для термистора +#define koef_A 0.001741624168166423 +#define koef_B 0.00017003940268680147 +#define koef_C 0.0000004890545443703666 + +#define TABLE_SIZE_LOOKUP 32 // Структура для хранения табличных данных typedef struct { @@ -104,10 +107,10 @@ static float interpolate_steinhart(float resistance, int index) { float r2 = ntc_table[index + 1].r_nom; // Вычисляем коэффициент B для интервала - float BB = logf(r1 / r2) / (1.0f / t1 - 1.0f / t2); + float B = logf(r1 / r2) / (1.0f / t1 - 1.0f / t2); // Используем уравнение Стейнхарта-Харта для вычисления температуры - float steinhart = logf(resistance / r1) / BB + 1.0f / t1; + float steinhart = logf(resistance / r1) / B + 1.0f / t1; float temp_k = 1.0f / steinhart; return temp_k - 273.15f; // Конвертация в °C @@ -127,8 +130,41 @@ static float interpolate_log_linear(float resistance, int index) { return t1 + (t2 - t1) * (log_r - log_r1) / (log_r2 - log_r1); } +// Более надежная версия с проверкой параметров +static float interpolate_steinhart_full(float resistance, int index) { + // Проверка корректности входных данных + 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)ntc_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)ntc_table[index].temp_c; + } + + return (float)(temp_K - 273.15f); +} + // Основная функция для получения температуры -float get_temperature_from_adc_KST45(uint16_t adc_value, int use_steinhart) { +float get_temperature_from_adc_KST45(uint16_t adc_value, eAlg use_alg) { float resistance = calculate_resistance(adc_value); if (resistance <= 0.0f) { @@ -144,26 +180,32 @@ float get_temperature_from_adc_KST45(uint16_t adc_value, int use_steinhart) { return -273.15f; // Ошибка } - if (use_steinhart) { + if (use_alg == ALG_STEINHART) { return interpolate_steinhart(resistance, index); + } else if (use_alg == ALG_STEINHART_FULL) { + return interpolate_steinhart_full(resistance, index); } else { return interpolate_log_linear(resistance, index); } } + + + + // Предварительно вычисленная таблица для быстрого доступа typedef struct { uint16_t adc_value; // Значение АЦП int16_t temp_c; // Температура в °C * 10 (для фиксированной точки) } adc_temp_lookup; -static adc_temp_lookup fast_lookup[256]; // Таблица на 256 значений +static adc_temp_lookup fast_lookup[TABLE_SIZE_LOOKUP]; // Таблица на TABLE_SIZE_LOOKUP значений -static void init_fast_lookup_table(void) { +void init_fast_lookup_table(eAlg use_alg) { // Создаем таблицу для быстрого преобразования АЦП->температура - for (int i = 0; i < 256; i++) { - uint16_t adc = i * 16; // Для 12-битного АЦП (0-4095) - float temp = get_temperature_from_adc_KST45(adc, 0); + for (uint16_t i = 0; i < TABLE_SIZE_LOOKUP; i++) { + uint16_t adc = i * (uint8_t)roundf(4095.0f / (TABLE_SIZE_LOOKUP - 1)); // Для 12-битного АЦП (0-4095) + float temp = get_temperature_from_adc_KST45(adc, use_alg); fast_lookup[i].adc_value = adc; fast_lookup[i].temp_c = (int16_t) (temp * 10.0f); // Храним с точностью 0.1°C } @@ -171,8 +213,8 @@ static void init_fast_lookup_table(void) { int16_t get_temperature_fast_KST45(uint16_t adc_value) { // Простой поиск в таблице с линейной интерполяцией - uint8_t index = adc_value >> 4; // Делим на 16 - if (index >= 255) return fast_lookup[255].temp_c; + uint16_t index = adc_value / (uint8_t)roundf(4095.0f / (TABLE_SIZE_LOOKUP - 1)); // Делим на 16 для TABLE_SIZE_LOOKUP = 256 + if (index >= (TABLE_SIZE_LOOKUP - 1)) return fast_lookup[TABLE_SIZE_LOOKUP - 1].temp_c; uint16_t adc1 = fast_lookup[index].adc_value; uint16_t adc2 = fast_lookup[index + 1].adc_value; @@ -182,38 +224,3 @@ int16_t get_temperature_fast_KST45(uint16_t adc_value) { // Линейная интерполяция return temp1 + ((temp2 - temp1) * (adc_value - adc1)) / (adc2 - adc1); } - - -// Функция расчёта температуры из сопротивления -static float calculate_temperature(float resistance) { - - if (resistance <= 0) return -273.15f; // Абсолютный ноль - - // Расчёт по уравнению Стейнхарта-Харта - float t_kelvin = 1.0f / (1.0f / T25 + (1.0f / B) * logf(resistance / R25)); - - return t_kelvin - 273.15f; -} - -// Прямой расчёт температуры из значения АЦП -float calculate_temperature_direct_KST45(uint16_t adc_value) { - float resistance = calculate_resistance(adc_value); - return calculate_temperature(resistance); -} - -// сигнал АЦП, (R резистора / R термистора), B термистора, t термистора, разрешение АЦП -//static float NTC_computeRR(float analog, float baseDiv, uint16_t BB, uint8_t t, uint8_t res) { -// if (analog <= 0 || isnan(analog)) return INFINITY; -// analog = baseDiv / ((float) ((1 << res) - 1) / analog - 1.0f); -// analog = (logf(analog) / (float)BB) + 1.0f / ((float)t + 273.15f); -// return (1.0f / analog - 273.15f); -//} - -// сигнал АЦП, R резистора, B термистора, t термистора, R термистора, разрешение АЦП -//float NTC_compute_KST45(float analog, uint32_t R, uint16_t BB, uint8_t t, uint32_t Rt, uint8_t res) { -// return NTC_computeRR(analog, (float) R / (float)Rt, BB, t, res); -//} - -//void zz_AAS_KST45() { -// NTC_compute_KST45(0, R25, B, 25, (uint32_t)R25, 12); -//} \ No newline at end of file diff --git a/ADC_Temp_KST45-14-2.h b/ADC_Temp_KST45-14-2.h index 517abd0..c470a39 100644 --- a/ADC_Temp_KST45-14-2.h +++ b/ADC_Temp_KST45-14-2.h @@ -1,8 +1,20 @@ // -// Created by cfif on 02.12.2025. +// Created by cfif on 04.12.2025. // -#ifndef HVAC_M7_ADC_TEMP_H -#define HVAC_M7_ADC_TEMP_H +#ifndef MDF_ADC_TEMP_KST45_14_2_H +#define MDF_ADC_TEMP_KST45_14_2_H -#endif //HVAC_M7_ADC_TEMP_H +#include + +typedef enum { + ALG_STEINHART = 0, + ALG_STEINHART_FULL = 1, + ALG_LINEAR = 2 +} eAlg; + +void init_fast_lookup_table(eAlg use_alg); +float get_temperature_from_adc_KST45(uint16_t adc_value, eAlg alg); +int16_t get_temperature_fast_KST45(uint16_t adc_value); + +#endif //MDF_ADC_TEMP_KST45_14_2_H