Подключение NTC-термистора к STM32 (измерение температуры)

Самых разных термисторов развелось много, они используются в БП для подавления броска тока, но нас интересует измерение температуры.

Купить на Aliexpress

Термистор 10K 1% B3950 1шт. 0.66$ 1pcs NTC Thermistor Accuracy Temperature Sensor 10K 1% 3950 Waterproof Probe 0.5 Meter Long

Термистор 10K 1% B3950 10шт. 2.46$ 10pcs NTC Thermistor10K 1% 3950 Waterproof

Другие NTC резисторы NTC Thermistors

Теплопроводящий клей Stars 922 0.76$ 5g Thermal Grease Paste Conductive Heatsink Plaster Adhesive Glue For Chip VGA RAM LED IC Cooler Radiator Cooling STARS-922

Выбор термистора

В наличии у меня готовый датчик  NTC-10K-B3950 с проводом 1 м и защитной металлической гильзой, в которой датчик залит герметиком (или термоклеем) вместе с разъемом. В некоторых случаях это очень удобно.

Также есть миниатюрный датчик NCP18XH103F03RB в корпусе 0603 (1.6х0.8х0.8 мм), который имеет точность 1%.

Построение основной характеристики

Построив зависимость сопротивления термистора с отрицательным коэффициентом температуры от температуры на примере  NTC-10K-B3950 видно, что получилась кривая. Да уж, при таком большом диапазоне температур линейности нет.

Но, если взять небольшую область по оси абсцисс ( T),  от 32 °C до 45 °C (например, для измерения температуры тела), то участок становится очень похож на прямую линию, что нам и нужно.

Вот также характеристика на NCP18XH103F03RB из тех.док.:

Таким образом термистор хорошо использовать в случаях, когда диапазон измеряемых температур заранее известен и мал!

Уравнение Стейнхарта-Харта

Но должна же быть какое-то хитрое выражение, которое сможет аналитически описать вот эту изогнутую линию. Вот:

Обычно используют только два/три первых члена, т.к последующие влияют незначительно.

Как найти коэффициенты A, B, C?

Для этого нужно решить СЛАУ (систему линейных алгебраических уравнение). Неизвестных у нас три, то есть нужно по меньшей мере три известных точки (их берем их тех.док на датчик или получаем опытным путем).

В нужном нам диапазоне температур берем крайние значение + значение посредине.

T, °C 0 60 120
R, Ом 32960.0 2467.99 387.294

Нужно просто домножить обе части на обратную матрицу.

Итак, задаем начальные данные (температура в градусах Кельвина!):

Посмотрим на обратную матрицу:

Вычисляем:

Вот такие вот маленькие значения получились:

A = 0.001111
B = 0.000237987
C = 0.000000065

Сравним полученное с начальным. Нормально.

Конечно уже есть онлайн-калькуляторы, позволяющее сделать то же самое, просто вводя значения.

Thermisotr Calculator Online

Подключение

Резистор 10к нужно использовать точный, 1%.

Также установите конденсатор 100 нФ параллельно термистору.

Создание проекта в STM32CubeMX

Тут настройка АЦП + ПДП, а также таймер с прерыванием 100 мс для планировки.

Файл, новый проект: File -> New Project

Выбираем нужный МК: STM32F103C8

Включаем отладчик: System Core -> SYS -> Debug: Serial Wire

Включаем АЦП, Канал 0: ADC1 -> IN0
Настраиваем работу ПДП: ADC1 -> DMA Settings -> Add -> ADC1 (DMA Request) -> Mode: Circular

Включаем тактирование Таймера 4: TIM4 -> Internal Clock
Включаем прерывание: NVIC Settings -> TIM4 global interrupt
И для периода вызова этого прерывания 100 мс:
Предделитель (Prescaler): 800-1
Регистр автоперезагрузки (Auto-reload register):  1000-1

Нужен период T = 100 мс (f = 10 Гц).

Частота шины, от которой тактируется таймер (смотреть в Clock Configuration) делится на необходимую.

PSC*ARR = fAHB/f = 8000000/10 = 800000

Распределяем полученное число (800000) между предделителем и регистром автоперезагрузки:

PSC = 800-1; ARR = 1000-1;

Отлично, 800*1000=800000. Почему минус один? Счет идет с нуля, когда в предделитель записано ноль, то частота делится конечно же не на ноль, а на единицу (не изменяется), когда 1, то на два. Получается нужная частота (формула из RF):

fTIM4 = fAHB/(PSC+1)*(ARR+1) = 8000000/(800-1+1)*(1000-1+1) = 10 Гц

Таким образом в регистры PSC, ARR, CCRx записывайте за вычетом единицы.

Во вкладке настройки тактирования ничего не меняем HCLK = 8 MHz:

Любое название и для Keil:
Project Name: thermistor
Toolchain/IDE: MDK-ARM, Min Version: V5.27

Генерируем код и открываем проект: GENERATE CODE -> Open Project

Неправильная реализация на МК

Вычисление натурального логарифма для МК это тяжело, ведь подключив библиотеку математики сожрется примерно 2.5 кБ памяти, что недопустимо много, но в целях обучения и проверки сгодится.

Подключаем библ. математики:

#include <math.h>

Определим переменные и постоянные для вычисления текущего сопротивления измерительного элемента:

/* USER CODE BEGIN PV */ /* adc vars */ uint16_t ADC_Raw[1]; /* ntc vars */ float Ntc_Tmp = 0; uint16_t Ntc_R; /* sheduler vars */ uint8_t Sch_100ms = 255;

