Ардуино управление газовым котлом


Предыстория. Очень хороший друг детства попросил отремонтировать бойлер т.к. он перестал отключаться при нагреве. Даже термометр на корпусе бойлера сплавился. Естественно сразу появилось подозрение на неисправность терморегулятора но т.к. он очень неудобно расположен сзади и сбоку бойлера что просто нереально открутить закрывающую его крышку и вообще оценить состояние терморегулятора. Было принято решение снять его и привезти на ремонт ко мне домой.

Сгоревший термодатчик
Сгоревший термодатчик

После снятия крышки терморегулятора была обнаружена неисправность собственно терморегулятора, точнее вместо терморегулятора стоял простой термопредохранитель на 95 градусов Цельсия.


попросту сплавился и его заклинило на «вечное включение». Я предложил снять один из двух предохранительных терморегуляторов которые стояли в том же бойлере снизу и практически никак не могли его защитить от перегрева. Друг сказал что ему надо хотя бы знать какая температура воды в бойлере… А термометр то сломан! На что я и предложил сделать ему схему на контроллере и отображением состояния бойлера на индикаторе. По цене это выйдет около 700р. только за все детали. За работу я с него денег естественно не возьму.  Он подумал и сказал- Делай. Вот с такой историей сломанный бойлер оказался в моем полном распоряжении.

Исследования.

  1. Я предложил другу сделать отдельную коробку (использовал бы распределительную электрическую коробку) и в ней разместить всю электронику. Он сказал что не хотелось бы вешать еще всяких коробок. Опять же пришлось ставить дополнительные разъемы под термодатчик и какую нибудь розетку для подключения ТЭНа бойлера. Но опять же такая схема была бы максимально защищена от возможной протечки бойлера, т.к. при сборке на нижней крышке вода может залить всю схему и, соответственно, все к херам выгорит. Сказано было сделать максимально компактно, т.е. в нижней крышке. Хорошо. Сказано- делаем.
  2. Следующий момент на который я обратил внимание т.к. схема должна монтироваться в непосредственной близости от бака бойлера- температурный режим 328 атмеги. Скачал даташит и увидел что максимальная температура кристалла- плюс 85 градусов Цельсия. Значит делаем вывод что максимальная рабочая температура бойлера должна составлять 80 градусов, лучше конечно поменьше, все равно это уже практически кипяток.

  3. Реле включения ТЭНа. Т.к. мощность ТЭНа составляет 1300Вт то рассчитываем ток из формулы I=P/U, где I- ток,А, P- мощность в Ваттах, U- напряжение , в данном случае 220В. Получаем 1300/220=5,91А. Таким образом нам подойдет релейная сборка KY-019 которая выдерживает ток до 10А и мощность при 220В аж целых 2,2кВт!  У меня в наличии оказалась только сдвоенная релейная сборка которая прям идеально подходила под крышку бойлера. Решил использовать одно реле на включение / отключение ТЭНа, т.е. регулировке температуры а вторую сделать как аварийной при температуре выше 83 градусов. Почему это сделано именно так. Ну во первых по даташиту контроллера температура не должна быть выше 85 градусов (см. п.2), соответственно нужно отключать ее немного раньше. Тут стоит взглянуть на строение бойлера. Термодатчик будет установлен в районе середины бака по высоте. Как известно тепло всегда стремится вверх, при этом холодная часть вещества будет всегда снизу. Понятно что при температуре на датчике в 83 градуса нижняя часть бойлера будет иметь меньшую температуру чем верхняя и мы имеем некий буфер от перегрева контроллера.
  4. Датчиком будет являться Dallas DS1820 который выдерживает температуру до 120 градусов. Можно конечно применить и терморезисторы но у меня их не оказалось и я решил использовать DS1820.

  5. Контроллер решил поставить Nano 3.0 хотя вот буквально только что подумал что хватило бы и 8 атмеги за глаза но… плата уже сделана, запущена и работает а переделывать… не хочется, все равно потом закажу еще деталей. Опять же под перепрошивку на Нано уже есть разъем а Атмегу пришлось бы ставить на панель и каждый раз перешивать.
  6. В роли регулятора температуры решил использовать простой переменный резистор на 10кОм подключенный крайними выводами к питанию а ползунок подключить к аналоговому входу через резистор 330 Ом (чтобы при питании выше 5 В нечаянно не пожечь вход).
  7. Блок питания решил взять из зарядника телефона. Можно конечно использовать 5 В по 50 руб с Али но у них мощности хватает в обрез и я боюсь что при длительном использовании они просто не выдержат и сгорят. Все устройство потребляет около 200 мА при включенных релюшках. Поэтому пришлось взять именно БП из зарядника телефона.
  8. Вы могли бы предложить поставить готовый терморегулятор с Али всего за 150-200 руб но… люди там до того боятся техники что им нужен минимализм во всем электронном. Т.е. буквально выключатель и регулятор температуры. А в китайском варианте в 3 кнопках они точно запутаются.

Вот такие небольшие исследования пришлось провести прежде чем взяться за реализацию проекта. Скетч был написан буквально за полчаса. Он был тупо переделан из моего датчика управления котлом из которого я вырезал библиотеку работы с ЕЕПРОМ (здесь она уже не нужна) и много чего другого. Скетч привожу ниже.


  #include <OneWire.h>  #include <LiquidCrystal.h>    LiquidCrystal lcd(12, 11, 5, 4, 3, 2);  OneWire ds(10);  int iNastrTemp; // настраиваемая температура  int16_t iTekTemp; // текущая температура  int Delta = 5; //дельта по умолчанию  byte sw = 0; // для включения реле    void setup() {   lcd.begin(16, 2);   pinMode(13, OUTPUT); // пин для управления РАБОЧИМ реле   pinMode(9, OUTPUT); // пин для управления ЗАЩИТНЫМ реле     // ВНИМАНИЕ! На реле активный уровень -LOW!!!     digitalWrite(9, LOW); // включаем защитное реле   digitalWrite(13, HIGH); // выключаем рабочее реле      iTekTemp = inCurTemp();// запускаем прогрев температурного датчика (850 мс)     // экран загрузки для стабилизации температурного датчика   lcd.setCursor(6, 0);   lcd.print("Hi");   lcd.setCursor(3, 1);   lcd.print("Loading");   delay(800);   byte count = 0;   while (count != 3)   {   lcd.print(".");   delay(600);   count++;   }   lcd.clear();    }    void loop() {     iTekTemp = inCurTemp();// измеряем температуру   iNastrTemp = map(analogRead(A7), 0, 1000, 10, 80); // устанавливаем температуру       // аварийное отключение     if (iTekTemp > 83 || iTekTemp < 0)   {   digitalWrite(13, HIGH); // выключ.  

"); } else // при повышенной температуре { digitalWrite(13, HIGH); lcd.setCursor(13, 0); lcd.print("OFF"); sw = 0; // флаг на то что система остывает на дельту } if (iTekTemp <= iNastrTemp - Delta) // при пониженной температуре { digitalWrite(13, LOW); lcd.setCursor(13, 0); lcd.print(" ON"); sw = 1; } } } //-------------------------функции-------------------------------// void display(int TCur, int TSet) { lcd.setCursor(0, 0); lcd.print("Current"); lcd.setCursor(8, 0); lcd.print(TCur); lcd.setCursor(10, 0); lcd.print("'C"); lcd.setCursor(0, 1); lcd.print("Set"); lcd.setCursor(8, 1); lcd.print(TSet); lcd.setCursor(10, 1); lcd.print("'C"); } int16_t inCurTemp() { byte data[2]; ds.reset(); ds.write(0xCC); ds.write(0x44); ds.reset(); ds.write(0xCC); ds.write(0xBE); data[0] = ds.read(); data[1] = ds.read(); int Temper = (data[1] << 8) + data[0]; Temper = Temper >> 4; return Temper; }

Описывать как все это работает смысла не вижу т.к. вы, если изучали  предыдущие уроки, уже вполне можете сами разобраться что и как написано. Критика кстати принимается. Принцип работы такой:


  1. При включении подаем на выходы управления реле (в моем случае 13 вывод- рабочее реле, 9- защитное реле) высокий потенциал на 13 вывод (отключаем реле принудительно) и низкий на 9 (включаем защитное реле). В первоначальном варианте я подавал по логике высокий уровень на включение а низкий- на отключение и у меня все работало… только в зеркальном варианте. Нашел схему и сразу все стало понятно что активный уровень в данном модуле- низкий. Хотя мне мой друг сказал что есть модули с высоким активным уровнем… Можно конечно было через транзисторы инвертировать сигнал но усложнять схему мне не захотелось.
  2. Затем запускаем измерение температуры функцией inCurTemp(). Выводим экран загрузки и снова измеряем температуру. Почему я 2 раза измеряю температуру спросите вы? При первом измерении запускается датчик температуры и он выдаст стандартное значение в 85 градусов т.к. сам термодатчик еще не инициализировался. По даташиту DS1820 необходимо 850 миллисекунд для выхода в рабочий режим. Поэтому придаем «красивость» интерфейсу через строку загрузки. За это время термодатчик выйдет в рабочий режим и начнет давать корректные показания. Поэтому просто измеряем температуру еще раз. Простое решение проблемы.

  3. Строка в рабочем цикле iNastrTemp = map(analogRead(A7), 0, 1000, 10, 80);  является одной из главных во всем скетче. Она отвечает за установку температуры нагрева. Раньше я объяснял как работать с оператором map но объясню еще раз. Мы берем этим оператором пределы значений одного измерения и преобразуем их в совершенно другой предел. В данной строке мы получаем данные с аналогового входа А7, берем значения от 0 до 1000 (напоминаю что аналоговые входы 10 битные и принимаю 1024 значения в пределах от 0 до 1023) и преобразуем их в предел от 10 до 80 (значение установленной температуры). Т.е простым преобразованием поступивших данных с входа А7 мы можем напрямую указать нужную температуру нагрева! Всего одна строка и никаких мучений с придумыванием формул и описанием буквально каждого состояния аналогового порта. Опять же значения вы можете поменять под себя. Можно было указать более низкую температуру но тогда придется еще ввести условие на значение температуры меньше 10 для корректного отображения на LCD. Или дописывать ноль перед значением, или ставить пробел после значения чтобы затереть предыдущие показания.
  4. Затем идут уже обработки на аварийное отключение защитного реле (больше 83 градусов) и сам цикл работы. Цикл работы следующий: нагревается вода до заданной температуры, отключается рабочее реле, как только вода в бойлере остынет на Delta градусов- реле опять включится.

    льту я установил равным 5 градусам. Меньшие значения позволят поддерживать температуру более точно но увеличивают количество срабатываний рабочего реле, что сократит срок его службы. Большие значения дельты будут проявляться в редком включении рабочего реле но и выходящая вода будет иметь большой разброс по температуре, что тоже не является нормальным т.к. заставляет постоянно подбирать нужную температуру моющемуся. Кстати защитное реле после перегрева больше не включается  до тех пор,  пока не перезапитаете бойлер, что позволит понять причину перегрева- залипание контактов рабочего реле.
  5. При аварийном срабатывании ВСЕГДА отключается сначала рабочее реле и лишь затем, через небольшую задержку, защитное. Это сделано для того чтобы защитное реле имело как можно меньшее срабатывании под нагрузкой. Т.е. максимально исключено воздействие электрической дуги на ее контакты и, соответственно, снижена вероятность залипания контактов реле. Что для защитного реле является самым главным условием. Т.е. при залипании контактов рабочего реле аварийное реле должно сработать и выдать сообщение о перегреве.

Функции вывода сообщений на дисплей и измерения температуры просто нет смысла описывать. Перейдем к самой конструкции и сборке бойлера. Первым делом я убрал с передней панели 2 выключателя и выпилил на их месте отверстие под LCD 1602. Слева просверлил на небольшом расстоянии отверстие диаметром 20мм пёркой под выключатель, а справа на таком же расстоянии отверстие диаметром 7 мм под переменный резистор для регулировки температуры.


е стало красиво на свои места! Затем был мучительный процесс придумывания как закрепить плату с контроллером, соединить его с дисплеем и остальной периферией. Решил напаять плату прямо на выводы дисплея. Но для такого варианта нужно было бы использовать двухсторонний текстолит. Он конечно есть но ковыряться с двухсторонней платой катастрофически не хотелось. Поэтому просто впаял под выводы подключения на плате изогнутые пин- штырьки и намертво припаял к штырькам дисплея. Получилось даже лучше чем ожидал.  Штырьки дисплея предварительно подогнул чтобы контроллер не упирался в дно бачка бойлера.

Установка температурного датчика DS1820
Установка температурного датчика DS1820

Датчик Dallas DS1820 установил на месте старого термопредохранителя. Для этого пришлось выгнуть из оцинковки S- образную полосу. Под место установки термодатчика поставил резиновую прокладку, сам термодатчик посадил на термоклей непосредственно к колбе бойлера и прижал сверху полосой через резиновую прокладку чтобы тепло меньше отводилось в металл. Выводы обязательно нужно затянуть в термоусадку чтобы они не могли замкнуть на корпус. Можно конечно поставить термодатчик в отверстие рядом с ТЭНом, которое собственно и предназначено для установки термодатчика но я сделал по старой схеме и просто тупо перетянул провода и установил датчик на старое место. Вы можете сколхозить какую нибудь конструкцию и закрепить термодатчик где вам больше нравится. Единственное условие- устанавливать надо на всю глубину гнезда.


Закрепленные модули в бойлере
Закрепленные модули в бойлере

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

Внешний вид готового терморегулятора
Внешний вид готового терморегулятора

Внешний вид полусобранного регулятора приведен на фото. Осталось только прикрутить саму крышку к корпусу.

Ниже привожу схему данного устройства.

Схема регулятора температуры для бойлера
Схема регулятора температуры для бойлера

На ней не указан блок питания, хотя это само собой подразумевается. Схема элементарная и доступна даже начинающему.

Хочу предупредить что на некоторых участках схемы будет опасное напряжение в 220 вольт. Будьте осторожны при сборке, настройке и подключении устройства! 

Печатную плату вы тоже можете скачать здесь.

PS. Ввиду того что WordPress некорректно отображает кавычки

Ошибка при переносе скетча в WordPress
Ошибка при переносе скетча в WordPress

и по замечанию пользователя Ruslan выкладываю сам скетч. Архив скетча можете скачать ЗДЕСЬ. Ruslan, спасибо за замечание. Тем кто хочет скачивать- просто замените кавычки как показано на скриншоте сбоку во всем скетче.

 

 

 

 

 

 

Руслан, специально для тебя- бойлер с звуковой индикацией неисправности:

  #include <OneWire.h>  #include <LiquidCrystal.h>    LiquidCrystal lcd(12, 11, 5, 4, 3, 2);  OneWire ds(10);  int iNastrTemp; // настраиваемая температура  int16_t iTekTemp; // текущая температура  int Delta = 5; //дельта по умолчанию  byte sw = 0; // для включения реле    void setup() {   lcd.begin(16, 2);   pinMode(13, OUTPUT); // пин для управления РАБОЧИМ реле   pinMode(9, OUTPUT); // пин для управления ЗАЩИТНЫМ реле   pinMode(11, OUTPUT); // пин для звука   // ВНИМАНИЕ! На реле активный уровень -LOW!!!     digitalWrite(9, LOW); // включаем защитное реле   digitalWrite(13, HIGH); // выключаем рабочее реле     iTekTemp = inCurTemp();// запускаем прогрев температурного датчика (850 мс)     // экран загрузки для стабилизации температурного датчика   lcd.setCursor(6, 0);   lcd.print("Hi");   lcd.setCursor(3, 1);   lcd.print("Loading");   delay(800);   byte count = 0;   while (count != 3)   {   lcd.print(".");   delay(600);   count++;   }   lcd.clear();    }    void loop() {     iTekTemp = inCurTemp();// измеряем температуру   iNastrTemp = map(analogRead(A7), 0, 1000, 10, 80); // устанавливаем температуру       // аварийное отключение     if (iTekTemp > 83 || iTekTemp < 0) { // прежде всего- выключаем питание с ТЭНа digitalWrite(13, HIGH); // выключаем рабочее реле delay(100); // небольшая задержка для отмены искрения защитного реле digitalWrite(9, HIGH); // выключаем защитное реле // теперь выводим сообщения и звук if (iTekTemp > 83 ) // перегрев бойлера   {   lcd.clear();   lcd.setCursor(0, 0);   lcd.print ("HIGH TEMPERATURE");   Sound(500, 1000); // вызываем функцию звука (описана ниже) через каждые 0,5 сек (500 мсек) издается звук 1000 Гц с длительностью 500 мсек.   lcd.clear();   }   if (iTekTemp < 0) // обрыв датчика   { lcd.clear();   lcd.setCursor(0, 0);   lcd.print ("NO DATA");   delay(100);   Sound(50, 1000); // вызываем функцию звука (описана ниже) через каждые 0,05 сек (50 мсек) издается звук 1000 Гц с длительностью 50 мсек. т.е. короткие и быстрые звуки   lcd.clear();   }   }   else // рабочий цикл   {   display(iTekTemp, iNastrTemp);   if ((iNastrTemp - Delta < iTekTemp) && (iTekTemp < iNastrTemp) && (sw == 1)) // работа в дельте   {   digitalWrite(13, LOW);   lcd.setCursor(13, 0);   lcd.print(" ON");   }   else // при повышенной температуре   {   digitalWrite(13, HIGH);   lcd.setCursor(13, 0);   lcd.print("OFF");   sw = 0; // флаг на то что система остывает на дельту     }     if (iTekTemp <= iNastrTemp - Delta) // при пониженной температуре   {   digitalWrite(13, LOW);   lcd.setCursor(13, 0);   lcd.print(" ON");   sw = 1;   }   }  }  //-------------------------функции-------------------------------//  void display(int TCur, int TSet)  {   lcd.setCursor(0, 0);   lcd.print("Current");   lcd.setCursor(8, 0);   lcd.print(TCur);   lcd.setCursor(10, 0);   lcd.print("'C");   lcd.setCursor(0, 1);   lcd.print("Set");   lcd.setCursor(8, 1);   lcd.print(TSet);   lcd.setCursor(10, 1);   lcd.print("'C");    }    int inCurTemp()  {   byte data[2];   ds.reset();   ds.write(0xCC);   ds.write(0x44);   ds.reset();   ds.write(0xCC);   ds.write(0xBE);   data[0] = ds.read();   data[1] = ds.read();   int Temper = (data[1] << 8) + data[0]; Temper = Temper >> 4;   return Temper;  }    void Sound (int tm, int freq)  {   tone (11, freq);   delay (tm);   noTone(11);   delay (tm);  }    

Источник: samosdel.ru

Схема отопления

Основной принцип данного проекта — это процесс регулирования электрокотла с помощью самой простой и приземлённой платой Arduino UNO.

Вот непосредственно сам шкаф управления, «мозги» на основе Arduino.

шкаф управления

Это как раз делалось для дома в деревне. Регулирование температуры ведётся в одной комнате.

Какое же само оборудование? Я не буду расписывать большие тексты. Напишу конкретно. Для системы требуется следующее.

  • Электрокотёл на 4-6 кВт
  • рециркуляционный насос

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

Система управления на Arduino не совсем простая, включать и выключать реле по PID-закону. Лучше всего два ТЭНа включать сразу, а одним поддерживать температуру, это самый надёжный и наиболее точный способ.

Ток потребления нагревателя составляет примерно 8 А. Лучше всего управлять твердотельными реле с запасом по мощности, примерно ампер 15-20 и с охлаждающим радиатором.

Есть готовые модули Solid State Relay, проще говоря — электросхема, собранная на мощном тиристоре, в корпусе, похожем на обычное реле. Из его плюсов — нет механики, ничего не залипнет. Не создаёт мощных ЭМ-помех, что важно для ethernet’a, о котором ниже.

Они уже содержат схему, которая включает и отключает реле при проходе нуля. На реле есть индикатор включения. Ну и ещё они беззвучные, хотя для нашего случае это не так и актуально. Были установлены SSR-25DA, что по-русски означает — твердотельное реле с постоянным управляющим током 3-5В и током нагрузки до 25А.

К ним есть штатные радиаторы, они должны быть установлены — ОБЯЗАТЕЛЬНО!! Не забываем смазать термопастой, для улучшения теплообмена.

шкаф электромеханики

Для измерения температуры были использованы цифровые датчики температуры на базе DS18B20.

Список оборудования и ПО

Что же применялось в конечном итоге:

  • Плата arduino. Использовалась UNO r3
  •  Ethernet Shield
  •  Витая пара
  •  Датчики температуры
  •  Блок питания на 110-240 — 12В 2А
  •  Стабилизатор LM7805
  •  Реле SSR-40DA 3 шт
  •  Радиаторы для реле

Но всё это, конечно, хорошо, но не стоять же постоянно с компьютером рядом с котлом, всё же хотелось бы знать о том, что происходит дома, удалённо через инет. Уже был самый простенький VPS сервер от majordomo для чего попало. На нём создана база данных на MySQL для хранения данных о температуре. (на этом мои познания пока ограничены).

Отопление

Теперь нам надо как-то положить данные из arduino в эту базу. Для этого, естественно, понадобится как минимум связать arduino с интернетом.

Для этого нам и понадобится Ethernet Shield и его библиотека. Установлен простенький роутер. Тянем стандартную витую пару к роутеру и добавляем в программу передачу данных. Передача идёт через вызов странички на PHP с параметрами — данными. Создаём страничку с именем temp.php на нашем инет-сервере.

После этого мы имеем данные о температурах и мощности работы котла, чтобы каждый раз не лазить в базу, а посмотреть последние данные, автор написал “временный” скрипт на php, gettemp.php

Вот и практическое применение языка PHP в сфере автоматизации. Честно говоря, пока не углублялся в такие дебри, но всё равно интересно!!!

Ну и, сам скетч.

Здесь я останавливаюсь, спасибо автору за его проект. Было бы интересно пообщаться, я всегда на связи. Спасибо за внимание! Всего доброго!!!

С уважением, Гридин Семён

Источник: kip-world.ru

История

Почему, собственно, Arduino? Простота, доступность, масса документации и библиотек. Как, наверное, многие, я долго присматривался к Arduino, с детства люблю всякие батарейки и моторчики, а тут новый уровень, полноценный язык программирования и куча возможностей ввода-вывода. Когда его начали выпускать наши “наиболее вероятные экономические партнёры”, цены на него упали до приемлемого уровня. В результате купил старт кит и, вдоволь наморгавшись светодиодами и индикаторами, поимел желание применить его где-то по хозяйству.

