Skip to content

Instantly share code, notes, and snippets.

@spaceCamel
Created February 13, 2011 19:28
Show Gist options
  • Save spaceCamel/824984 to your computer and use it in GitHub Desktop.
Save spaceCamel/824984 to your computer and use it in GitHub Desktop.
/*
TOMATO TIMER
CIRCUIT:
5 red leds, 1 green, 1 button
STATES:
STOPPED, COUNTING, HOLD (show period number), TOMATO_COMPLETED
DESCRIPTION
The timer when plugged is in STOPPED state, waiting for the button to be pressed.
Pressing the button makes the counter to start. When the count first starts
the first led starts blinking and continues for 5 minutes. After 5 minutes the
first led stays on and the second starts blinking. The counter continues to
count up to 25 minutes when all the red leds will be filled. At that point all
the RED are turned off and the green starts blinking for 5 minutes if we are on a short
break or 35 minutes if we are on a long break.
*/
// LEDs
const int RED05 = 4,
RED10 = 5,
RED15 = 6,
RED20 = 7,
RED25 = 9,
GREEN = 11;
const int LED_ARRAY_LENGTH = 5;
const int LED_ARRAY[LED_ARRAY_LENGTH] = {RED05,
RED10,
RED15,
RED20,
RED25};
// INPUTs
const int BUTTON = 13;
// STATES
//const int STOPPED, // counter is 0 and all led are OFF
// COUNTING, // led display the time passing by, this is the 25 minutes working phase
// HOLD, // led display the time the tomato was paused with a special blinking (double quick?)
// LONG_BREAK, // the green led blinks slowly
// SHORT_BREAK, // the green led blinks normally
// TOMATO_COMPLETED; // the tomato is completed (working and break) all led are on
// OTHER
const int TOMATO_MINUTES = 5, // The timer will be of 25 minutes
ROUND_LENGTH = 2; // every 4 rounds we have a long-break
const boolean ON = true,
OFF = false;
// GLOBAL VARIABLES
unsigned long start_time = 0;
byte tomatos_completed = 0;
void setup() {
pinMode(RED05, OUTPUT);
pinMode(RED10, OUTPUT);
pinMode(RED15, OUTPUT);
pinMode(RED20, OUTPUT);
pinMode(RED25, OUTPUT);
pinMode(GREEN, OUTPUT);
pinMode(BUTTON, INPUT);
Serial.begin(9600);
jingle(); // display fancy LEDs (and ignore pushed buttons)
}
void loop() {
Serial.print("Waiting button");
wait(BUTTON); // loop till the button is pressed
start_time = millis(); // let's start counting
Serial.print("Started at: ");
Serial.println(start_time);
// start counting (and displaying time) until the button is pressed or the period is finished
unsigned int minutes_passed = count();
// check for how long we counted
if (minutes_passed < TOMATO_MINUTES) {
// we didn't complete the tomato
hold(minutes_passed); // hold the time (blinking appropriately)
} else {
// we completed the tomato, let's go to break!
tomatoCompleted();
Serial.print("COMPLETED ");
Serial.println(tomatos_completed);
}
// variables were resetted?
scrollLed( 0, LOW);
}
void jingle() {
Serial.println("JINGLE!");
scrollLed( 0, LOW);
scrollLed(100, HIGH);
scrollLed(100, LOW);
}
void scrollLed(int time, int state) {
for (int n = 0; n < LED_ARRAY_LENGTH; n++) {
digitalWrite(LED_ARRAY[n], state);
delay(time);
}
digitalWrite(GREEN, state);
delay(time);
}
int count() {
Serial.println("Counting...");
int elapsedMinutes = 0;
while(!digitalRead(BUTTON) && (elapsedMinutes < TOMATO_MINUTES)) {
elapsedMinutes = readMinutes();
displayTime(elapsedMinutes);
delay(10);
}
delay(1000);
return elapsedMinutes;
}
void hold(int minutes) {
Serial.println("HOLDING");
// TURN EVERYTHING OFF
scrollLed(200, LOW);
digitalWrite(GREEN, HIGH);
int ledOn = LED_ARRAY[minutes / LED_ARRAY_LENGTH];
boolean led_state = ON;
int count = 0;
while(!digitalRead(BUTTON)) {
delay(50);
if (count == 10) {
led_state = !led_state;
digitalWrite(ledOn, led_state);
count = 0;
} else {
count += 1;
}
}
scrollLed(200, LOW);
}
void tomatoCompleted() {
Serial.println("Tomato COMPLETED!");
scrollLed(100, LOW);
tomatos_completed += 1;
if ((tomatos_completed % ROUND_LENGTH) != 0) shortBreak();
else longBreak();
}
void wait(int input) {
while(!digitalRead(input)) {
delay(10);
}
delay(100);
}
void shortBreak() {
Serial.println("SHORT BREAK");
boolean light = false;
while(!digitalRead(BUTTON)) {
delay(1000);
light = !light;
digitalWrite(GREEN, light);
}
}
void longBreak() {
Serial.println("LONG BREAK");
boolean light = false;
while(!digitalRead(BUTTON)) {
light = !light;
digitalWrite(GREEN, light);
if (light) {
delay(1500);
} else {
delay(500);
}
}
}
int readMinutes() {
return to_minutes(millis() - start_time);
}
int to_minutes(unsigned long milliseconds) {
return milliseconds / 1000 / 60;
}
void displayTime(unsigned int minutes) {
static unsigned long last_time = 0;
static unsigned int displayed_minutes = 0;
static boolean last_led_state = ON;
// check if the time to be displayed is different from the one already displayed
if (minutes != displayed_minutes) {
Serial.print(minutes);
Serial.println(" minutes");
// check how many led to turn on
int ledOn = minutes / (TOMATO_MINUTES / LED_ARRAY_LENGTH);
// for each led on the array decide...
for (int n = 0; n < LED_ARRAY_LENGTH; n++) {
// it's one of those to be turned on
if (n <= ledOn) digitalWrite(LED_ARRAY[n], HIGH);
// it's one of those to be turned off
if (n > ledOn) digitalWrite(LED_ARRAY[n], LOW);
}
last_led_state = ON; // last led should blink, remember that now it's on
last_time = millis();
displayed_minutes = minutes; // update the minutes we are displaying now
} else {
// we have to blink the last led
unsigned long time = millis();
// if it was toggled more then 1sec ago, let's toggle it again
if ((time - last_time) > 1000) {
last_led_state = !last_led_state;
int lastLED = minutes / (TOMATO_MINUTES / LED_ARRAY_LENGTH);
Serial.print((time - start_time) / 1000);
Serial.print(", ");
digitalWrite(LED_ARRAY[lastLED], last_led_state);
last_time = time;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment