Измеряем температуру без АЦП

Стояла как-то задача оснастить одну систему кучей термодатчиков. Причём оснастить максимально недорого.

Результаты изысканий (которые, по-моему, получились довольно изящными) предлагаю к рассмотрению в этой статье.

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

Давайте сперва перечислим некоторые особенности/требования измерений температуры:

Инерционность

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

Каким бы устройством мы ни управляли, будь то система управления холодильником или система, детектирующая перегрев какого-то элемента, скорость измерения температуры вряд ли будет критична. Измеряем температуру за 0.0001 секунды, или за 0.1 секунду, или даже (для многих случаев подойдёт) за 10 секунд - не так уж и важно.

Потребителя скорее будет интересовать точность измерения температуры, нежели скорость.

Помехоустойчивость

Зачастую проводники до термодатчика имеют довольно большую длину. Работающие рядом устройства создают набор помех/наводок. Требуется максимально нивелировать влияние помех на точность измерений.

Если учитывать предыдущую особенность (инерционность), то тут проблем обычно больших нет: в цепи измерения включают сильное интеграционное звено (например, конденсатор), которое нивелирует влияние помех.

Итого

Задачу нам надо решить:

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

Последние два пункта частично снимают (а не накладывают) ограничения на выбранные способы решения.

Например, не требуется скоростной АЦП.

Традиционные способы измерения

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

Датчик нагревается, его сопротивление увеличивается (или уменьшается).

Как можно измерить сопротивление термодатчика с помощью микроконтроллера?

Подключить его к прецизионному источнику тока и измерить полученное напряжение при помощи АЦП:

Вычислить сопротивление терморезистора можно по формуле:

Либо подключить его к прецизионному источнику напряжения с использованием дополнительного эталонного резистора и так же измерить полученное напряжение при помощи АЦП:

Вычислить сопротивление терморезистора можно по формуле:

Второй способ - наверное, самое дешёвое решение при наличии АЦП. Да, формула получилась нелинейной. Учитывая то, что скорость измерений нас не сильно волнует, скорость вычисления формул - тоже.

Какие тут недостатки?

  1. Из-за нелинейности во втором случае и начального сопротивления в обоих, диапазон измерения АЦП будет неполным. Измеряемый диапазон напряжений будет меньше диапазона АЦП. Вероятнее всего, в разы. То есть, 10 разрядный АЦП даст точность в 9 или 8 разрядов, а вычисления ещё больше её уменьшат.
  2. Требуется “дорогой” АЦП, который в случае множества термодатчиков надо переключать между ними. То есть, ещё и дорогой аналоговый мультиплексор.
  3. Требуется прецизионный источник тока или напряжения.

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

Часто этот операционный усилитель, резисторный мост, источник тока и сам термодатчик объединяют в одно целое и получается очень удобный в использовании датчик, но… дорогой. Если бы нам это решение подходило, то и незачем бы было писать эту статью.

Рефлексируем

Предположим, что у нас нет в наличии прецизионного источника тока/напряжения. Можем ли мы как-то измерить сопротивление термодатчика с приемлемой точностью?

Можем. Например, сравнивая сопротивление датчика с сопротивлением, заранее известным. Берём один источник тока и переключаем между двумя сопротивлениями, эталонным и измеряемым:

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

Итоговое сопротивление можно вычислить примерно так:

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

Тут пока мы имеем удорожание (вместо одного АЦП требуется пара), но зато у нас получился новый метод измерения, основанный на сравнении с эталоном.

Сравнение с эталоном позволяет нам отказаться от прецизионности источника тока (напряжения), заменив её прецизионностью эталонного сопротивления.

Откажемся от АЦП

Если у нас нет АЦП, какие варианты измерения сопротивления можно придумать?

Мы можем, например:

  1. Собрать RC-генератор с использованием нашего термосопротивления и измерить частоту выдаваемых им колебаний.
  2. Зарядить эталонный конденсатор C через наше термосопротивление и измерить время заряда.

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

