Термистор и Arduino
Термистор (терморезистор) - это резистор, который меняет свое сопротивление с изменением температуры.
Технически все резисторы являются термисторами, так как их сопротивление меняется в зависимости от температуры. Но эти изменения очень незначительны и измерить их очень сложно. Термисторы изготавливаются таким образом, чтобы сопротивление изменялось на значительную величину в зависимости от температуры. Около 100 Ом и даже больше при изменении температуры на 1 градус по Цельсию!
Существуют два вида термисторов - с NTC (negative temperature coefficient - отрицательный температурный коэффициент) и с PTC (positive temperature coefficient - положительный температурный коэффициент). В большинстве случаев для измерения температуры используются NTC сенсоры. PTC часто используются в качестве предохранителей - с увеличением температуры растет сопротивление, это приводит к тому, что через них проходит большая сила тока, они нагреваются и срабатывают как предохранители. Достаточно удобно для предохранительных цепей!
Если сравнивать термисторы с аналоговыми датчиками температуры типа LM35, TMP36, цифровыми вроде DS18B20, или термопарами, основными преимуществами термисторов можно назвать:
- Во первых, они гораздо дешевле чем все перечисленные выше датчики температуры!
- Их гораздо проще использовать в условиях повышенной влажности, так как это просто резистор.
- Термисторы работают с любым напряжением (цифровые датчики требуют 3 или 5 В питания логики).
- Если сравнить термистор и термопару, то первым не нужен усилитель сигнала, чтобы считывать данные. Соответственно, вы можете использовать практически любой микроконтроллер.
- Соотношение точность показаний/цена - потрясающие. Например, термистор 10 КОм 1% может производить измерения температуры с точностью ±0.25°C! (При условии, что у вас подходящий аналогово-цифровой преобразователь на микроконтроллере).
- Их практически невозможно поломать или повредить.
С другой стороны, диапазон температур, который можно измерить с помощью термисторов не такой широкий как у термопар и их настройка для снятия показаний тоже немного сложнее. А если на вашем контроллере нет встроенного аналогово-цифрового преобразователя, то лучше вообще обойтись цифровыми датчиками температуры.
Тем не менее простота исполнения термисторов дает им огромный бонус и они безумно популярны для базовых задач контроля температуры. Например, вы хотите, чтобы автоматически включился кондиционер, если в помещении стало слишком жарко. Для этого вы можете использовать цифровой датчик температуры, Arduino, и реле. А можете использовать и термистор, который подключен к базе транзистора. В результате, с повышением температуры, сопротивление падает, на транзистор подается все больше тока, пока он не включится.
Технические характеристики
Ниже приведены технические характеристики термисторов, которые чаще всего используются в DIY проектах на Arduino:
- Сопротивление при 25 °C: 10K ±1%.
- B25/50: 3950 ±1%.
- Диапазон измеряемых температур от -55°C до 125°C.
- Диаметр: 3.5 мм / 0.13 дюйма.
- Длина: 18 дюймов / 45 см.
- Зависимость сопротивления от температуры.
Обратите внимание на то, что сам термистор может измерять температуру до 125° C, но сами контакты порой рассчитаны на меньшую температуру. То есть, термистор не стоит использовать для контроля температуры слишком горячих жидкостей.
Тестируем термистор
Так как термисторы - по своей сути - резисторы , проверить их не составит труда. Достаточно измерить сопротивление с помощью мультиметра:

При комнатной температуре показания должны составить около 10 КОм. Например, показания при 30°C - 86°F, составляют около 8 КОм.
Подключение термистора к Arduino
Термисторы подключаются к Arduino очень просто. Достаточно использовать монтажную плату, как это показано на рисунке ниже. Так как сопротивление термистора достаточно высокое (около 10 КОм), сопротивление проводников практически не повлияет на результаты измерений.

