Проект ардуино автоматика для ректификации. Техническая сторона процесса. Что хочется добавить в будущем

18.04.2019

Для чего же мне понадобилась автоматика?

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

Делать я свою автоматику решил из готового проект . Работает она на arduino, к нему подключается датчик температуры, два реле, дисплей и кнопки. Первое реле управляет ТЭНом, второе реле насосом. Насос для затирания очень удобен, т.к. отпадает необходимость за весь процесс затирания перемешивать затор (подробнее как варить пиво, рекомендую прочитать в моих ранних )

Первую автоматику я собрал с помощью модулей:

- Arduino mini
- Блок из двух реле на 15А
- Дисплей 2004
- Температурный датчик
- 4 кнопки
- БП на 5 вольт
Удобство модульной сборки, только состоит в том, что достать все детали не составит труда и паять практически ничего не нужно. Но самый большой минус - это огромное количество проводов, а дешевое китайское реле создавало помехи на дисплее, по этому механическое реле пришлось заменить твердотельным.

Со временем я пришел к выводу, что надо собрать свою автоматику на чипе с 64кб памяти (у arduino mini всего 32 кб) на одной плате. Готового решения я не нашел, по этому сам стал создавать схему и в последующем плату для своей поделки.

Схема:

Схему разработал и рисовал так сказать на коленке и для себя, по этому возможны кое-какие недочеты, но схема полностью рабочая:

Плата:

Схему нарисовал, далее осталось нарисовать плату, сначала рисовал с помощью программы Sprint-Layout 6 , очень удобная, но маловато в ней функционал, по этому решил от нее уйти в сторону программы DipTrace и вот что у меня получилось:

Скачать исходники можно .
Как видно свою пивоварню я назвал QRBeer и это уже версия 0.5…

Плата готова, осталось ее как-то изготовить. Для этого я решил использовать . Почему именно им, а не ЛУТ? Просто решил испробовать для себя такую новую технологию, ЛУТ я уже испробовал, так сказать пощупал, не скажу, что мне она понравилась…

Фоторезист:

Для изготовления печатных плат с помощью фоторезиста понадобится:
- Пленка для принтера
-
- УФ лампа
- Сода кальцинированная

УФ лампа

Для начала поделюсь информацией как я делал свою УФ лампу . Сначала хотел использовать готовую лампу, а потом решил собрать ее на шести 3Вт светодиодах:
и куплены так же на тао:


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


Изготовление платы

1. Итак, шаблон я подготовил, осталось его только распечатать на пленке. Как я писал выше нужна пленка для принтера, я испробовал пленку как для лазерного принтера, так и для струйного, лучший вариант получается только на пленке для струйной печати. Печатать нужно в негативе и в зеркальном отражении:

Шаблон я сразу заламинировал, что бы отпечатки пальцев и мусор легко можно был смыть.
2. Далее нужно зашкурить нашу будущую плату (фальгированный стеклотекстолит). Для этого подойдет слегка смоченная обычная губка или меламиновая губка:


3. После этой процедуры, медь ещё нужно обезжирить ацетоном:


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


6. Когда фоторезист наклеен, текстолит с ним нужно пропусить через ламинатор 2-3 раза или воспользоваться теплым утюгом и проглаживать через лист бумаги сложенным в два раза:


Главное фоторезист не перегреть, а то получится вот так:


Если при наклеивании фоторезиста получился «косяк», то лучше его убрать (смыть или соскоблить) и заново наклеить, а то после травления платы будет печально… Я же убирать этот фоторезист не буду, покажу конечный результат.
7. Накладываем на текстолит с фоторезистом шаблон и прижимаем стеклом (я взял его от старой фоторамки), а на стекло устанавливаем груз:


8. Засвечиваем фоторезист с помощью УФ лампы. Моей лампы хватает примерно 2 минуты:


Как видно фоторезист который засветился поменял цвет со светло-синего до темно-синего, причем засвеченный фоторезист очень хрупкий.
9. Убираем стекло и шаблон. Лишний фоторезист можно (не обязательно) обрезать и аккуратно отделить пинцетом:


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


11. Берем кисточку и трем по фоторезисту в щелочи, постепенно непроявленный фоторезист смывается:


Щелочь можно не выливать, а оставить на следующую плату или для смывания фоторезиста после травления, но об этом чуть позже…
12. Травление платы:
Тут два способа доступнее всего: травление хлорным железом или перекисью+лимонная кислота и соль. Про хлорное железо писать не буду, а вот с помощью перекиси пожалуй опишу:
- 100 мл. перекиси водорода 3% - продается она в аптеке за 7-12 рублей
- 30 гр. лимонной кислоты (есть в любом продуктовом магазине)
- 1 ст. ложка соли (подойдет как мелкая так и каменная)