image

Что отапливаем

У меня бабушка живёт в деревенском доме под Москвой, там нет ни нормального водоснабжения, ни газа, ни отопления, а решение всех этих задач требует больших капиталовложений либо приложения рук. Вот тут и виделось место, где можно полноценно использовать arduino, есть где развернуться. Самый большой плюс деревенского дома в том, что он традиционно не большой и очень простой. Так и мой — типичный дом крестьянской семьи середины 20-го века, представляет из себя бревенчатый сруб с одной большой комнатой и кухней. Других отапливаемых помещений нет, что для нас плюс, достаточно поддерживать и контролировать температуру в единственной комнате.

Отопление

Оборудование для отопления. Традиционно в доме было печное отопление. Одна “немецкая” печь в комнате (греет за счёт длинной извилистой трубы), вторая “русская” на кухне (греет за счёт больших размеров самой топки). Если кто-то витает в киношных представлениях, что печь это классно и к тому же натурально и романтично, то беру на себя смелость предположить, что эти люди никогда не жили в доме с печным отоплением. На самом деле, это не очень комфортно, неудобно и пожароопасно. Поэтому лет 5 назад был заказан и осуществлён проект по разводке простейшего двухтрубного отопления с газовым котлом. Питать котёл предполагалось из газовых баллонов.

Впоследствии решено было систему модернизировать, добавить насос для принудительной рециркуляции теплоносителя и небольшой 2-киловаттный электрокотёл, чтобы не мучиться с разжиганием газа, когда ещё не очень холодно. Вся автоматизация сводилась к наличию большого рубильника на стене, когда становилось холодновато, его включали, а когда жарковато — выключали. Двух киловатт хватало где-то до температуры 0°C, дальше приходилось зажигать газ или печь, что было крайне неудобно.

image

Экономическая целесообразность

Перед тем как что-либо менять, естественно, было решено посчитать, имеет ли вообще вся эта задумка смысл. Просчитав по опыту расход газа из баллонов, прикинув ожидаемый расход дизтоплива, я пришёл к выводу, что в таких типах отопления нет никакого смысла при наличии достаточного количества электроэнергии. По цене баллоны выходили где то 6-7 тыс в месяц, дизтопливо, если покупать что-то палёное или летнее зимой, можно наэкономить до расхода 5 тысяч в месяц, при этом на чистой электроэнергии получалось 7 тыс. Прибавим сюда стоимость котла, постоянные таскания баллонов и запах от саляры, и станет ясно, что электричество куда проще и вовсе не дороже. Ещё, конечно, есть модные в последнее время пеллетные горелки, но они мне не подходили, так как они не умеют зажигаться сами и потому имеют минимальную мощность, при том совсем не малую (порядка 5кВт), которую 90% времени просто некуда девать, и требуют хотя бы 2 раза в неделю засыпать топливо, что иногда делать некому. Да и стоимость самих котлов на порядок больше предыдущих вариантов, поэтому они подходят для больших домов, где нужна большая мощность и большие затраты, а не в моём случае.

Heavy hardware

Попытался прикинуть требуемую мощность исходя из расхода газа и других прикидок, получилось, что надо 4-5 кВт, с запасом 6. Обзор рынка показал, что существует модель электрокотла, аналогичная уже установленному, но с 3-мя нагревательными элементами по 2 кВт каждый. При том продавалась она без управления, что мне было даже удобнее и дешевле. Вообще, сам котёл это крайне простая конструкция, металлический цилиндр с входной и выходной трубами, сверху притянутая болтами крышка, в которой закреплены ТЭНы. Дополнительно в корпус врезаны 2 датчика, резистивный датчик температуры и датчик, замыкающийся при перегреве, оба от системы охлаждения авто. Теперь встал вопрос о электроэнергии. Моя ситуация упрощалась тем, что рядом с домом находится мастерская, к которой подведены 3 фазы (в народе — 380). Естественно, возник соблазн питать каждый ТЭН от своей фазы, поэтому был куплен и проложен в котельную специализированный 4-жильный кабель в металлической оплётке для подземной укладки. Кабель введён в щиток с последовательно включенными УЗО и блоком из 3-х автоматов по 10А. Далее кабель шёл уже непосредственно в щиток с arduino и уже оттуда к элетрокотлу.

image

Light hardware

Понятно, что управлять ТЭНами будем с arduino, вопрос — как? Придерживаясь принципа — чем проще, тем надежнее, будем их просто включать или выключать с помощью реле безо всяких переходных вариантов. Облазив алиэкспресс, нашёл блок реле для ардуино, который может управлять сразу 5-ю силовыми линиями. Одна беда, максимальный ток, который эти реле могут выдерживать — 10А, а у меня получается 2кВт / 220В ~ 9А. То есть практически максимум, а желательно иметь запас хотя бы 25%. Однако решил рискнуть. Реле честно продержались почти неделю, затем просто начали плавиться. Надо было что-то решать и быстро, ибо была зима и останавливать отопление было нельзя. Потому были прикуплены 30А реле, правда, с обмотками на 12В. Поэтому быстренько припаял к каждому реле по транзистору, чтобы включать их от 5В ардуино.

