Предлагаю Вашему вниманию свою схему термостата. Данное устройство мне понадобилось для моего 3D принтера, а точнее для нагрева стола (у меня самодельная PRUSA I3, когда я поставил на неё подогреваемый столик, возникла проблема, из-за открытого корпуса принтера стол не может удержать температуру, и контролёр принтера кидает ошибку, а потом останавливает печать). Я решил собрать отдельный контроллер нагрева (из имевшихся у меня компонентов, да и просто ради развлечения). В наличии у меня были безымянные терморезисторы, дисплеи на tm1637 контроллеры, полумостовые драйверы ULN2803 и, естественно, микроконтроллеры.
Первое, что нужно было сделать - это понять, как работает терморезистор. Оказалось - очень просто. Надпись NTC - означает, что чем больше температура, тем меньше сопротивление. Здесь всё понятно. Теперь надо решить, как его подключить к контроллеру. Есть несколько вариантов, но основные из них - это делитель напряжения из двух резисторов с подтяжкой к земле или с подтяжкой к питанию. Я выбрал вариант номер два (так сделано в 3D принтере), подключил с подтяжкой к питанию резистором 10 килоом (смотрите на схеме).
С подключением определились. Вопрос номер два: как узнать какие значения АЦП будут соответствовать определённым значениям температуры? Здесь есть несколько путей. Можно взять термистор с известными параметрами и таблицами сопротивлений, или воспользоваться сложными формулами расчёта. Мне эти варианты не подошли (резистор неизвестный, а в высшей математике я не силён). Я выбрал другой и, наверное, самый простой путь. Так как я делал не термометр, а термореле, мне не нужно было знать, какому значению температуры соответствует каждое значение АЦП. Мне нужно знать значение АЦП для конкретных (нужных мне) температур в небольшом диапазоне. Поэтому я решил построить график зависимости АЦП от температуры по нескольким точкам, а потом по этому графику определить приблизительные значения АЦП для нужных мне температур. Для этого я собрал всю схему и написал простой код в arduino, который выводил к значения АЦП через uart в терминал.
const int termo_up = A2; //Вход терморезистора с подтяжкой на плюс void setup() { Serial.begin(9600); } void loop() { int adc_value=analogRead(termo_up); Serial.print("ADC = "); Serial.println(adc_value); delay(500); }
Затем я просто брал воду разной температуры, измерял её термометром, погружал в неё термистор и записывал значения АЦП. Потом по этим значениям строил график. Получилось примерно так: (это не окончательный вариант, только для наглядности, но форма графика приблизительно такая же. Полученные точки, которые сильно отдалялись от линии я корректировал (так сказать к общей тенденции).
График я строил онлайн, что очень удобно, можно в любой точке графика посмотреть значения x и y.
В итоге я составил массив значений АЦП с шагом в один градус Цельсия в диапазоне от 0 до 80 градусов:
//Массив значений АЦП (по возрастанию от 0 до 80 градусов по Цельсию) int termo[] = {976,975,974,973,972,971,970,969,968,967,966,965,964,963,962,961,960,959,958, 956,954,952,949,946,943,940,937,934,930,928,925,921,917,913,910,906,902,897, 893,888,884,878,874,870,865,861,856,852,847,843,837,834,830,825,820,815,810, 805,800,795,790,785,780,776,771,766,761,755,748,741,733,727,720,712,703,693, 685,674,663,654,643};
Теперь немного электроники. Схема довольно простая, atmega8, обвязка, драйвер реле в виде ULN2803, дисплей, кренка и терморезистор.
Несколько пояснений. На ножках атмеги отмечены названия выходов как портов контролёра, так и выводов arduino (в качестве контролёра можно использовать любой arduino совместимый). Выводов для релюшек четыре штуки только потому, что жалко свободных выводов атмеги (можно программно что-нибудь будет прикрутить к ним). Выводы драйвера спарены для надёжности и из-за их избытка тоже. Вместо ULN2803 можно использовать ULN2003 и подобные, они представляют из себя сборку транзисторов Дарлингтона, при желании можно просто сделать ключи на n-канальных мосфетах. Стабилизатор на 5 вольт - любой, входное питание 12 вольт позволяют ставить LM7805, у меня использовано low-drop ams1117-5,0, только не жалейте фильтрующих конденсаторов, можно также вывод AVCC атмеги запитать через дроссель для уменьшения помех АЦП. Кварц при желании можно поставить и на 8 MHz, только для этого в ардуино нужно скомпилировать свой hex или просто прошить через uart с правильным загрузчиком.
И, собственно, программа. Написана, естественно, в среде arduino, так как это очень быстро и удобно для такого простого устройства (не надо морочиться с драйверами для дисплея, АЦП, uart и т.д.).
#include <TM1637.h> #define CLK 3//pins definitions for TM1637 and can be changed to other ports #define DIO 4 TM1637 tm1637(CLK,DIO); //Массив значений АЦП (по возрастанию от 0 до 80 градусов по цельсию) int termo[] = {976,975,974,973,972,971,970,969,968,967,966,965,964,963,962,961,960,959,958, 956,954,952,949,946,943,940,937,934,930,928,925,921,917,913,910,906,902,897, 893,888,884,878,874,870,865,861,856,852,847,843,837,834,830,825,820,815,810, 805,800,795,790,785,780,776,771,766,761,755,748,741,733,727,720,712,703,693, 685,674,663,654,643}; int warm = 20; // Переменная, в которой хранится значение уровня температуры const int button1 = 13; //Пин первой кнопки ("нагрев вкл/выкл") const int button2 = 12; //Пин второй кнопки "+" const int button3 = 11; //Пин третьей кнопки "-" const int relay1 = 5; //Пины реле 1-4 const int relay2 = 6; //Просто жалко свободных ног МК и ULN2803 const int relay3 = 7; const int relay4 = 8; const int termo_up = A2; //Вход терморезистора с подтяжкой на плюс const int termo_down = A3; ////Вход терморезистора с подтяжкой на землю void setup() { pinMode(19, INPUT_PULLUP); //Настраиваем ноги на входы/выходы pinMode(18, INPUT_PULLUP); //Кнопки с подтяжкой к питанию pinMode(17, INPUT_PULLUP); //Можно и без, в схеме всёравно есть резисторы pinMode(relay1, OUTPUT); pinMode(relay2, OUTPUT); pinMode(relay3, OUTPUT); pinMode(relay4, OUTPUT); tm1637.set(BRIGHT_TYPICAL); //Настраиваем наш экранчик tm1637.init(); tm1637.point(false); digitalWrite(relay1,LOW); //Отключаем на всякий случай все реле digitalWrite(relay2,LOW); digitalWrite(relay3,LOW); digitalWrite(relay4,LOW); tm1637_disp(); //Выводим на экран значение переменной "warm" } void loop() { if(digitalRead(button1)==LOW){ //Если нажата кнопка 1 while(digitalRead(button1)==LOW); //Ждём, пока она нажата delay(20); nagrev(); //Переходим в функцию нагрева } if(digitalRead(button2)==LOW){ //Если нажата кнопка 2 while(digitalRead(button2)==LOW); //Ждём, пока она нажата delay(20); warm=warm+1; //Добавляем 1 к переменной warm if(warm>80){warm=80;} //Проверяем, чтобы не выходила за пределы наших значений tm1637.clearDisplay(); //Очищаем дисплей tm1637_disp(); //И выводим на него новое значение warm } if(digitalRead(button3)==LOW){ //Аналогично с кнопкой 2 while(digitalRead(button3)==LOW); delay(20); warm=warm-1; if(warm<0){warm=0;} tm1637.clearDisplay(); tm1637_disp(); } } void tm1637_disp(){ //Функция выводит на дисплей значение переменной warm if((warm/100)>0){ //Если warm больше или равно 100 tm1637.display(1,(warm/100)); //пишем во 2 разряд сотни tm1637.display(2,((warm%100)/10)); //пишем в 3 разряд десятки tm1637.display(3,((warm%100)%10)); //пишем в 4 разряд единицы } if((warm/100)==0){ if(((warm%100)/10)>0){ //если warm меньше ста tm1637.display(2,((warm%100)/10)); //десятки tm1637.display(3,((warm%100)%10));} //единицы else{tm1637.display(3,((warm%100)%10));} //если меньше десяти - только единицы } } void nagrev(){ //Функция нагрева tm1637.display(0,0xc); //Выводим букву "С" в первый разряд индикатора uint16_t adc; //Переменная для чтения значений АЦП //Цикл нагрева do{ adc = analogRead(termo_up); //Читаем значение АЦП if((adc>termo[warm]) ){ //Если значение температуры меньше заданного digitalWrite(relay3,HIGH); //Включаем реле } else if((adc<termo[warm])||(adc<termo[warm])){digitalWrite(relay3,LOW);} //Если больше - выключаем delay(500); } while((digitalRead(button1))==HIGH); while(digitalRead(button1)==LOW); //Проверяем, отпущена ли кнопка 1 digitalWrite(relay3,LOW); //Выключаем реле нагрева tm1637.clearDisplay(); tm1637_disp(); //Выводим на экран значение температуры без буквы "С" в первом разряде }
Как видите, код с подробными описаниями. В нём ничего сложного, в основном цикле идёт опрос кнопок, а в функции нагрева идёт опрос АЦП и сравнение, в зависимости от результатов которого включается или выключается реле нагрева. И отдельно вынесена функция вывода информации на экран. Так как код написан на ардуино, его легко адаптировать для любого дисплея (для которого хватит оставшихся ножек), можно даже выводить информацию через uart компьютера (что я обычно делаю при отладке устройств).
А вот и фото готового устройства (реле и термистор выносные на проводах):
В конце статьи я прикреплю скетч arduino, HEX для atmega8 (16 MHz, FUSE: high - DC, low - BF) , библиотеку для tm1637 и плату в layout (всё в архиве).
Список радиоэлементов
Обозначение | Тип | Номинал | Количество | Примечание | Магазин | Мой блокнот |
---|---|---|---|---|---|---|
МК AVR 8-бит | ATmega8 | 1 | tqfp32 | Поиск в магазине Отрон | ||
Составной транзистор | ULN2803 | 1 | можно uln2003 с переделкой платы | Поиск в магазине Отрон | ||
Cr1 | Кварц | 16 MHz | 1 | Поиск в магазине Отрон | ||
NTC1 | Термистор | NTC 100K | 1 | Можно любой | Поиск в магазине Отрон | |
R1-R5 | Резистор | 10 кОм | 5 | Поиск в магазине Отрон | ||
С1,С5 | Конденсатор | 10 мкФ | 2 | smd 0805 | Поиск в магазине Отрон | |
C3, C4 | Конденсатор | 22p | 2 | smd 0805 | Поиск в магазине Отрон | |
С2 | Конденсатор | 100n | 1 | smd 0805 | Поиск в магазине Отрон | |
Rel1-Rel4 | Реле | автомобильное или любое на 12В | 4 | Поиск в магазине Отрон | ||
VR1 | Линейный регулятор | AMS1117-5.0 | 1 | или LM7805 и др. | Поиск в магазине Отрон | |
Скачать список элементов (PDF)
Прикрепленные файлы:
- Термореле.rar (149 Кб)
Комментарии (7) | Я собрал (0) | Подписаться
Для добавления Вашей сборки необходима регистрация
[Автор]