Умный чайник

Для приготовления чая важно заваривать его водой с правильной температурой. Следить за выбранной температурой умеют умные чайники. Если такого под рукой нет, можно обойтись обычным электрочайником прокачав его до уровня SMART. В этой статье рассказывается как это сделать. Погнали!

Видеообзор

Что это?

Устройство подключается в разрыв цепи питания чайника. Герметичный термометр измеряет температуру воды. Когда она нагреется до заданного уровня, контроллер подаст звуковой сигнал и отключит питание переключив реле. Если температура опять опустится ниже заданной, реле снова включится. Таким образом устройство будет поддерживать температуру воды внутри чайника. Показания термометра выводятся на дисплей, боковые кнопки которого служат для установки необходимой температуры.

Что понадобится?

Исходный код

Установи библиотеку для работы с TroykaOLED дисплеем и две библиотеки для работы с датчиком температуры — OneWire и DallasTemperature

Прошейте плату Искра Нео кодом программы:

smart_kettler.ino
// подключим необходимые библиотеки
#include <OneWire.h>
#include <DallasTemperature.h>
#include <TroykaOLED.h>
 
// Укажем к каким пинам подключены элементы устройства
#define ONE_WIRE_BUS 1
#define BUZZER_PIN  9
#define RELAY_PIN 8
#define LED_BUTTON_PIN 13
#define BUTTON_PIN A0
#define PLUS_PIN 6
#define MINUS_PIN 7
 
// создадим массив для хранения мелодии
int notes[] = {
  700, 800, 1200
};
 
// настроим библиотеку 1-Wire для связи с датчиком
OneWire oneWire(ONE_WIRE_BUS);
 
// создадим объект для работы с библиотекой DallasTemperature
DallasTemperature sensors(&oneWire);
 
// создадим объект для работы с дисплеем и передадим его адрес 
TroykaOLED myOLED(0x3C); 
 
// Создадим переменные для хранения значений температуры
int Temp= 0;
int newTemp;
int setTemp= 65;
 
// Создадим переменные для хранения времени
long DisplayPreviousMillis = 0;
long previousMillis = 0;
int interval = 3000;
 
// Переменные для хранения состояний работы устройства
bool displayState = 0;
bool warmState = 0;
bool ledState = 0;
int buttonLedState = 0;
 
