Измерение температуры при помощи NTC термистора и микроконтроллера AVR


Автор: Погребняк Дмитрий

Самара, 2013.


Click here to read this article in English.


Одним из вариантов для измерения температуры является использование термисторов. Среди преимуществ термистора можно выделить большое значение температурного коэффициента, то есть значительное изменение сопротивления в зависимости от температуры (порядка 2-10% на Кельвин). Термисторы бывают двух типов: с положительным температурным коэффициентом (PTC, Positive Temperature Coefficient), то есть увеличивающие своё сопротивление с увеличением температуры, и с отрицательным (NTC, Negative Temperature Coefficient) – уменьшающие сопротивление с возрастанием температуры. Речь в данной статье пойдёт про вторые, и про их использования для измерения температуры в сочетании с микроконтроллерами AVR


Характеристика NTC термистора

Термисторы характеризуются рядом параметров, такими, как максимальный допустимый ток, точность, сопротивление при определённой температуре (как правило, при 25°С). Одним из параметров, характеризующим степень изменения сопротивления в зависимости от температуры является коэффициент температурной чувствительности, обозначаемый B. Этот коэффициент рассчитывается на основе значений сопротивления при двух конкретных значениях температур. Во многих случаях этими температурами выбираются 25°С и 100°С. Обычно температуры, использованные при вычислении коэффициента указываются после буквы, например B25/100. Коэффициент B измеряется в Кельвинах и вычисляется по следующей формуле:

B = (ln(R1) – ln(R2)) / (1 / T1 - 1 / T2) [1],

где R1 и R2 - значения сопротивлений при температурах соответственно T1 и T2, выраженных в Кельвинах.

Из этой формулы следуют и обратные:

R1 = R2 * e(B * (1 / T1 - 1 / T2)) [2].

и

T1 = 1 / ((ln(R1) – ln(R2)) / B + 1 / T2) [3].


Вычисление температуры

Термисторы обладают высокой степенью нелинейности параметров, и термисторы различных моделей, даже при одинаковых значениях параметра B25/100 могут по разному изменять сопротивление в зависимости от температуры. Поэтому формула [3] может лишь приблизительно оценить температуру. Кроме того, такая формула подразумевает сложные вычисления, которые требуют много процессорного времени, что часто является неприемлемым. Более простым и эффективным подходом является хранение таблицы, в которую заносятся предварительно рассчитанные значения, возвращаемые АЦП при тех, или иных температурах. Для экономии памяти можно хранить значения только для некоторых точек, искать их в таблице двоичным поиском, а промежуточные значения получать линейной интерполяцией. Для измерений температуры окружающего воздуха с точностью до 0.3°C, достаточно хранить значения с шагом 5°C. Если значения лежат в пределах 16 бит (и занимают 2 байта), то для хранения такой таблицы для диапазона измеряемых температур от -30 до 70 градусов потребуется всего 40 байт. Точность измерений можно повысить, уменьшив шаг таблицы. Так при шаге 2°C можно добиться точности до 0.1°C на широком диапазоне измерений.


Производители термисторов, как правило, приводят таблицы показывающие изменение сопротивления в зависимости от температур. Значения в этих таблицах также привязаны к сетке температур с некоторым шагом (например, 5°C). Используя формулы [1] и [2] можно с достаточной точностью интерполировать табличные значения.


Схемы подключения

Подключение термистора

Схема A
Схема A
Схема B
Схема B
Схема C
Схема C
Схема D
Схема D

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

Выбирая номиналы RA и термистора, следует учесть, что протекающий через термистор ток вызывает его нагрев и, как следствие, искажение показаний. Желательно чтобы мощность на термисторе не превышала 1 мВт. А значит, при напряжении U0 = 5В, RA должен быть как минимум, 10 килоОм. Сопротивление термистора в измеряемом диапазоне должно иметь примерно тот же порядок.


Схема B призвана ограничить мощность, рассеиваемую на термисторе.


Схемы C и D являются обратными к A и B. Их имеет смысл использовать, если требуется измерять низкие температуры, когда референтное значение АЦП (Uref) ниже U0.


Подключение к АЦП микроконтроллера ATmega

Подключение АЦП микроконтроллеров ATmega
Подключение АЦП микроконтроллеров ATmega

У контроллеров ATmega для снижения шумов используется отдельная линия питания для модуля АЦП. Инструкция рекомендует подключать эти входы через фильтр: индуктивность L = 10мкГн, и конденсатор C2 = 0,1мкФ.

Микроконтроллер может использовать либо внешнее референтное напряжение для АЦП, либо внутреннее (2,56В или 1,1В), либо, в качестве такового, использовать напряжение питания АЦП: AVCC. При использовании внешнего напряжения, оно должно быть подано на вход AREF. При использовании AVCC, или внутреннего напряжения 2,56В, между этим входом и землёй должен быть размещён конденсатор (на схеме C1). Инструкция не даёт чёткого указания для выбора ёмкости конденсатора, рекомендую использовать керамический конденсатор 0,1мкФ и более.


Для снижения измеряемых шумов, рекомендую термистор также подключать к фильтрованному напряжению параллельно AVCC, и настроить на использование этого напряжения в качестве референтного.

Дополнительно, для подавления шумов возникающих на линиях, можно установить конденсатор C3 в диапазоне 1-100нФ.


Следует учесть, что помимо модуля АЦП, вход AVCC запитывает также некоторые из портов ввода/вывода (как правило, на тех же выводах, что используются для АЦП). Использование этих портов на вывод и подключение к ним нагрузки может создать дополнительные шумы в работе АЦП.


Чтобы нивелировать шумы, возникающие на АЦП, рекомендую провести замеры несколько раз подряд и просуммировать полученные значения. В микроконтроллерах ATmega АЦП – 10-разрядный. Просуммировав результаты 64 подряд идущих измерений, результат остаётся в пределах 16-битного беззнакового целого, что не потребует дополнительной памяти для сохранения таблицы значений. При большем числе измерений также можно оставаться в пределах 16 бит, соответствующим образом сдвигая или деля результат.


Расчёт таблицы значений

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

Расчёт значений ведётся либо по двум значениям температур и сопротивлений, либо вводится списком, либо используется одна из предзагруженных R/T характеристик. В настоящее время загружены R/T характеристики термисторов фирмы Siemens/EPCOS. Выберите подходящую из списка.

Загруженные характеристики даны с шагом 5°С, при выборе меньшего шага сетки, значения получаются путём интерполяции по формулам [1] и [2] двух ближайших значений из таблицы.

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


Внимание! Так как параметры термисторов в значительной мере нелинейны, расчёт по двум значениям сопротивлений, либо по значению и коэффициенту будет очень приблизительным. Вычисленное значение температуры при измерении высоких, или низких температур в таком случае может значительно (на десятки градусов) отличаться от актуальной.

Чтобы узнать подходящий тип R/T характеристики для вашего термистора, скачайте документацию, данную заводом изготовителем.

Сводная таблица для некоторых моделей термисторов Siemens/Epcos приведена ниже. Нажмите на код R/T характеристики, чтобы подгрузить параметры в форму ниже:

КодСопротивление при 25°С, кОмR/T характеристикаB25/100, К
B57891S, выводной 4,5мм (datasheet, pdf)
B57891S0222+0082,210083560
B57891S0502+008520033980
B57891S0103+0081049013950
B57891S0203+0082029044300
B57891S0104+00810040034450

B57891M, выводной 3,5мм (datasheet, pdf)
B57891M0102+000110093930
B57891M0152+0001,510083560
B57891M0222+0002,210133900
B57891M0332+0003,320033980
B57891M0472+0004,720033980
B57891M0682+0006,820033980
B57891M0103+0001049013950
B57891M0153+0001520044100
B57891M0223+0002229044300
B57891M0333+0003329044300
B57891M0473+0004740124355
B57891M0683+0006840124355
B57891M0104+00010040034450
B57891M0154+00015020054600
B57891M0224+00022020054600
B57891M0334+00033020074830
B57891M0474+00047020065000

B57164K, выводной 5,5мм (datasheet, pdf)
B57164K0471+0000,4713063450
B57164K0681+0000,6813073560
B57164K0102+000110113730
B57164K0152+0001,510133900
B57164K0222+0002,210133900
B57164K0332+0003,340013950
B57164K0472+0004,740013950
B57164K0682+0006,829034200
B57164K0103+0001029044300
B57164K0153+0001510144250
B57164K0223+0002210124300
B57164K0333+0003310124300
B57164K0473+0004740034450
B57164K0683+0006820054600
B57164K0104+00010020054600
B57164K0154+00015020054600
B57164K0224+00022020074830
B57164K0334+00033020065000
B57164K0474+00047020065000

B57540G, выводной, стеклянный "капля" 0,8мм (datasheet, pdf)
B57540G0502+000, +002584023497
B57540G1103+000, +0021083073492
B57540G1103+005, +0071070033625
B57540G0203+000, +0022084154006
B57540G1303+005, +0073070023988
B57540G0503+000, +0025084034006
B57540G1104+000, +00210083044092
B57540G0234+000, +00223084054264
B57540G0145+000, +002140084064581

B57551G, выводной, стеклянный "капля" 1,8мм (datasheet, pdf)
B57551G0202+000, +002284013436
B57551G1103+000, +0021083073492
B57551G1103+005, +0071070033625
B57551G1303+005, +0073070023988
B57551G1104+000, +00210083044092

B57621С5, SMD 3,2х1,6мм (datasheet, pdf)
B57621C5102+0621,032063450
B57621C5472+0624,713093520
B57621C5103+0621010103530
B57621C5153+0621510083560

B57621С0, SMD 3,2х1,6мм (datasheet, pdf)
B57621C0222+0622,213083060
B57621C0332+0623,313093520
B57621C0472+0624,713093520
B57621C0103+0621010103530
B57621C0153+0621510083560
B57621C0223+0622210083560
B57621C0333+0623320033980
B57621C0473+0624720013920
B57621C0683+0626820013920
B57621C0104+06210049013950
B57621C0154+16215029034200
B57621C0224+06222029034200
B57621C0334+06233010144250
B57621C0474+06247010144250

B57703M, выводной 10мм, с "ухом" 8,5x3,7мм (datasheet, pdf)
B57703M0502G040580163988
B57703M0103G0401080163988
B57703M0303G0403080183964

Форма для он-лайн расчёта значений АЦП

Данные для таблицы
*Из-за нелинейности параметров термистора, расчёт температуры на основе таблицы, построенной по двум точкам, будет грубым и полученное значение может на десятки градусов отличаться от действительного при измерении высоких и низких температур. Для точного измерения в широком диапазоне выберите одну из предзагруженных R/T характеристик, соответствующую вашему термистору, или перечислите список значений R/R1 вручную.
T1 °С
R1, cопротивление при T1 килоОм
T2 °С
R2, сопротивление при T2 килоОм
Данные для таблицы:R/R1
начиная с T2, с выбранным шагом сетки.
Разделитель значений - запятая.
BT1/T2 K
Схема включения термистора
Номинал резистора RA килоОм
Номинал резистора RB килоОм
Разрядность АЦП
Множитель результата АЦП
U0, напряжение на входе В
Uref, референтное напряжение АЦП В
Рассчитать с °С по  °С
Шаг сетки
T,°СR/R1R,килоОмU,ВI,мкАP,мВтU/UrefADCE,°С

Пояснения к таблице:

жирным выделены значения R/R1 и R, полученные на основе табличных. Обычным шрифтом обозначены значения полученные интерполяцией или экстраполяцией по формулам.

ADC – округлённое значение на выходе АЦП, с учётом множителя. Значения, выходящие за предел измерений АЦП, не отображаются.

I,мкА - ток в цепи.

P,мВт - мощность, рассеиваемая на термисторе.

E – эвристическая оценка возможной погрешности вычисленной температуры, вызванной использованием линейной интерполяции табличных значений, и ограниченной точностью АЦП. Позволяет выбрать параметры и схему включения таким образом, чтобы в области измеряемых значений погрешность была минимальна. Эта оценка не учитывает возможный шум, возникающий на АЦП, а также погрешность, вызванную нагревом термистора из-за протекающих токов. Погрешность можно уменьшить выбрав меньший шаг таблицы, используя АЦП большей разрядности, или путём усреднения большего числа измерений, а также подбором номиналов сопротивлений в цепи.


Код, соответствующий таблице

#include <avr/io.h>
#include <avr/pgmspace.h>

// Значение температуры, возвращаемое если сумма результатов АЦП больше первого значения таблицы
#define TEMPERATURE_UNDER 0
// Значение температуры, возвращаемое если сумма результатов АЦП меньше последнего значения таблицы
#define TEMPERATURE_OVER 0
// Значение температуры соответствующее первому значению таблицы
#define TEMPERATURE_TABLE_START 0
// Шаг таблицы 
#define TEMPERATURE_TABLE_STEP 50

// Тип каждого элемента в таблице, если сумма выходит в пределах 16 бит - uint16_t, иначе - uint32_t
typedef uint16_t temperature_table_entry_type;
// Тип индекса таблицы. Если в таблице больше 256 элементов, то uint16_t, иначе - uint8_t
typedef uint8_t temperature_table_index_type;
// Метод доступа к элементу таблицы, должна соответствовать temperature_table_entry_type
#define TEMPERATURE_TABLE_READ(i) pgm_read_word(&termo_table[i])

/* Таблица суммарного значения АЦП в зависимости от температуры. От большего значения к меньшему
   Для построения таблицы использованы следующие парамертры:
*/
const temperature_table_entry_type termo_table[] PROGMEM = {
  0 // Нажмите "Построить  таблицу" на форме выше, чтобы заполнить этот массив
};

// Функция вычисляет значение температуры в десятых долях градусов Цельсия
// в зависимости от суммарного значения АЦП.
int16_t calc_temperature(temperature_table_entry_type adcsum) {
  temperature_table_index_type l = 0;
  temperature_table_index_type r = (sizeof(termo_table) / sizeof(termo_table[0])) - 1;
  temperature_table_entry_type thigh = TEMPERATURE_TABLE_READ(r);
  
  // Проверка выхода за пределы и граничных значений
  if (adcsum <= thigh) {
    #ifdef TEMPERATURE_UNDER
      if (adcsum < thigh) 
        return TEMPERATURE_UNDER;
    #endif
    return TEMPERATURE_TABLE_STEP * r + TEMPERATURE_TABLE_START;
  }
  temperature_table_entry_type tlow = TEMPERATURE_TABLE_READ(0);
  if (adcsum >= tlow) {
    #ifdef TEMPERATURE_OVER
      if (adcsum > tlow)
        return TEMPERATURE_OVER;
    #endif
    return TEMPERATURE_TABLE_START;
  }

  // Двоичный поиск по таблице
  while ((r - l) > 1) {
    temperature_table_index_type m = (l + r) >> 1;
    temperature_table_entry_type mid = TEMPERATURE_TABLE_READ(m);
    if (adcsum > mid) {
      r = m;
    } else {
      l = m;
    }
  }
  temperature_table_entry_type vl = TEMPERATURE_TABLE_READ(l);
  if (adcsum >= vl) {
    return l * TEMPERATURE_TABLE_STEP + TEMPERATURE_TABLE_START;
  }
  temperature_table_entry_type vr = TEMPERATURE_TABLE_READ(r);
  temperature_table_entry_type vd = vl - vr;
  int16_t res = TEMPERATURE_TABLE_START + r * TEMPERATURE_TABLE_STEP; 
  if (vd) {
    // Линейная интерполяция
    res -= ((TEMPERATURE_TABLE_STEP * (int32_t)(adcsum - vr) + (vd >> 1)) / vd);
  }
  return res;
}

Пример использования

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

Описание работы с индикатором смотрите в другой моей статье.

Вывод значения температуры на идникатор СС56-12GWA
Вывод значения температуры на идникатор СС56-12GWA


  ADMUX = 0b01000111; // референтное напряжение - Vcc, вход ADC7, реузультат по правому краю
  ADCSRA = 0b10000111; // 1/128 делитель частоты, включение АЦП

  while(1)  {
    temperature_table_entry_type summ = 0;
    for (uint8_t i = 0; i < 64; i++) {
      ADCSRA |= _BV(ADSC);
      loop_until_bit_is_clear(ADCSRA, ADSC);
      summ += ADC;
    }
    int16_t t = calc_temperature(summ);
    ledind_num(t, 1, 0b01010011); // Вывод значения на индикатор с префиксом в виде буквы t
    _delay_ms(250);
  }




0 ms; mod: Sat, 06 May 2017 20:41:51 GMT; gen: Tue, 24 Oct 2017 05:33:47 GMT