Все это смешивается в емкости и погружается туда плата с готовым фоторезистом, через некоторое время на плате появляются пузыри:


А через некоторое время «голая медь» полностью протравится:


Кстати, если травить в более высокой температуре, например у лампы накаливания или в водяной ванне, то тремя травления уменьшится, главное не переусердствовать, иначе лишнее протравится…
13. Убирать фоторезист удобнее всего в этой же щелочи, в которой смывали непротравленный фоторезист, минут через 20 он сам отпадет и ничего тереть не надо…

А вот и мои «косяки»:


Хоть и не значительные, но все же, а во всем виновата невнимательность, не заметил пузырьки воздуха под фоторезистом или перегрел…

Следующая плата у меня получилась «чистая»:


14. Далее сверлим отверстия и лудим плату:


15. Припаиваем все детали и отмываем от лишнего флюса:


Припаивал SMD компоненты китайской инфракрасной паяльной станцией, очень удобно:

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

Программирование atmega644

1. Для начала программирования нужно загрузить в него bootloader. Делается это не сложно с помощью Arduino UNO, но для начала нужно скачать и установить программу .
2. Следующим шагом в установленную программу добавить или взять сразу готовую сборку:
3. Заливаем на UNO скетч ArduinoISP:

4. И подключаем к UNO нашу плату:


В соответствии инструкции скетча:
// pin name // slave reset: 10: // MOSI: 11: // MISO: 12: // SCK: 13:
Получается по моей схеме так:

5. Далее устанавливаем в настройках нашу плату и загружаем bootloader:




Если все удачно прошло, то увидим сообщение: «Запись загрузчика завершена»
На этом загрузка bootloader"a завершена, можно подключать дисплей, кнопки, датчик температуры и заливать

В 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

Никто вам не запрещает спаять собственную плату и самому же её запрограммировать с помощью низкоуровневых языков. Однако автоматика на ардуино и готовых микроконтроллерах значительно облегчит весь процесс и сэкономит время. Ведь куда проще купить уже готовый продукт с набором библиотек и приспособить его под свои задачи. А доступная автоматика на ардуино мега 2560 может пригодиться во многих сферах жизни, от голосовых выключателей для умного дома и до электрических щеколд с детектором движения. Главные преимущества, которыми славится именно автоматика ардуино, это:

  1. Низкий порог вхождения. Нет необходимости получать образование инженера, достаточно просмотреть пару обучающих видео и иметь базу в программировании.
  2. Большое количество уже заготовленных библиотек. Ардуино применяется на просторах СНГ многими любителями робототехники, вплоть до того, что производство различной электроники становится их хобби. Соответственно, и в сети пользовательское сообщество крайне активно, размещает большое количество заготовок и готово вам помочь в решении любых проблем. Качество библиотек, из-за низкого порога вхождения, страдает, но никто не запрещает создать свою собственную, достаточно изучить семантику языка С++ или использовать уже готовые трансляторы.
  3. Большое количество периферии. Неважно, необходима вам автоматизация теплицы на ардуино или датчик освещённости, вы найдёте любые модули, вплоть до датчиков звука и распознавателей голоса. Да, часть плат стоит немалых денег, но всегда можно найти дешёвые аналоги, например, модуль wi-fi от сторонних производителей esp8269, стоящий в 10 раз дешевле официального.
  4. Большое количество информации. Любая проблема, с которой вы столкнулись, уже была у кого-то, и вы наверняка найдёте её решение в Гугле. Существует и полноценная литература, с которой можно ознакомиться.

Однако не стоит думать, что у Ардуино нет изъянов. Плата славится своей низкой производительностью. В особо сложных задачах и при большом количестве кода время отклика может достигать 1 секунды, что непозволительно для микроконтроллеров. Флеш-память у большинства модулей не превышает 1 Мб, чего недостаточно для создания нейросетей или использования медиафайлов. Конечно, можно подсоединить вспомогательную карту памяти, но это же увеличивает время отклика, забирает дополнительные ресурсы на её питание и делается полукустарным способом.

Однако простые автоматизированные системы, например, для варки пива или теплиц, не требуют и части тех ресурсов, что способна выдать плата. Соответственно, большинству пользователей эти недостатки покажутся бессмысленными. Если же вы решите собрать свой 3-Д принтер или более сложную конструкцию, стоит присмотреться к аналогам. Но и порог вхождения у конкурентов Ардуино будет куда выше.

Пример автоматизации процессов на основе мк Arduino

Простейшим примером автоматизации процесса может стать теплица на ардуино. Чтобы создать любую систему, стоит чётко расчертить задачи, которые та должна выполнять. На примере теплицы, это будет:

  1. Создание специального климата.
  2. Своевременное включение и выключение освещения.
  3. Своевременный полив растений и удержание влажности воздуха на одном уровне.

Исходя из этих задач, можно сразу подметить, что вам потребуется купить к основной плате:

  1. Датчик температуры. Он будет следить за тем, чтобы воздух не нагревался и не охлаждался, находясь в прописанных программой пределах. В случае изменения температуры плата будет включать кондиционер или электронные батареи.
  2. Датчик освещённости. Конечно, можно ограничиться программным решением и прикупить дорогостоящие лампы с имитацией дневного света. Но если вы хотите создать полноценную теплицу, то куда удобнее будет установить автоматический потолок, который будет контролироваться Ардуино.
  3. Датчик влажности. Здесь всё так же, как и с температурой, по прописанному сценарию, плата будет включать опрыскиватели и увлажнители воздуха, при необходимости.

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

Программирование мк Arduino для автоматизации процессов. Пример

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

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

Я студент технического ВУЗа. Однажды, сидя в кафе с другом, который тогда учился в медицинском университете, решили открыть бар. Было много идей, которые, в принципе, заслуживали некоторого внимания. Например, танц-пол, который изменяет угол наклона в зависимости от стиля музыки… Но, наряду со всем многообразием идей, так же была еще одна -

… а не сварить ли нам свое пиво?

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

Через несколько лет решил повторить процесс, немного автоматизировав его с помощью Arduino UNO. И вот, что получилось.

Начну с того, что должна делать вся установка.

  • Проверять себя - все ли работает, все ли подключено;
  • Чистить себя;
  • Подготавливаться к процессу пивоварения;
  • Варить пиво в полуавтоматическом режиме;
  • Варить пиво в ручном режиме;
  • Варить пиво в автоматическом режиме (как стиральная машина стирает белье).

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

Подготовка к процессу пивоварения

Сообщение от системы о том, что необходимо залить воду в чан -> программа ждет нажатия клавиши ОК - > программа посылает arduino команду на включение твердотельного реле -> твердотельное реле включает однокиловатный тенн в чане, доводит до температуры 37 градусов, отсылает программе команду, что все готово для варки. Поддерживает температуру 37 градусов.

Хочется, чтобы была проверка на наличие воды, но датчик еще ждет своего отправления от «китайских братьев».

Варка пива в полуавтоматическом режиме

В принципе, несложная процедура:

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

Нужно следовать инструкциям.

Варка пива в ручном режиме

Данный процесс позволяет задавать параметры варки, изменять их в цикле варки. До него еще не дошел.

Варка в автоматическом режиме

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

Закинул ингредиенты в соответствующие лотки, нажал кнопку и… через полтора месяца получил готовое пиво.

Это вкратце о процессе, а теперь перейдем к техническое стороне.

Техническая сторона процесса

Как сказано выше за управляющий микроконтроллер выступает arduino UNO. К нему подключены 2 реле, 2
цифровых термометра DS18B20 .

Arduino общается с основной программой через com порт. Т.к. у меня нет шильда реального времени к arduino, пришлось таймеры брать из visual c#. Опыта написания программ у нет, так что, если вдруг у кого есть идеи, критика - почту за честь. Критикуйте, дербаньте, так сказать, что вдруг не нравится.

Вот текст программы на arduino

