AVR-USB-MEGA16: измеряем и контролируем температуру Печать
Добавил(а) Сергей Кухтецкий   

В этой статье я хочу рассказать о двух небольших разработках, выполненных недавно в лаборатории проблем материаловедения Института химии и химической технологии СО РАН в Красноярске (www.icct.ru). Буду рад, если статья поможет сэкономить время и деньги кому-нибудь из моих коллег, решающих аналогичные проблемы.

Обе конструкции связаны с измерением и регулированием температурных режимов для лабораторных установок. В их основе лежит плата AVR-USB-MEGA16, которая выполняет следующие функции:

1. Программная реализация низкоскоростного USB для связи с ПК.
2. Аппаратная генерация сигналов ШИМ (Широтно-Импульсная Модуляция) для регулирования мощности нагревателей.
3. Программная реализация шины 1-Wire для обслуживания температурных датчиков DS18B20.
4. Аналого-цифровое преобразование сигналов с термопар.

Firmware в плате AVR-USB-MEGA16 спроектировано таким образом, что управление всеми необходимыми ресурсами микроконтроллера (инициализация портов, таймеров, ШИМ и т. п.) происходит со стороны хоста через класс-обертку ATMega16. Поэтому единственное firmware подходит для всех проектов ПО хоста, опубликованных в статье. 

Все проекты ПО хоста разработаны с использованием свободно доступной на сайте Microsoft среды разработки - Visual Studio 2008 Express Edition (подойдет также любая среда Visual Studio более свежей версии). Для работы с USB используется библиотека libusb-win32 [7]. Для построения графиков используется бесплатная библиотека zedGraph [9]. Все необходимые комментарии находятся в исходных файлах. Проекты и firmware, описываемые в статье, можно скачать по ссылке [8]. 

Устройства (или их фрагменты), представленные в данной статье, могут использоваться не только в физико-химической лаборатории, но и в быту. Например, системы типа «умный дом» - регулирование температуры в помещениях, недорогая реализация «хитрых» температурных режимов кухонной печи или духовки, водонагреватели и т.п. Другие примеры – моделирование естественных температурных режимов для обитателей аквариумов или растений в теплицах.

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

[Блок-схема устройств]

Первая разработка – программируемая водяная баня. Водяная баня – это просто водяной термостат, но в данной задаче температура термостата должна изменяться по некой задаваемой программе и иногда - весьма сложным образом. Мощность – до 1 кВт. Вторая разработка - печь для исследования реакций в сверхкритических флюидах. Температура – от 200oC до 400oC, но выходы на режимы и дальнейшее поведение температуры должно было регулироваться  по определенным законам, зависящим от процесса. Мощность – до 3 кВт.

По сути, проблема несложная – обычный температурный регулятор с компьютерным управлением. Различаются только датчики. В первом случае (водяная баня) решение очевидно – недорогие датчики DS18B20. В этом случае аппаратная реализации регулятора становится тривиальной задачей. Во втором случае (печь) я решил использовать термопары для измерения температуры в печи и те же датчики  DS18B20 для измерения температуры окружающей среды (и холодного спая термопары). Пара медь-константан вполне подходит для этого диапазона температур. Силовые блоки для регулирования мощности нагревателя различаются только маркой симисторов и размерами радиаторов для них.

Процессы медленные (минуты, десятки минут). Поэтому никаких особых требований к скорости электроники нет. Сам регулятор можно было бы реализовать на каком-нибудь несложном автономном микроконтроллере. Но в этом случае возникает непростая проблема пользовательского (приборного) интерфейса для программирования и протоколирования температурных режимов. Лучшее решение для таких вещей – все-таки персональный компьютер. Поэтому оптимальный вариант стенда для обеих задач мне представился таким (рис. 1). 
termreg01block-scheme.jpg

Рис. 1. Блок-схема регулятора

На долю персонального компьютера приходятся интерфейсные, сервисные функции и высокоуровневые функции управления температурой. На долю микроконтроллера платы AVR-USB-MEGA16 – низкоуровневые функции, перечисленные во введении: ШИМ, 1-Wire, АЦП и USB.

Начнем с силового блока.

[Силовой модуль]

Нагреватели питаются от сети переменного тока. Поэтому естественное решение для управления нагревом – фазовая регулировка мощности. Несложных схем тиристорных регуляторов в Сети много. Однако, можно еще упростить решение, если учесть инерционность нагревателя как нагрузки. В этом случае можно перейти к режиму регулирования мощности по количеству целых полупериодов, пропущенных в нагрузку. Для управления яркостью лампочек освещения (диммеров) это не пойдет, т.к. они будут сильно мигать, но для печек или водонагревателей – в самый раз. Единственная задача, возникающая при конструировании таких регуляторов, – синхронизация моментов отпирания симисторов или тиристоров с нулем сетевого напряжения. Можно было бы нагрузить на эту задачу микроконтроллер платы AVR-USB-MEGA16, но более изящное решение - использовать оптосимисторы с детекторами перехода через ноль (Zero Crossing). Например, MOC3061-MOC3063. Этот вариант и был положен в основу силового модуля.

Схема и конструкция

Схема силового модуля, взята непосредственно из datasheet на опторазвязки MOC3061-MOC3063 без изменений. Она приведена на рис. 2.
termreg02power-module-sch.jpg 

Рис. 2. Схема силового модуля

Токоограничивающий резистор Rin = 330 Ом для выбранной мною микросхемы MOC3061. Симистор – BT137-600 для бани, BT139-800 – для печки. Максимальный ток этого первого симистора в открытом состоянии - 8А, второго – 16А, так что моих этих задачи хватит с запасом. При подаче “0” на вход Vin, симистор откроется в ближайший момент прохождения нуля и нагрузка (нагреватель) будет подключена к сети. При подаче “1” – закроется и нагрузка от сети отключится.

На рис. 3 представлена конструкция силового модуля для водяной бани. Без радиатора симистор может работать на нагрузку 100-150 Вт.

ВНИМАНИЕ! Узлы этой схемы во время работы находятся под высоким напряжением. Поэтому соблюдайте правила электробезопасности при работе с этими устройствами в открытом виде. ПОДАВИТЕ в себе искушение потрогать симистор пальцем в процессе работы (нагрелся или еще не очень)!
termreg03power-module.jpg

Рис. 3. Конструкция силового модуля

Проверим работоспособность силового модуля самым простым способом. Подадим на Vcc (рис. 2) сигнал от генератора прямоугольных импульсов напряжением около 5 В, Vin – землю. В данной конструкции резистор Rin будет размещен на плате AVR-USB-MEGA16, поэтому на плате силового модуля разъем подключении непосредственно к ножке 1 микросхемы MOC3061. Следовательно, сигнал от генератора нужно подать на разъем через резистор 300-330 ом. В качестве нагрузки подключим лампочку 220 В мощностью до 100 Вт. Мне подвернулась под руку лампочка на 75 Вт. Частоту следования импульсов установим равную 1 Гц. Изменяя длительность импульсов (от 0 до 1 сек) мы можем менять длительность вспышек лампочки от нуля до постоянного свечения. На рис. 4 показан процесс такого испытания. В качестве генератора импульсов я использовал генератор, имеющийся в  USB-осциллографе PV6501 (светлая коробочка в правом верхнем углу снимка).
termreg04power-module-test.jpg

Рис. 4. Проверяем силовой модуль

Силовой блок успешно прошел испытания – идем дальше. Для подключения силового модуля к плате AVR-USB-MEGA16 нужно выполнить маленькую модификацию платы.

Модификация платы AVR-USB-MEGA16
Первая модификация платы AVR-USB-MEGA16 заключается во впаивании небольшого разъема (розетка на 2 гнезда) и резистора на 330 Ом. Вид модифицированной платы представлен на рис. 5.
termreg05avr-usb-mega16-changes01.jpg

Рис. 5. Модернизированная плата. Фрагмент для управления силовым модулем выделен красным

Схема подключения разъема показана на рис. 6. Эта и следующие модификации отмечены красным цветом. Данная модификация – правая на схеме сверху.
termreg06avr-usb-mega16-changes02.jpg

Рис. 6. Схема изменений и дополнений платы AVR-USB-MEGA16 (отмечено красным)

Разъем лучше сразу подключить к контакту P20 платы AVR-USB-MEGA16 (PD5 микроконтроллера ATMega16), т.к. именно с этого выхода мы впоследствии сможем взять сигнал аппаратного ШИМ.

Помигаем лампочкой через USB
Для проверки работы силового модуля от платы AVR-USB-MEGA16 напишем простейшее приложение, позволяющее включать или выключать лампочку. Программа называется Bulb. Проект приложения хоста для Visual Studio 2008 Express Edition находится в архиве «01 Управляем лампочкой по USB.zip» (см. ссылку [8]). Firmware для всех проектов этой статьи одно и то же и находится в архиве «00 Firmware.zip» (см. ссылку [8]). Hex-файл в этом архиве – прошивка для микроконтроллера платы AVR-USB-MEGA16. Прошиваем микроконтроллер. Подключаем к плате силовой модуль (с той же лампочкой на 75 Вт, что и в предыдущем эксперименте). Запускаем приложение хоста. Нажимая кнопку «Вкл/Выкл» в этом приложении мы можем включать и выключать лампочку через USB (см. рис. 7). Параллельно на плате AVR-USB-MEGA16 загорается и гаснет светодиод. 

termreg07lamp-control-USB.jpg

Рис. 7. Управление лампочкой через USB

Все работает. Силовая часть готова для построения простейшего позиционного (релейного) терморегулятора. Но перед этим нам нужно научиться измерять температуру. К этому и приступим.

[Работаем с датчиками температуры DS18B20]

