Hardware components | ||||||
![]() |
| × | 1 | |||
Hand tools and fabrication machines | ||||||
|
- It's an enhanced kitchen timer that can turn off any device that you would normally plug into the wall outlet. And, for a bonus, with 19 seconds remaining, the Arduino will play Europe's "Final Countdown" song, just like in the Geico commercial!
One day, I was playing slither.io just after completing my homework. While I was playing my game, my Dad asked me to turn on our wet grinder for exactly 45 minutes. And that's when my dilemma hit me like a meteor hits the Earth. I asked myself, "Why don't those Indian marketers add a timer that would automatically turn off my Grinder?"
**A wet grinder is a basically a big smoothie mixer, but instead of blades it uses cone-shaped granite to ground rice into dough**
Unfortunately, this model doesn't come with a timer(just an on and off switch).
This is what a wet grinder can make if the rice is ground properly:
It's called Dosa. And it looks scrumptious!
Realization:
That's when I thought about making my Arduino Uno turn off the grinder for me. After all, robots have a better reaction time than us humans. Personally, I just want to focus on playing slither.io and get to the top ranks(Trust me, I play pretty good when no one's watching).
But in this project, I thought I would make things a little more interesting; I decided to make a delay-free project.
To check out the rest of this project, continue to#include <Time.h>
#include <TimeLib.h>
/*
I am a free software; you can redistribute me and/or modify
me, but you must include the people who participated in making me.
Creator: Nathan Ramanathan(but my friends call me Nathan^2)
// Special thanks to the Bald Engineer for the FadeWithoutDelay Code
// See baldengineer.com/fading-led-analogwrite-millis-example.html for more information
*/
//-----------------------------------------------------------Do Not connect a pin to D12 because it is in use as a dummy pin---------------------------------------------------------//
int dummyPin = 12;//I had D33 originally and it created a bug on Arduino Boards, who have less than 33 I/O pins. So I decided to sacrifice a REAL Pin.
int PiezoPin = 6;//This pin is connected to the piezo buzzer
#define relay 8 //#define is an easier way to identify, in anyone's code, all pins the Arduino will meddle with.
#define led 11
int speakerPin;
//Global variables
int hr=1;//1 hour
int mn=30;//30 minutes
int sec=0; //0seconds //Therefore, 1 hr and 30 minutes is maxLoad. //Use maxLoad for the maximum amount of time for the switch to be open(For safety purposes).
double maxLoad = hr * (60 * 60 * 1E3)/*hours*/ + mn * (60 * 1E3)/*minutes*/ + sec * (1E3)/*seconds*/;
double h = 0, m = 0, s = 0, a = 0, b = 0, c = 0, BeepTime = .25E3;
bool e = false, d = false, f = false, fadeOrNot = false, viewer = false, pause = true, start = false, shortTime = false, lightOrNot = true, buzzOrNot = true; //If you music off as default, simply change buzzOrNot to false
String where = ""; String split = "";
int str = 0, count = 0, buzzerCount = 0;
double interval = 0;
double newInterval = 0;
////////////////////////////////////////////////////////////////////////////////////////////////////////
// define directions for LED fadeWithoutDelay
// constants for min and max PWM
const int minPWM = 0;
const int maxPWM = 255;
// State Variable for Fade Direction
bool q = true;
// Global Fade Value
// but be bigger than byte and signed, for rollover
int fadeValue = 0;
// How smooth to fade?
byte fadeIncrement = 5;
// millis() timing Variable, just for fading
unsigned long previousFadeMillis;
// How fast to increment?
int fadeInterval = 45;
//////////////////////////////////////////////// The FINAL COUNTDOWN song
#include "pitches.h"
unsigned long songMillis = 0;
int thisNote = -1;
// notes in the melody:
//int melody[] = {
// NOTE_E4, NOTE_F4, NOTE_FS4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5
//};
int melody[] = {//The FINAL COUNTDOWN song
NOTE_B4, NOTE_A4, NOTE_B4, NOTE_E4, 0, NOTE_C5, NOTE_B4, NOTE_C5, NOTE_B4, NOTE_A4, 0, NOTE_C5, NOTE_B4, NOTE_C5, NOTE_E4, NOTE_FS4, 0, NOTE_A4, NOTE_G4, NOTE_A4, NOTE_G4, NOTE_FS4, NOTE_A4, NOTE_G4, 0, NOTE_B4, NOTE_A4, NOTE_B4, NOTE_E4, 0, NOTE_C5, NOTE_B4, NOTE_C5, NOTE_B4, NOTE_A4, 0, NOTE_B4, NOTE_A4, NOTE_B4, NOTE_E4, NOTE_FS4, 0, NOTE_A4, NOTE_G4, NOTE_A4, NOTE_G4, NOTE_FS4, NOTE_A4, NOTE_G4
};
// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
16, 16, 4, 4, 2, 16, 16, 8, 8, 4, 2, 16, 16, 4, 4, 4, 4, 16, 16, 8, 8, 8, 8, 4, 8, 16, 16, 4, 4, 2, 16, 16, 8, 8, 4, 2, 16, 16, 4, 4, 4, 6, 16, 16, 8, 8, 8, 8, 4
};
const int lengthOfSong = 23 + 26; //For some reason the millis() doesn't like calculating array size.
///////////////////////////
////////////////////////////////////////For the Millis() function to meddle with
unsigned long psMillis = 0;
unsigned long shortTimeMillis = 0;
unsigned long placeHolder1 = 0;
unsigned long placeHolder2 = 0;
////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);//Depends on which Arduino you choose, since we are taking advantage of wireless programming and Bluetooth communications. For example, the Hc-05 and the Arduino are both running at a 115200 baud rate.
speakerPin = PiezoPin;
pinMode(speakerPin, OUTPUT); //Telling the Arduino which pins are output
pinMode(led, OUTPUT);
pinMode(relay, OUTPUT);
digitalWrite(relay, HIGH); //Turns off the AC switch(relay)
///////////////////////////////////////////////////////////Introduction(Runs only once)
Serial.println("Welcome to Nathan^2's Universal AC Switch. How long do you want to turn on this machine? For example 4 hours, 30 minutes, and 2 seconds is '4h 30m 2s'. Order doesn't matter.");
// Serial.println("\t\tBut, if you typed 4h 2m 3s, but you actually meant 1m 20s, just type what you meant '0h 1m 20s'. It's really that simple!");
// Serial.println("Type 'v' to view to see your timer. 1.5 hours is the max(Safety Hazard)!");
// Serial.println("DID you know there is a Light! To switch it on or off, type 'l'.");
// Serial.println("Type 'b' to turn the alarm off or on.");
}
void loop() {
// put your main code here, to run repeatedly:
unsigned long currentMillis = millis();
if (Serial.available()) {
str = Serial.read();
if (isAlpha(str)) {
if (!start)
switch (str) {
case 'h': //hours
h = where.toFloat(); //Don't modify variable h, m, or s because we want to show the user what they typed in!
interval -= a;
a = (h * 60 * 60 * 1E3);
where = "";
d = true;
interval += a;
psMillis = millis();
viewer = true;
break;
case 'm':
//minutes
m = where.toFloat();
interval -= b;
b = (m * 60 * 1E3);
where = "";
e = true;
interval += b;
psMillis = millis();
viewer = true;
break;
case 's':
//seconds
s = where.toFloat();
interval -= c;
c = (s * 1E3);
where = "";
f = true;
interval += c;
psMillis = millis();
viewer = true;
break;
case 'v':
if ((interval <= maxLoad)) {
Serial.print("You entered a time of ");
readTime(d, e, f, h, m, s);
Serial.println(split);
Serial.print("\t");
Serial.println("Type 'y' for yes and we will start!");
viewer = false;
}
else { //Safety precaution. To change just change the maxLoad at the Beginning all the code(Line 17-19).
Serial.println("Too long! Go under "+ String(hr) +" hours "+String(mn) +" minutes "+String(sec) +" seconds.");
}
break;
case 'y':
if ((interval <= maxLoad) && (interval > 0)) { /// Starts the machine
viewer = false;
fadeInterval = 4;
Serial.println("Starting now!");
Serial.println("To pause/resume:'p'\t reset:'r'\t end timer: 'e'\t Time remaining: 'w'.");
if (buzzOrNot) {
shortTime = true;
BeepTime = 1E3;
buzzerCount = 4;
}
if (lightOrNot) {
digitalWrite(led, HIGH);
}
digitalWrite(relay, LOW);
fadeOrNot = false;
newInterval = interval;
psMillis = millis();
start = true;
placeHolder1 = millis();
}
break;
}
switch (str) {
case 'p':
{
if (start) {////////////////////////////////////////////////////////////////////////////////////Probably one of the most complex codes I have written,but not that hard :)
if (!pause) { //This code allows the user to pause the machine timer and then continue back to where it left off.
pause = true;
fadeOrNot = false;
newInterval = newInterval - (placeHolder2 - placeHolder1);
psMillis = currentMillis;
placeHolder1 = currentMillis;
Serial.println("Resuming");
digitalWrite(relay, LOW);
}//Are you lost yet? ;)
else {
pause = false; //Beleive it or not, but we need to set pause to false, inorder to pause. :0
fadeOrNot = true;
placeHolder2 = currentMillis;
double pausedInterval = (newInterval - (placeHolder2 - placeHolder1));
Serial.print("Paused. Time Remaining: ");
readDuring(pausedInterval);
digitalWrite(relay, HIGH);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
break;
case 'r': //reset the timer
if (start) {
Serial.print("Resetting timer back to ");
readTime(d, e, f, h, m, s);
Serial.print(split);
newInterval = interval;
if (pause) {
Serial.println(", and resuming.");
}
else
{
Serial.println(", and still paused");
}
psMillis = millis();
placeHolder2 = millis();
placeHolder1 = millis();
thisNote = -1;
}
break;
case 'e': //End the Timer
if (start) {
Serial.println("Ending Timer ");
pause = true;
newInterval = 0;
thisNote = lengthOfSong + 1;
}
break;
case 'w': //End the Timer
if (start && pause) {
Serial.print("\t\t\t Time left: ");
double pausedInterval = (newInterval - (millis() - placeHolder1));
readDuring(pausedInterval);
}
break;
case 'l': //Light settings
lightOrNot = true;
if (count == 0) {
digitalWrite(led, LOW);
lightOrNot = false;
Serial.println("\t\tNightLight: Off");
fadeOrNot = true;
}
else if (count == 1 && !start) {
digitalWrite(led, HIGH);
Serial.println("\t\tNightLight: On");
fadeOrNot = true;
}
else if (count == 2 && !start) {
fadeOrNot = false;
Serial.println("\t\tNightLight: Fading");
}
else if (start && pause) {
if (count == 1) {
fadeOrNot = false;
Serial.println("\t\tNightLight: Resume fading");
count++;
}
}
else if (start && !pause) {
if (count == 1) {
count++;
fadeOrNot = true;
Serial.println("\t\tNightLight: Blinking");
}
}
if (count == 2) {
count = -1;
}
count++;
break;
case 'b': //Alarm settings
Serial.print("\t\tBuzzer: ");
if (buzzOrNot) {
buzzOrNot = false;
shortTime = false;
speakerPin = dummyPin;
Serial.println("Off");
}
else {
buzzOrNot = true;
Serial.println("On");
speakerPin = PiezoPin;
shortTime = true;
BeepTime = 75;
}
break;
}
}
else if (isDigit(str)) {
where += char(str); //Add numbers, not words, in a string that will be converted later with toFloat().
}
}
else { //This else statement will probably have more instances than the if statement, so it is perfect for code that needs to be updated every millisecond!
if (fadeOrNot == false) {
doTheFade(currentMillis); //fading the led(... 'cause it looks cool)
}
if (!pause && lightOrNot) {
if (currentMillis - psMillis >= 500) { //to indicate the timer is paused
digitalWrite(led, !digitalRead(led)); //a fast way to turn the led off and on.
psMillis = currentMillis;
}
}
if (shortTime) {
if (currentMillis - shortTimeMillis >= BeepTime) {
if (buzzerCount > 5) {
shortTime = false;
buzzerCount = 0;
}
else {
digitalWrite(speakerPin, !digitalRead(speakerPin));
shortTimeMillis = currentMillis;
buzzerCount++;
}
}
}
if ((viewer)) {
if (currentMillis - psMillis >= 3E3) { //After inputing the timer, the user might not know what to do next. So a hint will pop up like an annoying ad after 3 seconds.
Serial.println("\t\tHint: Type 'v' to view your timer.");
psMillis = currentMillis;
viewer = false;
}
}
if (start && pause) { //This, if() statement, activates when 'y' is typed into serial.
//Is it time yet?
if (interval >= 18.5E3) {
if (currentMillis - psMillis >= (newInterval - 18.5E3)) { //This will turn off the machine when statement is true. 18.5E3 seconds is the time for the music to play.
MelodyWithoutDelay(currentMillis);//ends timer with THE FINAL COUNTDOWN song
}
}
else {
if (currentMillis - psMillis >= (newInterval)) {
thisNote = lengthOfSong;
MelodyWithoutDelay(currentMillis);//Ends Timer with beeps
}
}
}
}
}
void doTheFade(unsigned long thisMillis) { // Special thanks to the Bald Engineer for the FadeWithoutDelay Code
// See baldengineer.com/fading-led-analogwrite-millis-example.html for more information
// Created by James Lewis
// is it time to update yet?
// if not, nothing happens
if (lightOrNot) {
if (thisMillis - previousFadeMillis >= fadeInterval) {
// yup, it's time!
if (q) {
fadeValue += fadeIncrement;
if (fadeValue >= maxPWM) {
// At max, limit and change direction
fadeValue = maxPWM;
q = false;
}
} else {
//if we aren't going up, we're going down
fadeValue -= fadeIncrement;
if (fadeValue <= minPWM) {
// At min, limit and change direction
fadeValue = minPWM;
q = true;
}
}
// Only need to update when it changes
analogWrite(led, fadeValue);
// reset millis for the next iteration (fade timer only)
previousFadeMillis = thisMillis;
}
}
}
void readTime(bool a_a, bool b_b, bool c_c, int hh, int mm, int ss) {
split = "";
if (a_a) {
split += (hh + String(" hours"));
}
if (a_a && b_b) {
split += ((", and ") + String(mm) + String(" minutes"));
}
else if (b_b) {
split += (mm + String(" minutes"));
}
if ((b_b && c_c) || (c_c && a_a)) {
split += ((", and ") + String(ss) + String(" seconds"));
}
else if (c_c) {
split += (ss + String(" seconds."));
}
if (!(a_a) && !(b_b) && !(c_c)) {
split = ("apparently nothing.");
}
}
void readDuring(double Get) {
int ha = hour(Get / (1E3));
int ma = minute(Get / (1E3));
int sa = second(Get / (1E3));
bool aTrue = false; bool bTrue = false; bool cTrue = false;
if (ha != 0)
aTrue = true;
if (ma != 0)
bTrue = true;
if (sa != 0)
cTrue = true;
readTime(aTrue, bTrue, cTrue, ha, ma, sa);
Serial.println(split);
}
//
void MelodyWithoutDelay(double cMillis) {
int noteDuration = 1700 / noteDurations[thisNote];
int pauseBetweenNotes = noteDuration * 1.2;
if ((cMillis - songMillis <= pauseBetweenNotes / 4)) {
digitalWrite(led, LOW);
}
else if ((cMillis - songMillis <= pauseBetweenNotes)) {
tone(speakerPin, melody[thisNote], noteDuration);
if (lightOrNot)
digitalWrite(led, HIGH);
}
else {
fadeOrNot = true;
if (thisNote >= lengthOfSong) {
thisNote = -2;
psMillis = cMillis;
digitalWrite(relay, HIGH);
Serial.println("Time's up!");
fadeInterval = 45;
fadeOrNot = false;
start = false;
shortTime = true;
BeepTime = 1E3;
}
thisNote++;
noTone(speakerPin);
songMillis = cMillis;
}
}
Comments
Please log in or sign up to comment.