#include OneWire ds(8); // датчики температуры сидят на 8 пине int reley1 = 13; int reley2 = 12; int reley3 = 11; int reley4 = 10; int reley5 = 7; //включение тен int reley6 = 6; // тен на заторном чане float temp1; float temp2; void setup(void) { Serial.begin(9600); pinMode(reley1,OUTPUT); pinMode(reley2,OUTPUT); pinMode(reley3,OUTPUT); pinMode(reley4,OUTPUT); pinMode(reley5,OUTPUT); pinMode(reley6,OUTPUT); digitalWrite(reley1,LOW); digitalWrite(reley2,LOW); digitalWrite(reley3,LOW); digitalWrite(reley4,LOW); digitalWrite(reley5,LOW); digitalWrite(reley6,LOW); } void loop(void) { if (Serial.available()) { switch (Serial.read()){ case "i": infuz(); break; case "p": progrev(); break; case "a": avariya(); break; case "v": varka(); break; case "t": temperature(); break; } } } void varka() { digitalWrite(reley6, HIGH); while(Serial.read()!="m") { temperature(); if (temp1 >= 52.00) digitalWrite(reley6,LOW); else digitalWrite(reley6,HIGH); } while(Serial.read()!="n") { //digitalWrite(reley6,HIGH); temperature(); if(temp1>= 62.00) digitalWrite(reley6,LOW); else digitalWrite(reley6,HIGH); } while(Serial.read()!="b") { //digitalWrite(reley6,HIGH); temperature(); if(temp1 >= 75.00) digitalWrite(reley6,LOW); else digitalWrite(reley6,HIGH); } digitalWrite(reley6,LOW); while(Serial.read()!="c") delay(1000); while(Serial.read()!="x") { digitalWrite(reley5,HIGH); temperature(); } digitalWrite(reley5,LOW); } void infuz() { //temperature(); //Serial.available(); while (Serial.read()!="s"){ //выключение цикла инфузионной варки if (temp<=69.50) digitalWrite(reley5,HIGH); else digitalWrite(reley5,LOW); } digitalWrite(reley5,LOW); } void progrev() { while (temp1 <=36.00) temperature(); digitalWrite(reley6,HIGH); digitalWrite(reley6,LOW); //while (temperature() >40.0) //delay(1000); Serial.println("s"); } void avariya(){ digitalWrite(reley1,LOW); digitalWrite(reley2,LOW); digitalWrite(reley3,LOW); digitalWrite(reley4,LOW); digitalWrite(reley5,LOW); } void temperature() { byte i; byte present = 0; byte data; byte addr; byte zator = {40, 23, 218, 43, 6, 0, 0, 22}; // адрес температурного датчика в заторе byte varilka = {40, 255, 240, 115, 59, 4, 0, 234}; //адрес температурного датчика в варильном чане float celsius; // float temp; boolean gde; if (!ds.search(addr)) { //Serial.println("No more addresses."); //Serial.println(); ds.reset_search(); delay(250); // return; } if (OneWire::crc8(addr, 7) != addr) { Serial.println("CRC is not valid!"); // return; } ds.reset(); ds.select(addr); ds.write(0x44, 1); // start conversion, with parasite power on at the end delay(840); // maybe 750ms is enough, maybe not // we might do a ds.depower() here, but the reset will take care of it. present = ds.reset(); ds.select(addr); ds.write(0xBE); // Read Scratchpad for (i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read(); } int16_t raw = (data << 8) | data; byte cfg = (data & 0x60); if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms celsius = (float)raw / 16.0; for(i = 0; i<8; i++) { if (addr[i] == zator[i]) gde = true; else { gde = false; break; } } if (gde) { Serial.print("t2 "); //temperatura варочника temp2 = celsius; Serial.print(temp2); Serial.println(); } else { Serial.print("t1 "); //температура затора temp2 = celsius; Serial.print(temp1); } }

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

Вкратце опишу, что делает программа.

Программа разделена на подпрограммы, каждая из которых активируется, если на com порту появляется определенный символ. Например, если в порт попадает буква «p», то включается режим «Прогрев». Или же, если «a» - то вызывается подпрограмма avariya() и все отключается. При вызове подпрограммы temperature() данные записываются в глобальные переменные temp1, temp2. Оттуда и попадают в нужные подпрограммы.

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

Теперь, что касается основной программы управления.

Основная программа управления

Она написана на visual studio c#.

Исходный код программы:

Исходный код программы

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 порта программа не подвисала на момент выполнения подпрограммы. После окончания подпрограммы программа отвисает, но пока это не критично и даже некий плюс. Защита от дурака - чтобы не нажать ничего во время определенной процедуры.

Итого, программа умеет

- готовить оборудование к варке;
- варить;
- писать простенький лог работы (очень полезно при дальнейшем анализе варки);
- выбирать порт для подключение к управляющему контроллеру(arduino UNO);
кипятить варочник и заторный чаны.

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

to be continued...

UPD:

Вот несколько фотографий пивоварни

Это варочный котел. Таких у меня два. С боку установлен датчик температуры DS18B20 в герметичной оправе.
Долго не мог понять, почему периодически arduino виснет, пока не осенило, что нужно все заземлить, наче пробивает на корпус, далее на корпус датчика и на arduino.

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

Пока рано говорить о результате, вот что получилось

Общий вид чана выглядит вот так.

Использовал обычные коннекторы
для подключения датчиков температуры, подключающиеся к двойной розетке. Удобнее мыть оборудование. Отключил, понес в ванную. Помыл, подключил и все работает.

Все пенилось по графику, лишнего не вытекало. А самых ближайших планах - слить на дображивание партию пива, сварить еще одну. Рецепт, в принципе можно посмотреть в коде в подпрограмме varka() у arduino.

Наконец-то пришли соленойдные клапаны. Процесс автоматизации продолжается.

Похожие статьи