Схема неплохо работала почти месяц, а потом я заметил, что дома как-то слишком жарко. Проверка показала, что одно реле “запало” в включенном положении. Постучал по нему — заработало опять, но хватило на несколько дней. Поменял его в надежде, что это брак, но уже через неделю то же самое случилось со 2-м реле. Поставив последнее запасное, отправился опять на али. Там были обнаружены специализированные реле для ардуино на 40А! Этих-то должно хватить наверняка, подумал я. Пара-тройка недель ожидания, и вот опять выкидываю транзисторы и ставлю новые реле с уже готовой обвязкой и индикацией. Радость была недолгой, недели через 2-3 опять залипшее реле. Начал изучать вопрос, оказывается, чтобы уменьшить нагрузку на реле и убрать искрение контактов, реле надо включать не как попало, а в момент, когда синусоида напряжения проходит через 0. Ну, в теории это можно сделать с помощью нашего же ардуино, только на подключить через делить все три фазы и смотреть напряжение. Проблема ещё и в том, что реле имеет некоторое время реагирования и, собственно, нам ещё надо его установить опытным путём. В общем, задачка не такая простая.

image

И тут я наталкиваюсь на так называемые Solid State Relay, проще говоря — электросхемка, собранная на мощном тиристоре, в корпусе, похожем на обычное реле. Из его плюсов — нет механики, ничего не залипнет. Не создаёт мощных ЭМ-помех, что важно для ethernet’a, о котором ниже. Они уже содержат схему, которая включает и отключает реле при проходе нуля. На реле есть индикатор включения. Ну и ещё они беззвучные, хотя для нашего случае это не так и актуально. После изучения инструкций и характеристик были заказаны SSR-40DA, что по-русски означает — твёрдотельное реле с постоянным управляющим током 3-5В и током нагрузки до 40А. Заодно решил немного отойти от принципа «проще-лучше» и сделать ещё контроль тока в ТЭНах. Это позволило бы узнать о перегоревшем ТЭНе/реле или отключении питания на одной из фаз. Добавил в заказ модуль контроля тока на 20А, хотя выглядели они хлипковато для такого тока (2.5 квадрата кабель даже не лез в их зажим). Когда реле и модули измерения тока пришли, оказалось, что реле достаточно громоздкие, поэтому было решено перенести всё, что связано с высоковольтной частью в новый ящик, а ардуино оставить в старом.

После первых экспериментов оказалось, что я совершенно забыл, что эти реле, так как собраны на тиристорах, довольно сильно греются. Через сутки работы реле нагревались так, что я не мог терпеть, держа на них палец, то есть градусов 60C, а это уже близко к критическим 80C. Опять полез на али, прикидывая, какие радиаторы приспособить, и тут узнал, что для этих SSR есть штатные радиаторы! На момент установки радиаторов также обнаружил, что один модуль контроля тока сам ток больше не пропускает, а со стороны платы видна подгорелая дорожка. Ещё один модуль также не вызывал уверенности, решил снять их все. В таком виде они всё же слабоваты и опасны, а толку от них не так и много. Проблему отключения фаз или ТЭНов пока отложил как не очень актуальную, за 3 года ни первого, ни второго не случалось не разу.

Теперь о ПО

image

image

Arduino

Сразу же в примерах был найден кусок, который позволял управлять средней мощностью, имея двоичное управление — вкл и выкл. Смысл простой, берём некое окно времени, скажем, 1 минута, и в цикле включаем либо выключаем нагрузку в зависимости от пройденного времени. То есть, если нам надо 50% мощности, то включаем нагрузку в первые 30 сек и выключаем в последние 30, затем цикл повторяется. Быстренько переделал это под 3 независимых реле, если мощность больше 33%, то включаю второе реле, если больше 66% — то третье, а первое включаю и выключаю по основному алгоритму. Теперь встаёт главный вопрос, а по какому алгоритму подбирать мощность? Будучи программистом по профессии сначала решил, что задачка довольно простая, холодно — добавляй, тепло — отбавляй, и попытался прикинуть всё это в уме.

Оказалось, не так и просто. Полез смотреть, как это делают в продаваемых системах, оказалось, там всё либо максимально просто, как в утюге — +1C = выкл, -1 = вкл. Но тогда мы получаем почти 4C колебаний из-за инертности системы! Это слишком грубо, ибо мы можем получать данные с точностью до десятой доли градуса. Также посмотрел алгоритмы работы с использованием температуры уличного воздуха, они оказались достаточно простые и работали на готовых таблицах, которые были заранее зашиты и просто менялись в зависимости от теплопотерь дома. Копая глубже и глубже, я докопался до промышленных установок, в них повсеместно использовали алгоритмы PID-регуляторов. И, о слава популярности, оказывается, у Arduino есть бесплатная PID-библиотека!

Пару слов о том, что такое PID применительно к нашему случаю. Смысл алгоритма в том, что мы сообщаем ему требуемое значение некоторого параметра (температура внутри дома) и в цикле передаём текущее значение, а он выдаёт нам необходимое воздействие (мощность, которую надо подать на котёл). Не вдаваясь в подробности математической модели, как же он работает с точки зрения программиста. Итак, мы имеем температуру в комнате, пусть 20C, желательную температуру 22С, и даём их нашему PID-алгоритму.

Сам алгоритм имеет 3 независимые части, по имени P, I и D. Первая часть работает крайне просто, смотрит на разницу между желательной температурой и текущей температурами. То есть чем холоднее, тем большую мощность нам даст алгоритм. Вроде бы, этого и достаточно, но ведь у нас есть постоянные теплопотери дома, то есть, чтобы держать нужную температуру, нам надо постоянно давать какую-то мощность. То есть даже если температура в комнате равна заданной, нельзя отключать котёл, а надо как-то искать какую-то мощность, равную теплопотерям. А теплопотери меняются в зависимости от температуры на улице. Вот этим и занимается вторая часть под именем I. Алгоритм пытается подобрать мощность, при которой наша температура будет постоянной. И вроде тут-то уже точно всё, но нет.

