Урок 25. Кремниевые термодатчики серии KTY81 в системе Ардино. Проект термометра-регистратора.

Диаграмма температуры

Урок рассказывает об использовании кремниевых датчиков температуры в системе Ардуино. Приводится рабочий проект термометра. Попутно рассматривается вопрос измерения сопротивления в системе Ардуино.

Предыдущий урок     Список уроков     Следующий урок

В предыдущем уроке для измерения температуры мы использовали интегральные датчики, у которых напряжение на выходе пропорционально зависит от температуры. Причем эта зависимость линейная с известным масштабным коэффициентом. Для вычисления температуры достаточно измерить напряжение и разделить его на масштабный коэффициент.

 

Кремниевые термодатчики в зависимости от температуры меняют свое сопротивление. Т.е. это не активные элементы, требующие питания, не интегральные микросхемы, а просто терморезисторы.

Типичными представителями кремниевых датчиков являются термодатчики серии KTY81. Я написал о них большую статью. Там есть параметры, характеристики, схемы включения. Частично я повторю эту информацию.

Достоинства и недостатки термодатчиков серии KTY81.

Датчики такого типа большинство разработчиков просто не замечают. Я, напротив, считаю, что в некоторых приложениях они незаменимы.

На мой взгляд, эти устройства имеют  только один существенный недостаток – нелинейная характеристика и невысокая точность измерения. У лучших вариантов датчиков серии KTY81  нелинейность:

± 3,5 °C в диапазоне температуры до + 100 °C;

± 8,5 °C в диапазоне температуры до + 150 °C.

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

Но если такая точность измерения  приемлема, то по остальным характеристикам и эксплуатационным возможностям KTY81 значительно превосходят интегральные термодатчики. А именно:

  • У кремниевых термодатчиков широкий диапазон измеряемых температур  -55 … +150 °C. Интегральные устройства, как правило, работают в диапазоне  -40 … +125 °C, многие до +100 °C. Часто этих лишних 25-50 °C и не хватает, например, при контроле температуры радиаторов мощных полупроводниковых приборов.
  • Для подключения к микроконтроллеру требуется всего два провода, что особенно важно, когда датчики расположены на большом расстоянии от контроллера.
  • Обеспечивается высокая помехоустойчивость за счет двух проводной линии связи, симметричной для помех. Для подключения датчика KTY81 на расстоянии десятков и даже сотен метров достаточно простой витой пары.
  • Высокое сопротивление KTY81 (1000 Ом и 2000 Ом) позволяет пренебречь активным сопротивлением проводов связи.
  • Нет ограничений на работу с емкостной нагрузкой. Это качество позволяет использовать линии связи с большой емкостью и шунтировать термодатчик конденсатором значительной емкости для фильтрации помех. Интегральные термодатчики не работают на емкостную нагрузку более 10 нФ.
  • Устройства не имеют полярности. Сколько полупроводниковых приборов было выведено из строя из-за попутки полярности!
  • Низкая цена. Это одни из самых дешевых датчиков температуры.

Решайте сами, в каких проектах использовать эти датчики. В моих разработках – мощных станциях катодной защиты на каждом радиаторе установлено по термодатчику KTY81/120.

 

Кремниевые термодатчики серии KTY81.

Подробно об этих устройствах можно почитать по ссылке. Сейчас коротко скажу, что:

  • серия включает 10 типов датчиков, отличающихся погрешностью измерения и сопротивлением;
  • у всех устройств рабочий диапазон температуры – 55 … + 150 °C;
  • характеристика (зависимость сопротивления от температуры) задана табличным способом;
  • устройства выполнены в корпусе SOD70 (как TO-92, только два вывода).

KTY81

Для вычисления реальной температуры необходимо выполнить следующие действия:

  • измерить сопротивление термодатчика;
  • используя табличную характеристику вычислить температуру (линеаризовать характеристику).

Измерение активного сопротивления в системе Ардуино.

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

