Измеряем температуру без АЦП
Стояла как-то задача оснастить одну систему кучей термодатчиков. Причём оснастить максимально недорого.
Результаты изысканий (которые, по-моему, получились довольно изящными) предлагаю к рассмотрению в этой статье.
В данной статье разбираются контактные способы измерения температур в системах с микроконтроллером.
Давайте сперва перечислим некоторые особенности/требования измерений температуры:
Инерционность
В большинстве случаев температурные процессы сильно инерционны.
Следствие из этого в том, что скорость произведения повторных измерений, как правило, не сильно важна.
Каким бы устройством мы ни управляли, будь то система управления холодильником или система, детектирующая перегрев какого-то элемента, скорость измерения температуры вряд ли будет критична. Измеряем температуру за 0.0001 секунды, или за 0.1 секунду, или даже (для многих случаев подойдёт) за 10 секунд — не так уж и важно.
Потребителя скорее будет интересовать точность измерения температуры, нежели скорость.
Помехоустойчивость
Зачастую проводники до термодатчика имеют довольно большую длину. Работающие рядом устройства создают набор помех/наводок. Требуется максимально нивелировать влияние помех
на точность измерений.
Если учитывать предыдущую особенность (инерционность), то тут проблем обычно больших нет: в цепи измерения включают сильное интеграционное звено (например, конденсатор), которое нивелирует влияние помех.
Итого
Задачу нам надо решить:
- с минимальной стоимостью (требование)
- с мягкими требованиями к скорости измерений
- с максимальной помехоустойчивостью
Последние два пункта частично снимают (а не накладывают) ограничения на выбранные способы решения.
Например, не требуется скоростной АЦП.
Традиционные способы измерения
В рамках данной статьи рассмотрим способы измерения, где в качестве датчика используется термосопротивление.
Датчик нагревается, его сопротивление увеличивается (или уменьшается).
Как можно измерить сопротивление термодатчика с помощью микроконтроллера?
Подключить его к прецизионному источнику тока и измерить полученное напряжение при помощи АЦП:
Вычислить сопротивление терморезистора можно по формуле:
Либо подключить его к прецизионному источнику напряжения с использованием дополнительного эталонного резистора и так же измерить полученное напряжение при помощи АЦП:
Вычислить сопротивление терморезистора можно по формуле:
Второй способ — наверное, самое дешёвое решение при наличии АЦП.
Да, формула получилась нелинейной. Учитывая то, что скорость измерений нас не сильно
волнует, скорость вычисления формул — тоже.
Какие тут недостатки?
- Из-за нелинейности во втором случае и начального сопротивления в обоих, диапазон измерения АЦП будет неполным. Измеряемый диапазон напряжений будет меньше диапазона АЦП. Вероятнее всего, в разы. То есть, 10 разрядный АЦП даст точность в 9 или 8 разрядов, а вычисления ещё больше её уменьшат.
- Требуется «дорогой» АЦП, который в случае множества термодатчиков надо переключать
между ними. То есть, ещё и дорогой аналоговый мультиплексор. - Требуется прецизионный источник тока или напряжения.
Вопросы нелинейности и неполноты диапазона можно порешать, добавив в игру операционный усилитель и резисторный мост. Рассмотрение такой системы выходит за рамки данной статьи.
Часто этот операционный усилитель, резисторный мост, источник тока и сам термодатчик объединяют в одно целое и получается очень удобный в использовании датчик, но… дорогой. Если бы нам это решение подходило, то и незачем бы было писать эту статью.
Рефлексируем
Предположим, что у нас нет в наличии прецизионного источника тока/напряжения. Можем ли мы как-то измерить сопротивление термодатчика с приемлемой точностью?
Можем. Например, сравнивая сопротивление датчика с сопротивлением, заранее известным.
Берём один источник тока и переключаем между двумя сопротивлениями, эталонным и измеряемым:
Переключатель на схеме нарисован механическим для упрощения. Схема приведена для иллюстрации принципа действия.
Итоговое сопротивление можно вычислить примерно так:
От одной прецизионности избавились, несколько нагрузив CPU математическими вычислениями.
Тут пока мы имеем удорожание (вместо одного АЦП требуется пара), но зато у нас получился новый метод измерения, основанный на сравнении с эталоном.
Сравнение с эталоном позволяет нам отказаться от прецизионности источника тока (напряжения), заменив её прецизионностью эталонного сопротивления.
Откажемся от АЦП
Если у нас нет АЦП, какие варианты измерения сопротивления можно придумать?
Мы можем, например:
- Собрать RC-генератор с использованием нашего термосопротивления и измерить частоту выдаваемых им колебаний.
- Зарядить эталонный конденсатор C через наше термосопротивление и измерить время заряда.
Пока оставим за кадром реализацию обоих способов, сразу попытаемся указать на недостатки:
Недостаток: Для точного измерения требуется точное знание ёмкости конденсатора,
который будет использован в этой системе.
Как можно избавиться от точного знания ёмкости конденсатора? Так же, как в предыдущем случае мы избавлялись от необходимости иметь прецизионный источник опорного тока (напряжения): вместо одного измерения будем делать два и сравнивать с эталонным резистором.
Осталось выбрать, каким путём идти: первым или вторым?
Очевидно, что вторая дорога в микроконтроллерном применении более проста в реализации:
- В среднем современном микроконтроллере есть входы с уровнями (триггером) Шмитта (но даже если и нет, то система будет работать и без них).
- В среднем современном микроконтроллере есть система, с помощью которой можно измерить интервал времени между событиями (таймер).
Итого, у меня получилась примерно такая схема измерительной части (Вход Шмитта и выходы логических элементов с 3 состояниями — это входы/выходы микроконтроллера):
Алгоритм измерения
- Начальное состояние: конденсатор разряжен, все выходы (PORT1-PORTx, PORTe) с Z состоянием выдают логический ноль.
- Переводим все выходы в состояние Z.
- Переводим выход PORTe в состояние логической единицы, начав одновременно с этим отсчёт времени (заряжаем конденсатор через эталонный резистор).
- Когда конденсатор зарядится до порогового уровня, сработает прерывание.
В обработчике прерывания запомним, сколько тактов таймера занял заряд конденсатора через эталонный резистор — числоNe
. - Разрядим конденсатор снова, включив все выходы в состояние логического нуля.
- Далее зарядим конденсатор через первый термодатчик — получим измерение
Nt1
. - Вычислим сопротивление терморезистора исходя из формулы:
Повторим предыдущие (5, 6 и 7) пункты для всех остальных термодатчиков.
Итого
Для измерений N температур нам требуется:
- N + 1 выходов с тремя состояниями (полно в любом микроконтроллере).
- Один вход прерывания с уровнями Шмитта (требование уровней Шмитта нестрогое, но они есть сейчас в среднем CPU, почему бы не использовать).
- Один эталонный резистор.
- Конденсатор.
Критерий выбора ёмкости конденсатора.
В общем и целом — чем больше, тем лучше (тем большую точность измерений можно получить).
Конденсатор тут является и средством сглаживания помех (интегрирующее звено), и участником измерений.
Я использовал танталовый конденсатор 100 мкф. Но в целом можно строить измерения на любых конденсаторах в диапазоне 0.1 мкФ — 1000 мкФ. С маленьким конденсатором при том же сопротивлении скорость измерения будет выше, но и тактовая частота таймера нужна выше (чтобы получить достаточную точность измерений).
При конденсаторе 100 мкФ, при измеряемых сопротивлениях 3–30кОм у меня получились 12–24 разрядные числа отсчётов измерений (использовался 8-битный аппаратный таймер контроллера AVR и ещё 16-битный счётчик переполнений).
Суммарно при таких параметрах получается выполнять 2–5 измерений в секунду. На опрос 16 термодатчиков требуется несколько секунд.
Примечания
- Можно проводить измерения и на заряде, и на разряде конденсатора. Это увеличит скорость измерений вдвое. Но надо и эталон обмерять в обоих направлениях.
- Если системе требуется много термодатчиков, то разряжать конденсатор можно через все датчики сразу. Это ускорит подготовку нового измерения (я использовал этот вариант).
- Если в систему внести этап «подстройки», то эталонный резистор может быть не прецизионным: берём любой резистор (главное, чтобы у него не было температурной зависимости), затем вводим программную коррекцию погрешности.
- Вычисления лучше всего проводить не в обработчике прерываний, а в фоне. То есть в результате работы системы измерений получаем пары чисел Ne-Nt. Фоновая программа, уже делая умножение/деление, приводит их к омам сопротивления или прямо к градусам.
- В предложенную схему довольно просто добавить гальваническую развязку и значительно повысить помехоустойчивость и безопасность.
Итог
Предложенный метод похоже имеет минимальную из возможных аппаратную стоимость измерения температуры, высокую помехоустойчивость. Однако плата за это — необходимость выполнения некоторого количества математических действий микроконтроллером.