This commit is contained in:
cfif 2026-05-13 15:50:47 +03:00
parent 927ae65602
commit 8ac9d543b3
3 changed files with 43 additions and 74 deletions

View File

@ -44,7 +44,10 @@ typedef enum {
#define TABLE_SIZE_DUCT 26 #define TABLE_SIZE_DUCT 26
#define TABLE_SIZE_INCAR 38 #define TABLE_SIZE_INCAR 38
#define TABLE_SIZE_AMBIENT 39 #define TABLE_SIZE_AMBIENT 39
#define TABLE_SIZE_LOOKUP 4096
#define TABLE_SIZE_LOOKUP 1024 // Размер таблицы для быстрого доступа
#define ADC_STEP (ADC_MAX / TABLE_SIZE_LOOKUP) // Шаг между значениями АЦП (4095/1024 ≈ 4)
// Предварительно вычисленная таблица для быстрого доступа для каждой таблицы // Предварительно вычисленная таблица для быстрого доступа для каждой таблицы
typedef struct { typedef struct {

View File

@ -31,7 +31,7 @@ void save_temperature_int_one_line(const char* filename, const adc_temp_lookup*
printf("Температуры (int one-line) для '%s' сохранены в файл: %s\n", table_name, filename); printf("Температуры (int one-line) для '%s' сохранены в файл: %s\n", table_name, filename);
} }
// Функция для сохранения таблицы в C файл в виде статического массива // Функция для сохранения таблицы в C файл с информацией о равномерном распределении
void save_table_to_c_file(const char* filename, const adc_temp_lookup* table, void save_table_to_c_file(const char* filename, const adc_temp_lookup* table,
const char* table_name, const char* array_name) { const char* table_name, const char* array_name) {
FILE* file = fopen(filename, "w"); FILE* file = fopen(filename, "w");
@ -49,9 +49,15 @@ void save_table_to_c_file(const char* filename, const adc_temp_lookup* table,
(table_name[0] == 'D' && table_name[1] == 'U') ? g_fast_tables.duct_r1 : (table_name[0] == 'D' && table_name[1] == 'U') ? g_fast_tables.duct_r1 :
(table_name[0] == 'I') ? g_fast_tables.incar_r1 : g_fast_tables.ambient_r1); (table_name[0] == 'I') ? g_fast_tables.incar_r1 : g_fast_tables.ambient_r1);
fprintf(file, "// Всего записей: %d\n", TABLE_SIZE_LOOKUP); fprintf(file, "// Всего записей: %d\n", TABLE_SIZE_LOOKUP);
fprintf(file, "// Шаг между ADC значениями: %.2f (ADC_MAX/%d)\n", ADC_STEP, TABLE_SIZE_LOOKUP);
fprintf(file, "//\n\n"); fprintf(file, "//\n\n");
fprintf(file, "#include <stdint.h>\n\n"); fprintf(file, "#include <stdint.h>\n");
fprintf(file, "#include <math.h>\n\n");
// Константы для быстрого доступа
fprintf(file, "#define TABLE_SIZE_%s %d\n", table_name, TABLE_SIZE_LOOKUP);
fprintf(file, "#define ADC_STEP_%s %.2f\n\n", table_name, ADC_STEP);
// Структура для элемента таблицы // Структура для элемента таблицы
fprintf(file, "// Структура для хранения записи таблицы\n"); fprintf(file, "// Структура для хранения записи таблицы\n");
@ -92,57 +98,14 @@ void save_table_to_c_file(const char* filename, const adc_temp_lookup* table,
} }
fprintf(file, "};\n\n"); fprintf(file, "};\n\n");
// Добавляем функцию для быстрого доступа по ADC // Функция для быстрого доступа (прямая индексация)
fprintf(file, "// Быстрый поиск температуры по ADC (прямая индексация)\n"); fprintf(file, "// Быстрый поиск температуры по ADC (прямая индексация)\n");
fprintf(file, "static inline int16_t %s_get_temp(uint16_t adc_value) {\n", array_name); fprintf(file, "static inline int16_t %s_get_temp(uint16_t adc_value) {\n", array_name);
fprintf(file, " if (adc_value >= %d) return %s[%d].temp_c;\n", fprintf(file, " uint16_t index = adc_value / ADC_STEP_%s;\n", table_name);
TABLE_SIZE_LOOKUP, array_name, TABLE_SIZE_LOOKUP - 1); fprintf(file, " if (index >= TABLE_SIZE_%s) index = TABLE_SIZE_%s - 1;\n", table_name, table_name);
fprintf(file, " return %s[adc_value].temp_c;\n", array_name); fprintf(file, " return %s[index].temp_c;\n", array_name);
fprintf(file, "}\n\n"); fprintf(file, "}\n\n");
fprintf(file, "// Быстрый поиск сопротивления по ADC (прямая индексация)\n");
fprintf(file, "static inline float %s_get_resistance(uint16_t adc_value) {\n", array_name);
fprintf(file, " if (adc_value >= %d) return %s[%d].resistance_ohm;\n",
TABLE_SIZE_LOOKUP, array_name, TABLE_SIZE_LOOKUP - 1);
fprintf(file, " return %s[adc_value].resistance_ohm;\n", array_name);
fprintf(file, "}\n\n");
// Добавляем функцию для обратного поиска (температура -> сопротивление)
fprintf(file, "// Поиск сопротивления по температуре (бинарный поиск)\n");
fprintf(file, "static inline float %s_get_resistance_by_temp(int16_t temp_c10) {\n", array_name);
fprintf(file, " if (temp_c10 >= %s[0].temp_c) return %s[0].resistance_ohm;\n", array_name, array_name);
fprintf(file, " if (temp_c10 <= %s[%d].temp_c) return %s[%d].resistance_ohm;\n",
array_name, TABLE_SIZE_LOOKUP - 1, array_name, TABLE_SIZE_LOOKUP - 1);
fprintf(file, " \n");
fprintf(file, " // Бинарный поиск\n");
fprintf(file, " int left = 0, right = %d;\n", TABLE_SIZE_LOOKUP - 1);
fprintf(file, " while (left <= right) {\n");
fprintf(file, " int mid = left + (right - left) / 2;\n");
fprintf(file, " if (temp_c10 >= %s[mid].temp_c && temp_c10 <= %s[mid + 1].temp_c) {\n", array_name, array_name);
fprintf(file, " // Нашли интервал, интерполируем в логарифмическом масштабе\n");
fprintf(file, " int16_t t_high = %s[mid].temp_c;\n", array_name);
fprintf(file, " int16_t t_low = %s[mid + 1].temp_c;\n", array_name);
fprintf(file, " float r_high = %s[mid].resistance_ohm;\n", array_name);
fprintf(file, " float r_low = %s[mid + 1].resistance_ohm;\n", array_name);
fprintf(file, " \n");
fprintf(file, " if (t_high == t_low) return r_high;\n");
fprintf(file, " \n");
fprintf(file, " float log_r_high = logf(r_high);\n");
fprintf(file, " float log_r_low = logf(r_low);\n");
fprintf(file, " float log_r = log_r_high + (log_r_low - log_r_high) * \n");
fprintf(file, " (float)(t_high - temp_c10) / (float)(t_high - t_low);\n");
fprintf(file, " return expf(log_r);\n");
fprintf(file, " }\n");
fprintf(file, " \n");
fprintf(file, " if (temp_c10 > %s[mid].temp_c) {\n", array_name);
fprintf(file, " right = mid - 1;\n");
fprintf(file, " } else {\n");
fprintf(file, " left = mid + 1;\n");
fprintf(file, " }\n");
fprintf(file, " }\n");
fprintf(file, " return %s[%d].resistance_ohm;\n", array_name, TABLE_SIZE_LOOKUP - 1);
fprintf(file, "}\n");
fclose(file); fclose(file);
printf("Таблица '%s' сохранена в файл: %s\n", table_name, filename); printf("Таблица '%s' сохранена в файл: %s\n", table_name, filename);
} }

