
If you want to keep track of time without using delay(), you will need the millis() function, which allows the program to run without stopping. In this project, we will create a digital hourglass using an Arduino, six LEDs, and a tilt sensor. Every 10 minutes, a new LED will light up, and after an hour, all six LEDs will be on. The main feature of this project is the use of millis() to count the time instead of the usual delay(), which allows the microcontroller to do other tasks while the countdown is running. We will also use a tilt sensor, which acts as a regular switch and allows you to reset the timer when the device changes position.
IN THIS PROJECT, YOU’LL BUILD A DIGITAL HOURGLASS THAT TURNS ON AN LED EVERY TEN MINUTES. KNOW HOW LONG YOU’RE WORKING ON YOUR PROJECTS BY USING THE ARDUINO’S BUILT-IN TIMER.
Up to now, when you’ve wanted something to happen at a specific time interval with the Arduino, you’ve used delay(). This is handy, but a little confining. When the Arduino calls delay(), it freezes its current state for the duration of the delay. That means there can be no other input or output while it’s waiting. Delays are also not very helpful for keeping track of time. If you wanted to do something every 10 seconds, having a 10 second delay would be fairly cumbersome.
The millis() function helps to solve these problems. It keeps track of the time your Arduino has been running in milliseconds. You used it previously in Project 6 when you created a timer for calibration.
So far you’ve been declaring variables as int. An int (integer) is a 16-bit number, it holds values between -32,768 and 32,767. Those may be some large numbers, but if the Arduino is counting 1000 times a second with millis(), you’d run out of space in less than a minute. The long datatype holds a 32-bit number (between -2,147,483,648 and 2,147,483,647). Since you can’t run time backwards to get negative numbers, the variable to store millis() time is called an unsigned long.
When a datatype is called unsigned, it is only positive. This allows you to count even higher. An unsigned long can count up to 4,294,967,295. That’s enough space for milis() to store time for almost 50 days. By comparing the current millis() to a specific value, you can see if a certain amount of time has passed. When you turn your hourglass over, a tilt switch will change its state, and that will set off another cycle of LEDs turning on.
The tilt switch works just like a regular switch in that it is an on/off sensor. You’ll use it here as a digital input. What makes tilt switches unique is that they detect orientation. Typically they have a small cavity inside the housing that has a metal Time: 30 MINUTES Level: Builds on projects: 1, 2, 3, 4 Discover: long data type, creating a timer DIGITAL HOURGLASS 87 ball. When tilted in the proper way, the ball rolls to one side of the cavity and connects the two leads that are in your breadboard, closing the switch.
With six LEDs, your hourglass will run for an hour, just as its name implies.а
Connect power and ground to your breadboard.
Connect the anode (longer leg) of six LEDs to digital pins 2-7. Connect the LEDs to ground through 220-ohm resistors.
Connect one lead of the tilt switch to 5V. Connect the other to a 10-kilohm resistor to ground. Connect the junction where they meet to digital pin 8
You don’t need to have your Arduino tethered to the computer for this to work. Try building a stand with some cardboard or styrofoam and power the Arduino with a battery to make a portable version. You can create a cover with some numeric indicators alongside the lights.
Tilt switches are great, inexpensive tools for determining the orientation of something. Accelerometers are another type of tilt sensor, but they give out much more information. They are also significantly more expensive. If you’re just looking to see if something is up or down, a tilt sensor works great.
Declare a named constant. You’re going to need a number of global variables in your program to get this all working. To start, create a constant named switchPin. This will be the name of the pin your tilt switch is on.
Create a variable to hold the time. Create a variable of type unsigned long, This will hold the time an LED was last changed.
Name variables for the inputs and outputs. Create a variable for the switch state, and another to hold the previous switch state. You’ll use these two to compare the switch’s position from one loop to the next.
Declare a variable describing the interval between events. The last variable you’re creating is going to be the interval between each LED turning on. This will be be a long datatype. In 10 minutes (the time between each LED turning on) 600,000 milliseconds pass. If you want the delay between lights to be longer or shorter, this is the number you change.
Set the direction of your digital pins. In your setup(), you need to declare the LED pins 2-7 as outputs. A for() loop declares all six as OUTPUT with just 3 lines of code. You also need to declare switchPin as an INPUT.
Check the time since the program started running. When the loop() starts, you’re going to get the amount of time the Arduino has been running with millis() and store it in a local variable named currentTime.
Evaluate the amount of time that has passed since the previous loop(). Using an if() statement, you’ll check to see if enough time has passed to turn on an LED. Subtract the currentTime from the previousTime and check to see if it is greater than the interval variable. If 600,000 milliseconds have passed (10 minutes), you’ll set the variable previousTime to the value of currentTime
const int switchPin = 8; unsigned long previousTime = 0; int switchState = 0; int prevSwitchState = 0; int led = 2; long interval = 600000; void setup() { for(int x = 2;x<8;x++){ pinMode(x, OUTPUT); } pinMode(switchPin, INPUT); } void loop(){ unsigned long currentTime = millis(); if(currentTime - previousTime > interval) { previousTime = currentTime;
Turn on an LED, prepare for the next one. previousTime indicates the last time an LED was turned on. Once you’ve set previousTime, turn on the LED, and increment the led variable. The next time you pass the time interval, the next LED will light up.
Check to see if all lights are on. Add one more if statement in the program to check if the LED on pin 7 is turned on. Don’t do anything with this yet. You’ll decide what happens at the end of the hour later.
Read the value of the switch. Now that you’ve checked the time, you’ll want to see if the switch has changed its state. Read the switch value into the switchState variable.
Reset the variables to their defaults if necessary. With an if() statement, check to see if the switch is in a different position than it was previously. The != evaluation checks to see if switchState does not equal prevSwitchState. If they are different, turn the LEDs off, return the led variable to the first pin, and reset the timer for the LEDs by setting previousTime to currentTime.
Set the current state to the previous state. At the end of the loop(), save the switch state in prevSwitchState , so you can compare it to the value you get for switchState in the next loop().
Once you’ve programmed the board, check the time on a clock. After 10 minutes have passed, the first LED should have turned on. Every 10 minutes after that, a new light will turn on. At the end of an hour, all six light should be on. When you flip the circuit over, and cause the tilt switch to change its state, the lights will turn off and the timer will start again.
digitalWrite(led, HIGH); led++; if(led == 7){ } } switchState = digitalRead(switchPin); if(switchState != prevSwitchState){ for(int x = 2;x<8;x++){ digitalWrite(x, LOW); } led = 2; previousTime = currentTime; } prevSwitchState = switchState; }
When the clock reaches one hour and all six lights are on, they just stay on. Can you think of a way to get your attention when the hour is up? Sound or flashing the lights are both good indicators. The led variable can be checked to see if all the lights are on, that’s a good place to check for grabbing someone’s attention. Unlike an hourglass filled with sand, the lights go either up or down depending on the orientation of the switch. Can you figure out how you can use the switchState variable to indicate what direction the lights should go?
To measure the amount of time between events, use the millis() function. Because the numbers it generates are larger than what you can store in an int, you should use the datatype unsigned long for storing its values.