Схема делителя

Между сигналом питание 5 В и землей подключен делитель напряжения из двух резисторов:

  • Ro – образцовый резистор;
  • Rx – измеряемый резистор.

Напряжение на выходе делителя будет:

Uвых = Uвх * Rx  /  ( Ro + Rx )

Отсюда:

Rx = Ro  /  (Uвх / Uвых   - 1)

Из этой формулы видно основное преимущество такого способа измерения. Нам не важно значение напряжение питания делителя (Uвх), не важна его стабильность, т.к. в формулу входит соотношение Uвх / Uвых. А так как источником опорного напряжение для АЦП служит питание 5 В, то АЦП измеряет именно соотношение Uвх / Uвых. Совершенно не важно, какое там напряжение. Мы даже не будем задавать разрешающую способность АЦП в вольтах. Мы зададим Uвх / Uвых как 1023 / N, где 1023 – максимальное значение кода АЦП, N – код АЦП.

В результате формула вычисления сопротивления будет выглядеть так:

Rx = Ro  /  (1023 / N   - 1),

N – код АЦП.

Точность измерения сопротивления по схеме делителя не зависит от погрешности напряжения питания схемы, а определяется только точностью сопротивления образцового резистора Ro.

Правда, у этой схемы явно нелинейная характеристика и разрешающая способность. Определим ее на конкретном примере.

Если использовать датчик KTY81/120, то надо ориентироваться на следующие параметры:

Минимальное сопротивление при – 55 °C 490 Ом
Максимальное сопротивление при + 150 °C 2211 Ом
Предельно допустимый ток при + 150 °C 2 мА

Выберем образцовый резистор сопротивлением 3300 Ом. Тогда ток при + 150 °C будет равным

5 В / (3300 + 2211) = 0,9 мА.

Для наглядности я построил два графика в Excel. Первый это зависимость сопротивления от кода АЦП.

Характеристика измерителя сопротивления

Видна нелинейность преобразования. Если мы используем датчик KTY81/120, то требуется измерять сопротивление в диапазоне 490 … 2211 Ом. По графику видно, что этот диапазон соответствует коду АЦП примерно 130 … 410. Можно посчитать точнее, но сейчас в этом необходимости нет. У нас примерно 280 единиц дискретности АЦП, что вполне достаточно.

Второй график показывает зависимость сопротивления соответствующего единице дискретности АЦП от кода АЦП. Т.е. он показывает насколько меняется разрешающая способность измерителя сопротивления в рабочем диапазоне.

Характеристика измерителя сопротивления

Видно, что худшее значение разрешения измерителя сопротивления при коде 410, и равно 9 Ом. Это соответствует примерно 1 °C и нас вполне устраивает.

В итоге схема подключения термодатчика KTY81/20 к микроконтроллеру выглядит так.

Схема подключения KTY81
Для дальнейших расчетов определим точные границы рабочего диапазона измерителя сопротивления.

N    =  Rx * 1023 /  ( Ro + Rx )

Граница Сопротивление датчика,
Rx
Код АЦП,
N
Минимальная температура,  – 55 °C 490 Ом 132
Максимальная температура,  + 150 °C 2211 Ом 410

 

Проект Ардуино термометра на датчике температуры KTY81/120.

Разработаем термометр – полный функциональный аналог устройства из предыдущего урока, только с использованием термодатчика KTY81/120. Применение кремневого датчика:

  • расширило диапазон измерения температуры до  – 55 … + 150 °C;
  • позволило размещать датчик на большом расстоянии (до сотен метров) и использовать в качестве линии связи витую пару;
  • снизило точность измерения до :
    • ± 5 °C в диапазоне  – 55 … + 100 °C
    • ± 10 °C в диапазоне  + 100 … + 150 °C.

Точность измерения можно улучшить использованием термодатчиков типа KTY81/110 до:

  • ± 3,5 °C в диапазоне  – 55 … + 100 °C;
  • ± 8,5 °C в диапазоне  + 100 … + 150 °C.

