diff --git a/APP/inc/ADC_Temp.h b/APP/inc/ADC_Temp.h index b3f3aef..7033dcc 100644 --- a/APP/inc/ADC_Temp.h +++ b/APP/inc/ADC_Temp.h @@ -40,5 +40,5 @@ int16_t get_temperature_log_fast(uint16_t adc_value); int16_t get_temperature_linear_fast(uint16_t adc_value); float get_resistance_from_adc(uint16_t adc_value); // Новая функция для получения сопротивления - +float get_resistance_log_fast(int16_t temperature_c10); #endif //MDF_ADC_TEMP_KST45_14_2_H \ No newline at end of file diff --git a/APP/main.c b/APP/main.c index 92508b3..a7e7046 100644 --- a/APP/main.c +++ b/APP/main.c @@ -18,9 +18,21 @@ int main() { printf("T_FAST = %.1f °C\n", T_FAST / 10.0f); printf("Resistance = %.2f Ω\n", resistance); +// float R = get_resistance_log_fast(250); +// printf("Resistance FAST = %.2f Ω\n", R); + + // Пример доступа к таблице printf("\nПример данных из таблицы быстрого поиска:\n"); - for(int i = 2048; i < 2048 + 5; i++) { + for(int i = TABLE_SIZE_LOOKUP - 1; i > TABLE_SIZE_LOOKUP - 5; i--) { + printf("ADC: %u, Temp: %.1f °C, Resistance: %.2f Ω\n", + fast_lookup[i].adc_value, + fast_lookup[i].temp_c / 10.0f, + fast_lookup[i].resistance_ohm); + } + + printf("\nПример данных из таблицы быстрого поиска:\n"); + for(int i = 0; i < 5; i++) { printf("ADC: %u, Temp: %.1f °C, Resistance: %.2f Ω\n", fast_lookup[i].adc_value, fast_lookup[i].temp_c / 10.0f, diff --git a/APP/src/ADC_Temp.c b/APP/src/ADC_Temp.c index 9e94980..67b0376 100644 --- a/APP/src/ADC_Temp.c +++ b/APP/src/ADC_Temp.c @@ -223,15 +223,55 @@ float get_resistance_from_adc(uint16_t adc_value) { } void init_fast_lookup_table(eAlg use_alg) { - // Создаем таблицу для быстрого преобразования АЦП->температура - for (uint16_t i = 0; i < TABLE_SIZE_LOOKUP; i++) { - // Правильное распределение значений АЦП от 0 до ADC_MAX - uint16_t adc = (uint16_t) ((float) i * ADC_MAX / (TABLE_SIZE_LOOKUP - 1)); - float temp = get_temperature_from_adc(adc, use_alg); + // Сначала найдем рабочий диапазон АЦП, который дает температуры в пределах таблицы + uint16_t min_valid_adc = 0; + uint16_t max_valid_adc = 0; + float min_temp = TABLE_START_TEMP; + float max_temp = TABLE_END_TEMP; + + // Ищем минимальное АЦП, при котором температура >= TABLE_START_TEMP + for (uint16_t adc = 1; adc < ADC_MAX; adc++) { float resistance = calculate_resistance(adc); + float temp = get_temperature_from_adc(adc, ALG_STEINHART); + + if (temp >= TABLE_START_TEMP && temp <= TABLE_END_TEMP) { + min_valid_adc = adc; + break; + } + } + + // Ищем максимальное АЦП, при котором температура <= TABLE_END_TEMP + for (uint16_t adc = (uint16_t)(ADC_MAX - 1); adc > 0; adc--) { + float resistance = calculate_resistance(adc); + float temp = get_temperature_from_adc(adc, ALG_STEINHART); + + if (temp >= TABLE_START_TEMP && temp <= TABLE_END_TEMP) { + max_valid_adc = adc; + break; + } + } + + // Если не нашли корректные значения, используем весь диапазон + if (min_valid_adc == 0) min_valid_adc = 1; + if (max_valid_adc == 0) max_valid_adc = (uint16_t)(ADC_MAX - 1); + + printf("Диапазон АЦП: %u - %u\n", min_valid_adc, max_valid_adc); + + // Заполняем таблицу, равномерно распределяя АЦП в рабочем диапазоне + for (uint16_t i = 0; i < TABLE_SIZE_LOOKUP; i++) { + // Линейная интерполяция АЦП в рабочем диапазоне + float ratio = (float)i / (TABLE_SIZE_LOOKUP - 1); + uint16_t adc = min_valid_adc + (uint16_t)(ratio * (max_valid_adc - min_valid_adc)); + + float resistance = calculate_resistance(adc); + float temp = get_temperature_from_adc(adc, use_alg); + + // Ограничиваем температуру пределами таблицы + if (temp < TABLE_START_TEMP) temp = TABLE_START_TEMP; + if (temp > TABLE_END_TEMP) temp = TABLE_END_TEMP; fast_lookup[i].adc_value = adc; - fast_lookup[i].temp_c = (int16_t) (temp * 10.0f); // Храним с точностью 0.1°C + fast_lookup[i].temp_c = (int16_t)(temp * 10.0f); fast_lookup[i].resistance_ohm = resistance; } } @@ -304,4 +344,62 @@ int16_t get_temperature_linear_fast(uint16_t adc_value) { } return temp1 + ((int32_t) (temp2 - temp1) * (adc_value - adc1)) / (adc2 - adc1); +} + + +// Функция для получения сопротивления из температуры (обратное преобразование) +float get_resistance_log_fast(int16_t temperature_c10) { + // temperature_c10 - температура в °C * 10 (например, 250 = 25.0°C) + + // Защита от выхода за границы + if (temperature_c10 <= fast_lookup[0].temp_c) { + return fast_lookup[0].resistance_ohm; + } + if (temperature_c10 >= fast_lookup[TABLE_SIZE_LOOKUP - 1].temp_c) { + return fast_lookup[TABLE_SIZE_LOOKUP - 1].resistance_ohm; + } + + // Бинарный поиск интервала по температуре + int left = 0; + int right = TABLE_SIZE_LOOKUP - 1; + + while (left <= right) { + int mid = left + (right - left) / 2; + + if (fast_lookup[mid].temp_c <= temperature_c10 && + (mid == TABLE_SIZE_LOOKUP - 1 || temperature_c10 < fast_lookup[mid + 1].temp_c)) { + // Нашли интервал + if (mid == TABLE_SIZE_LOOKUP - 1) { + return fast_lookup[mid].resistance_ohm; + } + + // Линейная интерполяция по температуре + int16_t temp1 = fast_lookup[mid].temp_c; + int16_t temp2 = fast_lookup[mid + 1].temp_c; + float res1 = fast_lookup[mid].resistance_ohm; + float res2 = fast_lookup[mid + 1].resistance_ohm; + + // Избегаем деления на ноль + if (temp2 == temp1) { + return res1; + } + + // Интерполяция в логарифмическом масштабе для сопротивления + // (так как сопротивление изменяется экспоненциально) + float log_res1 = logf(res1); + float log_res2 = logf(res2); + float log_res = log_res1 + (log_res2 - log_res1) * + (float)(temperature_c10 - temp1) / (float)(temp2 - temp1); + + return expf(log_res); + } + + if (temperature_c10 < fast_lookup[mid].temp_c) { + right = mid - 1; + } else { + left = mid + 1; + } + } + + return fast_lookup[0].resistance_ohm; // Если не нашли, возвращаем первое значение } \ No newline at end of file