Init
This commit is contained in:
parent
2d5e7010d2
commit
927ae65602
|
|
@ -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);
|
||||
|
|
|
|||
84
APP/main.c
84
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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
Loading…
Reference in New Issue