Далее определим ранее найденные множители A, B, C:

/* R1 resistance */ #define NTC_UP_R 10000.0f /* constants of Steinhart-Hart equation */ #define A 0.001111f #define B 0.000237987f #define C 0.000000065f /* USER CODE END PV */

В прерывании от таймера присваиваем переменной-флагу 255.

/* USER CODE BEGIN 4 */ /************** timer 4 irqhandler *************/ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance == TIM4) { /* set every 100ms */ Sch_100ms = 255; } } /* USER CODE END 4 */

Калибровка и запуск АЦП, врубаем прерывания от Таймера 4:

/* USER CODE BEGIN 2 */ /* adc calibration */ HAL_ADCEx_Calibration_Start(&hadc1); /* adc dma start */ HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC_Raw, 1); /* timer 4 (f=10Hz, T=100ms start */ HAL_TIM_Base_Start_IT(&htim4); /* USER CODE END 2 */

И в главном цикле:

/* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { if(Sch_100ms){ /* get adc value */ HAL_ADC_Start_IT(&hadc1); /* filtering (sma) */ uint16_t Ntc_Temp_ADC = Filter_SMA(ADC_Raw[0]); /* calc. ntc resistance */ Ntc_R = ((NTC_UP_R)/((4095.0/Ntc_Temp_ADC) - 1)); /* temp */ float Ntc_Ln = log(Ntc_R); /* calc. temperature */ Ntc_Tmp = (1.0/(A + B*Ntc_Ln + C*Ntc_Ln*Ntc_Ln*Ntc_Ln)) - 273.15; /* nullify */ Sch_100ms = 0; } /* USER CODE END WHILE */

Проверка (отладка)

После запуска отладки добавляем переменную температуры в окно Watch 1/Live Expressions:

И также в Logic Analyzer/SWV Data Trace (нужно переделывать свисток стлинк) для получение графика:

Правильная реализация на МК

Все уже давно придумано,  отлична статья здесь. На странице есть калькулятор, забиваете параметры своего датчика и получаете таблицу и код. Нужно только подстроить под работу с библиотекой HAL и чутка подпилить напильником.

Нужно закинуть ntc_table.c в папку Src, а ntc_table.h и pgmspace.h в Inc, а далее ПКМ в дереве проекта на эти папки и нажать Обновить (Refresh).

Всё то же самое, как и выше, но подключаем ntc_table.h:

/* USER CODE BEGIN Includes */ #include "ntc_table.h" /* USER CODE END Includes */

И в главном цикле получаем значение с АЦП и кладем его в соответствующую функцию calc_temperature. Для получение значения в градусах Цельсия умножаем возвращаемое число на 0.1 (особенность связана с выводом измерений на индикатор).

/* USER CODE BEGIN WHILE */ while (1) { if(Sch_100ms) { HAL_ADC_Start_IT(&hadc1); float Ntc_Tmp_Raw = calc_temperature(ADC_Raw[0]); Ntc_Tmp = 0.1*Ntc_Tmp_Raw; /* nullify */ Sch_100ms = 0; } /* USER CODE END WHILE */

Этот код конечно же занимает намного меньше места и действительно предназначен для встраиваемых систем.

Но и первом и втором случае очень советую применить  фильтр среднего скользящего, с принципом работы и программой ознакомиться в статье, а ниже реальный пример работы с термистором:

На желтой кривой (сырые значения) куча всплесков, на самом деле они невелики (несколько значений АЦП), но все же очень часты, что приведет к бесящему дерганью последний разрядов значения. А вот красная кривая (отфильтрованное значение) не имеет таких резких изменений и довольно плавная, что дает хорошее показание.

Защита термистора от окружающей среды +водонепроницаемость

Хорошо бы запихнуть маленький термистор в небольшую медную (высокая теплопроводность) гильзу, а внутри для крепления и хорошей теплопередачи залить теплопроводящего клея Stars-922.

Но обычно используется запаянный на конце цилиндр из нержавеющей стали. В качестве проводников были использованы не самые удачные провода, неплохим выбором будут в силиконовой изоляции, термостойкие.

Сравнение показаний с жидкостным термометром

Вроде показывает адекватные цифры, но нужно сравнить в точным измерителем, да еще и при известной температуре (кипение воды при н.у.).

Ой, блин, примерно 970 Ом при настоящих 100°C, что соответствует по таблице только 88°C (то же самое выводиться и на телефоне). Вообщем, показания недостоверные, два датчика ведут себя одинаково, так что уж не знаю, то ли указанные параметры не соответствуют, то ли что.

При использовании хорошего терморезистор от MURATA (поверхностного монтажа) показания очень неплохи, тем более что коэффициенты подбирались по точкам 25°C-50°C-80°C:

Передача сырых показаний через Bluetooth

Применяя термистор (и другие аналоговые сенсоры) вместе с bluetooth-приемопередатчиком JDY-23 можно отправлять только значения с АЦП, а сложные математические вычисления делать в приложении на телефоне, как это и было сделано при подключении фоторезистора!

Несложное приложение легко запилить в конструкторе App Invertor 2 и считать дроби с умножением на маленькие числа каким-нибудь Снепдрегоном телефона.

Видео

Скачать

https://github.com/Egoruch/NTC-STM32-HAL
(ссылка на GitHub)
Рабочие проекты простой (уравнение) и правильной (таблица) реализации измерения температуры.  STM32CubeIDE, STM32F103C8T6
92
RSS
Нет комментариев. Ваш будет первым!
Загрузка...