I have a coffee-making machine that makes nice coffee:
Unfortunately it is supposed to be cleaned each week (each day?) using these rather complex instructions:
Every time I go to do that, it almost drives me insane as I try to get it right (run 5 seconds, off 2 seconds, repeat 10 times, etc.). So I thought, "why not make a gadget that does that?". So here it is:
Everything is "off the shelf" hardware-wise, except the addition of a soldered-on piezo buzzer (circled).
Buttons ($US 8.90):
http://iteadstudio.com/store/index.php?main_page=product_info&cPath=18&products_id=351
LCD ($US 6.80):
http://iteadstudio.com/store/index.php?main_page=product_info&cPath=57_60&products_id=155
Plus an Arduino Uno ($US 30).
You basically hit the "clean" or "rinse" button and it counts down the correct number of cycles, with a beep to alert you to change modes on the coffee machine. It doesn't operate the machine, but it does the timing and counting for you.
Code:
// Program for timing Cappuccino machine cleaning cycle
// Author: Nick Gammon
// Date: 15 June 2011
#include <avr/pgmspace.h>
#include <iBridge_Keypad.h>
#include <iBridge_LCD_display.h>
#define CLEANCYCLES 5 // number of cleaning cycles
#define CLEANSECS 5 // seconds to clean
#define CLEANSITSECS 15 // seconds to sit idle
#define RINSECYCLES 10 // number of rinse cycles
#define RINSESECS 5 // seconds to rinse
#define RINSESITSECS 2 // seconds to sit idle
// beep sound
#define FREQUENCY 880L // Hz
#define PERIOD 500000L / FREQUENCY // (1 / frequency) * 1e6 / 2
// pins buzzer is connected to
#define BUZZER1 A2
#define BUZZER2 A4
// keypad
const byte ROWS = 3;
const byte COLS = 3;
const char keys[ROWS][COLS] = {
{ '1', '2', '3' },
{ '4', '5', '6' },
{ '7', '8', '9' },
};
byte rowPins[ROWS] = { 2, 3, 4 }; //connect to the row pinouts of the keypad
byte colPins[COLS] = { 5, 6, 7 }; //connect to the column pinouts of the keypad
// Create the Keypad
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
// Create the LCD
iBridge_LCD_display lcd;
// Beep for duration times x number
void beep (const int duration, const int number = 1)
{
for (int j = 0; j < number; j++)
{
for(int i = 0 ; i < duration ; i++)
{
digitalWrite (BUZZER1, HIGH);
digitalWrite (BUZZER2, LOW);
delayMicroseconds(PERIOD);
digitalWrite (BUZZER1, LOW);
digitalWrite (BUZZER2, HIGH);
delayMicroseconds(PERIOD);
} // end of for duration
digitalWrite (BUZZER1, LOW);
digitalWrite (BUZZER2, LOW);
delay (100);
} // end of for each number
} // end of beep
void menu ()
{
lcd.clear ();
lcd.gotoxy (0, 0);
lcd.string ("Coffee cleaner");
lcd.gotoxy (0, 2);
lcd.string ("1: Clean");
lcd.gotoxy (0, 3);
lcd.string ("3: Rinse");
} // end of menu
void showcounter (char * s, byte line, byte c1, byte c2)
{
lcd.gotoxy (0, line - 1);
lcd.string (s);
lcd.writeDecimal (c1);
lcd.string ("/");
lcd.writeDecimal (c2);
lcd.string (" ");
} // end of showcounter
void clean ()
{
for (byte cycle = 1; cycle <= CLEANCYCLES; cycle++)
{
beep (50, 2);
lcd.gotoxy (0, 0);
lcd.clear ();
showcounter ("Clean #", 1, cycle, CLEANCYCLES);
for (byte s = 1; s <= CLEANSECS; s++)
{
showcounter ("Run: ", 3, s, CLEANSECS);
delay (1000);
}
beep (50, 5);
for (byte s = 1; s <= CLEANSITSECS; s++)
{
showcounter ("Sit: ", 3, s, CLEANSITSECS);
delay (1000);
}
} // end of for
beep (50, 10);
lcd.gotoxy (0, 0);
lcd.clear ();
lcd.string ("Rinse and");
lcd.gotoxy (0, 1);
lcd.string (" reinsert");
lcd.gotoxy (0, 2);
lcd.string (" handle.");
delay (5000);
} // end of clean
void rinse ()
{
for (byte cycle = 1; cycle <= RINSECYCLES; cycle++)
{
beep (50, 2);
lcd.gotoxy (0, 0);
lcd.clear ();
showcounter ("Rinse #", 1, cycle, RINSECYCLES);
for (byte s = 1; s <= RINSESECS; s++)
{
showcounter ("Run: ", 3, s, RINSESECS);
delay (1000);
}
beep (50, 5);
for (byte s = 1; s <= RINSESITSECS; s++)
{
showcounter ("Sit: ", 3, s, RINSESITSECS);
delay (1000);
}
} // end of for
beep (50, 10);
lcd.gotoxy (0, 0);
lcd.clear ();
lcd.string ("Brew and");
lcd.gotoxy (0, 1);
lcd.string (" discard");
lcd.gotoxy (0, 2);
lcd.string (" coffee.");
delay (5000);
} // end of rinse
void setup()
{
lcd.begin();
pinMode (BUZZER1, OUTPUT); // piezo buzzer pins
pinMode (BUZZER2, OUTPUT);
beep (10); // beep to show we started up
menu ();
} // end of setup
void loop()
{
byte key = kpd.getKey();
if (key)
{
delay (500); // debounce
switch (key)
{
case '1': clean (); break;
case '3': rinse (); break;
} // end of switch
menu ();
} // end if key pressed
} // end of loop