Методика считывания аналогового напряжения
Для того, чтобы определить температуру, мы должны измерить сопротивление. При этом на Arduino нет встроенного измерителя сопротивления. Но зато есть возможность считать напряжение с помощью аналогово-цифрового конвертера. Так что нам надо преобразовать сопротивление в напряжение. Для этого мы последовательно добавим в схему подключения еще один резистор. Теперь, когда вы будете мерять напряжение по центру, с изменением сопротивления, будет меняться и напряжение.
Скажем, мы используем резистор с постоянным номиналом 10K и переменный резистор, который называется R. При этом напряжение на выходе (Vo), которое мы будем передавать Arduino, будет равно:
Vo = R / (R + 10K) * Vcc,
где Vcc - это напряжение источника питания (3.3 В или 5 В)
Теперь мы хотим подключить все это к Arduino. Не забывайте, что когда вы измеряете напряжение (Vi) с использованием АЦП на Arduino, вы получите числовое значение.
ADC value = Vi * 1023 / Vcc
Теперь мы совмещаем два напряжения (Vo = Vi) и получаем:
ADC value = R / (R + 10K) * Vcc * 1023 / Vcc
Что самое прекрасное, Vcc сокращается!
ADC value = R / (R + 10K) * 1023
То есть вам неважно, какое напряжение питания вы используете!
В конце мы все же хотим получить R (сопротивление). Для этого надо использовать еще одно преобразование, в котором R переносятся в одну сторону:
R = 10K / (1023/ADC - 1)
Отлично. Давайте попробуем, что из этого всего выйдет. Подключите термистор к Arduino как это показано на рисунке ниже:

Подключите один контакт резистора на 10 КОм к контакту 5 В, второй контакт резистора 10 КОм 1% - к одному контакту термистора. Второй контакт термистора подключается к земле. 'Центр' двух резисторов подключите к контакту Analog 0 на Arduino.
Теперь запустите следующий скетч для Arduino:
// значение 'другого' резистора
#define SERIESRESISTOR 10000
// к какому пину подключается термистор
#define THERMISTORPIN A0
void setup(void) {
Serial.begin(9600);
}
void loop(void) {
float reading;
reading = analogRead(THERMISTORPIN);
Serial.print("Analog reading ");
Serial.println(reading);
// преобразуем полученные значения в сопротивление
reading = (1023 / reading) - 1;
reading = SERIESRESISTOR / reading;
Serial.print("Thermistor resistance ");
Serial.println(reading);
delay(1000);
}
В результате вы должны получить значения, которые соответствуют измеренным с помощью мультиметра.
Более точные измерения
При проведении измерений аналоговых значений, особенно с 'шумными' платами вроде Arduino, можно использовать два метода для улучшения качества показаний. Первый - использовать пин 3.3 В для аналогового сигнала и второй - собрать небольшой массив экспериментальных значений и усреднить их.
Первое. Питание 5 В от Arduino подается напрямую от USB вашего персонального компьютера. В результате сигнал гораздо более зашумленный, чем питание от контакта 3.3 В (этот контакт предусматривает предварительную обработку через интегрированный в плату регулятор). То есть просто подключите 3.3 к контакту AREF и используйте его в качестве источника напряжения VCC.
Второе. Снять несколько показаний для того, чтобы получить усредненное значение также значительно улучшит показания, так как будут учтены внешние шумы. Для усреднения рекомендуется брать не меньше 5 значений.
В результате схема подключения и новый скетч для Arduino будут имеет следующий вид:

В этом скетче учтены оба "апгрейда". В результате вы сможете подучить более точные показания температуры.
// к какому аналоговому контакту мы подключены
#define THERMISTORPIN A0
// сколько показаний берется для определения среднего значения
// чем больше значений, тем дольше проводится калибровка,
// но и показания будут более точными
#define NUMSAMPLES 5
// емкость второго резистора в цепи
#define SERIESRESISTOR 10000
int samples[NUMSAMPLES];
void setup(void) {
Serial.begin(9600);
// подключите AREF к 3.3 В и используйте именно этот контакт для питания,
// так как он не так сильно "шумит"
analogReference(EXTERNAL);
}
void loop(void) {
uint8_t i;
float average;
// формируем вектор из N значений с небольшой задержкой между считыванием данных
for (i=0; i< NUMSAMPLES; i++) {
samples[i] = analogRead(THERMISTORPIN);
delay(10);
}
// определяем среднее значение в сформированном векторе
average = 0;
for (i=0; i< NUMSAMPLES; i++) {
average += samples[i];
}
average /= NUMSAMPLES;
Serial.print("Average analog reading ");
Serial.println(average);
// конвертируем значение в сопротивление
average = 1023 / average - 1;
average = SERIESRESISTOR / average;
Serial.print("Thermistor resistance ");
Serial.println(average);
delay(1000);
}
Преобразовываем показания с термистора в температуру
Естественно, от сопротивления на термисторе нам не холодно не жарко. Нам надо узнать именно температуру! Если вам достаточно на скорую руку оценить температуру (например, если температура ниже какого-то значения X, выполняем определенную задачу, если же выше какого-то Y, выполняем другую задачу), вы можете просто использовать таблицу зависимости температуры от сопротивления.
Но скорее всего, вам понадобятся фактические значения температуры. Для этого можно использовать уравнение Стейнхарта-Харта, которое позволит реализовать достаточно достоверную аппроксимацию конвертированных значений.

