Arduino Kitchen Timer

Arduino Kitchen Timer is made of 4-digit 7-segment LED, and 12-key keypad, 8-bit shift register 74HC164, and some resistors, decoupling capacitor, and Piezo speaker for the sound output.

* Do not imagine I am using this timer in my kitchen because I don’t. :) It’s just the name of device…

Feature:
Kitchen Timer. Maximum duration is 99 minutes and 99 sec. Beep when it’s done.

Parts:
1 x Keypad 12 Button
1 x 7-Segment Yellow 4 Digit LED
1 x 74AC164
8 x 470 ohm Resistor (LED)
* 220 ohm may work but it’s a little bit brighter. I used 470 ohm resistor array.
3 x 4.7K ohm Resistor (Keypad pullup resistors)
1 x Piezo Speaker taken out from old PC.

Pin Assignment:
Digital 02-05 Common Cathode of LED
Digital 06-12 Keypad Scanning
Digital 13 Piezo Speaker Output
Analog 0 74AC164 Data
Analog 1 74AC164 Clock
Analog 3-5 Not Used.

Video and Semantic in eagle format will be added soon.
Porting to Arduino Kitchen Timer Shield is on the way, but I will replace the keypad with just three or four buttons.

 
#include   <GenKeypad.h> //My keypad library
#include   <MsTimer2.h> //download this library at http://www.arduino.cc/playground/Main/MsTimer2

#define SHIFT_DATA 15     // 74AC164 data pin
#define SHIFT_CLOCK  14   // clock pin
#define SPEAKER_PIN 13

int NumPins[4] = {2, 3, 4, 5};
int SS = 0;
int MM = 0;
int start = 0;
char input[4] = {0, 0, 0, 0};
int inputIndex = 0;
int length = 15; // the number of notes
char notes[] = "ccccccccccccccc";
int beats[] = { 3, 1, 1, 3, 1, 1, 3, 1, 1, 3, 1, 1, 3, 1, 1 };

int tempo = 300;
int beeping = 0;

/**
   Keypad 
 **/
GenKeypad keypad;

//Key Input Callback Functions 
  
void keyUP(char key)  
{  
  //Serial.print("keyUP: ");  
  //Serial.println(key);  
}  

int atoi(char c)
{
  if (c == 0)
    return 0;
  else
    return (c - '0');
}

void keyDOWN(char key)  
{           
  Serial.print("keyDOWN: ");  
  Serial.println(key);  
    
  if (key == '#' && start == 0)
  {
    //Convert input chars into MM:SS
    MM = atoi(input[0]) * 10 + atoi(input[1]);
    SS = atoi(input[2]) * 10 + atoi(input[3]);
    
    if (MM + SS > 0)
      start = 1;
    return;
  }
  else if (key == '#' && start == 1)
  {
    start = 0;
    return;
  }

  if (key == '*')    
  {
    if (beeping == 0)
    {
      for (int i = 0; i < 4; i++)
        input[i] = 0;
    }
          
    inputIndex = 0;
    start = 0;
    beeping = 0;
    digitalWrite(SPEAKER_PIN, LOW);
  }
  else
  {  
    shiftDigit(input);
    input[3] = key;      
    
    inputIndex++;
    inputIndex %= 4;  
  }
}  

void shiftDigit(char input[4])
{
  input[0] = input[1];
  input[1] = input[2];
  input[2] = input[3];
}

void keyPRESSING(char key)  
{  
  //Serial.print("keyPressed: ");  
  //Serial.println(key);  
}

void setup(void) 
{
  Serial.begin(9600);
  
  //Digital pins parameter order matters!!
  keypad.setRowPins(11, 6, 7, 9);  //These pins are used as OUTPUT pins.
  keypad.setColPins(10, 12, 8);    //These pins are used as INPUT pins.  
  keypad.setFunction(GenKeypad::EVENT_KEY_UP,       keyUP); 
  keypad.setFunction(GenKeypad::EVENT_KEY_DOWN,     keyDOWN); 
  keypad.setFunction(GenKeypad::EVENT_KEY_PRESSING, keyPRESSING);
  
  pinMode(SPEAKER_PIN, OUTPUT);
  
  pinMode(SHIFT_DATA, OUTPUT);
  pinMode(SHIFT_CLOCK, OUTPUT);
  
  pinMode(NumPins[0], OUTPUT);
  pinMode(NumPins[1], OUTPUT);
  pinMode(NumPins[2], OUTPUT);
  pinMode(NumPins[3], OUTPUT);
  
  digitalWrite(NumPins[0], HIGH);
  digitalWrite(NumPins[1], HIGH);
  digitalWrite(NumPins[2], HIGH);
  digitalWrite(NumPins[3], HIGH);
  
  // writing default values (from the datasheet)
  
  MsTimer2::set(1000, secPulse);
  MsTimer2::start();
}

int digitSS = 0;
int digitMM = 0;
int digit = 0;

  byte font[10] = {
	//abcdefg.
    0b11111100,
    0b01100000,
    0b11011010,
    0b11110010,
    0b01100110,
    0b10110110,
    0b10111110,
    0b11100100,
    0b11111110,
    0b11100110
  };
  
byte c2font(char c)
{
  const byte blank = 0b00000000;
  
  if (c == 0)
    return blank;
  else  
    return font[c-'0'];
}


void setChars(char input[4], int delaymsec)
{
  digitalWrite(NumPins[0], LOW);
  shiftOut(SHIFT_DATA, SHIFT_CLOCK, LSBFIRST, c2font(input[3])); 
  delay(delaymsec);
  digitalWrite(NumPins[0], HIGH);

  digitalWrite(NumPins[1], LOW);
  shiftOut(SHIFT_DATA, SHIFT_CLOCK, LSBFIRST, c2font(input[2])); 
  delay(delaymsec);
  digitalWrite(NumPins[1], HIGH);


  digitalWrite(NumPins[2], LOW);
  shiftOut(SHIFT_DATA, SHIFT_CLOCK, LSBFIRST, c2font(input[1])); 
  delay(delaymsec);
  digitalWrite(NumPins[2], HIGH);

  digitalWrite(NumPins[3], LOW);
  shiftOut(SHIFT_DATA, SHIFT_CLOCK, LSBFIRST, c2font(input[0])); 
  delay(delaymsec);
  digitalWrite(NumPins[3], HIGH);
  
  delay(delaymsec);
}

void beep()
{
  if (start)
  {
    digitalWrite(SPEAKER_PIN, HIGH);
    beeping = 1;  
    start = 0;
  }
  else
    digitalWrite(SPEAKER_PIN, LOW);
}

void secPulse()
{
  if (start)
  {
    SS--;  
    if (SS == 0 && MM == 0)
    {
      beep();
      start = 0;
      return;
    }
    
    if (SS == -1 && MM > 0)
    {
      MM--;
      SS = 59;
    }

  }
}
void playTone(int tone, int duration) {
  for (long i = 0; i < duration * 1000L; i += tone * 2) 
  {          
    digitalWrite(SPEAKER_PIN, HIGH);
    delayMicroseconds(tone);
    digitalWrite(SPEAKER_PIN, LOW);
    delayMicroseconds(tone);
  }
}

void playNote(char note, int duration) {
  char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C', 'F', 'G'};
  int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 473, 478};
  
  // play the tone corresponding to the note name
  for (int i = 0; i < 10; i++) {
    if (names[i] == note) 
    {
      playTone(tones[i], duration);
    }
  }
}

char * clearLeadingZero(char input[4])
{
  if (input[0] == '0')
  {
    input[0] = 0;    
    if (input[1] == '0')    
    {
      input[1] = 0;
      if (input[2] == '0')    
        input[2] = 0;
    }
  }
  
  return input;
}

void processLCD()
{
  static char chs[4] = {'0', '0', '0', '0'};
 
  if (start)
  {
    chs[3] = SS%10 + '0';
    chs[2] = SS/10 + '0';
    chs[1] = MM%10 + '0';
    chs[0] = MM/10 + '0';
    
    setChars(clearLeadingZero(chs), 2);
  }
  else
  {   
    setChars(input, 2);
  }  
}

void loop()
{  
  int someKeyDown = keypad.scanKeys(0);
  keypad.handlePostEvents(someKeyDown);      
 
  processLCD();
  
  if (beeping = 1)
  {
     beeping++;
     beeping %=3;
     
     for (int i = 0; i < length; i++) 
     {
       someKeyDown = keypad.scanKeys(0);
       keypad.handlePostEvents(someKeyDown);      

       processLCD();
       if (beeping != 0)
         playNote(notes[i], beats[i] * tempo/2);
    
       // pause between notes
       delay(tempo / 2); 
     } 
  } 
}