Следующий этап разработки – очередная (вторая) модификация платы, необходимая для реализации шины 1-Wire. Она позволит нам измерять температуру при помощи недорогих датчиков фирмы Dallas Semiconductor - DS18B20. DS18B20 – это, по сути, готовый цифровой термометр с разрешением до 12 разрядов и способный обмениваться данными по шине 1-Wire. Рабочий диапазон температур  от -55oC до +125oC. Время оцифровки температуры для 12 разрядов около 750 мс.

Программная реализация шины 1-Wire

В шине 1-Wire всего один сигнальный провод. Его нужно «подтянуть» к +5В через резистор 4.7 кОм. Еще один провод – земля. В принципе, устройства, работающие на шине 1-Wire, могут использовать паразитное питание от сигнального провода, но в данной разработке мы используем отдельный провод для питания датчиков. Таким образом, модификация платы заключается в установке 6-гнездовой розетки (мы планируем использовать два датчика – по три гнезда на датчик) и подтягивающего резистора. На схеме (рис. 6) эта модификация отображена в центре сверху. Сигнальная линия шины 1-Wire подключен к разряду 1 порта B (PB1). На рис. 8 представлен  вид платы. Красным выделен фрагмент для работы с 1-Wire.
termreg08avr-usb-mega16-changes03.jpg

Рис. 8. Реализация 1-Wire для двух датчиков

Интерфейс 1-Wire достаточно хорошо описан в Сети (в том числе и программная реализация на микроконтроллерах AVR). Соответствующие фрагменты кода подробно прокомментированы в исходных файлах программного обеспечения firmware (см. файл «main.c» в архиве «00 Firmware.zip», ссылка [8]). Поэтому перейдем к работе с конкретными устройствами 1-Wire - температурными датчиками DS18B20.

Измеряем температуру при помощи датчиков DS18B20

Если низкоуровневая программная реализация шины 1-Wire выполнена на микроконтроллере платы AVR-USB-MEGA16, то работа с датчиками (DS18B20) реализована в приложении хоста. Во втором архиве (файл «02 Работаем с датчиками температуры.zip», см. ссылку [8]) находится пример программного обеспечения хоста (программа TempTest), обслуживающего несколько датчиков (до 16 в данном примере, но может быть и другое - просто константу DMAX в firmware я установил равную 16). Все термодатчики подключаются параллельно (у нас их будет максимум два), см. рис. 6.

Логика работы приложения следующая (см. файл Form1.cs). После запуска приложения и инициализации USB, запускается таймер timer1sec (в конце метода Form1_Load()). Каждую секунду этот таймер генерирует событие, которое обрабатывается в методе timer1sec_Tick(). В этом методе сначала определяется количество датчиков, подключенных к шине 1-Wire. Если на шине есть датчики, то всем им посылается команда начать оцифровать температуру. Время преобразования не превышает 750 мс. Поэтому после команды «начать преобразование» запускается второй таймер timer750ms. Через 750 мс этот таймер генерирует событие, при котором вызывается метод timer750ms_Tick(). В этом методе таймер timer750ms  выключается  и далее в цикле опрашиваются все датчики, подключенные к шине. Полученный двухбайтовый код температуры преобразуется в десятичное число со знаком и выводится на экран. Программа отслеживает наличие датчиков в каждом цикле. Поэтому датчики можно подключать и отключать в любой момент. Скриншот работающей программы показан на рис. 9. Первый датчик я положил на настольную лампу сверху, а второй показывает температуру в комнате.
termreg09temperature-measuring.jpg 

Рис. 9. Пример работы с несколькими датчиками

[Водяная баня]

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

Собираем экспериментальный стенд – модель водяной бани

Общий вид стенда представлен на рис. 10.
termreg10waterbath-model.jpg

Рис. 10. Стенд для отработки алгоритмов температурного регулятора

Мощность нагревателя составляет около 400 Вт, поэтому симистор силового блока нужно прикрепить к радиатору. Термометр термостата, представляет собой датчик DS18B20, помещенный в узкую пробирку с тонкими стенками, заполненную трансформаторным маслом для улучшения контакта с водой термостата. Второй датчик, измеряющий температуру окружающей среды, воткнут непосредственно в разъем шины 1-Wire на плате AVR-USB-MEGA16. Правильнее было бы поместить его где-нибудь вблизи наружной стенки термостата, но для данных тестов это не так существенно.

Реализуем простейший регулятор

Рассмотрим простейший алгоритм регулирования температуры, который называется позиционным или релейным. Суть этого алгоритма проста. Если текущая температура термостата меньше заданной величины (она называется «уставка»), то нагреватель включается (естественно, на полную мощность). Если температура сравнялась или превысила уставку – нагреватель сразу же выключается. В архиве «03 Простейший регулятор.zip» (см. ссылку [8]) представлен проект приложения, реализующего этот алгоритм.

Пример работы приложения показан на рис. 11. Температурный режим водяной бани запрограммирован следующим образом. Температура бани должна быть поднята до 80oC с шагом 20oC. На каждом шаге – прогрев в течении 20 мин. После прогрева на максимальной температуре – естественное охлаждение до 50oC и поддержание температуры на этом уровне до конца эксперимента. На графике по горизонтали отложено время с начала процесса в минутах, по вертикали – температура термостата в oC.
termreg11pos-reg-diagram01.jpg

Рис. 11. Работа бани с позиционным регулятором

Видно, что результат работы простейшего регулятора трудно назвать удовлетворительным. Видны заметные колебания температуры около точек равновесия, есть серьезные выбросы  температуры (почти на 5oC) после фронтов нагрева.

Причина плохой работы релейных регуляторов известна и довольно очевидна - тепловая инерция нагревателя. Действительно, как только температура термостата станет равна уставке, нагреватель выключится. Но, нагревателя имеет ненулевую теплоемкость, а его температура несколько выше температуры воды (иначе он просто не будет греть воду). Поэтому нагреватель какое-то время продолжает отдавать тепло в воду, несмотря на то, что он уже отключен от сети. И наоборот. Если температура воды станет меньше заданной - реле включает нагреватель. Но его температура уже сравнялась с температурой окружающей воды. Поэтому должно пройти некоторое время, пока температура нагревателя станет выше температуры воды и он начнет отдавать ей тепло.
Есть различные варианты исправления ситуации. Можно уменьшать инерцию нагревателя, вводить более сложные критерии включения/выключения регуляторов. Но все равно, радикально улучшить работу регулятора таким способом не удается. Можно уменьшить мощность нагревателя, но тогда увеличится время выхода термостата на заданный режим и тоже полностью удалить колебания не удается.

Один из наиболее действенных способов добиться цели – изменять мощность нагревателя в процессе регулирования температуры. В частности, линейно уменьшать ее при приближении температуры к заданному значению. Т. е. мощность нагревателя устанавливается пропорциональной разнице текущей температуры термостата и уставки. Поэтому такой регулятор называется «пропорциональным регулятором». Он действительно позволяет резко улучшить ситуацию. Но, прежде чем приступить к исследованию такого регулятора мы должны научиться плавно регулировать мощность нагрева.

Делаем ШИМ

ШИМ означает широтно-импульсную модуляцию (по-английски PWM - Pulse-Width Modulation). ШИМ сигнал – это прямоугольные импульсы, следующие с некоторой частотой, но длительность (т. е. ширину) этих импульсов мы можем изменять по нужному нам закону.

Силовой модуль в нашей системе управляется дискретно. Симистор закрыт, когда на вход модуля подается «1» (+5В) и открыт, когда «0», причем момент открытия симистора «привязан» к моменту прохождения питающего напряжения через 0. Поэтому, если мы возьмем достаточно длительный период повторения открывающих импульсов (например, 1 сек) и будем изменять их длительность, то мы будем регулировать количество пропущенных к нагрузке полуволн питающего напряжения, т. е. регулировать среднюю мощность, поступающую в нагрузку.

Например, при периоде 1 сек, мы сможем регулировать мощность с точностью 1% (в секунде как раз 100 полупериодов сети переменного тока 50 Гц). Как только длительность открывающего импульса станет больше 0.01 сек, каждую секунду в нагрузку будет подаваться 1 полупериод питающего напряжения и нагреватель будет работать с 1% мощностью от номинала. Как только ширина импульса превысит 0.02 сек, то к нагрузке будут проходить два полупериода каждую секунду и мощность возрастет до 2% от номинала и т.д. Когда длительность импульсов сравняется с периодом их следования, все 100 полупериодов будут поступать в нагрузку каждую секунду, и, следовательно, нагреватель будет работать с полной мощностью. Вот так все просто.

Реализовать ШИМ можно несколькими способами. Можно реализовать программно на микроконтроллере или на ПК. Но в этом случае мы можем столкнуться со сбоями в работе ШИМ, особенно при малых или больших скважностях импульсов. Это связано с тем, что и микроконтроллер и ПК должен выполнять еще некоторые функции (обмениваться данными по USB, осуществлять их преобразование, вывод на экран и т.д.) и они могут не успевать обработать все прерывания при коротких интервалах.

К счастью, в микроконтроллере ATMega16 есть возможность реализовать аппаратный ШИМ с регулируемой частотой следования импульсов и скважностью. Для исследования этой возможности разработаем небольшое приложение, которое представлено в архиве «04 Помигаем лампочкой при помощи ШИМ и USB.zip» (см. ссылку [8]). Для генерирования сигналов ШИМ используется таймер TIMER1 микроконтроллера. Его инициализация и настройка подробно прокомментирована в исходных файлах проекта ПО хоста (файл «Form1.cs») – это происходит с помощью класса-обертки Atmega16.

Испытаем наш ШИМ-генератор. К выходу платы AVR-USB-MEGA16, который служит для подключения силового блока, подключим силовой модуль с лампочкой 75 Вт (как мы делали в самом начале статьи). А можно и просто воткнуть в этот разъем светодиод или подключить осциллограф. Запустим приложение PWM.exe из указанного архива. Устанавливая различную величину мощности нагревателя, мы увидим, что лампочка или светодиод мигают с различной длительностью в зависимости от установленного значения. На рис. 12 представлена осциллограмма ШИМ-сигнала, полученного с выхода платы AVR-USB-MEGA16 (порт PD5 микроконтроллера).
termreg12PWM-testing.jpg

Рис. 12. Тестирование аппаратного ШИМ

Теперь мы можем приступить к созданию и изучению пропорционального регулятора.

Исследуем пропорциональный регулятор

Никаких аппаратных изменений по сравнению с позиционным регулятором не потребуется. Вся разработка сводится к написанию программы. В архиве «05 Пропорциональный регулятор.zip» (см. ссылку [8]) приведен проект приложения хоста для Visual Studio 2008 Express Edition. Все необходимые комментарии находятся в файле «Form1.cs».

Логика работы приложения следующая. При загрузке формы (метод Form1_Load()) создается объект dev класса ATMega16. В конструкторе этого класса происходит инициализация USB. Если с USB все в порядке, происходит инициализация рабочих переменных и запускается основной таймер программы timer1sec. Этот таймер генерирует события раз в секунду. В обработчике это события и происходит основная работа программы. Вернем к методу Form1_Load(). После запуска таймера timer1sec происходит настройка портов B и D и инициализация таймера Timer1 микроконтроллера ATMega16 для генерирования ШИМ-сигнала с регулируемой частотой и скважностью (управление настраиваемыми ресурсами микроконтроллера поддерживается firmware и классом-оберткой Atmega16). В оставшейся части метода Form1_Load() происходит инициализация библиотеки для построения графиков zedGraph. По событию Tick таймера timer1 вызывается метод timer1sec_Tick() в котором происходит измерение температуры и установка мощности нагревателя в зависимости от ситуации.

Измерение температур происходит следующим образом. Вначале определяется количество датчиков на шине 1-Wire. Если это количество не менее двух, то считается что первые два датчика участвуют в процессе (первый датчик измеряет температуру термостата, а второй – окружающей среды). Всем датчикам подается команда «начать преобразование» и включается таймер на 750 мс. По тику этого таймера произойдет считывание значений с датчиков и установка значений соответствующих переменных (см. метод timer750ms_Tick()). Параллельно продолжается работа метода timer1sec_Tick() – регулирование температуры (по их предыдущим значениям, полученным на секунду раньше).

Регулирование мощности нагревателя происходит просто. Определяется неувязка err, равная разности текущей температуры термостата и установленной (уставка). В зависимости от значения err устанавливается мощность нагревателя. Если невязка меньше 0, то греть не нужно, мощность устанавливается в 0. Если до желаемого значения далеко (т. е. невязка больше зоны пропорциональности), то мощность устанавливается в 100% от номинала. Если же мы находимся в зоне пропорциональности (т. е. недалеко от уставки), то мощность устанавливается пропорциональной невязке.

Вот, собственно, и вся логика. Пример работы водяной бани с той же программой прогрева, как и в случае позиционного регулятора показана на рис. 13. Мы видим, что никаких колебаний температуры уже нет.
 termreg13proportional-reg-daigram02.jpg

Рис. 13. Работа бани с пропорциональным регулятором

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

Но так ли уж все безоблачно для пропорционального регулятора? Если посмотреть внимательно вторую и третью «полочки» (60oC и 80oC на рис. 13), то мы видим, что равновесный уровень заметно ниже уставки (соответственно, 60oC и 80oC). На рис. 14 представлен увеличенный фрагмент. Видно, что систематическая ошибка на уровне 80oC составляет почти полтора градуса.
 termreg14proportional-reg-diagram03.jpg

Рис. 14. Иллюстрация систематической ошибки регулятора

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

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

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

Пропорциональный регулятор с компенсатором тепловых потерь

Этот алгоритм был реализован и опробован на этой же модели водяной бани. Изменения по сравнению с предыдущим кодом минимальные. Модифицированный проект находится в архиве «06 Пропорциональный регулятор с компенсатором потерь.zip» (см. ссылку [8]). Результат работы на той же программе тепловых режимов показан на рис. 15. Видно, что систематическая ошибка пропорционального регулятора скомпенсирована при значении коэффициенте компенсатора 0.2. Уменьшая этот коэффициент до 0 мы получим чисто пропорциональный регулятор. Поэтому его значение также нужно подбирать экспериментально в зависимости от конструкции термостата и мощности нагревателя.
termreg15proportional-reg-diagram04.jpg

Рис. 15. Работа пропорционального регулятора с компенсатором тепловых потерь

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

[Печь]

Для измерения температуры в печи датчики DS18B20 уже не подойдут (они работают только до 125oC). Температура печи не должна превышать 400oC. Поэтому можно использовать низкотемпературные термопары. Поскольку термопара выдает аналоговый сигнал – необходимо использовать АЦП (аналого-цифровой преобразователь). В микроконтроллере ATMega16 есть 10 разрядный АЦП. Он достаточно быстрый (около 100 мкс на 10 разрядов) и снабжен аналоговым мультиплексором на 8 каналов. Для данной задачи вполне подойдет. Единственная проблема – малая термо-ЭДС термопары. Например, для пары медь-константан это порядка 40-60 мкВ/градус. Т. е. при разнице температуры между горячим и холодным спаем 400 градусов, мы имеем ЭДС всего 16-20 мВ. Поэтому перед АЦП необходимо поставить усилитель.

Термопара

Итак, для измерения температуры в печи мы собираемся использовать термопару медь-константан, которая как раз работает до 400oC. Константан – это сплав меди с никелем. Поскольку один провод термопары медный мы можем обойтись всего двумя спаями, а измерительную цепь включить в разрыв медного провода. Холодный спай будет расположен на датчике DS18B20, который у нас измерял температуру окружающей среды, а горячий спай – непосредственно в печке. По измеренной ЭДС термопары мы можем определить разность температур горячего и холодного спая. Поскольку температуру холодного спая мы знаем (датчик DS18B20, рядом с которым находится холодный спай), то, следовательно, мы будем знать и абсолютную температуру в печке. Естественно, что термопару мы предварительно должны откалибровать.

Способов изготовления термопар много. Описания легко найти в Сети. Используемые материалы достаточно легкоплавкие и поэтому я просто сходил в институтскую стеклодувную мастерскую и попросил стеклодува спаять мне две проволочки при помощи горелки на очень узеньком кончике пламени. Проволочки я предварительно пропустил в стеклянные капилляры для электрической изоляции в высокотемпературной зоне.  В холодной зоне достаточно лаковой изоляции, которая была на проводниках. У стеклодува получились два маленьких аккуратных шарика-спая. В разрез медного провода я впаял небольшую вилку. Что вышло в конечном итоге - показано на рис. 16.
termreg16termopair.jpg

Рис. 16. Готовая термопара для отладочных экспериментов

Теперь займемся предварительным усилителем.

Усилитель

В целом, изготовление усилителя для термопары для лабораторных условий не представляет серьезной проблемы. Коэффициент усиления порядка 100-200, желательно минимальный дрейф и смещение. Сигналы медленные, поэтому сетевая наводка легко отфильтровывается. Существуют усилители специально для термопар с компенсатором холодного спая. Но целью данной работы было использование только недорогих и достаточно доступных компонентов.

Немного поэкспериментировав с однополярным 5-вольтовым питанием операционных усилителей, я разочаровался в своих способностях справиться с нулем при помощи подручных средств и имеющихся у меня корпусов, поэтому решил вернуться к двухполярному питанию. Положительные 5 вольт возьмем с платы AVR-USB-MEGA16, а отрицательные (почти 5 вольт) получим при помощи преобразователей напряжения на коммутируемых конденсаторах. У меня под рукой оказались микросхемы LMC7660. Они рассчитаны на выходной ток до 20 мА, т. е. вполне подойдут для питания одного маломощного усилителя.

В качестве операционного усилителя была взята микросхема OP07 (отечественный аналог – 140УД17). Схема усилителя представлена на рис. 17.
termreg17termopair-ampl-sch.jpg

Рис. 17. Схема усилителя для термопары

Работоспособность усилителя, запас по коэффициенту усиления и балансировку при питании от платы AVR-USB-MEGA16 я проверил на макетной плате (рис. 18). Но перед этим нужно опять слегка модернизировать плату AVR-USB-MEGA16. Схема этой третьей, и последней модернизации изображена на рис. 6 (красным слева). На плате появился еще один разъем, к которому необходимо подпаять +5В, землю и порт P1 (PA0) от АЦП.

Мы будем использовать внутренний источник опорного напряжения для работы АЦП. Поэтому необходима еще одна маленькая модификация. Выпаиваем аккуратно резистор R3 с платы AVR-USB-MEGA16, а ножку AREF выводим на этот же разъем для аналоговых модулей. Это опорное напряжение нам потребуется в другом проекте (измеритель pH) для смещения двухполярного сигнала в положительную область. Термопара, если горячий спай всегда теплее, чем холодный, будет выдавать однополярный сигнал (медь – плюс, константан – минус для нашей термопары). Поэтому в этом проекте напряжение AREF на внешней плате не потребуется, но резистор R3 отпаять все-таки нужно.
 termreg18termopair-ampl-maket.jpg

Рис. 18. Предварительный усилитель на макетной плате

Усилитель на OP07 мне понравился. Запас усиления достаточный, сбалансированный нуль стоит как вкопанный. Заметных шумов и наводок также не наблюдается. Так что можно переносить на печатную плату.

Плата усилителя разрабатывалась в Sprint Layout 5.0. Наконец-то появился повод попробовать метод «лазерного утюга» (точнее - «лазерно-утюжный») для изготовления платы. Получилось с первого же раза. Действительно, вполне работоспособная и удобная технология. Особенно если не нужны слишком узкие зазоры и тонкие отверстия и плата небольшая. Для тонкой работы нужно очень хорошо сбалансировать давление и температуру на подошве утюга, т.к. тонер может расплавляться неравномерно и расплываться (в местах где давление или температура избыточны). Итог работы представлен на рис. 19 и рис. 20.
termreg19termopair-ampl-connected-AVR-USB-MEGA16a.jpg 

Рис. 19. Готовый усилитель термопары

Плату усилителя можно соединить с платой AVR-USB-MEGA16 непосредственно, как показано на рис. 20.
 termreg20termopair-ampl-connected-AVR-USB-MEGA16b.jpg

Рис. 20. Вся электроника печи в сборе

Теперь осталось разобраться с АЦП.

Работаем с АЦП

Работа с АЦП очень проста. Пример простого приложения, работающего с одним каналом АЦП, находится в архиве «07 Проверяем работу АЦП.zip» (см. ссылку [8]). Firmware и класс-обертка ATMega16 разработаны так, что можно работать с портами и регистрами микропроцессора непосредственно из хоста через USB. Это делает работу с АЦП почти тривиальной. Логика работы программы такова (см. файл Form1.cs в проекте из архива «07 Проверяем работу АЦП.zip», ссылка [8]).

При создании объекта dev класса ATMega16 происходит инициализация USB. Если все прошло успешно (см. метод Form1_Load()), мы инициализируем АЦП. Собственно говоря работа идет с регистрам ADMUX и статусным регистром ADCSRA.

Сначала указываем, что мы будем работать с внутренним источником опорного напряжения (устанавливаем биты REFS0 и REFS1 регистра ADMUX в 1), разрешаем работу АЦП (бит ADEN регистра ADCSRA – в 1) и задаем коэффициент деления тактовой частоты процессора для работы АЦП (см. комментарий в тексте программы). В конце инициализации запускаем таймер, по событиям которого (каждые 0.1 сек) будем запускать АЦП, считывать и выводить результат. Это происходит в методе timer1_Tick().

Биты с 0 по 4 регистра ADMUX определяют режимы работы аналоговых входов. Установка их в 0 – означает работу с одиночным каналом AD0, который мы и собирались использовать. Запуск процесса преобразования происходит путем установки бита ADSC регистра ADCSRA в 1. По концу преобразования бит ADIF этого же регистра устанавливается в 1. Т.к. время преобразования весьма мало, ждем этого радостного события просто в цикле. После этого берем результат преобразования в регистрах ADCL и ADCH и выводим их в TextBox. Вот и все. Пример работы программы показан на рис. 21. Сигнал на вход АЦП удобно взять с того самого AREF, который мы вывели на разъем при последней модификации платы AVR-USB-MEGA16 (естественно, поделив его переменным резистором). Вот и пригодился AREF и в этом проекте.
termreg21ADC-testing.jpg

Рис. 21. Тестирование АЦП

Все. Теперь все это нужно собрать вместе в единый стенд, подключить печь и откалибровать термопару. Этим мы сейчас и займемся.

Сборка стенда и калибровка

Фотография собранного стенда представлена на рис. 22. Приступим к калибровке термопары.
termreg22stove-with-reg.jpg

Рис. 22. Все готово для калибровки термопары

Сам процесс калибровки несложен. Нагреем печь до максимальной рабочей температуры (в нашем случае 400oC). Регулируя коэффициент усиления усилителя (подстроечный резистор «Усиление», рис. 17) добьемся того, чтобы код АЦП был в конце диапазона с небольшим запасом (в случае 10 разрядного АЦП, пусть будет около 900). После этого оставляем печь остывать, фиксируя периодически код АЦП термопары, показания термометра, который считаем образцовым, и температуру холодного спая. Хотя это и не очень принципиально, но лучше производить калибровку именно при остывании печи, чем при нагреве (меньше градиенты температуры в печи).

Для облегчения этого процесса напишем небольшое приложение, которое представлено в архиве «08 Калибруем термопару.zip» (см. ссылку [8]). Вид работающего приложения показан на рис. 23.

 termreg23calibrate-termopair-process.jpg

Рис. 23. Процесс калибровки термопары

При нажатии на кнопку «Зафиксировать значения», текущие значения температур T0, T1 и код АЦП сигнала термопары заносятся в список справа панели. Потом по этим данным можно построить градуировочный график или использовать их непосредственно в табличном виде в программе регулятора температуры печи.

Построенный градуировочный график термопары показан на рис. 24. Видно, что в диапазоне от 100oC до 400oC градуировочная кривая хорошо описывается линейной функцией. Уравнение тренда – на графике слева вверху. Поэтому в программе регулятора можно использовать это уравнение для пересчета кода АЦП в градусы (естественно, не забывая прибавить температуру холодного спая, которая измеряется датчиком DS18B20).
 termreg24calibrate-diagram.jpg