Устройство:

  • отображает значение температуры на LED индикаторе (в автономном режиме);
  • передает значение температуры на компьютер;
  • при использовании программы верхнего уровня из предыдущего урока:
    • отображает текущую температуру на дисплее компьютера;
    • регистрирует изменение температуры с дискретностью по времени 1 сек;
    • отображает изменение температуры в графическом виде.

 

Схема термометра.

К плате Ардуино подключим:

  • 4х разрядный LED индикатор;
  • Датчик температуры KTY81/120.

Все как в предыдущем уроке.

Схема Ардуино термометра с датчиком KTY81/120.

Схема Ардуино термометра

R1 – образцовый резистор. C1 – фильтрует высокочастотные помехи, можно его увеличить до 1 мкФ. Применение электролитических конденсаторов нежелательно. У них большой ток утечки. Датчик лучше подключить к контроллеру витой парой.

На макетной плате устройство выглядит так.

Ардуино термометр

Резидентная программа Ардуино термометра.

Программа должна:

  • считывать значение АЦП;
  • усреднять коды АЦП для повышения помехозащищенности;
  • вычислять температуру, используя табличную характеристику датчика KTY81/120;
  • отображать значение температуры на LED индикаторе  в формате:
    • знак;
    • сотни;
    • десятки;
    • единицы °C;
  • передавать значение температуры раз в секунду на компьютер.

Программа большей частью аналогична программе из предыдущего урока. Изменения коснулись только принципа вычисления температуры.

Скетч программы термометра.

// термометр, датчик KTY81/120
#include <MsTimer2.h>
#include <Led4Digits.h>

#define MEASURE_PERIOD 500  // время измерения, * 2 мс
#define RO  3300  // сопротивление образцового резистора, Ом
#define MIN_ADC 132 // минимальное значение рабочего диапазона АЦП
#define MAX_ADC 410 // максимальное значение рабочего диапазона АЦП
#define POL_NUM 24  // число полюсов характеристики

int sensTable[POL_NUM][2] = {  // таблица характеристики датчика
  {-55, 490}, {-50, 515}, {-40, 567}, {-30, 624}, {-20, 684}, {-10, 747},
  {0, 815}, {10, 886}, {20, 961}, {25, 1000}, {30,1040}, {40, 1122},
  {50, 1209}, {60, 1299}, {70, 1392}, {80, 1490}, {90, 1591}, {100, 1696},
  {110, 1805}, {120, 1915}, {125, 1970}, {130, 2023}, {140, 2124}, {150, 2211}
};

int codToTempTable[MAX_ADC - MIN_ADC +1];  // таблица преобразования код в температуру

int timeCount;     // счетчик времени измерения
long  sumA0;       // переменная суммирования кодов АЦП
long  avarageTemp; // среднее значение температуры (сумма кодов АЦП, среднее значение * 500)
boolean flagTempReady;  // признак готовности измерения температуры
int temperature;  // рассчитанная температура, °C

// тип индикатора 1; выводы разрядов 5,4,3,2; выводы сегментов 6,7,8,9,10,11,12,13
Led4Digits disp(1, 5,4,3,2, 6,7,8,9,10,11,12,13);

void setup() {
  MsTimer2::set(2, timerInterrupt); // задаем период прерывания по таймеру 2 мс
  MsTimer2::start();               // разрешаем прерывание по таймеру
  Serial.begin(9600); // инициализируем порт, скорость 9600 

  //--------- предварительный расчет значений температуры -------------
  // вычисление массива codToTempTable[]
  int codBeginPol=0;  // код полюса начала отрезка
  int codEndPol;  // код полюса конца отрезка
  float koeff;  // коэффициент для отрезка между полюсами

  // цикл перебора полюсов
  for ( int p= 0; p < (POL_NUM-1); p++ ) {

    // вычисление кода для следующего полюса N= Rx * 1023 / (Ro + Rx)
    codEndPol = (int)(((float)sensTable[p+1][1] * 1023.) / (RO + (float)sensTable[p+1][1]) + 0.5) - MIN_ADC ;               
    codToTempTable[codEndPol] = sensTable[p+1][0];  // температура для следующего полюса

    // вычисление коэффициента для отрезка
    koeff = (float)(sensTable[p+1][0] - sensTable[p][0]) / (float)(codEndPol - codBeginPol);

    // интерполяция температуры
    for ( int n = codBeginPol; n < codEndPol; n++ ) {
      codToTempTable[n]= sensTable[p][0] + (int)((float)(n - codBeginPol) * koeff +0.5 );
    }
    codBeginPol=codEndPol;   
  }   
}

void loop() { 

  if ( flagTempReady == true ) {
    flagTempReady= false;
    // данные готовы

    // вычисление температуры
    temperature = (int)((float)avarageTemp / 500. + 0.5);

    // проверка диапазона
    if (temperature < MIN_ADC) temperature= MIN_ADC;
    if (temperature > MAX_ADC) temperature= MAX_ADC;

    // выборка готового значения из массива
    temperature= codToTempTable[temperature - MIN_ADC];
   
    // вывод температуры на индикатор
    if (temperature >= 0) {
      // температура положительная
      disp.digit[3]= 0; // минус не светится
      disp.print((int)(temperature), 3, 1);  
    }
    else {
      // температура отрицательная
      disp.digit[3]= 0x40;  // отображается минус
      disp.print((int)(temperature * -1), 3, 1);        
    }
           
    // передача температуры на компьютер
    Serial.println(temperature);   
    }       
}

//-------------------------------------- обработчик прерывания 2 мс
void  timerInterrupt() {
  disp.regen(); // регенерация индикатора

  // измерение среднего значения темпрературы
  timeCount++;  // +1 счетчик выборок усреднения
  sumA0+= analogRead(A0);  // суммирование кодов канала A0 АЦП

  // проверка числа выборок усреднения
  if ( timeCount >= MEASURE_PERIOD ) {
    timeCount= 0;
    avarageTemp= sumA0; // перегрузка среднего значения
    sumA0= 0;
    flagTempReady= true;  // признак готовности результата
    } 
}

Загрузить скетч программы Ардуино термометр.

Должны быть подключены библиотеки Led4Digits.h  и MsTimer2.h. Загрузить библиотеки можно из урока 20 и урока 10.

Вычисление температуры по характеристике датчика , заданной таблицей.

Итак, у нас есть таблица зависимости сопротивления датчика от температуры. Она взята из материалов по этой ссылке.

Температура, °C Сопротивление, Ом
-55 490
-50 515
-40 567
-30 624
-20 684
-10 747
0 815
10 886
20 961
25 1000
30 1040
40 1122
50 1209
60 1299
70 1392
80 1490
90 1591
100 1696
110 1805
120 1915
125 1970
130 2023
140 2124
150 2211

Зависимость задана в виде 24 точек (полюсов) с разным шагом 5 или 10 °C.  Нам надо из кода АЦП вычислить температуру. Для вычисления значений между полюсами характеристики следует использовать линейную интерполяцию, т.е. соединить точки отрезками прямой.

В графическом виде интерполированная характеристика датчика KTY81/120 выглядит так.

Характеристика KTY81/120

Для вычисления температуры можно сделать следующую последовательность действий:

  • считать код АЦП;
  • вычислить сопротивление;
  • перебрать полюса характеристики и определить, в какой отрезок попадает измеренное сопротивление;
  • по линейной зависимости между полюсами более точно вычислить температуру.

Но такой способ очень сложный и медленный. Сделаем другим способом – заранее рассчитаем значения температуры для каждого значения АЦП.

В разделе об измерении сопротивления мы вычислили, что рабочий диапазон датчика в кодах АЦП 132 … 410, т.е. 279 значений. Нам надо рассчитать соответствие температуры каждому коду в этом диапазоне (132 … 410).

Предварительный расчет значений температуры происходит один раз, при запуске программы в функции setup(). В результате формируется массив

int codToTempTable[MAX_ADC - MIN_ADC +1];  // таблица преобразования код в температуру

Теперь для вычисления измеренной температуры достаточно считать значение температуры из этого массива по адресу – коду АЦП.

// выборка готового значения из массива    
temperature= codToTempTable[temperature - MIN_ADC];

Простая, быстрая операция.

Лучший вариант рассчитать массив codToTempTable[] заранее программой верхнего уровня и использовать его, как инициализированный массив с модификатором const. Тогда в программе Ардуино предварительных расчетов для температуры вообще не будет. Но я предпочел рассчитать его в программе микроконтроллера для наглядности.

Несколько слов об отладке программы. Вычисления довольно сложные, легко совершить ошибку. Поэтому я сделал две проверки:

  • При формировании массива codToTempTable[] через последовательный порт я вывел на компьютер таблицу со значениями код, полюс, коэффициент, температура. Значение температуры в полюсах сравнил с табличными и убедился, что между полюсами значения монотонные и примерно равномерные.
  • В программе временно отключил АЦП и задал имитацию изменения кода на единицу раз в секунду. С помощью регистратора программы Thermometer убедился, что изменение значения температуры монотонное.

 

Работа Ардуино термометра-регистратора в составе с компьютером.

В автономном режиме термометр отображает значение температуры на LED индикаторах. При подключении к устройству компьютера можно наблюдать измеренную температуру  с помощью монитора последовательного порта Arduino IDE или программы верхнего уровня Thermometer.

Окно программы верхнего уровня

Это программа из предыдущего урока. Загрузить ее можно по этой ссылке. В уроке подробно рассказано об установке и работе с программой Thermometer.

Напомню, что программа, кроме индикации температуры, выполняет функцию регистратора температуры с временной дискретностью 1 секунда.

Диаграмма температуры

Диаграмма температуры

Описанный принцип измерения температуры с помощью кремниевых датчиков KTY81/120 вполне применим для других типов датчиков с нелинейным сопротивлением.

 

В следующем уроке научимся работать с датчиком температуры DS18B20, разработаем термометр с этим датчиком.

Предыдущий урок     Список уроков     Следующий урок

9 комментариев на «Урок 25. Кремниевые термодатчики серии KTY81 в системе Ардино. Проект термометра-регистратора.»

  1. Спасибо Вам за уроки, очень познавательно.
    Я использую 3х разрядный 7 сегментный led индикатор. Интересует как зажечь точку и указать десятые доли температуры?

    • Спасибо.
      Принцип вывода дробных значений на индикатор описывается в уроке 20. И есть примеры в уроках 24 и 26.

      • Точку я зажег, но теперь в десятых всегда горит 0, как понимаю округление до целых?

        • А откуда дробная часть появится, если программа для этого датчика вычисляет в целых. В уроках 24 и 26 температура вычисляется в формате с дробной частью. Там дробная часть и отображается.

          • Значит дробную часть не вывести с этим датчиком?

          • Можно вывести. Но нужны другие вычисления и для этого датчика практически не имеет смысла. У него невысокая точность и дробная часть практической информации иметь не будет. Посмотрите урок 26. Там датчик точный и термометр показывает дробную часть.
            Павел, если Вас какой-нибудь вопрос интересует подробно, открывайте тему на форуме сайта. Это просто.

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

  3. Добрый день, спасибо за уроки.
    Необходимо упомянуть ещё об одном существенном недостатке терморезисторов — внесение погрешности измерительным током (происходит доп. нагрев терморезистора от рассеиваемой им мощности). При выбранных вами номиналах это ощутимо. Обычно выход — выбор номиналов в сотни кОм, но это ухудшает помехозащищённость, особенно актуально при длинных шлейфах.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *