Обновление

This commit is contained in:
cfif 2025-12-16 11:12:00 +03:00
parent cc32ab8bfc
commit a56859a4c2
6 changed files with 1295 additions and 1791 deletions

199
ADC_Temp.c Normal file
View File

@ -0,0 +1,199 @@
//
// Created by cfif on 02.12.2025.
//
#include "stdint.h"
#include "ADC_Temp.h"
#include <math.h>
adc_temp_lookup fast_lookup[TABLE_SIZE_LOOKUP]; // Таблица на TABLE_SIZE_LOOKUP значений
// Таблица из документа KST45-14-2
static const ntc_table_entry ntc_table[] = {
{-40, 100950.0f},
{-35, 72777.0f},
{-30, 53100.0f},
{-25, 39111.0f},
{-20, 29121.0f},
{-15, 21879.0f},
{-10, 16599.0f},
{-5, 12695.0f},
{0, 9795.0f},
{5, 7616.0f},
{10, 5970.0f},
{15, 4712.0f},
{20, 3747.0f},
{25, 3000.0f},
{30, 2417.0f},
{35, 1959.0f},
{40, 1598.0f},
{45, 1311.0f},
{50, 1081.0f},
{55, 895.9f},
{60, 746.4f},
{65, 624.9f},
{70, 525.6f},
{75, 444.4f},
{80, 377.4f},
{85, 321.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);
}
// Более надежная версия с проверкой параметров
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(uint16_t adc_value, eAlg use_alg) {
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_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);
}
}
void init_fast_lookup_table(eAlg use_alg) {
// Создаем таблицу для быстрого преобразования АЦП->температура
for (uint16_t i = 0; i < TABLE_SIZE_LOOKUP; i++) {
uint16_t adc = i * (uint8_t) roundf(ADC_MAX / (TABLE_SIZE_LOOKUP - 1)); // Для 12-битного АЦП (0-4095)
float temp = get_temperature_from_adc(adc, use_alg);
fast_lookup[i].adc_value = adc;
fast_lookup[i].temp_c = (int16_t) (temp * 10.0f); // Храним с точностью 0.1°C
}
}
int16_t get_temperature_fast(uint16_t adc_value, adc_temp_lookup *fast_temp_lookup, uint16_t size_fast_temp_lookup) {
// Простой поиск в таблице с линейной интерполяцией
uint16_t index = adc_value /
(uint8_t) roundf(ADC_MAX / ((float) size_fast_temp_lookup - 1)); // Делим на 16 для TABLE_SIZE_LOOKUP = 256
if (index >= (size_fast_temp_lookup - 1)) return fast_temp_lookup[size_fast_temp_lookup - 1].temp_c;
uint16_t adc1 = fast_temp_lookup[index].adc_value;
uint16_t adc2 = fast_temp_lookup[index + 1].adc_value;
int16_t temp1 = fast_temp_lookup[index].temp_c;
int16_t temp2 = fast_temp_lookup[index + 1].temp_c;
// Линейная интерполяция
return temp1 + ((temp2 - temp1) * (adc_value - adc1)) / (adc2 - adc1);
}

46
ADC_Temp.h Normal file
View File

@ -0,0 +1,46 @@
//
// Created by cfif on 04.12.2025.
//
#ifndef MDF_ADC_TEMP_KST45_14_2_H
#define MDF_ADC_TEMP_KST45_14_2_H
#include <stdint.h>
// Константы
#define ADC_MAX 4095.0f // 12-битный АЦП
#define R1 3000.0f // Сопротивление делителя напряжения
#define TABLE_START_TEMP (-40)
#define TABLE_END_TEMP 85
#define TABLE_SIZE 38
// Параметры Steinhart-Hart для термистора
#define koef_A 0.001741624168166423
#define koef_B 0.00017003940268680147
#define koef_C 0.0000004890545443703666
#define TABLE_SIZE_LOOKUP 512
// Структура для хранения табличных данных
typedef struct {
int temp_c; // Температура (°C)
float r_nom; // Номинальное сопротивление (Ω)
} ntc_table_entry;
typedef enum {
ALG_STEINHART = 0,
ALG_STEINHART_FULL = 1,
ALG_LINEAR = 2
} eAlg;
// Предварительно вычисленная таблица для быстрого доступа
typedef struct {
uint16_t adc_value; // Значение АЦП
int16_t temp_c; // Температура в °C * 10 (для фиксированной точки)
} adc_temp_lookup;
void init_fast_lookup_table(eAlg use_alg);
float get_temperature_from_adc(uint16_t adc_value, eAlg alg);
int16_t get_temperature_fast(uint16_t adc_value, adc_temp_lookup *fast_temp_lookup, uint16_t size_fast_temp_lookup);
#endif //MDF_ADC_TEMP_KST45_14_2_H

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +0,0 @@
//
// Created by cfif on 04.12.2025.
//
#ifndef MDF_ADC_TEMP_KST45_14_2_H
#define MDF_ADC_TEMP_KST45_14_2_H
#include <stdint.h>
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

1037
ADC_Temp_Table.c Normal file

File diff suppressed because it is too large Load Diff

13
ADC_Temp_Table.h Normal file
View File

@ -0,0 +1,13 @@
//
// Created by cfif on 16.12.2025.
//
#ifndef HVAC_M7_ADC_TEMP_TABLE_H
#define HVAC_M7_ADC_TEMP_TABLE_H
#include "ADC_Temp.h"
extern const adc_temp_lookup fast_lookup_Incar[TABLE_SIZE_LOOKUP];
extern const adc_temp_lookup fast_lookup_KST45[TABLE_SIZE_LOOKUP];
#endif //HVAC_M7_ADC_TEMP_TABLE_H