Недостаток: Для точного измерения требуется точное знание ёмкости конденсатора, который будет использован в этой системе.

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

Осталось выбрать, каким путём идти: первым или вторым?

Очевидно, что вторая дорога в микроконтроллерном применении более проста в реализации:

  1. В среднем современном микроконтроллере есть входы с уровнями (триггером) Шмитта (но даже если и нет, то система будет работать и без них).
  2. В среднем современном микроконтроллере есть система, с помощью которой можно измерить интервал времени между событиями (таймер).

Итого, у меня получилась примерно такая схема измерительной части (Вход Шмитта и выходы логических элементов с 3 состояниями - это входы/выходы микроконтроллера):

Алгоритм измерения

  1. Начальное состояние: конденсатор разряжен, все выходы (PORT1-PORTx, PORTe) с Z состоянием выдают логический ноль.
  2. Переводим все выходы в состояние Z.
  3. Переводим выход PORTe в состояние логической единицы, начав одновременно с этим отсчёт времени (заряжаем конденсатор через эталонный резистор).
  4. Когда конденсатор зарядится до порогового уровня, сработает прерывание. В обработчике прерывания запомним, сколько тактов таймера занял заряд конденсатора через эталонный резистор - число Ne.
  5. Разрядим конденсатор снова, включив все выходы в состояние логического нуля.
  6. Далее зарядим конденсатор через первый термодатчик - получим измерение Nt1.
  7. Вычислим сопротивление терморезистора исходя из формулы:

Повторим предыдущие (5, 6 и 7) пункты для всех остальных термодатчиков.

Итого

Для измерений N температур нам требуется:

  1. N + 1 выходов с тремя состояниями (полно в любом микроконтроллере).
  2. Один вход прерывания с уровнями Шмитта (требование уровней Шмитта нестрогое, но они есть сейчас в среднем CPU, почему бы не использовать).
  3. Один эталонный резистор.
  4. Конденсатор.

Критерий выбора ёмкости конденсатора.

В общем и целом - чем больше, тем лучше (тем большую точность измерений можно получить).

Конденсатор тут является и средством сглаживания помех (интегрирующее звено), и участником измерений.

Я использовал танталовый конденсатор 100мкф. Но в целом можно строить измерения на любых конденсаторах в диапазоне 0.1 мкФ - 1000 мкФ. С маленьким конденсатором при том же сопротивлении скорость измерения будет выше, но и тактовая частота таймера нужна выше (чтобы получить достаточную точность измерений).

При конденсаторе 100мкФ, при измеряемых сопротивлениях 3-30кОм у меня получились 12-24 разрядные числа отсчётов измерений (использовался 8-битный аппаратный таймер контроллера AVR и ещё 16-битный счётчик переполнений).

Суммарно при таких параметрах получается выполнять 2-5 измерений в секунду. На опрос 16 термодатчиков требуется несколько секунд.

Примечания

  1. Можно проводить измерения и на заряде, и на разряде конденсатора. Это увеличит скорость измерений вдвое. Но надо и эталон обмерять в обоих направлениях.
  2. Если системе требуется много термодатчиков, то разряжать конденсатор можно через все датчики сразу. Это ускорит подготовку нового измерения (я использовал этот вариант).
  3. Если в систему внести этап “подстройки”, то эталонный резистор может быть не прецизионным: берём любой резистор (главное, чтобы у него не было температурной зависимости), затем вводим программную коррекцию погрешности.
  4. Вычисления лучше всего проводить не в обработчике прерываний, а в фоне. То есть в результате работы системы измерений получаем пары чисел Ne-Nt. Фоновая программа, уже делая умножение/деление, приводит их к омам сопротивления или прямо к градусам.
  5. В предложенную схему довольно просто добавить гальваническую развязку и значительно повысить помехоустойчивость и безопасность.

Итог

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