Через несколько лет решил повторить процесс, немного автоматизировав его с помощью 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.
Наконец-то пришли соленойдные клапаны. Процесс автоматизации продолжается.
Всем привет!
С момента, когда я решил построить свою автоматизированную пивоварню прошло много времени. Вот первый пост .
Сегодня контроллер полностью готов, осталось сделать само варочно-фильтровальное устройство. Все делалось моими собственными руками. Прошу не судить строго, у меня нет инженерного образования, я простой гуманитарий! Расскажу по-порядку, как и из чего это делалось. Внимание, траффик, много фоток! Коротко о разработке. Выполнено на Arduino. Звуковая, световая индикация, индикация тока и напряжения (т.к. аппарат отладочный, мне необходимо следить за этими показателями). Аварийное отключение. Вся система на полупроводниковых реле. Силовая часть развязана с цифровой. Управление 4 нагрузками 25-40А (масштабируется), память рецептов на 8 штук. 8 температурных пауз. Интуитивно понятный интерфейс. Полностью ручной или полностью автоматический режим. Автоматическая CIP мойка. 2 температурных датчика с точностью 0,1гр. Датчик жидкости в котле. Датчик жидкости при перекачке. Производительность - от 20л до 1000л. Управление аэрацией, вирпулом, помпой, резервный выход. Настраиваемый PID, под разные емкости (beta), USB для обновления софта, в скором будущем - дистанционное управление с iPhone/iPad. Сейчас можно управлять с компа, с экрана монитора, даже через интернет.
Начнем. Сначала я выбрал в магазине корпус. Цены очень разные. Выбрал приемлемый по размеру и цене, забегая вперед, скажу, что начинка влезла на пределе, в меньший корпус не поместилась бы:
Сложная работа по разметке управляющих элементов. Все начинка, кроме корпуса, проводов и контактора, были куплены за рубежом. В этой стране по внятной цене ничего не купить.
С конфигурацией определился, нижний ряд кнопок оставлен на будущее, под расширение возможностей:
Наклеил малярный скотч и нарисовал карандашом разметку.
Дело за малым. Вырезать отверстия. Прямоугольные делались электролобзиком, пилкой с самым мелким зубом. Круглые - ступенчатым сверлом-ёлочкой. Мелкие круглые - дрелью.
Все отверстия обрабатывались напильником.
И покрасил. Замечу, сделал я это зря, краска нещадно откалывается при любом контакте. Красил на 3-4 слоя. Грунт не использовал.
Подождал сутки, когда высохнет краска и разместил элементы.
Радиатор я купил по объявлению, он с местного телецентра, стоял на ТВ передатчике на местной телевышке, пришлось отпилить, отдавал на завод, т.к. лобзик не берет, он тяжеленный из неведомого сплава.
С обратной стороны.
Внутри.
В сборе.
Проверка электроники.
Набросал очень сложную схему, без схемы - никуда!
Подключил все и припаял. Пошагово не снимал, не до этого было.
Еще один вид. Каждую компрессионною клемму я пропаиваю.
Розетки на исполнительные устройства.
SSR реле. Использовал двух номиналов и разных производителей, так интереснее.
Вот, что получилось. Кнопки выбора поставил другие, более удобные и зеленые, так, я думаю выглядит красивее, а то красного слишком много:)
Немного прибрался на столе и на тест! Вместо ТЭН, нагрузкой и нагревающим элементом является винтажная настольная лампа.
Наклеил таблички на Момент Кристалл. Таблички специальные, заказанные в фирме. Бывают двух видов Гравертон и Гедаколор, отличаются по цене, качеству и стойкости. Какие у меня, уже и не помню. И все готово!
А тем временем, на столе уже ждет новый мозг с новыми возможностями для новейшей разработки! :)
Следующий этап, подбор компонентов для варочника и окончательная постройка. Но об этом в следующей части
Чтобы я сделал, по-другому, не стал бы красить, на фотках видны многочисленные сколы. Но блок предназначен к настенной стационарной установке, поэтому краска не будет так отбиваться. На данный момент все работает как положено, осталось доделать варочник со всей обвязкой. Вопрос времени и денег.
Мое пожелание начинающим пивоварам, не пытайтесь сразу строить автомат, не выйдет. Нужно сначала, вникнуть во все детали, выбросите деньги и время.
По договоренности с автором кода, код не выкладывается в открытый доступ по нескольким причинам: программа заточена под мою конкретную разработку, под конкретный цикл, и возможно, в дальнейшем, превратится в коммерческий продукт. Я лишь показал пример.
Попрошу прощение за качество фоток, все делалось на телефон. Спасибо всем, кто дочитал до конца!
Для тех, кого заинтересовало домашнее пивоварение,
Мне хотелось бы представить очередной пример использования Arduino в реальных задачах. Тут я представлю максимально простой, но реально работающий проект регулировки отопления дома с помощью электрокотла на базе Arduino. Я очень надеюсь, что эта статья поможет кому-то отбросить страхи и попробовать самостоятельно применить свои руки по назначению, это очень здорово тренирует руки, мозги и даёт редкое чувство удовлетворения созданием чего-то интересного. Начав работать с этим контроллером, я до сих пор нахожусь в некотором замешательстве от возможностей, открывающихся при его использовании.
Впоследствии решено было систему модернизировать, добавить насос для принудительной рециркуляции теплоносителя и небольшой 2-киловаттный электрокотёл, чтобы не мучиться с разжиганием газа, когда ещё не очень холодно. Вся автоматизация сводилась к наличию большого рубильника на стене, когда становилось холодновато, его включали, а когда жарковато - выключали. Двух киловатт хватало где-то до температуры 0°C, дальше приходилось зажигать газ или печь, что было крайне неудобно.
Схема неплохо работала почти месяц, а потом я заметил, что дома как-то слишком жарко. Проверка показала, что одно реле “запало” в включенном положении. Постучал по нему - заработало опять, но хватило на несколько дней. Поменял его в надежде, что это брак, но уже через неделю то же самое случилось со 2-м реле. Поставив последнее запасное, отправился опять на али. Там были обнаружены специализированные реле для ардуино на 40А! Этих-то должно хватить наверняка, подумал я. Пара-тройка недель ожидания, и вот опять выкидываю транзисторы и ставлю новые реле с уже готовой обвязкой и индикацией. Радость была недолгой, недели через 2-3 опять залипшее реле. Начал изучать вопрос, оказывается, чтобы уменьшить нагрузку на реле и убрать искрение контактов, реле надо включать не как попало, а в момент, когда синусоида напряжения проходит через 0. Ну, в теории это можно сделать с помощью нашего же ардуино, только на подключить через делить все три фазы и смотреть напряжение. Проблема ещё и в том, что реле имеет некоторое время реагирования и, собственно, нам ещё надо его установить опытным путём. В общем, задачка не такая простая.
И тут я наталкиваюсь на так называемые Solid State Relay, проще говоря - электросхемка, собранная на мощном тиристоре, в корпусе, похожем на обычное реле. Из его плюсов - нет механики, ничего не залипнет. Не создаёт мощных ЭМ-помех, что важно для ethernet’a, о котором ниже. Они уже содержат схему, которая включает и отключает реле при проходе нуля. На реле есть индикатор включения. Ну и ещё они беззвучные, хотя для нашего случае это не так и актуально. После изучения инструкций и характеристик были заказаны SSR-40DA, что по-русски означает - твёрдотельное реле с постоянным управляющим током 3-5В и током нагрузки до 40А. Заодно решил немного отойти от принципа «проще-лучше» и сделать ещё контроль тока в ТЭНах. Это позволило бы узнать о перегоревшем ТЭНе/реле или отключении питания на одной из фаз. Добавил в заказ модуль контроля тока на 20А, хотя выглядели они хлипковато для такого тока (2.5 квадрата кабель даже не лез в их зажим). Когда реле и модули измерения тока пришли, оказалось, что реле достаточно громоздкие, поэтому было решено перенести всё, что связано с высоковольтной частью в новый ящик, а ардуино оставить в старом.
После первых экспериментов оказалось, что я совершенно забыл, что эти реле, так как собраны на тиристорах, довольно сильно греются. Через сутки работы реле нагревались так, что я не мог терпеть, держа на них палец, то есть градусов 60C, а это уже близко к критическим 80C. Опять полез на али, прикидывая, какие радиаторы приспособить, и тут узнал, что для этих SSR есть штатные радиаторы! На момент установки радиаторов также обнаружил, что один модуль контроля тока сам ток больше не пропускает, а со стороны платы видна подгорелая дорожка. Ещё один модуль также не вызывал уверенности, решил снять их все. В таком виде они всё же слабоваты и опасны, а толку от них не так и много. Проблему отключения фаз или ТЭНов пока отложил как не очень актуальную, за 3 года ни первого, ни второго не случалось не разу.
Оказалось, не так и просто. Полез смотреть, как это делают в продаваемых системах, оказалось, там всё либо максимально просто, как в утюге - +1C = выкл, -1 = вкл. Но тогда мы получаем почти 4C колебаний из-за инертности системы! Это слишком грубо, ибо мы можем получать данные с точностью до десятой доли градуса. Также посмотрел алгоритмы работы с использованием температуры уличного воздуха, они оказались достаточно простые и работали на готовых таблицах, которые были заранее зашиты и просто менялись в зависимости от теплопотерь дома. Копая глубже и глубже, я докопался до промышленных установок, в них повсеместно использовали алгоритмы PID-регуляторов. И, о слава популярности, оказывается, у Arduino есть бесплатная PID-библиотека!
Пару слов о том, что такое PID применительно к нашему случаю. Смысл алгоритма в том, что мы сообщаем ему требуемое значение некоторого параметра (температура внутри дома) и в цикле передаём текущее значение, а он выдаёт нам необходимое воздействие (мощность, которую надо подать на котёл). Не вдаваясь в подробности математической модели, как же он работает с точки зрения программиста. Итак, мы имеем температуру в комнате, пусть 20C, желательную температуру 22С, и даём их нашему PID-алгоритму.
Сам алгоритм имеет 3 независимые части, по имени P, I и D. Первая часть работает крайне просто, смотрит на разницу между желательной температурой и текущей температурами. То есть чем холоднее, тем большую мощность нам даст алгоритм. Вроде бы, этого и достаточно, но ведь у нас есть постоянные теплопотери дома, то есть, чтобы держать нужную температуру, нам надо постоянно давать какую-то мощность. То есть даже если температура в комнате равна заданной, нельзя отключать котёл, а надо как-то искать какую-то мощность, равную теплопотерям. А теплопотери меняются в зависимости от температуры на улице. Вот этим и занимается вторая часть под именем I. Алгоритм пытается подобрать мощность, при которой наша температура будет постоянной. И вроде тут-то уже точно всё, но нет.
Дело в том, что сам котёл, теплоноситель, а тем более дом имеют очень большую инертность. И если вы врубили котёл на 100%, то снижать мощность нужно куда раньше, чем температура достигнет желательной, иначе даже при полном отключении мы всё равно успеем перегреть комнату градуса на 2. То же самое при понижении температуры, добавлять мощность надо ещё до того, как температура дошла до нужной. Вот этим и занимается третья часть алгоритма D. Ну теперь, конечно, всё, осталось только понять, какой части давать какой вес, а вот этим занимаются множители каждой части, которые и надо подбирать. Кстати, подбор этих множителей - отдельная и довольно сложная математическая задача, я подбирал их “на глаз”, вспоминая сказанное выше. Сначала ставил все нули, кроме P, и подбирал его так, чтобы не началось само возбуждение. Потом добавлял I, а в конце и D.
То есть, не считая витой пары и самого котла, весь проект укладывается в 4 тысячи рублей.
Складываем данные в базу и показываем.
Но всё это, конечно, хорошо, но не стоять же постоянно с компьютером рядом с котлом, всё же хотелось бы знать о том, что происходит дома, удалённо через инет. У меня давно уже был самый простенький VPS сервер от majordomo для чего попало. На нём создал базу данных на MySQL для хранения данных о температуре.
Теперь нам надо как-то положить данные из arduino в эту базу. Для этого, естественно, понадобится как минимум связать arduino с интернетом, это не просто, а очень просто. Для этого нам и понадобится Ethernet Shield и его библиотека. В доме давно уже установлен простенький роутер со “свистком” сначала от megafon, а потом от yota. Тянем стандартную витую пару к роутеру и добавляем в программу передачу данных. Передача идёт через вызов странички на PHP с параметрами - данными. Создаём страничку с именем temp.php на нашем инет-сервере
Data upload error!
";} else {echo "";} mysql_close($connect); ?>\n"; while ($line = mysql_fetch_array($result, MYSQL_NUM)) { echo "
#include