Дело в том, что сам котёл, теплоноситель, а тем более дом имеют очень большую инертность. И если вы врубили котёл на 100%, то снижать мощность нужно куда раньше, чем температура достигнет желательной, иначе даже при полном отключении мы всё равно успеем перегреть комнату градуса на 2. То же самое при понижении температуры, добавлять мощность надо ещё до того, как температура дошла до нужной. Вот этим и занимается третья часть алгоритма D. Ну теперь, конечно, всё, осталось только понять, какой части давать какой вес, а вот этим занимаются множители каждой части, которые и надо подбирать. Кстати, подбор этих множителей — отдельная и довольно сложная математическая задача, я подбирал их “на глаз”, вспоминая сказанное выше. Сначала ставил все нули, кроме P, и подбирал его так, чтобы не началось само возбуждение. Потом добавлял I, а в конце и D.

Меряем температуру

Для измерения температуры всё на том же волшебном сайте были заказаны цифровые датчики температуры на базе DS18B20. Датчик сам по себе просто замечательный, его не надо ни калибровать, ни как-то настраивать, при этом он может мерить температуру с заданной точностью, а общается с Arduino по протоколу OneWier. То есть на 3 провода длиной до 50 метров можно вешать практически неограниченное число датчиков. При желании их можно даже не питать, а работать только по 2-м проводам (на самом деле, они питаются, но от провода с сигналом), но работают медленнее. В моём случае датчики я заказал в герметичном корпусе, а соединял обычной витой парой. Я поставил 3 датчика, один в котельной, один в доме, в комнате, и один на чердаке под потолком, чердак никак не отапливается и там я получаю температуру на улице.

image

Список закупленного железа

— Плата arduino. Я использовал UNO r3. Цена около 350 р.
— Ethernet Shield, около 500 р.
— Витая пара (смотря сколько надо), бухта в 305м обойдётся около 4 тыс.
— Датчики температуры, около 200 р.
— Блок питания на 110-240 — 12В 2А, 420 р.
— Стабилизатор LM7805, где-то 20 р.
— Реле SSR-40DA 3 шт. по 330 р.
— Радиаторы для реле по 200 р.

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

image

Складываем данные в базу и показываем.

Но всё это, конечно, хорошо, но не стоять же постоянно с компьютером рядом с котлом, всё же хотелось бы знать о том, что происходит дома, удалённо через инет. У меня давно уже был самый простенький VPS сервер от majordomo для чего попало. На нём создал базу данных на MySQL для хранения данных о температуре.

image

Теперь нам надо как-то положить данные из arduino в эту базу. Для этого, естественно, понадобится как минимум связать arduino с интернетом, это не просто, а очень просто. Для этого нам и понадобится Ethernet Shield и его библиотека. В доме давно уже установлен простенький роутер со “свистком” сначала от megafon, а потом от yota. Тянем стандартную витую пару к роутеру и добавляем в программу передачу данных. Передача идёт через вызов странички на PHP с параметрами — данными. Создаём страничку с именем temp.php на нашем инет-сервере

<?php $dbhost = 'localhost'; $dbuser = '***'; $dbpass = '***'; $dbname = 'nikolaarduino'; $client_ip = $_SERVER['REMOTE_ADDR']; $temp1 = $_GET["t1"]; $temp2 = $_GET["t2"]; $temp3 = $_GET["t3"]; $power = $_GET["p"];  $connect = mysql_connect($dbhost, $dbuser, $dbpass); if(! $connect ) {  die('Could not connect: ' . mysql_error()); } mysql_select_db ($dbname, $connect);  $sql = "INSERT INTO Temp (datetime, temp1, temp2, temp3, power, ip) VALUES (Now(), '$temp1', '$temp2', '$temp3', '$power', '$client_ip')";  if(!mysql_query($sql)) {echo '<p><b>Data upload error!</b></p>';} else {echo '<p><b>OK</b></p>';} mysql_close($connect); ?> 

После этого мы имеем данные о температурах и мощности работы котла, чтобы каждый раз не лазить в базу, а посмотреть последние данные, написал “временный” скриптик на php, но, как известно, нет ничего более постоянного, чем временные вещи, так им и пользуюсь.
gettemp.php

<?php $dbhost = 'localhost'; $dbuser = '***'; $dbpass = '***'; $dbname = 'nikolaarduino'; $client_ip = $_SERVER['REMOTE_ADDR'];  $connect = mysql_connect($dbhost, $dbuser, $dbpass); if(! $connect ) {  die('Could not connect: ' . mysql_error()); } mysql_select_db ($dbname, $connect);  $query = 'SELECT * FROM Temp WHERE id=(SELECT MAX(ID) FROM Temp)'; $result = mysql_query($query) or die('Error get data: ' . mysql_error());  echo "<table style='text-align: left; width: 100%;' border='1' cellpadding='2' cellspacing='2'>n"; while ($line = mysql_fetch_array($result, MYSQL_NUM)) {  echo "<tr align='center'><td colspan='2' rowspan='1'>$line[1]</td></tr>";  echo "<tr align='center'><td>TempIN = $line[2]</td><td> TempOUT = $line[3]</td></tr>n";  echo "<tr align='center'><td colspan='2' rowspan='1'>TempKotel = $line[4]</td></tr>n";  echo "<tr align='center'><td colspan='2' rowspan='1'>Power = $line[5]</td></tr>n"; } echo "</table>n";  mysql_free_result($result);  mysql_close($connect); ?> 

image

Что хочется добавить в будущем

