Wednesday, May 15, 2013

Arduino Controlled Water Boiler and Warmer / Thermo Pot

By leorick  |  5/15/2013 07:35:00 PM No comments








I have an electric water boiler and warmer AKA thermo pot which was struck by lightning. The circuit board was heavily damaged beyond repair.



But the good news is all other parts such as heating elements, DC motor pump and temperature sensor still OK. So this is how the project started.


Before this project started, I did talk to my brother about Arduino. Sounds like fun. So I give them a try. I choose Arduino Uno for this project since it is highly recommended for a beginner.


Typical electric water boiler and warmer has 2 heating elements, boiler and warmer.
  • Boiler : 3A : 80Ω : 720W
  • Warmer : 0.6A : 390Ω : 144W
The DC motor pump working voltage is DC 9V.

I'm not sure what type of temperature sensor used by this boiler but from my study, it measures;
  • Around 100kΩ when 33°C (room temp)
  • Around 10kΩ when 100°C (boiled)
The question now is how to translate this value 100kΩ<=>10kΩ to  33°C<=>100°C? I start with a simple voltage divider, 5V DC, smoothing E capacitor and link them to Arduino pin A0 (AnalogInput)...

  • R5 = 10kΩ
  • C1 = 1µF
...wrote a simple program as below to get the AnalogInput value during both room temperature and boiled temperature.
int sensorPin = A0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println(analogRead(sensorPin));
  delay(1000);             
}
From this test it reads...
  • Analog Value 116 while 33°C (room temp)
  • Analog Value 594 while 100°C (boiled)
So a simple linear equation (y = mx + c) in a function like below could be used to read the analog input and translate them to °C
float getTemp(int sensorValue){
  float y1 = 100;
  float x1 = 594;
  float y2 = 33;
  float x2 = 116;
  float m = (y1 - y2) / (x1 - x2);
  float c = y1 - (m * x1);
  return (m * sensorValue) + c;
}
From there I continue with other features;

16X2 LCD to show status and temperature. (pin D8 - D13). Notice that I ignore the contrast control pin? This because this LCD display is an old display that is having problem. :-( so I leave the pin open.



Unlock button, using Interrupt (pin D2) that will enable the pump and light up the LCD back-light for a period of time. I'm too lazy to built the Debounce module for this button so I use a capacitor :-)





Outputs (pin D5 and D6) to turn on boiler and warmer thru transistors and relays.



Buzzer (pin D4) for overheat alert, 1kHz tone.



Complete schematic diagram


Flow chart below would explain the system flow.

Complete Arduino sketch

#include <LiquidCrystal.h>

LiquidCrystal lcd(13, 12, 11, 10, 9, 8);
int sensorPin = A0;            //temp sensor analog in pin
int samplingRate = 500;        //sampling/pulse rate
int unlockInt = 0;             //interrupt value not pin
int unlockTimer = 10000;       //unlocked timer in msec
int unlockTimerCount = 0;
int lcdBackLightPin =  7;      //lcd backlight signal pin
int lcdBackLightState = LOW;   //lcd initial state
int warmerPin = 5;             //warmer signal pin
int boilerPin = 6;             //boiler signal pin
boolean boiling = false;
int boiledTimer = 10000;       //in msec
int boiledTimerCount = 0;
int warmLowLimit = 80;
int warmHiLimit = 85;
int reboilTemp = 65;
int boiledTemp = 95;
int emcyTemp = 105;
int buzzerPin = 4;
int buzzerFreq = 500;

void setup() {
  //Serial.begin(9600);
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Temp =");

  //set up unlock int pin
  attachInterrupt(unlockInt, unlock, RISING);

  //set lcd backlight signal pin
  pinMode(lcdBackLightPin, OUTPUT);

  //set warmer & boiler pin
  pinMode(warmerPin, OUTPUT);
  pinMode(boilerPin, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
}

void loop() {
  float temp = getTemp(analogRead(sensorPin));
  //Serial.println(temp);
  printTemp(temp);
  checkUnlock();
  heatingFunc(temp);
  checkOverHeat(temp);
  delay(samplingRate);
}

void checkOverHeat(float localTemp){
  if(localTemp >= emcyTemp){
    int buzzerPinState = LOW;
    digitalWrite(boilerPin, LOW);
    digitalWrite(warmerPin, LOW);
    lcdClearLine(1);
    lcd.setCursor(0, 1);
    lcd.print("Overheat!!!");
    while(true){
      digitalWrite(buzzerPin, buzzerPinState);
      delayMicroseconds(buzzerFreq);
      buzzerPinState = !buzzerPinState;
    }
  }
}

void heatingFunc(float localTemp){
  if(!boiling){
    if(localTemp < reboilTemp){
      boiling = true;
      boiledTimerCount = boiledTimer;
      digitalWrite(boilerPin, HIGH);
      digitalWrite(warmerPin, LOW);
      lcdClearLine(1);
      lcd.setCursor(0, 1);
      lcd.print("Boiler ON");
    }else if(localTemp < warmLowLimit){
      digitalWrite(warmerPin, HIGH);
      lcdClearLine(1);
      lcd.setCursor(0, 1);
      lcd.print("Warmer ON");
    }else if(localTemp > warmHiLimit){
      digitalWrite(warmerPin, LOW);
      lcdClearLine(1);
      lcd.setCursor(0, 1);
      lcd.print("Warmer OFF");
    }
  }else{
    if(localTemp > boiledTemp){
      boiledTimerCount = boiledTimerCount - samplingRate;
      lcdClearLine(1);
      lcd.setCursor(0, 1);
      lcd.print("95");
      lcd.print((char)223);
      lcd.print("C hitted");
    }
    if(boiledTimerCount <= 0){
      digitalWrite(boilerPin, LOW);
      boiling = false;
      lcdClearLine(1);
      lcd.setCursor(0, 1);
      lcd.print("Boiler OFF");
    }
  }
}

void lcdClearLine(int lineNo){
  lcd.setCursor(0, lineNo);
  lcd.print("                ");
}

void checkUnlock(){
  if(lcdBackLightState == HIGH){
    unlockTimerCount = unlockTimerCount - samplingRate;
    if(unlockTimerCount <= 0){
      lcdBackLightState = LOW;
      digitalWrite(lcdBackLightPin, lcdBackLightState);
    }
  }
}

void unlock(){
  lcdBackLightState = HIGH;
  unlockTimerCount = unlockTimer;
  digitalWrite(lcdBackLightPin, lcdBackLightState);
}

float getTemp(int sensorValue){
  float y1 = 100;
  float x1 = 594;
  float y2 = 33;
  float x2 = 116;
  float m = (y1 - y2) / (x1 - x2);
  float c = y1 - (m * x1);
  return (m * sensorValue) + c;
}

void printTemp(float localTemp){
  //clear last 10 char
  lcd.setCursor(6, 0);
  lcd.print("          ");
  if(localTemp>99){
    lcd.setCursor(8, 0);
  }
  else if(localTemp>9){
    lcd.setCursor(9, 0);
  }
  else{
    lcd.setCursor(10, 0);
  }
  lcd.print(localTemp);
  lcd.print((char)223);
  lcd.print("C");
}

The flow is quite similar to the original design and other model/brand. Reboil at 65°C, stop boiling several minutes after 95°C, cut off at 105°C. I did salvage an old circuit board from a different model of boiler and found 3 thermostats 65°C, 95°C and 105°C. So I guess all boilers are using the similar flow.

The final test...







Next is to built a proper circuit board and put it back together in one piece.

0 comments :

Recent Articles

Distributed By My Blogger Themes | Created By BloggerTheme9 | © 2014 DIY Electronics
TOP