Project showcase
Morse Code Kitchen Timer

Morse Code Kitchen Timer © GPL3+

Don't buy a kitchen timer, they are all boring. Make one like this.

  • 1,799 views
  • 0 comments
  • 9 respects

Components and supplies

Necessary tools and machines

dremel
09507 01
Soldering iron (generic)
Hy gluegun
Hot glue gun (generic)

About this project

I made a kitchen timer that doesn't stop, using a Nano. Also, setting timers is usually annoying, so I used encoders: one for mins, one for seconds. The morse key is used to start or stop the timer, or to stop the alarm when the timer hits zero.

Code

Kitchen timer codeArduino
Handle 2 encoders, peizo beeper, and 4x 7 segment displays
/* 
jjn timer
20161022
*/
#include <Wire.h> // Include the Arduino SPI library
bool showColon=0;

/*start encoders*/
int val; 
int encoder0PinA = 2;
int encoder0PinB = 3;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int encoder1PinA = 7;
int encoder1PinB = 8;
int encoder1Pos = 0;
int encoder1PinALast = LOW;
int n = LOW;
bool startup = true;
bool doBeeper=false;
int mins=0;
int secs=0;
/*end encoders*/

/*beep*/
int SPKR=9;
/*end beep*/

/*toggle button*/
  
// constants won't change. They're used here to
// set pin numbers:
const int buttonPin = 5;    // the number of the pushbutton pin
const int ledPin = 13;      // the number of the LED pin

// Variables will change:
int ledState = HIGH;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 50;    // the debounce time; increase if the output flickers
/*end toggle button*/


// Here we'll define the I2C address of our S7S. By default it
//  should be 0x71. This can be changed, though.
const byte s7sAddress = 0x71;

unsigned int counter = 0;  // This variable will count up to 65k
char tempString[10];  // Will be used with sprintf to create strings
int scan=1;
bool doCountdown=true;


void setup(){
  Serial.begin(9600);
  Wire.begin();  // Initialize hardware I2C pins

  /*start encoder pins*/
   pinMode (encoder0PinA,INPUT);
   pinMode (encoder0PinB,INPUT);
   pinMode (encoder1PinA,INPUT);
   pinMode (encoder1PinB,INPUT);  
  /*end encoder pins*/
  

  // Clear the display, and then turn on all segments and decimals
  clearDisplayI2C();  // Clears display, resets cursor

  // Custom function to send four bytes via I2C
  //  The I2C.write function only allows sending of a single
  //  byte at a time.
  //s7sSendStringI2C("TIMR");
  //setDecimalsI2C(0b111111);  // Turn on all decimals, colon, apos

  // Flash brightness values at the beginning
  //setBrightnessI2C(0);  // Lowest brightness
  //delay(130);
  setBrightnessI2C(255);  // High brightness
  //  setBrightnessI2C(105);  // med brightness
  //delay(150);
  //s7sSendStringI2C("TIMR");
  //delay(150);
  // Clear the display before jumping into loop
  //clearDisplayI2C();  

  /*toggle button*/
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  //pinMode (SPKR,OUTPUT);  

  // set initial LED state
  //digitalWrite(ledPin, ledState);
  /*end toggle button*/
}


void loop(){
   /*read encoders*/
   int delta=0;
   n = digitalRead(encoder0PinA);
   if ((encoder0PinALast == LOW) && (n == HIGH)) {
     if (digitalRead(encoder0PinB) == LOW) {
       encoder0Pos++;
       delta=1;
     } else {
       encoder0Pos--;
       delta=-1;
     }
     Serial.print ("B");
     Serial.print (encoder0Pos);
     Serial.print ("/");
   } 
   if(encoder0PinALast != n) {
     StopBeeperAndCountdown();
     mins+=delta;//=encoder0Pos;
   }
   encoder0PinALast = n;
   
   n = digitalRead(encoder1PinA);
   if ((encoder1PinALast == LOW) && (n == HIGH)) {
     if (digitalRead(encoder1PinB) == LOW) {
       encoder1Pos++;
       delta = 5;
     } else {
       encoder1Pos--;
       delta = -5;
     }
     Serial.print ("A");
     Serial.print (encoder1Pos);
     Serial.print ("/");
   } 
   if(encoder1PinALast != n){
     StopBeeperAndCountdown();
     secs+=delta;//encoder1Pos*5;
   }
   encoder1PinALast = n;

   if(mins>99)mins=0;  //mins
   if(mins<0)mins=99;
   if(secs>59)secs=0;  //secs 
   if(secs<0)secs=55;
     
   /*read encoders end*/
   if(startup){
     startup = false;
     encoder0Pos = 0;
     encoder1Pos = 0;
     mins = 0;
     secs = 0;
   }
  
  // Magical sprintf creates a string for us to send to the s7s.
  //  The %4d option creates a 4-digit integer.
  //sprintf(tempString, "%4d", counter);
  //sprintf(tempString, "%s%2d%s%2d",(mins<10)?"":"0", mins,(secs<10)?"":"0",secs);
  if(mins>9&&secs>9)sprintf(tempString, "%2d%2d", mins,secs);
  if(mins<=9&&secs>9)sprintf(tempString, "0%d%2d", mins,secs);
  if(mins>9&&secs<=9)sprintf(tempString, "%2d0%d", mins,secs);
  if(mins<9&&secs<=9)sprintf(tempString, "%02d0%d", mins,secs);
  
  if(scan%1000==0){  //only update every so many cycles
    // This will output the tempString to the S7S
    s7sSendStringI2C(tempString);
  }
  // Print the decimal at the proper spot
  /* 
  setDecimalsI2C(0b00000100);  // Sets digit 3 decimal on
  */
    
  //delay(50);  // This will make the display update at 10Hz.*/

  scan++;
  if(scan > 60000){scan=0;}
  
  if(doCountdown){
    if(scan % 5000==0 && !doBeeper){
      if(secs >= 0)secs--;
      if(secs < 0){
        secs = 59;
        mins--;
      }
      if(mins < 0){
        secs = 0;
        mins = 0;
        doCountdown = false;
        doBeeper = true;
      }
    }
  }
  
  if(scan % 3000 == 0){
    showColon=!showColon;
    //  [MSB] (X)(X)(Apos)(Colon)(Digit 4)(Digit 3)(Digit2)(Digit1)
    if(doCountdown && showColon){//showColon
      setDecimalsI2C(0b010000);  // Turn on colon
    }else{
      setDecimalsI2C(0b000000);  // hide colon
    }
    if(doBeeper){
      alarm();
    }
  }
  
  CheckToggleButton();
}

void CheckToggleButton(){
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);

  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH),  and you've waited
  // long enough since the last press to ignore any noise:

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      snick();
      if(doCountdown&&doBeeper)StopBeeperAndCountdown();
      buttonState = reading;

      // only toggle the LED if the new button state is HIGH
      if (buttonState == HIGH) {
        //ledState = !ledState;
        
     
        doCountdown=!doCountdown;
      }
    }
  }

  // set the LED:
  //digitalWrite(ledPin, ledState);

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState = reading;
}

// This custom function works somewhat like a serial.print.
//  You can send it an array of chars (string) and it'll print
//  the first 4 characters in the array.
void s7sSendStringI2C(String toSend){
  Wire.beginTransmission(s7sAddress);
  for (int i=0; i<4; i++)
  {
    Wire.write(toSend[i]);
  }
  Wire.endTransmission();
}

// Send the clear display command (0x76)
//  This will clear the display and reset the cursor
void clearDisplayI2C(){
  Wire.beginTransmission(s7sAddress);
  Wire.write(0x76);  // Clear display command
  Wire.endTransmission();
}

// Set the displays brightness. Should receive byte with the value
//  to set the brightness to
//  dimmest------------->brightest
//     0--------127--------255
void setBrightnessI2C(byte value){
  Wire.beginTransmission(s7sAddress);
  Wire.write(0x7A);  // Set brightness command byte
  Wire.write(value);  // brightness data byte
  Wire.endTransmission();
}

// Turn on any, none, or all of the decimals.
//  The six lowest bits in the decimals parameter sets a decimal 
//  (or colon, or apostrophe) on or off. A 1 indicates on, 0 off.
//  [MSB] (X)(X)(Apos)(Colon)(Digit 4)(Digit 3)(Digit2)(Digit1)
void setDecimalsI2C(byte decimals){
  Wire.beginTransmission(s7sAddress);
  Wire.write(0x77);
  Wire.write(decimals);
  Wire.endTransmission();
}

void snick(){
  // put your setup code here, to run once:
  pinMode (SPKR,OUTPUT);
  
  for (int i=0; i<300; i++) {  // generate a 1KHz tone for 1/2 second
    digitalWrite(SPKR, HIGH);
    delayMicroseconds(100);
    digitalWrite(SPKR, LOW);
    delayMicroseconds(100);
  }
  pinMode (SPKR,INPUT);
  //delay(1000);
}

void alarm(){
  //return;
  // put your setup code here, to run once:
  pinMode (SPKR,OUTPUT);
  
  for (int i=0; i<350; i++) { 
    digitalWrite(SPKR, HIGH);
    delayMicroseconds(120);
    digitalWrite(SPKR, LOW);
    delayMicroseconds(50);
    digitalWrite(SPKR, HIGH);
    delayMicroseconds(60);
  }
  pinMode (SPKR,INPUT);
  //delay(1000);
}

void StopBeeperAndCountdown(){
  doBeeper=false;
  doCountdown=false;
  //secs=30;
  //mins=encoder1Pos*5;
  //secs=encoder0Pos*5;
}

Schematics

Schematic
Here is the kitchen timer breadboard
analogue_kitchen_timer_npBqYQqs0Y.fzz
Breadboard image
Schematic from fritzing 7uidysqfsk
Vero board version
analogue_kitchen_timer_-_vero_Jbe84ep5HM.fzz

Comments

Similar projects you might like

Adaptive LED Morse Code Decoder and Timer Interrupt

Project tutorial by shjin

  • 1,359 views
  • 0 comments
  • 12 respects

Arduino Kitchen Timer

Project tutorial by Team I and myself

  • 54,451 views
  • 37 comments
  • 77 respects

Arduino Morse Code Machine

Project showcase by Vlada Krsmanovic

  • 10,221 views
  • 1 comment
  • 30 respects

Morse Code Transmitter - Light Signal

Project showcase by Alireza Karkon

  • 1,230 views
  • 1 comment
  • 7 respects

Retro View Timer

Project tutorial by yilmazyurdakul

  • 978 views
  • 1 comment
  • 2 respects

Morse Code Translator

Project showcase by Team ONYX

  • 10,193 views
  • 2 comments
  • 15 respects
Add projectSign up / Login