Конечно, это, в принципе, минимум, который однако позволяет сделать полноценное и достаточно удобное управление отоплением в небольшом доме. Хотя с некоторыми переделками его можно использовать и в многокомнатных и вообще строениях любой сложности, arduino может тут очень многое, если не всё. Именно в этом проекте хотелось бы добавить в будущем:

  • регулятор температуры. Хотя практика показала, что 22.5 это вполне оптимальное значение и в принципе не требует корректировки. Опять же, регулятор хотелось бы сделать удалённо от основного arduino, но для этого надо либо сложную схему, либо ещё один arduino. В общем, есть о чём подумать.
  • Хотелось бы возможность не только читать температуру, но и менять параметры PID на лету. Возможно, сделать отдельно режим “первоначального прогрева”, а то параметр I долго нормализуется после каждого перезапуска программы.
  • Хочется простенькое приложение под android, чтобы на телефоне не тыкать в мелкий браузер. Это самое простое и уже в процессе.
  • Всё же подключить датчик температуры теплоносителя и передавать его данные, как и другие данные температуры.
  • Сигнализация аварийных случаев. То есть автоматически определять потерю напряжения на линиях, отказ реле или ТЭНов.
  • Сделать “карусель”, менять местами назначения ТЭНов. Иначе получается, что один ТЭН работает всегда больше других, и он в теории должен отказать первым. Надо просто время от времени менять PIN’ы в программке. Вроде просто, но никак не дойдут руки добавить.

Текст программы для Arduino:

#include <OneWire.h> #include <DallasTemperature.h> #include <PID_v1.h> #include <DHT.h> #include <Ethernet.h> #include <SPI.h>  // OneWire DS18S20, DS18B20, DS1822 Temperature Example // // http://www.pjrc.com/teensy/td_libs_OneWire.html // // The DallasTemperature library can do all this work for you! // http://milesburton.com/Dallas_Temperature_Control_Library  OneWire ds(6); // on pin 10 (a 4.7K resistor is necessary) DallasTemperature sensors(&ds); boolean waithTemp = false; int TEMPERATURE_PRECISION = 10;  int lamp1 = 7; int lamp2 = 8; int lamp3 = 9;  DeviceAddress IntThermometer = { 0x28, 0x8E, 0xF4, 0x28, 0x05, 0x00, 0x00, 0x07 }; DeviceAddress OutThermometer = { 0x28, 0x65, 0x15, 0x32, 0x05, 0x00, 0x00, 0xE2 }; DeviceAddress KatThermometer = { 0x28, 0x61, 0x43, 0x28, 0x05, 0x00, 0x00, 0x14 };  byte addr[8]; unsigned long StartTime = 0; unsigned long WorkWindow = 60000; // 10min unsigned long WorkTime, TenTime; float maxData = 100; float celsius, temp; double Setpoint, Input, Output;  int ThermometerCount; DeviceAddress Thermometer[100];  PID myPID(&Input, &Output, &Setpoint, 10, 0.1, 5, DIRECT); //0.000006 0.03 40  double targetTemp = 22.5;  byte mac[] = { 0xE0, 0x69, 0x95, 0x72, 0x65, 0xE8 }; byte ip[] = { 192, 168, 1, 100 }; byte server[] = { ?, ?, ?, ? }; EthernetClient client; byte webskipcount = 10; byte webcount = 0;   void setup(void) {   Serial.begin(9600);    //Ethernet.begin(mac, ip);  Ethernet.begin(mac);    sensors.begin();    pinMode(lamp1, OUTPUT);  pinMode(lamp2, OUTPUT);  pinMode(lamp3, OUTPUT);      Setpoint = targetTemp;  myPID.SetOutputLimits(0, maxData);  myPID.SetMode(AUTOMATIC);    celsius = targetTemp;    StartTime = millis(); }  long filter(long x, long Nb, long k) {  static long y = 0, z = 0;  z += (x - y);  return y = (Nb * z) >> k; };   void loop(void) {   byte i;  byte type_s;  byte data[12];  long Out;    if (millis() < StartTime) {  StartTime = millis();  }    WorkTime = millis() - StartTime;  if (WorkTime > WorkWindow) {  WorkTime = WorkTime - WorkWindow;  StartTime = millis() + WorkTime;  }   //Serial.println("cycle");  sensors.requestTemperatures();  celsius = sensors.getTempC(IntThermometer);  Input = celsius;  if (webcount >= webskipcount) {  char buffer[10];  String temperatureS1 = dtostrf(celsius, 2, 2, buffer);  String temperatureS2 = dtostrf(sensors.getTempC(OutThermometer), 2, 2, buffer);  String temperatureS3 = dtostrf(sensors.getTempC(KatThermometer), 2, 2, buffer);  String OutputPowerS = dtostrf(Output, 2, 2, buffer);  String msg = "GET /temp.php?t1="+ temperatureS1 + "&t2=" + temperatureS2 + "&t3=" + temperatureS3 + "&p="+OutputPowerS;  Serial.println(msg);  client.connect(server, 80);  client.println(msg);  client.stop();  webcount = 0;  } else {  webcount += 1;  }   myPID.Compute();  //Serial.print(Input);Serial.print(" ");Serial.print(Output);Serial.print(" ");Serial.println(Setpoint);    if (Output > maxData/3*2) {  digitalWrite(lamp1, HIGH);  digitalWrite(lamp2, HIGH);  Out = Output - maxData/3*2;  } else if (Output > maxData/3) {  digitalWrite(lamp1, HIGH);  digitalWrite(lamp2, LOW);  Out = Output - maxData/3;  } else {  digitalWrite(lamp1, LOW);  digitalWrite(lamp2, LOW);  Out = Output;  }   TenTime = map(Out, 0, maxData/3, 0, WorkWindow);   Serial.print(celsius);  Serial.print(" ");  Serial.print(sensors.getTempC(OutThermometer));  Serial.print(" ");  Serial.print(sensors.getTempC(KatThermometer));  Serial.print(" ");  Serial.print(Output);  Serial.print(" ");  Serial.print(TenTime);  Serial.print(" ");  Serial.println(WorkTime);    if (WorkTime < TenTime) {  digitalWrite(lamp3, HIGH);  }  if (WorkTime > TenTime) {  digitalWrite(lamp3, LOW);  }   } 

Источник: habr.com


Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.