MODEL_ADC/APP/src/aterlux.c

77 lines
2.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Created by cfif on 03.12.2025.
//
#include <math.h>
#include <stdint.h>
// Значение температуры, возвращаемое если сумма результатов АЦП больше первого значения таблицы
#define TEMPERATURE_UNDER (-400)
// Значение температуры, возвращаемое если сумма результатов АЦП меньше последнего значения таблицы
#define TEMPERATURE_OVER 800
// Значение температуры соответствующее первому значению таблицы
#define TEMPERATURE_TABLE_START (-400)
// Шаг таблицы
#define TEMPERATURE_TABLE_STEP 50
/* Таблица суммарного значения АЦП в зависимости от температуры. От большего значения к меньшему
Для построения таблицы использованы следующие параметры:
R1(T1): 3кОм(25°С)
Схема включения: A
Ra: 3кОм
Напряжения U0/Uref: 5В/5В
*/
const uint16_t termo_table[] = {
3978, 3934, 3877, 3804, 3713, 3602, 3469, 3313,
3136, 2939, 2726, 2503, 2275, 2048, 1828, 1618,
1424, 1246, 1085, 942, 816, 706, 611, 528,
458, 397
};
// Функция вычисляет значение температуры в десятых долях градусов Цельсия
// в зависимости от суммарного значения АЦП.
int16_t calc_temperature(uint16_t adcsum) {
uint8_t l = 0;
uint8_t r = (sizeof(termo_table) / sizeof(termo_table[0])) - 1;
uint16_t thigh = termo_table[r];
// Проверка выхода за пределы и граничных значений
if (adcsum <= thigh) {
#ifdef TEMPERATURE_UNDER
if (adcsum < thigh)
return TEMPERATURE_UNDER;
#endif
return TEMPERATURE_TABLE_STEP * r + TEMPERATURE_TABLE_START;
}
uint16_t tlow = termo_table[0];
if (adcsum >= tlow) {
#ifdef TEMPERATURE_OVER
if (adcsum > tlow)
return TEMPERATURE_OVER;
#endif
return TEMPERATURE_TABLE_START;
}
// Двоичный поиск по таблице
while ((r - l) > 1) {
uint8_t m = (l + r) >> 1;
uint16_t mid = termo_table[m];
if (adcsum > mid) {
r = m;
} else {
l = m;
}
}
uint16_t vl = termo_table[l];
if (adcsum >= vl) {
return l * TEMPERATURE_TABLE_STEP + TEMPERATURE_TABLE_START;
}
uint16_t vr = termo_table[r];
uint16_t vd = vl - vr;
int16_t res = TEMPERATURE_TABLE_START + r * TEMPERATURE_TABLE_STEP;
if (vd) {
// Линейная интерполяция
res -= ((TEMPERATURE_TABLE_STEP * (int32_t)(adcsum - vr) + (vd >> 1)) / vd);
}
return res;
}