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_INCAR 38
#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 {

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);
}
// Функция для сохранения таблицы в C файл в виде статического массива
// Функция для сохранения таблицы в C файл с информацией о равномерном распределении
void save_table_to_c_file(const char* filename, const adc_temp_lookup* table,
const char* table_name, const char* array_name) {
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] == 'I') ? g_fast_tables.incar_r1 : g_fast_tables.ambient_r1);
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, "#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");
@ -92,57 +98,14 @@ void save_table_to_c_file(const char* filename, const adc_temp_lookup* table,
}
fprintf(file, "};\n\n");
// Добавляем функцию для быстрого доступа по ADC
// Функция для быстрого доступа (прямая индексация)
fprintf(file, "// Быстрый поиск температуры по ADC (прямая индексация)\n");
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",
TABLE_SIZE_LOOKUP, array_name, TABLE_SIZE_LOOKUP - 1);
fprintf(file, " return %s[adc_value].temp_c;\n", array_name);
fprintf(file, " uint16_t index = adc_value / ADC_STEP_%s;\n", table_name);
fprintf(file, " if (index >= TABLE_SIZE_%s) index = TABLE_SIZE_%s - 1;\n", table_name, table_name);
fprintf(file, " return %s[index].temp_c;\n", array_name);
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);
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;
}
// Заполняем таблицу - теперь ADC растет от 0 до MAX
// При ADC=0: минимальное сопротивление, максимальная температура
// При ADC=MAX: максимальное сопротивление, минимальная температура
// Заполняем таблицу с равномерным шагом
// Теперь ADC значения распределены равномерно с шагом ADC_STEP
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 temp;
@ -534,7 +540,7 @@ void init_fast_lookup_table(eNtcTable table_type, float r1, eAlg use_alg) {
}
fill_entry:
// Заполняем запись - теперь ADC=i
// Заполняем запись
fast_table[i].adc_value = adc;
fast_table[i].temp_c = (int16_t)(temp * 10.0f);
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);
}
// Быстрая функция для конкретной таблицы
// Быстрая функция для конкретной таблицы (оптимизирована для равномерного шага)
int16_t get_temperature_log_fast_for_table(uint16_t adc_value, eNtcTable 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);
// Простой линейный поиск (так как таблица небольшая - 4096 элементов)
for (uint16_t i = 0; i < TABLE_SIZE_LOOKUP - 1; i++) {
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;
// Для равномерного распределения можно вычислить индекс напрямую
uint16_t index = adc_value / ADC_STEP;
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);
}
}
// Если не нашли, возвращаем ближайшее значение
if (adc_value <= fast_table[0].adc_value) {
return fast_table[0].temp_c;
} else {
return fast_table[TABLE_SIZE_LOOKUP - 1].temp_c;
}
return fast_table[index].temp_c;
}
// Быстрые функции с использованием активной таблицы
int16_t get_temperature_log_fast(uint16_t adc_value) {
return get_temperature_log_fast_for_table(adc_value, TABLE_DUCT);