iotPlita или кому нужен такой контроль на кухне?

в 21:56, , рубрики: arduino, esp8266, IoT, Lua, программирование микроконтроллеров
iotPlita или кому нужен такой контроль на кухне? - 1

Привет!

Эта статья не про кулинарию и не самодисциплину, а про решение одной ежедневной задачи.

Моя боль

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

В том числе программирование или другие увлекательные задачи и как следствие сотни подгоревших блюд и замен посуды.

Попытки решить это недоразумение с помощью таймеров и самодисциплины со временем выходили на нет. Возможно можно было бы посмотреть в сторону мультиварки (или налаживания более прочных контактактов с противоположным полом), но к моменту решения я уже был знаком c ESP8266.

Как оказалось, нужно совсем не много:

  1. ESP8266 (Или аналог).

  2. Модуль MAX6675 + термопара.

  3. Реле электромеханическое 10A.

  4. Блок питания от телефона.

  5. Вилка и розетка

Примерно прикинув, что конфорке нужно около 6,5А, я успокоился по реле.
Хотя был еще один вопрос, то что реле включается от 5В а ESP8266 оперирует 3.3В.
Но и это не оказалось проблемой, на плате есть пин который идет напрямую от питания, т.е. те самые заветные 5В. (от 3.3 вольта реле реально не завелось)

По инфраструктуре

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

В итоге имеем:
Точка доступа на плате (с паролем - минимальная степень защиты).

Что по коду?

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <HttpClient.h> 
#include <ESP8266HTTPClient.h>
#include <ESP8266HTTPUpdateServer.h>  // либа для обновления по воздуху

// гайвер температура
#include <GyverMAX6675.h>

// Пины модуля MAX6675K
#define CLK_PIN   D3  // Пин SCK 
#define CS_PIN    D2  // Пин CS
#define DATA_PIN  D1  // Пин SO

// указываем пины в порядке SCK SO CS
GyverMAX6675<CLK_PIN, DATA_PIN, CS_PIN> sens;


// * Установить свой SSID и пароль * /
const char* ssid = "iPlita";
const char* password = "12345678";
// * Настройка IP-адрес * /
IPAddress local_ip(192,168,1,1);
IPAddress gateway(192,168,1,1);
IPAddress subnet(255,255,255,0);

ESP8266WebServer webserver(80);

ESP8266HTTPUpdateServer httpUpdater;


int tnow; // температура сейчас
int tgo=-2;  // температура к которой стремиться

int   secafter; // секунд после последней комманды или включения
int   tout=25;   // время после которого система отключает плиту - в минутах


String imode='off';

uint32_t tmr1;    // сеунд после последней комманды или включения

Выбор подключаемых библиотек очевиден, но немного прокомментирую.

Планируется работа с вайфай в качестве сервера (+ поднятие точки доступа).
А так же была выбрана легковесная библиотека работы с термопарой (От Алекса Гайвера).
В начале были сомнения по поводу нее, но так как был всего день на сборку, то допустил и надо сказать свои функции она выполняет прекрасно.

Так, же понравилось решение - поднятие сервера обновления прошивки по воздуху, что в условиях статического монтажа облегчает жизнь.

Сетап и цикл

void setup() {
  Serial.begin(9600);
  
  WiFi.softAP(ssid, password);
  WiFi.softAPConfig(local_ip, gateway, subnet);
  delay(100);

  // Start Web Server
  webserver.on("/", rootPage);
  //---------------------------
  webserver.on("/gtemp", gett ); // отдать температуру 


  //--------------------------- задать  температуру 
  webserver.on("/stemp", HTTP_GET, [](){
    if (!webserver.hasArg("temp")) {
      return webserver.send(500,   "application/json", "{"message":"No temp found"}"); //
   }
    tgo = (webserver.arg("temp")).toInt();
    int tnn=sens.getTempInt();
    if (tgo>tnn) {imode="warm";}  
    if (tgo<tnn) {imode="cold";}
    //if (tgo>tnn) {imode="ready";}   

    tmr1 = millis();          
    
    return webserver.send(200, "application/json", "{"message":"ok"}"); //
  });



//---------------------------  задать интервал работы
  webserver.on("/stime", HTTP_GET, [](){
    if (!webserver.hasArg("time")) {
      return webserver.send(500, "application/json", "{"message":"No time found"}"); //
   }
    tout = (webserver.arg("time")).toInt();
    tmr1 = millis();          
    
    return webserver.send(200, "application/json", "{"message":"ok"}"); //
  });


  //---------------------------  // отдать режим
  webserver.on("/gmode", HTTP_GET, [](){
    
    return webserver.send(200, "application/json", "{"mode":""+imode+""}"); //
  });

  webserver.onNotFound(notfoundPage);
   
  httpUpdater.setup(&webserver,"/firm","admin","1234");
  
  webserver.begin();

  pinMode(D4, OUTPUT); 
  pinMode(D5, OUTPUT);
  pinMode(D6, OUTPUT);
  
  digitalWrite(D5, 0);
  digitalWrite(D6, 0);
  digitalWrite(D4, 0);

  tmr1 = millis();   

  imode="off";

}

void loop() {
   webserver.handleClient(); 
  
     
     if ( (tmr1+(tout*60*1000)) < millis() ) { imode="off"; }     

     if ( (millis() - tmr1)>(tout*60*1000) ) { imode="off"; }     
     
     if (imode=="warm") {Warm(); digitalWrite(D4, 0); }
     if (imode=="keep") {Keep(); digitalWrite(D4, 0); }
     if (imode=="cold") {Cold(); digitalWrite(D4, 0); }

     if (imode=="off") {digitalWrite(D5, 0);   digitalWrite(D4, 1);}
  
  delay(1000); 
   

}

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

И собственно тут, что щелкнуло

А именно то, что для меня стало логичным (и собственно, что побудило написать на Хабр).

"Если происходит включение (задание температуры), то автоматом должно назначаться время воздействия".

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

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

Остальной код

// Handle Root
void rootPage() { 

  if (webserver.hasArg("temp")) { 
       tgo = (webserver.arg("temp")).toInt(); 
        
       int tnn=sens.getTempInt();
       if (tgo>tnn) {imode="warm";   digitalWrite(D4, 0);}  
       if (tgo<tnn) {imode="cold";   digitalWrite(D4, 0);}
       //if (tgo>tnn) {imode="ready";}  


       
       tmr1 = millis();  
    }

  if (webserver.hasArg("time")) { 
    if ( webserver.arg("time")!="" ){
       tout = (webserver.arg("time")).toInt(); 
       tmr1 = millis(); 
      }
    }

   
   
  
   //String indexh = MAIN_page;
   //webserver.send(200, "text/plain", String(temperature(0), 3)  );
   //webserver.send(200, "text/html; charset=utf-8", indexh );
   String sss="<meta name='viewport' content='width=device-width, initial-scale=1'>"; 
   sss+="<meta charset="utf-8">";
   sss+="<meta http-equiv='refresh' content='30;URL=/'>";
   sss+="Температура датчика: "+String(sens.getTempInt())+"<br>";
   sss+="Температура цель: "+String(tgo)+"<br>";
   sss+="<hr>";
   
   sss+="Время системы: "+String(( millis() )/1000)+"<br>";
   sss+="Время последней отсечки: "+String(tmr1/1000)+"<br>";
   sss+="уст Время работы сек: "+String( tout*60)+"<br>";

   int too=( (tmr1/1000) + (tout*60) )-( millis()/1000 );
   
   //if (too>( (millis()/1000) - ( ( tout/1000 )+(tmr1/1000) )   )) { too=0; }

   //if (too>999999) { too=0; }

    if (too<0) { too=0; }
   
   sss+="Время выкл через в сек :"+String(too)+"<br>";
   sss+="Время выкл через в мин :"+String(too/60)+"<br>";
 

   sss+="<hr>";
   sss+="Режим:"+imode+"<br>";
   sss+="<hr>";
   sss+="<form method='get' action=' '> <input type='text' name='temp'> <input type='submit' value='УстТемп'>  </form>";
   sss+="<br>";
   sss+="<form method='get' action=' '> <input type='text' name='time'> <input type='submit' value='УстВрем'>  </form>";
   
   
   webserver.send(200, "text/html", sss  ); 
   
}

