Урок 1.8. Термистор. Делитель напряжения. Термометр со световой индикацией температуры
Базовый курс "Программирование микроконтроллеров"
Модуль 1. Введение в Arduino. Работа с цифровым и аналоговым сигналом
Терморезистор NTC 100K
Терморезистор (или термистор) — это такой резистор, который меняет свое электрическое сопротивление в зависимости от температуры.
Существует два вида термисторов:
PTC (Positive Temperature Coefficient) — с положительным температурным коэффициентом: их сопротивление растёт при повышении температуры.
NTC (Negative Temperature Coefficient) — с отрицательным температурным коэффициентом: их сопротивление уменьшается при повышении температуры.
Также термисторы отличаются номинальным сопротивлением, которое соответствует комнатной температуре — 25 C°. Например, популярными являются термисторы с номиналом 100 кОм и 10 кОм. Такие термисторы часто используют в 3D-принтерах.
В этом уроке мы будет использовать термистор NTC 100K в стеклянном корпусе.
Делитель напряжения. Схема проекта
Соберем проект световой индикации температуры по схеме:
Как Вы можете заметить, последовательно термистору стоит резистор, наверняка многие из Вас спросят зачем он нужен?
Делитель напряжения — устройство, в котором входное U_{in} и выходное U_{out} напряжения связаны коэффициентом передачи.
Делитель состоит из двух последовательно подключенных резисторов, которые называются верхним и нижним плечом.
Эта несложная схема делит (отсюда и название — делитель) напряжение, приложенное к контактам на его входе на части пропорционально отношению сопротивлений R_1 и R_2. Найдём это отношение.
Обратите внимание: важно знать, что сопротивление нагрузки на выходе делителя должно быть много больше сопротивлений R_1 и R_2. Соответственно, и ток, текущий через эту нагрузку должен быть много меньше тока на самом делителе. Именно по этой причине нерационально использовать делитель для питания устройств.
Вспомним, что:
– Сила тока в последовательно соединенных участках цепи одинакова: I_1=I_2;
– Общее сопротивление последовательно соединенных резисторов равняется их сумме: R_{общ} = R_1 + R_2.
Согласно закону Ома:
R_{общ} = \frac{U_{вх}}{I_{общ}}
Таким образом ток протекающей в схеме будет равен:
I = \frac{U_{вх}}{R_{общ}}=\frac{U_{вх}}{R_1+R_2}
Напряжение на R_2, по закону Ома, равно:
U_2= I{R_2}=\frac{R_2}{R_1+R_2}U_{вх}
Таким образом мы по сути снижаем напряжение на термисторе, делая его более “чувствительным” к АЦП Ардуино.
Представим, что нам нужно питать ту же плату Arduino Uno с несколькими светодиодами от аккумулятора с напряжением 12 Вольт. Для работы подобной схемы потребуется ток около 150 мА. Сопротивление такой нагрузки можно грубо посчитать как R_Н = \frac{U}{I}=\frac{5B}{0.15A}=33,3 Ом.
Следовательно, сопротивление плечей делителя должно составлять десятые доли Ома и иметь мощность десятки Ватт. При таких параметрах делитель превращается в нагреватель, преобразующий в тепло огромное количество ценной энергии аккумулятора.
Программа вычисления сопротивления термистора в Омах
Первая программа, которую мы напишем, будет вычислять сопротивление термистора в Омах, но пока ещё немного теории.
Используя базовые законы физики найдём формулу для расчёта сопротивления.
Общее напряжение является суммой напряжений на двух участках цепи
U_{общ}=U_1+U_2Согласно закону Ома: U = RI
Подставим это в первое уравнение и получим:
U_{общ}=R_1I+R_2IОбратите внимание на то, что сила тока протекающего через оба резистора одинакова.
Из закона Ома сила тока равна:
I = \frac{U_2}{R_2}
Подставим в предыдущее уравнение и получим:
U_{общ}= \frac{R_1U_2}{R_2} +\frac{R_2U_2}{R_2}=U_2(\frac{R_1}{R_2}+1)
Выразим отсюда R_1:
U_{общ}=U_2(\frac{R_1}{R_2}+1) \Rightarrow \frac{U_{общ}}{U_2}=\frac{R_1}{R_2}+1 \Rightarrow \frac{U_{общ}}{U_2}-1=\frac{R_1}{R_2} \Rightarrow R_2=\frac{R_1}{ \frac{U_{общ}}{U_2}-1}
Обратите внимание: в этой формуле U_2 - это показания АЦП, считанные командой analogRead, а {U_{общ}} - это максимальное значение АЦП, т.е. 1023.
Таким образом итоговая формула будет иметь вид: R_2=\frac{R_1}{\frac{1023}{АЦП}-1}
Напишем следующую программу:
#define SERIAL_R 100000 // сопротивление последовательного резистора, 100 кОм
const byte tempPin = A0;
void setup() {
Serial.begin(9600);
pinMode(tempPin, INPUT);
}
void loop() {
int t = analogRead( tempPin );
float term_r = 1023.0 / t - 1;
term_r = SERIAL_R / term_r;
Serial.println(term_r);
delay(100);
}
Откроем монитор порта и посмотрим на измеренное значения сопротивления:
Программа вычисления сопротивления термистора в градусах Цельсия
Наш следующий шаг — вычисление температуры в градусах Цельсия. Чтобы вычислить значение температуры используют формулу Стейнхарта — Харта:
\frac{1}{T} =A+B\cdot ln(R) +C(ln(R))^3
Уравнение имеет параметры A, B и C, которые нужно брать из спецификации к датчику. Так как нам не требуется большой точности, можно воспользоваться модифицированным уравнением (B-уравнением):
\frac{1}{T} =\frac{1}{T_0}+\frac{1}{B}ln(\frac{R}{R_0})
В этом уравнении неизвестным остается только параметр B, который для NTC-термистора равен 3950. Остальные параметры нам уже известны:
T_0 — комнатная температура в Кельвинах, для которой указывается номинал термистора, T_0 = 25 + 273.15;
T — искомая температура, в Кельвинах;
R — измеренное сопротивление термистора в Омах;
R_0 — номинальное сопротивление термистора в Омах.
Модифицируем программу для Ардуино, добавив расчет температуры:
#define B 3950 // B-коэффициент
#define SERIAL_R 100000 // сопротивление последовательного резистора, 100 кОм
#define THERMISTOR_R 100000 // номинальное сопротивления термистора, 100 кОм
#define NOMINAL_T 25 // номинальная температура (при которой TR = 100 кОм)
const byte tempPin = A0;
void setup() {
Serial.begin(9600);
pinMode(tempPin, INPUT);
}
void loop() {
int t = analogRead(tempPin);
float term_r = 1023.0 / t - 1;
term_r = SERIAL_R / term_r;
Serial.print("R=");
Serial.print(term_r);
Serial.print(", t=");
float steinhart;
steinhart = term_r / THERMISTOR_R; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= B; // 1/B * ln(R/Ro)
steinhart += 1.0 / (NOMINAL_T + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15;
Serial.println(steinhart);
delay(100);
}
Остаётся добавить световую индикацию:
#define B 3950 // B-коэффициент
#define SERIAL_R 100000 // сопротивление последовательного резистора, 100 кОм
#define THERMISTOR_R 100000 // номинальное сопротивления термистора, 100 кОм
#define NOMINAL_T 25 // номинальная температура (при которой TR = 100 кОм)
const byte tempPin = A0;
const byte red_led = 5;
const byte blue_led = 6;
void setup() {
Serial.begin(9600);
pinMode(tempPin, INPUT);
pinMode(red_led, OUTPUT);
pinMode(blue_led, OUTPUT);
}
void loop() {
int t = analogRead(tempPin);
float term_r = 1023.0 / t - 1;
term_r = SERIAL_R / term_r;
Serial.print("R=");
Serial.print(term_r);
Serial.print(", t=");
float steinhart;
steinhart = term_r / THERMISTOR_R; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= B; // 1/B * ln(R/Ro)
steinhart += 1.0 / (NOMINAL_T + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15;
Serial.println(steinhart);
int x;
steinhart = constrain(steinhart, 20, 40);
x = map(steinhart, 20, 40, 0, 255);
analogWrite(red_led, 255 - x);
analogWrite(blue_led, x);
}