Для чего же мне понадобилась автоматика?
Автоматика нужна для облегчения процесса , т.к. этот контроллер сам будет следить за температурой, поддерживать ее и поднимать до необходимой температурной паузы. Так же сигнализировать звуковым сигналом о необходимом вмешательстве, например, нужно засыпать солод или сделать йодную пробу.
Делать я свою автоматику решил из готового проект . Работает она на arduino, к нему подключается датчик температуры, два реле, дисплей и кнопки. Первое реле управляет ТЭНом, второе реле насосом. Насос для затирания очень удобен, т.к. отпадает необходимость за весь процесс затирания перемешивать затор (подробнее как варить пиво, рекомендую прочитать в моих ранних )
Со временем я пришел к выводу, что надо собрать свою автоматику на чипе с 64кб памяти (у arduino mini всего 32 кб) на одной плате. Готового решения я не нашел, по этому сам стал создавать схему и в последующем плату для своей поделки.
Плата готова, осталось ее как-то изготовить. Для этого я решил использовать . Почему именно им, а не ЛУТ? Просто решил испробовать для себя такую новую технологию, ЛУТ я уже испробовал, так сказать пощупал, не скажу, что мне она понравилась…
А вот и мои «косяки»:
Хоть и не значительные, но все же, а во всем виновата невнимательность, не заметил пузырьки воздуха под фоторезистом или перегрел…
Следующая плата у меня получилась «чистая»:
14. Далее сверлим отверстия и лудим плату:
15. Припаиваем все детали и отмываем от лишнего флюса:
Припаивал SMD компоненты китайской инфракрасной паяльной станцией, очень удобно:
Вот и все, самое сложное позади, осталось прозвонить дорожки на предмет короткого замыкания и приступить к программирования чипа.
Устройство используется для автоматизации процесса затирания солода. Не предназначена для кипячения сусла.
Изначально было собрано как информационный таймер с индикатором времени и температуры. В последствии было добавлено реле и автоматизирован весь процесс затирания.
Для автоматизации затирания солода понадобятся следующие детали.
Arduino UNO R3
1.8 «серийный 128×160 SPI TFT ЖК-дисплей модуль Дисплей + адаптер PCB Мощность IC SD Разъем
5 В реле Модуль 1 канал низкого уровня для СКМ Бытовая техника Управление для (10A 220V, на пределе, лучше использовать более сильное, на пример Твердотельное реле SSR-40DA + радиатор для отвода тепла)
Перемычки Dupont (папа, мама)
DS1820 из нержавеющей стали посылка Водонепроницаемый DS18B20 датчик температуры датчик 18B20 для Arduino
Пищалка (Пьезодинамик)
Резистор на 4.7кОм
Кабель USB A-B + USB зарядка для питания ардуино
Схема подключения датчика, реле, пищалки
Схема подключения TFT экрана к arduino uno
1.8 TFT SPI 128×160 | Arduino UNO |
SCK | Pin 13 |
SDA | Pin 11 |
CS | Pin 10 |
A0 | Pin 9 |
RESET | Pin 8 |
VCC | +5V |
GND | GND |
LED+ | +5V |
Силовая схема.
Подключение ТЭНа, насоса
Сечение проводов и силовое реле подбираем по суммарной мощности ТЭНа и насоса.
Скетч для arduino uno (файл ino 30.03.2018).zip (2,32 Kb)
Для загрузки скетча необходимо установить Arduino IDE.
Подключаем arduino к компьютеру, запускаем Arduino IDE. В меню «Инструменты» — Плата — выбираем «Arduino/Genuino Uno». «Инструменты» — Порт — выбираем тот куда подключена arduino. Скорее всего будет один com порт. Так же номер порта можно посмотреть в диспетчере устройств.
Открываем скетч и жмем кнопку «Загрузить».
Все устройство готово к работе.
Настройка пауз производиться непосредственно в самом скетче (строки с 12 по 29):
Пример:
int c1 = 52; //температура первой паузы 52 градуса
unsigned long p1 = 20
* 60000; //время первой паузы 20 минут
int c2 = 63; //температура второй паузы 63 градуса
unsigned long p2 = 30 * 60000; //время второй паузы 30 минут
В строке 177 скетча производиться корректировка показаний датчика температуры.
celsius = celsius + 1; // +1 градус
1. Показание реле: Vk — включено / замкнуто, Ot — выключено / разомкнуто.
2. Температуры пауз.
3. Текущее показание датчика температуры.
4. Общее время работы.
5. Время температурных пауз.
6. Таймер (обратный отсчет) текущей паузы.
!!!ВАЖНО
При включении реле включено / замкнуто.
По окончании паузы Mash out реле выключено / разомкнуто.
Если необходимо меньшее количество пауз, на пример однопаузное затирание, для этого настройки следующие:
1 пауза, 67 градусов 60 мин.
2, 3, 4 паузы градусы и время устанавливаем НОЛЬ.
76 mash out 5 мин.
На практике используется следующим образом.
Датчик температуры установлен в стенку бака.
ТЭН 2КВт под фальш дном.
Насос на 12В, забор сусла через кран под фальш дном, но выше ТЭНа., возвращает в бак сверху.
!!!Насос и ТЭН «висят» на одном реле (10A 220V, на пределе, лучше использовать более сильное)
Заливается вода, засыпается солод.
Включается устройство.
Сразу начинается подъем температуры до первой паузы, по достижению тэн и насос отключаются.
Включается таймер. Происходит поддержание температуры, по окончании времени, происходит подъем температуры до след паузы и т.д.
Вопросы, ответы, обсуждения в Группе ВК vk.com/brewmate
В 2014 году я наткнулся на видео где мужик делает пиво из концентрата пивного сусла. Я загорелся идеей пивоварения и тут понеслось…
Варка пива из консервов мне стала не интересной после 2-го раза и я решил перейти на all-grain. Раз сварил пиво на газу и понял, что это не мой метод. Решил сделать автоматику. Вечера стали интересней. Я так втянулся в программирование, что кодил аж до 2-3 часов ночи. Нужны были испытания в реальных условиях. В закромах откопал кипятильник и граненый стакан.
И вот, что в итоге у меня получилось
А теперь расскажу как сделать такую автоматику.
Для начала нам понадобятся следующие детали. Я их купил в Китае.
ssd1289 или ili9341.
Твердотельное реле для управления ТЭНом (или схема на )
Твердотельное реле для управления насосом (для насоса на переменном токе) или (на постоянном токе)
Термодатчик или или
Блок питания 7.5-9В 1А. Например
Разьемы для подключения термодатчика и насоса и
(еще )
(buzzer)
Резистор на 4.7кОм
Схема низкого напряжения
Силовая схема. Будьте осторожны. Не уверены — доверьте профессионалам.
Сечение проводов берем в зависимости от суммарной мощности насоса и ТЭНа. Для твердотелки ТЭНа нужен радиатор т.к. греется он не слабо. Запихиваем все это в коробок. Заливаем прошивку,настраиваем и варим пиво.
Но базовых функций мне было мало. И я решил прикрутить wifi. Прикупил на aliexpress модуль ESP8266 . Заодно заказал модуль т.к. ребята с форума ну очень просили внедрить его в проект (можно и без него) . И подключил по следующей схеме
Для питания wifi модуля нам нужен источник питания 5В. Использовать arduino нельзя. Можно использовать отдельный источник питания либо преобразовать 9В в 5В. Для этого можно собрать простенькую схему со стабилизатором напряжения или купить готовый у китайцев. Например (есть еще куча других вариантов).
Следующим шагом будет прошивка нашего модуля прошивкой NodeMCU. Скачиваем . Запускаем. Нажимаем Start и ждем окончания заливки прошивки. Прошили? Вот и отлично. Теперь загружаем скрипт. Для этого нам понадобится . Есть конечно другие программы типа . Но у меня не получилось их заставить работать с моим модулем. В ESPlorer-е создаем новый файл init.lua с следующим содержанием:
Меняем имя wifi сети и пароль на свои. Ставим скорость 9600. Жмем кнопку «Open»(если не конектится может помочь нажатие кнопки reset на модуле). И жмем «Save to ESP». После загрузки скрипта, модуль должен подключится к вашему роутеру. Это можно проверить зайдя в роутер и посмотреть клиентов DHCP. Если вашего модуля там не видно, то что-то пошло не так.
В web-интерфейсе присутствуют следующие функции.
1. Мониторинг процессов. Можно следить за температурой, состоянием насоса, показателями затирания и варки. Веб интерфейс снабжен звуковым сигнализатором.
2. Загружать рецепты в память контроллера и на флешку.
3. Построение глобального графика всей варки.
Вход в web-интерфейс
Через несколько лет решил повторить процесс, немного автоматизировав его с помощью Arduino UNO. И вот, что получилось.
Начну с того, что должна делать вся установка.
Первый пункт в данный момент не реализован. Пока даже мыслей нет, как реализовать.
Второй - тоже не реализован, но в ближайшее время доделаю, только дождусь, когда доставят насосы с ebay.
Третий пункт - достаточно простой.
Хочется, чтобы была проверка на наличие воды, но датчик еще ждет своего отправления от «китайских братьев».
Нажимаем в управляющей программе кнопку «Прогрев», остальные управляющие кнопки не активны;
- После прогрева программа выводить сообщение «Все готово, можно варить»;
- Засыпаем ингредиенты, выбираем программу для варки - кнопка «Варка пива» становится активной;
- Нажимаем кнопку «Варка пива», процесс пошел;
- Далее система периодически будет оповещать информационными сообщениями, что делать и когда.
Нужно следовать инструкциям.
Закинул ингредиенты в соответствующие лотки, нажал кнопку и… через полтора месяца получил готовое пиво.
Это вкратце о процессе, а теперь перейдем к техническое стороне.
Arduino общается с основной программой через com порт. Т.к. у меня нет шильда реального времени к arduino, пришлось таймеры брать из visual c#. Опыта написания программ у нет, так что, если вдруг у кого есть идеи, критика - почту за честь. Критикуйте, дербаньте, так сказать, что вдруг не нравится.
Вот текст программы на arduino
#include
Все бы хорошо, но почему-то третий датчик показывает постоянно 85 градусов. Пока не могу сказать, почему. А нужен он для дальнейшей автоматизации - поддержание температуры в холодильнике.
Вкратце опишу, что делает программа.
Программа разделена на подпрограммы, каждая из которых активируется, если на com порту появляется определенный символ. Например, если в порт попадает буква «p», то включается режим «Прогрев». Или же, если «a» - то вызывается подпрограмма avariya() и все отключается. При вызове подпрограммы temperature() данные записываются в глобальные переменные temp1, temp2. Оттуда и попадают в нужные подпрограммы.
В будущем появятся подпрограммы для варки различных сортов и даже самогона.
Теперь, что касается основной программы управления.
Исходный код программы:
Исходный код программы
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO.Ports; namespace WindowsFormsApplication1 { public partial class Form1: Form { // String portnumber; SerialPort Port1 = new SerialPort("COM5", 9600); int s=0; public Form1() { InitializeComponent(); } /*private const int CP_NOCLOSE_BUTTON = 0x200; protected override CreateParams CreateParams { get { CreateParams myCp = base.CreateParams; myCp.ClassStyle = myCp.ClassStyle | CP_NOCLOSE_BUTTON; return myCp; } }*/ private void Form1_Load(object sender, EventArgs e) { label2.Text = Port1.PortName; Port1.Open(); } //Проверка оборудования private void button1_Click(object sender, EventArgs e) { if (Port1.IsOpen == false) { try { //программу можно доработать информация из podrugomu.com/node/987 Port1.PortName = label2.Text; Port1.Open(); Port1.Write("Check"); //SerialPort Port2 = new SerialPort("COM4", 9600); //Port2.Open(); //label3.Text = Convert.ToString(Port2.ReadByte()); //проверка показаний порта MessageBox.Show("Процес проверки оборудования запущен", "Инфорамационное сообщение"); richTextBox1.Text = richTextBox1.Text + "\n" + "Запуск процесса проверки оборудования"+" "+DateTime.Now.ToString("HH:mm"); button1.Enabled = false; button2.Enabled = false; button3.Enabled = false; if (Port1.ReadByte() == 1000) { richTextBox1.Text = richTextBox1.Text + "\n" + "Окончание процесса проверки оборудования"+" "+DateTime.Now.ToString("HH:mm"); button1.Enabled = true; button2.Enabled = true; button3.Enabled = true; Port1.Close(); MessageBox.Show("Конец Цикла проверки оборудования" +" "+ DateTime.Now.ToString("HH:mm")); richTextBox1.SaveFile("CheckLOG.rtf"); } } catch { richTextBox1.Text = richTextBox1.Text + "\n" + "Ошибка процесса проверки оборудования" +" "+ DateTime.Now.ToString("HH:mm"); MessageBox.Show("Неверно выбран порт устройства. Процесс проверки не может быть запущен", "Warninig"); richTextBox1.SaveFile("log/Check_"+DateTime.Now.ToString("ddMMyyyy")+".rtf"); } } } // Чистка оборудования private void button3_Click(object sender, EventArgs e) { if (Port1.IsOpen == false) { try { //программу можно доработать информация из podrugomu.com/node/987 MessageBox.Show("Вы точно налили дезинфектор", "WARNING", MessageBoxButtons.OK, MessageBoxIcon.Warning); Port1.PortName = label2.Text; Port1.Open(); Port1.Write("Clean"); MessageBox.Show("Процес чистки оборудования запущен", "Инфорамационное сообщение"); button1.Enabled = false; button2.Enabled = false; button3.Enabled = false; if (Port1.ReadByte() == 1000) { button1.Enabled = true; button2.Enabled = true; button3.Enabled = true; Port1.Close(); MessageBox.Show("Конец Цикла чистки оборудования"); } } catch { MessageBox.Show("Неверно выбран порт устройства. Процесс чистки не может быть запущен", "Warninig"); } } } private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) { } private void cOM1ToolStripMenuItem_Click(object sender, EventArgs e) { SerialPort Port1 = new SerialPort("COM1", 9600); // MessageBox.Show("Выбран порт COM1"); label1.Visible = true; label2.Text = "COM1"; } private void label2_Click(object sender, EventArgs e) { } private void cOM2ToolStripMenuItem_Click(object sender, EventArgs e) { SerialPort Port1 = new SerialPort("COM2", 9600); // MessageBox.Show("Выбран порт COM2"); label1.Visible = true; label2.Text = "COM2"; } private void cOM3ToolStripMenuItem_Click(object sender, EventArgs e) { SerialPort Port1 = new SerialPort("COM3", 9600); // MessageBox.Show("Выбран порт COM3"); label1.Visible = true; label2.Text = "COM3"; } private void cOM4ToolStripMenuItem_Click(object sender, EventArgs e) { SerialPort Port1 = new SerialPort("COM4", 9600); // MessageBox.Show("Выбран порт COM4"); label1.Visible = true; label2.Text = "COM4"; } private void cOM5ToolStripMenuItem_Click(object sender, EventArgs e) { SerialPort Port1 = new SerialPort("COM5", 9600); // MessageBox.Show("Выбран порт COM5"); label1.Visible = true; label2.Text = "COM5"; } private void cOM6ToolStripMenuItem_Click(object sender, EventArgs e) { SerialPort Port1 = new SerialPort("COM6", 9600); // MessageBox.Show("Выбран порт COM6"); label1.Visible = true; label2.Text = "COM6"; } private void cOM7ToolStripMenuItem_Click(object sender, EventArgs e) { SerialPort Port1 = new SerialPort("COM7", 9600); // MessageBox.Show("Выбран порт COM7"); label1.Visible = true; label2.Text = "COM5"; } private void программаВаркиToolStripMenuItem_Click(object sender, EventArgs e) { } // Варка пива private void button2_Click(object sender, EventArgs e) { // if (Port1.IsOpen == false) //{ // try //{ //программу можно доработать информация из podrugomu.com/node/987 //Port1.PortName = label2.Text; //Port1.Open(); switch (label3.Text) { case "Выбрано инфузионное затирание": MessageBox.Show("Процесс инфузионного затирания Запущен", "Инфорамационное сообщение"); Port1.WriteLine("i"); timer1.Start(); break; case "Выбрана варка Cooper": MessageBox.Show("Процесс затирания Cooper запущен", "Инфорамационное сообщение"); Port1.WriteLine("v"); timer3.Start(); break; } button1.Enabled = false; button2.Enabled = false; button3.Enabled = false; // button5.Enabled = false; // richTextBox1.Text = Port1.ReadLine()+"\n"; /* if (Port1.ReadLine() == "e\r") { button1.Enabled = true; button2.Enabled = true; button3.Enabled = true; button5.Enabled = true; */ //Port1.Close(); // MessageBox.Show("Конец Цикла варки пива"); // } // } // catch //{ // MessageBox.Show("Неверно выбран порт устройства. Процесс варки не может быть запущен", "Warninig"); //} // } } private void button5_Click(object sender, EventArgs e) { Port1.Write("p"); button1.Enabled = false; button2.Enabled = false; button3.Enabled = false; timer2.Start(); richTextBox1.Text = richTextBox1.Text + "\n" + "Запуск подогрева воды в заторном чане до 37 градусов" + " " + DateTime.Now.ToString("HH:mm"); /* Port1.Open(); //Port1.Open(); //richTextBox1.Text = richTextBox1.Text + "\n" + Port1.ReadLine(); Port1.WriteLine("o"); Port1.Close(); */ } private void выходToolStripMenuItem_Click(object sender, EventArgs e) { Close(); } private void button4_Click(object sender, EventArgs e) { } private void инфузионноеЗатираниеToolStripMenuItem_Click(object sender, EventArgs e) { label3.Text = "Выбрано инфузионное затирание"; } private void timer1_Tick(object sender, EventArgs e) { textBox1.Text = Convert.ToString(Convert.ToInt32(s / 60)); textBox2.Text = Convert.ToString(Convert.ToInt32((s))); s++; label5.Text = Port1.ReadLine(); if (s==4200){ //70 минут это 4200 секунд timer1.Stop(); //timer2.Start(); //Port1.Open(); Port1.WriteLine("s"); // Port1.Close(); MessageBox.Show("инфузионное затирание окончено необходимо отфильтровать сусло"); button1.Enabled = true; button2.Enabled = true; button3.Enabled = true; button5.Enabled = true; textBox1.Text = ""; textBox2.Text = ""; } //Port1.Close(); } private void label4_Click(object sender, EventArgs e) { } private void timer2_Tick(object sender, EventArgs e) { label5.Text = Port1.ReadLine(); if (Port1.ReadLine() == "s\r") { timer2.Stop(); MessageBox.Show("Вода имеет температуру 37 градусов. Можно засыпать солод и включать режим затирания"); richTextBox1.Text = richTextBox1.Text + "\n" + "Окончание процесса подготовки заторного чана. Т=37 градусов" + " " + DateTime.Now.ToString("HH:mm"); button2.Enabled = true; } } private void аварийноеОтключениеToolStripMenuItem_Click(object sender, EventArgs e) { Port1.WriteLine("a"); MessageBox.Show("Пользователь аварийно отключил всю систему"); } private void заторногоКотлаToolStripMenuItem_Click(object sender, EventArgs e) { Port1.WriteLine("k"); MessageBox.Show("Включен режим кипячения заторного чана. Ждите 60 минут"); richTextBox1.Text = richTextBox1.Text + "\n" + "Включен режим кипячения заторного чана. Ждите 60 минут" + " " + DateTime.Now.ToString("HH:mm"); } private void timer3_Tick(object sender, EventArgs e) { string s1 = ""; Port1.ReadLine(); if (s1.Substring(0, 2) == "t1") label5.Text = s1.Substring(4, 5); if (s1.Substring(0, 2) == "t2") label9.Text = s1.Substring(4, 5); s++; if (s == 900) { Port1.WriteLine("m"); MessageBox.Show("Этап затирания при 62 градусах"); richTextBox1.Text = richTextBox1.Text + "\n" + "Этап затирания при 62 градусах" + " " + DateTime.Now.ToString("HH:mm"); } if(s== 2250) { Port1.WriteLine("n"); MessageBox.Show("Этап затирания при 78 градусах"); richTextBox1.Text = richTextBox1.Text + "\n" + "Этап затирания при 78 градусах" + " " + DateTime.Now.ToString("HH:mm"); } if (s ==2700) { Port1.WriteLine("b"); MessageBox.Show("Этап затирания закончен, можно сливать сусло"); richTextBox1.Text = richTextBox1.Text + "\n" + "Этап затирания окончен. Можно сливать сусло" + " " + DateTime.Now.ToString("HH:mm"); } } private void обычнаяToolStripMenuItem_Click(object sender, EventArgs e) { label3.Text = "Выбрана варка Cooper"; } } }
Программа общается с arduino через com порт. Единственное, никак не могу победить, чтобы при опрашивании com порта программа не подвисала на момент выполнения подпрограммы. После окончания подпрограммы программа отвисает, но пока это не критично и даже некий плюс. Защита от дурака - чтобы не нажать ничего во время определенной процедуры.
Когда придут помпы и солинойдные клапаны, буду автоматизировать дальше. А пока каждое воскресение буду добавлять по одной программе варки. В сумме будет 5 программ. Так же ждет своей очереди реализация ручного режима.
Как говорится,
Это варочный котел. Таких у меня два. С боку установлен датчик температуры DS18B20 в герметичной оправе.
Долго не мог понять, почему периодически arduino виснет, пока не осенило, что нужно все заземлить, наче пробивает на корпус, далее на корпус датчика и на arduino.
Медная трубка внутри - это для фильтрования сусла. Можно сделать красивее, но лучше использовать фальшдно. К сожалению китайские собрать не торопятся высылать его.
Пока рано говорить о результате, вот что получилось
Общий вид чана выглядит вот так.
Использовал обычные коннекторы
для подключения датчиков температуры, подключающиеся к двойной розетке. Удобнее мыть оборудование. Отключил, понес в ванную. Помыл, подключил и все работает.
Все пенилось по графику, лишнего не вытекало. А самых ближайших планах - слить на дображивание партию пива, сварить еще одну. Рецепт, в принципе можно посмотреть в коде в подпрограмме varka() у arduino.
Наконец-то пришли соленойдные клапаны. Процесс автоматизации продолжается.
Друзья, нужна помощь домашнему пивовару. С момента желания сделать умный термометр , прошло много времени и возникло новое желание - построить автоматизированную домашнюю пивоварню. Для ее автоматизации необходим блок управления. Решено было отказаться от использования покупных PID контроллеров, для управления ТЭНом, т.к. имеется Arduino, к ней SSR реле, дисплей 4 на 20 строк и к нему Serial Board для передачи инфы по одному проводу, не считая землю и питание.На данный момент, контроллер выглядит вот так:
В замен, обещаю стать личным наставником и учителем в пивоварении, кому, интересно! :)
UDP! Топик на Хабре!