void setup() {
  // Инициализируем работу датчика температуры
  sensors.begin();
  // Инициализируем работу дисплея
  myOLED.begin();
 
  // Сконфигурируем назначение пинов
  pinMode(PLUS_PIN, INPUT_PULLUP);
  pinMode(MINUS_PIN, INPUT_PULLUP);
  pinMode(LED_BUTTON_PIN, OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
 
  // Выведем статичную информацию на дисплей
  myOLED.setFont(fontRus12x10);
  myOLED.invertText();
  myOLED.setCursor(0, 0);
  myOLED.print("Темпера");
  myOLED.setCursor(83, 0);
  myOLED.print("т");
  myOLED.setCursor(94, 0);
  myOLED.print("у");
  myOLED.setCursor(104, 0);
  myOLED.print("ра");
  myOLED.invertText(0);
  myOLED.setFont(fontRus12x10);
  myOLED.setCursor(77, 32);
  myOLED.print("o");
  myOLED.drawRect(6, 46, 24, 48, 1);
  myOLED.drawRect(103, 46, 121, 48, 1);
  myOLED.drawRect(111, 38, 113, 56, 1);
  myOLED.drawCircle(15, 47, 15);
  myOLED.drawCircle(112, 47, 15);
  myOLED.drawCircle(15, 47, 14);
  myOLED.drawCircle(112, 47, 14);
  Temp = sensors.getTempCByIndex(0);
}
 
void loop() {
  // Запрашиваем данные с датчика температуры
  sensors.requestTemperatures();
  newTemp = sensors.getTempCByIndex(0); 
 
  // Считываем нажатия кнопок и устанавливаем режим работы
  if(!digitalRead(BUTTON_PIN) && warmState == 0){
    warmState = 1;
    buttonLedState = 1;
  }
  if(!digitalRead(BUTTON_PIN) && (buttonLedState == 2)){
    buttonLedState = 0;
    warmState = 0;
    digitalWrite(13, LOW);
  }
 
  // Определяем режим работы светодиодной индикации
  if(buttonLedState == 1){
    ledBlink();
  }
  if(buttonLedState == 2){
    digitalWrite(LED_BUTTON_PIN, HIGH);
  }
  if(buttonLedState == 0){
    digitalWrite(LED_BUTTON_PIN, LOW);
  }
 
 // Если включен режим нагрева
  if(warmState == 1){
    // Если температура ниже заданой включаем реле
    if((Temp+1) < setTemp){
      digitalWrite (RELAY_PIN, HIGH);
    }
    // Если температура выше или равна - выключаем реле
    if(Temp >= setTemp){ 
      digitalWrite (RELAY_PIN, LOW);
      // Проигрываем мелодию
      if(buttonLedState == 1){
        for(int thisSensor = 0; thisSensor < 3; thisSensor++) {
           tone(BUZZER_PIN, notes[thisSensor], 500);
           delay(500);
        }
        // Устанавливаем режим индикации работы устройства
        buttonLedState = 2;
      }
    }
  } else{
       digitalWrite (RELAY_PIN, LOW);
    }
 
  // Считываем нажатия кнопок и увеличиваем или уменьшаем значение установленой температуры
  if(!digitalRead(MINUS_PIN)){
    displayState = 1;
    DisplayPreviousMillis = millis();
    setTemp = setTemp - 1;
    delay(20);
    // Выводим прямоугольную заплатку стирающую предыдущее значение
    myOLED.drawRect(31, 36, 78, 60, 1, BLACK);
 
  }
 
  if(!digitalRead(PLUS_PIN)){
      displayState = 1;
      DisplayPreviousMillis = millis();
      setTemp = setTemp + 1;
      delay(20);
      // Выводим прямоугольную заплатку стирающую предыдущее значение
      myOLED.drawRect(31, 36, 78, 60, 1, BLACK);
 
  }
 
  // Если время после нажатия кнопок установки температуры больше 3-х секунд — переключаемся на отображение текущей температуры
  if(millis() - DisplayPreviousMillis > interval && displayState == 1){
    // Выводим прямоугольную заплатку стирающую предыдущее значение
    myOLED.drawRect(31, 36, 78, 60, 1, BLACK);
    displayState = 0;
  }
 
  // Проверяем изменилась ли температура
  if(Temp != newTemp){
    // Выводим прямоугольную заплатку стирающую предыдущее значение
    myOLED.drawRect(31, 36, 78, 60, 1, BLACK);
    // Присваиваем новое значение температуры
    Temp = newTemp; 
  }
 
  // Выбираем шрифт отображения и выводим значение температур на дисплей
  myOLED.setFont(bigNumbers);
  if(displayState){
    view(setTemp);
  }else{
    view(Temp);
  }
}
 
// Создадим функцию для отображения температур на дисплее
void view (int a){
  if(a > 99){
    myOLED.setCursor(35, 35);
  }else{
    myOLED.setCursor(49, 35);
  }
  myOLED.print(a); 
}
 
// Создадим функцию мигания подсветки кнопки
void ledBlink (){
  if(millis() - previousMillis > 500){
    previousMillis = millis();   
    if (ledState == LOW){
      ledState = HIGH;
    } else{
      ledState = LOW;
    }
    digitalWrite(LED_BUTTON_PIN, ledState);
  }
}

Как собрать?

  1. Для начала возьмем Искру Нео прошитую исходным кодом и поставим на неё AC/DC Shield.
  2. Теперь подключим к клеммникам шилда провода питания и провод ведущий к чайнику. Кроме того установи перемычку на пин 8.
  3. Установим два комплекта контактных колодок Arduino и наденем сверху слот шилд.
  4. Соберем корпус для получившегося бутерброда. Для этого идеально подойдет Slot Box XL.
  5. Теперь подключим чайник в розетку устройства, опустим датчик внутрь чайника и воткнем вилку устройства в сеть 220.
  6. Установи кнопками на дисплее нужную температуру и запусти нагрев и поддержание температуры нажатием на Troyka-кнопку. Чайник нагреет воду и будет её поддерживать в пределах 2-х градусов. Когда поддерживать температуру больше не нужно — повторно нажми на Troyka-кнопку.