// ------ отдаем температуру
void gett() { 
  
   int tn=sens.getTempInt();
   //int tn=sens.getTempInt();
   
   //webserver.send(200, "text/plain", String(temperature(0), 3)  );
   webserver.send(200, "application/json; charset=utf-8","{"body":{"tn":"+String(tn)+"}}" );
   //webserver.send(200, "text/plain", "111"  ); 
}
 
// Handle 404
void notfoundPage(){ 
  webserver.send(404, "text/plain", "404: Not found"); 
  
}

void Warm(){

    // сделать предел 

  
    int tnn=sens.getTempInt();
   
    if (tgo>tnn) { digitalWrite(D5, 1); } 

    if (tgo<=tnn) { 
         digitalWrite(D5, 0);  
         // обнулить счеткик времени 
         imode="keep"; 
         
      } 
    
   
  }



  void Keep(){
   int tnn=sens.getTempInt();
   
    if (tgo>tnn) { digitalWrite(D5, 1); } 
    if (tgo<=tnn) { digitalWrite(D5, 0); } 
    
   
  }


  void Cold(){
   int tnn=sens.getTempInt();
   
      digitalWrite(D5, 0); 
     
    
   
  }

В этом участке:
Домашняя страница с авто обновлением без JS :-)

Переключение на режим keep с warm, по достижению целевой температуры:

Устройство на "рабочем месте" (на даче)
Устройство на "рабочем месте" (на даче)
Контакт с термопарой
Контакт с термопарой
iotPlita или кому нужен такой контроль на кухне? - 4

Что было бы логично

После такого опыта разогрева и готовки, мне будет "странно" пользоваться обычной плитой. Это то чувство, когда после телевизора с пультом - возврат на кнопочный.

Неужели это так сложно дать в массы такую простую комфортность?

Вот какие социальные изменения ? Какие новые политические веяния?
(я не говорю и передовых местах в электронике)

Что дальше ?

В планах - наладить производство электроконфорок (стандартных типоразмеров) со встроенной термопарой. (Потому как основной проблемой вижу крепление термопары ) Оформить в печатную плату и устройство для быстрого подключения к плите которая досталась тебе от родителей, оставив возможность включения привычным способом. Что бы на выходе мог быть советский тип электро плиты + управление с телефона.

UPD

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

Да, есть мультиварки. Из минусов: во-первых это расширяемость и дополняемость, т.е. добить свои режимы - ну это непросто. (хотя была как идея - взять мультиварку и запихнуть туда ESP c с реле - не исключаю такие эксперименты).
Второе цена заметно выше, хотя если взять не работающую мультиварку и паяльник ...).
Третье это бытрая смена посуды: Для блинов, картошки, варить суп или варенье, задачи бывают очень разные.

Плюсы у мультиварки - да есть. Взял и юзай, кому-то и хватит (может просто у меня никогда не было мультиварки и давит жаба купить аппарат, на котором не смогу подстроить функционал под себя).

И да, я все больше понимаю, что "изобрел" мультиварку.
Но, это даже хорошо, просто свой подход :-)

Я таки перевел проект на MQTT :-)

И написал на производство конфорок, с вопросом, о возможности производства со встроенной термопарой.. и вот ответ:

"Добрый день!

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

С уважением, заместитель директора ООО"Элекон" Андрей Ворожцов

сот. 8(912)826-53-10"

(Что, они там курят... Без комментариев )

Автор:
Uglevod

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js