From 14c8bbddd9573f9dc5bf947f7a8740f4af53a4c8 Mon Sep 17 00:00:00 2001 From: cfif Date: Tue, 2 Dec 2025 14:58:17 +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?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ADC_Temp_AAS-920-141A.c | 237 ++++++++++++++++++++++++++++++++++++++++ ADC_Temp_AAS-920-141A.h | 8 ++ ADC_Temp_KST45-14-2.c | 221 +++++++++++++++++++++++++++++++++++++ ADC_Temp_KST45-14-2.h | 8 ++ modular.json | 13 +++ 5 files changed, 487 insertions(+) create mode 100644 ADC_Temp_AAS-920-141A.c create mode 100644 ADC_Temp_AAS-920-141A.h create mode 100644 ADC_Temp_KST45-14-2.c create mode 100644 ADC_Temp_KST45-14-2.h create mode 100644 modular.json diff --git a/ADC_Temp_AAS-920-141A.c b/ADC_Temp_AAS-920-141A.c new file mode 100644 index 0000000..ae6b09c --- /dev/null +++ b/ADC_Temp_AAS-920-141A.c @@ -0,0 +1,237 @@ +// +// Created by cfif on 02.12.2025. +// +#include "stdint.h" +#include + +// Константы +#define ADC_MAX 4095.0f // 12-битный АЦП +#define R1 20000.0f // Сопротивление делителя напряжения +#define TABLE_START_TEMP (-40) +#define TABLE_END_TEMP 105 +#define TABLE_SIZE 42 + +// Структура для хранения табличных данных +typedef struct { + int temp_c; // Температура (°C) + float r_nom; // Номинальное сопротивление (Ω) + float r_min; // Минимальное сопротивление (Ω) + float r_max; // Максимальное сопротивление (Ω) +} ntc_table_entry; + +// Таблица из документа +static const ntc_table_entry ntc_table[] = { + {-40, 101.0f, 95.63f, 106.3f}, + {-35, 72.60f, 68.95f, 76.26f}, + {-30, 52.72f, 50.20f, 55.25f}, + {-25, 38.66f, 36.91f, 40.42f}, + {-20, 28.62f, 27.39f, 29.85f}, + {-15, 21.39f, 20.51f, 22.26f}, + {-10, 16.12f, 15.50f, 16.74f}, + {-5, 12.26f, 11.81f, 12.71f}, + {-4, 11.62f, 11.20f, 12.04f}, + {-3, 11.01f, 10.62f, 11.41f}, + {-2, 10.44f, 10.08f, 10.81f}, + {-1, 9.907f, 9.563f, 10.25f}, + {0, 9.399f, 9.077f, 9.722f}, + {1, 8.924f, 8.621f, 9.227f}, + {2, 8.473f, 8.189f, 8.757f}, + {3, 8.048f, 7.781f, 8.315f}, + {4, 7.646f, 7.396f, 7.897f}, + {5, 7.267f, 7.032f, 7.502f}, + {6, 6.909f, 6.688f, 7.130f}, + {7, 6.570f, 6.363f, 6.778f}, + {8, 6.250f, 6.055f, 6.445f}, + {9, 5.947f, 5.764f, 6.131f}, + {10, 5.661f, 5.489f, 5.833f}, + {15, 4.441f, 4.315f, 4.568f}, + {20, 3.512f, 3.418f, 3.606f}, + {25, 2.795f, 2.726f, 2.865f}, + {30, 2.239f, 2.179f, 2.299f}, + {35, 1.806f, 1.754f, 1.858f}, + {40, 1.464f, 1.420f, 1.509f}, + {45, 1.195f, 1.157f, 1.233f}, + {50, 0.980f, 0.947f, 1.014f}, + {55, 0.809f, 0.780f, 0.837f}, + {60, 0.670f, 0.646f, 0.695f}, + {65, 0.559f, 0.538f, 0.581f}, + {70, 0.468f, 0.450f, 0.487f}, + {75, 0.394f, 0.378f, 0.410f}, + {80, 0.333f, 0.319f, 0.347f}, + {85, 0.283f, 0.271f, 0.296f}, + {90, 0.241f, 0.230f, 0.252f}, + {95, 0.207f, 0.197f, 0.216f}, + {100, 0.178f, 0.169f, 0.186f}, + {105, 0.153f, 0.146f, 0.161f} +}; + +// Функция расчёта сопротивления 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 B = logf(r1 / r2) / (1.0f / t1 - 1.0f / t2); + + // Используем уравнение Стейнхарта-Харта для вычисления температуры + float steinhart = logf(resistance / r1) / B + 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); +} + + +// Константы для датчика +#define R25 20000.0f // Сопротивление при 25°C +#define B 3930.0f // Коэффициент B25/50 +#define T25 298.15f // 25°C в Кельвинах + +// Функция расчёта температуры из сопротивления +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 new file mode 100644 index 0000000..d2ee223 --- /dev/null +++ b/ADC_Temp_AAS-920-141A.h @@ -0,0 +1,8 @@ +// +// 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 new file mode 100644 index 0000000..9e8327b --- /dev/null +++ b/ADC_Temp_KST45-14-2.c @@ -0,0 +1,221 @@ +// +// Created by cfif on 02.12.2025. +// +#include "stdint.h" +#include + +// Константы +#define ADC_MAX 4095.0f // 12-битный АЦП +#define R1 3000.0f // Сопротивление делителя напряжения +#define TABLE_START_TEMP (-40) +#define TABLE_END_TEMP 85 +#define TABLE_SIZE 26 + +// Структура для хранения табличных данных +typedef struct { + int temp_c; // Температура (°C) + float r_nom; // Номинальное сопротивление (Ω) + float r_min; // Минимальное сопротивление (Ω) + float r_max; // Максимальное сопротивление (Ω) +} ntc_table_entry; + +// Таблица из документа +static const ntc_table_entry ntc_table[] = { + {-40, 100950.0f, 98626.0f, 103274.0f}, + {-35, 72777.0f, 71232.0f, 74322.0f}, + {-30, 53100.0f, 52064.0f, 54136.0f}, + {-25, 39111.0f, 38413.0f, 39809.0f}, + {-20, 29121.0f, 28647.0f, 29595.0f}, + {-15, 21879.0f, 21556.0f, 22201.0f}, + {-10, 16599.0f, 16379.0f, 16819.0f}, + {-5, 12695.0f, 12544.0f, 12845.0f}, + {0, 9795.0f, 9697.0f, 9893.0f}, + {5, 7616.0f, 7526.0f, 7706.0f}, + {10, 5970.0f, 5892.0f, 6048.0f}, + {15, 4712.0f, 4645.0f, 4780.0f}, + {20, 3747.0f, 3689.0f, 3805.0f}, + {25, 3000.0f, 2950.0f, 3050.0f}, + {30, 2417.0f, 2374.0f, 2460.0f}, + {35, 1959.0f, 1923.0f, 1996.0f}, + {40, 1598.0f, 1566.0f, 1630.0f}, + {45, 1311.0f, 1283.0f, 1338.0f}, + {50, 1081.0f, 1057.0f, 1104.0f}, + {55, 895.9f, 875.5f, 916.2f}, + {60, 746.4f, 728.7f, 764.1f}, + {65, 624.9f, 609.6f, 640.2f}, + {70, 525.6f, 512.3f, 538.9f}, + {75, 444.4f, 432.8f, 456.1f}, + {80, 377.4f, 367.2f, 387.6f}, + {85, 321.7f, 312.8f, 330.7f} +}; + +// Функция расчёта сопротивления 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 B = logf(r1 / r2) / (1.0f / t1 - 1.0f / t2); + + // Используем уравнение Стейнхарта-Харта для вычисления температуры + float steinhart = logf(resistance / r1) / B + 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_KST45(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_KST45(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_KST45(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); +} + + +// Константы для датчика +#define R25 3000.0f // Сопротивление при 25°C +#define B 3930.0f // Коэффициент B25/50 +#define T25 298.15f // 25°C в Кельвинах + +// Функция расчёта температуры из сопротивления +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 new file mode 100644 index 0000000..517abd0 --- /dev/null +++ b/ADC_Temp_KST45-14-2.h @@ -0,0 +1,8 @@ +// +// Created by cfif on 02.12.2025. +// + +#ifndef HVAC_M7_ADC_TEMP_H +#define HVAC_M7_ADC_TEMP_H + +#endif //HVAC_M7_ADC_TEMP_H diff --git a/modular.json b/modular.json new file mode 100644 index 0000000..9589ff8 --- /dev/null +++ b/modular.json @@ -0,0 +1,13 @@ +{ + "dep": [ + + ], + "cmake": { + "inc_dirs": [ + "./" + ], + "srcs": [ + "./**.c" + ] + } +} \ No newline at end of file