Уравнение достаточно сложное и требует большого количества переменных-параметров, которых может не быть для конкретного термистора. Вместо этого уравнения можно использовать упрощенное B parameter уравнение.

Для этой зависимости нам надо знать исключительно To (этот параметр для комнатной температуры (25 °C) = 298.15 K), B (в данном конкретном случае равен 3950 - коэффициент, который зависит от используемого термистора), и Ro (сопротивление при комнатной температуре. В данном случае он равен 10 КОм). Подставляем R (измеренное сопротивление) и получаем значение T (температура по Кельвину), которую преобразовываем в °C.
В программе для Arduino, которая приведена ниже, рассчитывается температура в °C.
// к какому аналоговому пину мы подключены
#define THERMISTORPIN A0
// сопротивление при 25 градусах по Цельсию
#define THERMISTORNOMINAL 10000
// temp. для номинального сопротивления (практически всегда равна 25 C)
#define TEMPERATURENOMINAL 25
// сколько показаний используем для определения среднего значения
#define NUMSAMPLES 5
// бета коэффициент термистора (обычно 3000-4000)
#define BCOEFFICIENT 3950
// сопротивление второго резистора
#define SERIESRESISTOR 10000
int samples[NUMSAMPLES];
void setup(void) {
Serial.begin(9600);
analogReference(EXTERNAL);
}
void loop(void) {
uint8_t i;
float average;
// сводим показания в вектор с небольшой задержкой между снятием показаний
for (i=0; i< NUMSAMPLES; i++) {
samples[i] = analogRead(THERMISTORPIN);
delay(10);
}
// рассчитываем среднее значение
average = 0;
for (i=0; i< NUMSAMPLES; i++) {
average += samples[i];
}
average /= NUMSAMPLES;
Serial.print("Average analog reading ");
Serial.println(average);
// конвертируем значение в сопротивление
average = 1023 / average - 1;
average = SERIESRESISTOR / average;
Serial.print("Thermistor resistance ");
Serial.println(average);
float steinhart;
steinhart = average / THERMISTORNOMINAL; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= BCOEFFICIENT; // 1/B * ln(R/Ro)
steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // инвертируем
steinhart -= 273.15; // конвертируем в градусы по Цельсию
Serial.print("Temperature ");
Serial.print(steinhart);
Serial.println(" *C");
delay(1000);
}

Для того, чтобы получить еще более точные измерения, рекомендуется учесть точный номинал резистора. В данном случае он, например, не будет равен ровно 10 КОм, а будет принимать значение близкое к 10 КОм.
Насколько точно можно определить температуру с помощью термистора и Arduino?
Вероятно, вы заметили выше, что значение температуры равно 28.16°C. Значит ли это, что точность показаний составляет 0.01°C? К сожалению, нет. У нас есть погрешность самого термистора и погрешность аналоговой электрической цепи.
Можно аппроксимировать ожидаемую погрешность, если учесть ошибку сопротивления самого термистора. Например, на термисторе указано 1%. Это значит, что при 25 °C он может выдать показания в диапазоне от 10,100 до 9900 Ом. При 25°C разница в показаниях в 450 Ом соответствует 1°C, так что погрешность 1% составляет около +-0.25 °C (можно провести калибровку термистора при 0 °C и исключить отклонения). Также можно использовать термистор с погрешностью 0.1%. Это поможет уменьшить ошибку в показаниях до +-0.03°C
Есть вторая погрешность, которая возникает при аналогово-цифровом преобразовании. Каждый некорректно прочитанный бит может давать отклонения около 50 Ом. В принципе эта погрешность меньше, чем ошибка самого термистора +-(0.1°C), но, используя Arduino Uno или Arduino Pro Mini, уменьшить эту погрешность невозможно. Если вас такая точность не устраивает, необходимо использовать более "продвинутые" можели Arduino (которые обеспечат 12-16 бит вместо 10 при аналогово-цифровом преобразовании).
В общем, термисторы обеспечивают большую точность при измерении температуры по сравнению с термопарами и большинством недорогих цифровых датчиков температуры, но, используя Arduino и термистор, вы не получите измерения с точностью более чем +-0.1 °C. Используя 1% термистор, показания не будут точнее +-0.5 °C.
Оставляйте Ваши комментарии, вопросы и делитесь личным опытом ниже. В дискуссии часто рождаются новые идеи и проекты!