Рис. 24. Градуировочный график

Теперь осталось определить оптимальную зону пропорциональности и коэффициент компенсатора для терморегулятора печи и – печь готова. Мы это уже один раз делали при настройке водяной бани, поэтому повторяться не будем.

Байты перемычек (fuse bits) ATmega16 должны быть 0xFF (low) и 0x09 (high).

@ S.V.Kukhtetskiy, 2009
Кухтецкий Сергей Владимирович,
лаборатория проблем материаловедения,
Институт химии и химической технологии СО РАН, Красноярск
E-mail: ku@icct.ru

[Решение возможных проблем]

Здесь описаны некоторые типичные проблемы, которые возникают при использовании прошивки Сергея Кухтецкого. Решение других проблем см. в статье AVR-USB-MEGA16, V-USB, FAQ: переписка по вопросам программирования.

1. Записал в платку прошивку Сергея Кухтецкого с помощью загрузчика USB и программы Khazama, но платка не определяется как устройство USB. Если снова установить перемычку для активации загрузчика USB, то платка определяется, и загорается светодиод. В чем проблема? Ответ: платка у Вас исправна, но Вы записали в неё не ту прошивку. Например, прошивка соответствует другой частоте кварца, не той что используется на Вашей макетной плате AVR-USB-MEGA16. Прошейте HEX-файл прошивки Сергея Кухтецкого, рассчитанный на нужную частоту кварца, который стоит у Вас. Частоту кварца можно прочитать на его корпусе, например если на корпусе написано 12.000, то кварц на 12 МГц.

2. При подключении платки к компьютеру (в платку записана прошивка Сергея Кухтецкого) система Windows запрашивает драйвер. Что это за драйвер, где его брать? Ответ: это драйвер библиотеки LibUSB, скачайте его по ссылке [10].

3. На моей системе Windows драйвер LibUSB не устанавливается, и о причине система не сообщает. Как быть? Ответ: такое нередко бывает на урезанных версиях Windows. Причина может быть в том, что не отключена система проверки цифровой подписи драйвера, либо пакет драйвера неполон (например, если Вы скачали драйвер по ссылке из статьи на сайте vanoid.ru, то там не хватает некоторых файлов, требуемых для 64-битных версий Windows). Поэтому, во-первых, перезагрузите систему, и при загрузке отключите проверку цифровой подписи драйвера (нажимайте при старте F8, и на черном экране выберите соответствующую нижнюю строчку загрузочного меню). Во-вторых, устанавливайте полную версию драйвера LibUSB (скачайте его по ссылке [10]).

4. Скомпилированное ПО хоста на C# не запускается с ошибкой. Что делать? Ответ: возможно не установлена библиотека .NET 3.5 от Microsoft. В этом случае могут выскакивать разные ошибки (наподобие The application failed to initialize properly 0xc0000135), но программа в любом случае не запустится. Чтобы решить проблему, скачайте и установите эту библиотеку (строка для поиска Microsoft .NET Framework 3.5 site:microsoft.com). Инсталлятор для библиотеки можете скачать по ссылке [10] (инсталлятор требует подключения к интернет, так как он закачивает недостающие модули).

[Ссылки]

1. Макетные платы с интерфейсом USB.
2. AVR-USB-MEGA16: быстрая разработка USB приложений на C# при помощи класса-обертки ATMega16. Класс C# (для Visual Studio Express Edition 2008) и соответствующая прошивка, позволяющие быстро сделать USB HID устройство и написать для него приложение для компьютера. Вы управляете микроконтроллером прямо из кода на C# (дергаете его ножками, читаете регистры и т. п.).
3. avr-usb-russian.rar - библиотека V-USB, примеры, документация на русском языке.
4. Как работать с платой AVR-USB-MEGA16 из Visual Studio (версия 2003). На примере описано управление светодиодом на макетной плате из кода на C++.
5. V-USB Projects site:obdev.at - проекты, которые основаны на V-USB. Все эти проекты можно реализовать на макетной плате AVR-USB-MEGA16.
6. Пример управления портами микроконтроллера через USB.
7. Разработка устройства USB - как начать работу с библиотеками AVR USB и libusb.
8. 101022V-USB_C#_libusb.zip - здесь собраны в одном архиве все исходники программ, описанные в статье (ПО хоста и firmware), а также скомпилировал прошивки на все варианты частот кварцев для микроконтроллеров ATmega16 и ATmega32.
9. zedGraph site:sourceforge.net.
10140808LibUSB-driver.zip - архив с драйвером библиотеки LibUSB, он нужен для корректной работы прошивки Сергея Кухтецкого совместно с операционными системами Windows. Драйвер подходит для всех версий операционных систем Windows XP (32 bit и 64 bit), Windows 7 (32 bit и 64 bit), Windows 8 (32 bit и 64 bit). В этом же архиве найдете инсталлятор для библиотеки .NET 3.5 (требуется для приложений ПО хоста, написанных на Visual Studio C# 2010).