Умный чайник

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

Видеообзор

Что это?

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

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

Исходный код

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

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); 
 
// Подключим используемые шрифты
extern uint8_t MediumFontRus[];
extern uint8_t BigNumbers[];
 
// Создадим переменные для хранения значений температуры
int Temp;
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(MediumFontRus);
  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(MediumFontRus);
  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);
}
 
void loop() {
  // Запрашиваем данные с датчика температуры
  sensors.requestTemperatures();
  Temp = 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);
  }
 
  if(!digitalRead(PLUS_PIN)){
      displayState = 1;
      DisplayPreviousMillis = millis();
      setTemp = setTemp + 1;
      delay(20);
  }
 
  // Если время после нажатия бельше 3-х секунд переключаемся на отображение текущей температуры
  if(millis() - DisplayPreviousMillis > interval){
    displayState = 0;
  }
 
  // Выбираем шрифт отображения и выводим значение температур на дисплей
  myOLED.setFont(BigNumbers);
  if(displayState){
    view(setTemp);
  }else{
    view(Temp);
  }
}
 
// Создадим функцию для отображения температур на дисплее
void view (int a){
  if(a > 99){
    myOLED.setCursor(35, 35);
  }else{
    myOLED.drawRect(45, 35, 47, 57, 1, 0);
    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.