View File

@ -464,11 +464,17 @@ void init_fast_lookup_table(eNtcTable table_type, float r1, eAlg use_alg) {
max_valid_adc = temp; max_valid_adc = temp;
} }
// Заполняем таблицу - теперь ADC растет от 0 до MAX // Заполняем таблицу с равномерным шагом
// При ADC=0: минимальное сопротивление, максимальная температура // Теперь ADC значения распределены равномерно с шагом ADC_STEP
// При ADC=MAX: максимальное сопротивление, минимальная температура
for (uint16_t i = 0; i < TABLE_SIZE_LOOKUP; i++) { for (uint16_t i = 0; i < TABLE_SIZE_LOOKUP; i++) {
uint16_t adc = i; // Просто индекс = ADC (0...4095) // Рассчитываем ADC с равномерным шагом
uint16_t adc = (uint16_t)((float)i * ADC_STEP);
// Убеждаемся, что ADC не выходит за пределы
if (adc > (uint16_t)(ADC_MAX - 1)) {
adc = (uint16_t)(ADC_MAX - 1);
}
float resistance; float resistance;
float temp; float temp;
@ -534,7 +540,7 @@ void init_fast_lookup_table(eNtcTable table_type, float r1, eAlg use_alg) {
} }
fill_entry: fill_entry:
// Заполняем запись - теперь ADC=i // Заполняем запись
fast_table[i].adc_value = adc; fast_table[i].adc_value = adc;
fast_table[i].temp_c = (int16_t)(temp * 10.0f); fast_table[i].temp_c = (int16_t)(temp * 10.0f);
fast_table[i].resistance_ohm = resistance; fast_table[i].resistance_ohm = resistance;
@ -599,7 +605,7 @@ bool is_vcc_equal_to_vref(void) {
return (VCC_DIVIDER_MV_INT == VREF_MV_INT); return (VCC_DIVIDER_MV_INT == VREF_MV_INT);
} }
// Быстрая функция для конкретной таблицы // Быстрая функция для конкретной таблицы (оптимизирована для равномерного шага)
int16_t get_temperature_log_fast_for_table(uint16_t adc_value, eNtcTable table_type) { int16_t get_temperature_log_fast_for_table(uint16_t adc_value, eNtcTable table_type) {
if (!is_table_initialized(table_type)) { if (!is_table_initialized(table_type)) {
// Если таблица не инициализирована, используем обычный расчет // Если таблица не инициализирована, используем обычный расчет
@ -611,31 +617,28 @@ int16_t get_temperature_log_fast_for_table(uint16_t adc_value, eNtcTable table_t
adc_temp_lookup* fast_table = get_fast_table_by_type(table_type); adc_temp_lookup* fast_table = get_fast_table_by_type(table_type);
// Простой линейный поиск (так как таблица небольшая - 4096 элементов) // Для равномерного распределения можно вычислить индекс напрямую
for (uint16_t i = 0; i < TABLE_SIZE_LOOKUP - 1; i++) { uint16_t index = adc_value / ADC_STEP;
if (adc_value >= fast_table[i].adc_value && adc_value <= fast_table[i + 1].adc_value) {
// Линейная интерполяция
uint16_t adc1 = fast_table[i].adc_value;
uint16_t adc2 = fast_table[i + 1].adc_value;
int16_t temp1 = fast_table[i].temp_c;
int16_t temp2 = fast_table[i + 1].temp_c;
if (adc2 == adc1) { // Проверяем границы
return temp1; if (index >= TABLE_SIZE_LOOKUP) {
} index = TABLE_SIZE_LOOKUP - 1;
}
// Если нужно более точное значение - интерполируем с соседними точками
if (adc_value > fast_table[index].adc_value && index < TABLE_SIZE_LOOKUP - 1) {
uint16_t adc1 = fast_table[index].adc_value;
uint16_t adc2 = fast_table[index + 1].adc_value;
int16_t temp1 = fast_table[index].temp_c;
int16_t temp2 = fast_table[index + 1].temp_c;
if (adc2 > adc1) {
return temp1 + ((int32_t)(temp2 - temp1) * (adc_value - adc1)) / (adc2 - adc1); return temp1 + ((int32_t)(temp2 - temp1) * (adc_value - adc1)) / (adc2 - adc1);
} }
} }
// Если не нашли, возвращаем ближайшее значение return fast_table[index].temp_c;
if (adc_value <= fast_table[0].adc_value) {
return fast_table[0].temp_c;
} else {
return fast_table[TABLE_SIZE_LOOKUP - 1].temp_c;
}
} }
// Быстрые функции с использованием активной таблицы // Быстрые функции с использованием активной таблицы
int16_t get_temperature_log_fast(uint16_t adc_value) { int16_t get_temperature_log_fast(uint16_t adc_value) {
return get_temperature_log_fast_for_table(adc_value, TABLE_DUCT); return get_temperature_log_fast_for_table(adc_value, TABLE_DUCT);