Skip to content

Instantly share code, notes, and snippets.

@brian-lc
Last active October 5, 2015 00:00
Show Gist options
  • Select an option

  • Save brian-lc/4c105f4276c1196fc421 to your computer and use it in GitHub Desktop.

Select an option

Save brian-lc/4c105f4276c1196fc421 to your computer and use it in GitHub Desktop.
Power monitoring and state inspection of Breville tea maker
#include "EmonLib.h" // Include Emon Library
EnergyMonitor Emon1; // Create an instance
int LedPin = 5;
int BasketDownPin = 2; // Will pulse this pin 10ms when the basket drops
int BasketUpPin = 3; // Will pulse this pin 10ms when the basket raises
double IrmsBase = 0.0; // Baseline current sampled at startup
int BaseLen = 5;
double Baseline[5]; // History for baseline so we update baseline overtime
String States[3] = {"Waiting", "Heating", "Basket"};
int HistLen = 4;
int StateHist[4] = {0,0,0,0}; // Stores the state history
int TrigerState[3] = {2,2,2}; // When the history array shows Basket Motion (3 events)
boolean Heating = false; // Flag to indicate we have started heating
boolean Basket = false; // Flag to indicate basket in motion
boolean Brewing = false; // Flag to indicate we have started brewing
boolean Done = false; // Flag to indicate we have finished brewing
void setup()
{
//Serial.begin(9600); // Serial for debugging
Emon1.current(1, 13.43); // Current: input pin, manual calibration constant
pinMode(LedPin, OUTPUT); // Calibration process: http://openenergymonitor.org/emon/buildingblocks/calibration
pinMode(BasketDownPin, OUTPUT);
pinMode(BasketUpPin, OUTPUT);
digitalWrite(BasketDownPin, LOW);
digitalWrite(BasketUpPin, LOW);
digitalWrite(LedPin, HIGH); // Baseline capture, power up LED on
double sum = 0.0;
int samples = 10;
for (int i=0; i <= samples; i++){ // Sample Irms and average to create baseline
sum = sum + Emon1.calcIrms(1480);
digitalWrite(LedPin, LOW);
delay(100);
digitalWrite(LedPin, HIGH);
}
double bootBase = sum/samples; // set the baseline Irms for sensing tea maker states
initialBaseline(bootBase); // Baseline capture done
}
void loop()
{
digitalWrite(BasketDownPin, LOW);
digitalWrite(BasketUpPin, LOW);
double irms = Emon1.calcIrms(1480); // Calculate Irms only
int teaStat = senseStatus(irms);
saveStat(teaStat);
if (histCheck(1)){ // if we have applied heat for a little bit then
Heating = true; // We're heating water!
Brewing = false; // Reset all state
Basket = false;
Done = false;
}
if (Heating && !Basket && !Brewing && histCheck(2)){ // if we were heating, and not brewing and the basket is not moving, but now the basket IS moving...
printTrans("DOWN"); // basket going down!
digitalWrite(BasketDownPin, HIGH);
delay(10);
digitalWrite(BasketDownPin, LOW);
Heating = false; //done heating
Brewing = false; //not yet brewing
Basket = true; //basket is moving
}
if (!Heating && !Basket && Brewing && histCheck(2)){ // if we are not heating and not moing the basket and were brewing but now the basket is moving...
printTrans("UP"); // basket coming up!
digitalWrite(BasketUpPin, HIGH);
delay(10);
digitalWrite(BasketUpPin, LOW);
Brewing = false; // Must be done brewing
Basket = true; // basket is moving
Done = true;
}
if (!Done && Basket && histCheck(0)){ // if not done and the basket was in motion and we are waiting now...
Basket = false; // basket is done moving
Brewing = true; // We are brewing!!
}
if (Done && Basket && !Brewing && histCheck(0)){ // if done, the basket was moving, brew is done and we are waiting now...
Basket = false; // All done with the brew cycle
}
// Fairly certain this is causing more problems than it solves
// if (Done && !Heating && !Basket && !Brewing && histCheck(0)){ // To adjust for drift
// updateBaseline(irms); // update our baseline when not in a cycle
// }
updateBrewLight();
//printStatus(irms, teaStat);
delay(10); //if not printing serial, delay.
}
// Pushes the current tea Status value to the top of the
// StatHist array, shifts all existing values right.
void saveStat(int teaStat){
int temp[HistLen];
temp[0] = teaStat;
for(int x=0; x < (HistLen-1); x++){
temp[x+1] = StateHist[x];
}
for(int x=0; x < HistLen; x++){
StateHist[x] = temp[x];
}
}
// Senses our teamaker state by looking at RMS current.
// Based on what component is on, heater vs motor vs base
// there are different levels of current used. The heater is
// 100x the base current, and the motor is 1.5x the base current.
int senseStatus(double irms){
String tStat;
if (irms >= (IrmsBase * 100)){
return 1; // Heating
}
else if (irms >= (IrmsBase * 1.4) && irms < (IrmsBase * 10)){
return 2; // Basket Motion
}
else {
return 0; // Waiting
}
}
// Look back at the previous status values
// and see if they all match the tStat value
boolean histCheck(int tStat){
int x = 0;
while (x < HistLen){
if (tStat == StateHist[x]){
x++; //move on to check the next
}
else {
return false;
}
}
return true;
}
// Initialize our history to the boot baseline
void initialBaseline(double allBase){
for (int x=0; x < BaseLen; x++){
Baseline[x] = allBase;
}
IrmsBase = allBase;
}
// Compute updated average based on new Irms sample
// Store it in our Baseline and update the global
void updateBaseline(double newBase){
// add to top of array
double temp[BaseLen];
temp[0] = newBase;
for(int x=0; x < (BaseLen-1); x++){
temp[x+1] = Baseline[x];
}
for(int x=0; x < BaseLen; x++){
Baseline[x] = temp[x];
}
double sum = 0.0;
for (int x=0; x < BaseLen; x++){
sum = sum + Baseline[x];
}
IrmsBase = sum/BaseLen;
}
// Simple time-based LED flasher
boolean LEDon = false;
void updateBrewLight(){
if (Brewing && !Done){
if (!LEDon){
digitalWrite(LedPin, HIGH);
LEDon = true;
}
else {
digitalWrite(LedPin, LOW);
LEDon = false;
}
}
if (!Brewing){
digitalWrite(LedPin, HIGH);
}
}
// Simple debugging print function
void printStatus(double irms, int teaStat){
Serial.print(irms); // Irms current
Serial.print(" ");
Serial.print(States[teaStat]); // Waiting, Heating, Basket Motion
// Print the state array
Serial.print(" [");
for(int x=0; x < HistLen; x++){
Serial.print(StateHist[x]);
Serial.print(",");
}
Serial.print("]");
Serial.print(" Bsl:");
Serial.print(IrmsBase);
// Print the baseline history
Serial.print(" [");
for(int x=0; x < BaseLen; x++){
Serial.print(Baseline[x]);
Serial.print(",");
}
Serial.print("]");
// print our boolean states
Serial.print(" Htg:");
Serial.print(Heating);
Serial.print(" Bsk:");
Serial.print(Basket);
Serial.print(" Brw:");
Serial.print(Brewing);
Serial.print(" Dn:");
Serial.print(Done);
Serial.println(" ");
}
void printTrans(String updown){
Serial.println("!!!!!!! BASKET TIME !!!!!!!");
Serial.print("!!!!!!! GOING ");
Serial.print(updown);
Serial.println(" !!!!!!!");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment