Introduction: Disco Alarm

We are going to make an disco alarm using an rgb led, a potentiometer

and a real time clock.

In the serial monitor, it will print the real time and when you set your alarm.

Step 1: Getting Your Libraries

For this tutorial, you will need 2 libraries, the Time library and the Real Time Clock library.
Add them into your sketch like this:
#include <Time.h>

#include <TimeLib.h>
#include <DS3232RTC.h>

You will also need an RTC DS3232RTC.

Make sure you install these first via Sketch> Include Library > Manage Libraries.

Geef boven de setup aan dat je rtc van DS3232RTC is.

DS3232RTC rtc;

Step 2: Setting Up Your RGB Led on Your Breadboard

First of all, make sure you have a red wire connecting from the 5v to your plus on your breadboard,

do the same with a black wire from your ground (GND) to your minus on your breadboard.

Now, we will set up your RGB led.

It is best do use a red wire for the Red, and so on. Use a black one for ground.

The longest steel side is the ground. The sole one next to it is red.

Between your red and green wire and your LED, you want a 180 Ohm resistor.

Between the blue one, a 220 Ohm resistor.

Set up your code like this. Where you choose to wire your RGB led to is set up here. I chose 9, 10 and eleven.
Make sure an ~sign is before the number so you can work with analogWrite.

Above setup:

const int Red=9;
const int Green=10;
const int Blue=11;

boolean ledOn = false;
int ledColor = 0;

In your setup:

pinMode(Red, OUTPUT);
pinMode(Green, OUTPUT);
pinMode(Blue, OUTPUT);

In your loop, make a switch case with a couple of colors based on the integer ledColor.

switch(ledColor) {
//Red

case 0:
digitalWrite(Red, HIGH);
digitalWrite(Green, LOW);
digitalWrite(Blue, LOW);
break;
case 1:
//Green
digitalWrite(Red, LOW);
digitalWrite(Green, HIGH);
digitalWrite(Blue, LOW);
break;
case 2:
//Blue
digitalWrite(Red, LOW);
digitalWrite(Green, LOW);
digitalWrite(Blue, HIGH);
break;
case 3:
// Yellow
digitalWrite(Green, HIGH);
analogWrite(Red, 255);
digitalWrite(Blue, LOW);
break;
case 4:
// Purple
digitalWrite(Green, LOW);
analogWrite(Red, 180);
analogWrite(Blue, 70);
break;
case 5:
// Cyan
digitalWrite(Red, LOW);
analogWrite(Green, 180);
analogWrite(Blue, 75); } }

Step 3: Setting Your Potentiometer

Set up the potentiometer.
It is important that the wire in the middle goes to an Analog input on your Arduino. I chose A0.

In your code, above setup, write this:

const int pot = 0;
int val = 0;

In your setup, set your serial baud rate to 38400, to make sure it's quick enough.

Serial.begin(38400);
pinMode(pot, INPUT);

You don't need to see it's values yet.

Step 4: Setting Up Your 2 Buttons.

We will need 2 buttons: one that sets your time definitely, and one that makes sure you can switch between setting the hours or minutes.

One thing that is important for your button to work is the use of a pull down resistor. As you can see on the picture, the 10K Ohm resistor is before your wire to the Arduino and it goes to the ground.

Set up both of them like the picture.

Now we're going to input a lot of booleans here.

const int timeSwitchButton = 3; (The switch to hours or minutes button is set on 3)
const int setTimeButton = 5; (the set alarm is on 5)
boolean lastSwitchButton = LOW;
boolean currentSwitchButton = LOW;
boolean lastSetButton = LOW;
boolean currentSetButton = LOW;

These booleans are for debouncing your buttons, but we will need some more.

int setHour = 0; (The value you will give to the hour, between 0 and 23)
int setMin = 0; (The minute value, between 0 and 59)
boolean hourOrMin = true; (Are you working on setting the hour or minute? True is hour, false is minute)
boolean timeIsSet = false; (Is your alarm time set)
boolean alarmOn = false; (and is your alarm going off?)

Now, we need to make sure both buttons properly debounce. We use these 2 functions:

boolean debounceSwitch(boolean last) {
boolean current = digitalRead(timeSwitchButton);
if (last != current) {
delay(5);
current = digitalRead(timeSwitchButton);
}
return current; }

boolean debounceSet(boolean last) {
boolean current = digitalRead(setTimeButton);
if (last != current) {
delay(5);
current = digitalRead(setTimeButton);
} return current; }

In your loop, make sure that if your Switch button is used:

currentSwitchButton = debounceSwitch(lastSwitchButton);
if (lastSwitchButton == LOW && currentSwitchButton == HIGH) {
hourOrMin = !hourOrMin;
}
lastSwitchButton = currentSwitchButton;

You are differing between hours and minutes.

But for the Set button:

currentSetButton = debounceSet(lastSetButton);
if (lastSetButton == LOW && currentSetButton == HIGH) {
timeIsSet = true; }
lastSetButton = currentSetButton;

Let's get into coding the rest.

Step 5: Void Loop

Now, to get everything working, we just have to do a couple of things in our loop.

We'll begin with some static bools.

static bool once = true;
static bool oncetoo = true;
static bool setOnce = true;

Sometimes, we want the code in our evergoing loop only to be used once. Therefore, these static booleans will only bet set once (henceforth static).

To print our text in the Serial monitor neatly, we'll use this:

static char regel[100] (Regel is Dutch for line. 100 defines the amount of characters that is going into our sentence line).

Now, we'll want to get the actual time from our RTC.

time_t t1 = rtc.get();

Our time_t instance called t1 calls the function get from the rtc structure to get the actual time and store it into t1.

We want to print this time now once:

if (once) {
sprintf(regel,"Time and day: %02d:%02d:%02d, %02d",hour(t1),minute(t1),second(t1),day(t1)); Serial.println(regel);
once = false; }

So, if our static bool once is true, we'll use sprintf, to give to our neatly defined sentence line 'regel' the string:

'Time and day " plus what follows after. the %02d simply says: I want you to look after the comma. It is an integer, or digit, therefore the d. also, it has to have 2 characters (02d), but if it hasn't, I want you to add a 0.

This is so the time prints 12:04 for example, instead of 12:4.

After this sentence, you define what every %02d is. Namely the hour, minute, second and day.

When that is all set, you print via Serial.println(regel) and you set the once to false so it doesn't run again.

This code goes above your currentSwitchbutton debounce.

Directly under this code, we'll set the alarm time by using our potentiometer.

if (timeIsSet == false){
val = analogRead(pot);
if (hourOrMin == true) {
setHour = val / 44,4782;
} else {
setMin = val / 17,33898;
}
Serial.print(setHour);
Serial.print(":");
Serial.println(setMin); }

If you haven't set your alarm yet, you want to keep reading the value from your potentiometer. If you're working on hour (so HourorMin is true) you want the integer setHour to be 1023 (the values of your potentiometer) to be between 0 and 23. therefore, by dividing 1023 by 44,4782, we'll have a nice range.

If you're working on hours you'll have to divide it by something else to get it to go between 0 and 59.

You also want to see your values while you're setting them, so make sure it prints.

After this code, put the code where you debounce your setButton.

THEN.

if your time is set, we want another bit of code to run once: the one where you print the alarm you set.

if (timeIsSet == true && setOnce == true) {
sprintf(regel,"Alarm time: %02d:%02d",setHour,setMin);
Serial.println(regel);
delay(3000);
rtc.setAlarm(ALM1_MATCH_HOURS,setMin,setHour,day(t1));
setOnce = false; }

We'll then print the time and use the RTC function to set our alarm.

You then want to exit this code by setting setOnce to false.

if (rtc.alarm(ALARM_1)) {
Serial.println("ALARM!!");
alarmOn = true; }

If the alarm goes off, this function will not last very long. But we want our led to keep shining.

So, use the function of RTC to ask if alarm 1 is going off, and if so, set your boolean alarmOn to true.

Now, we want to make sure our LED goes on and keep disco'ing.

Step 6: Making Your Led Go Wild But Not Too Much

Changing colors
without Delay:

In order to make the lamp change colors at set intervals we originally used the delay function.

This however causes the whole machine to stop and thus prevent the clock from counting forward and that will desync the alarm clock.

More about Blink without delay:

https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay

So in order to fix this problem you have to use the millis() parameter which Arduino uses to register the amount of milliseconds the program is running.

More about millis:

https://www.arduino.cc/en/reference/millis

So, how do we keep track of the Millis and use them to change the ledColor variable. Well, to do that we use the modulo function within Arduino.

Modulo can be used to get the remainder after a division.

I.E. 5 % 2 = 1; 15 % 4 = 3; 100 % 10 = 0;

So, if we make sure that when we devide the amount of millis that have passed by for example 250 we make sure that you can get it to trigger every time millis pass a multiplayer of 250.

I.E. 250, 500, 750, 1000, 1250, 1500…, etc.

Our implementation in the code:

if (millis() % 250 == 0) {

ledColor = random(0, 6);

}

More about modulo:

https://www.arduino.cc/en/Reference/modulo

After doing all this the code should only assign a new number to the ledColor variable every ~250 millis. You can increase this number to enlarge the amount of time needed for the Arduino. Or you could also decrease the time in order to make the Arduino change colors faster.

Step 7: The Last Code

When your alarm is on, you want to make sure that your Led goes off. Now the delay function is fixed,

where do we implement this code?

Right beneath where we left off, put this:

if (alarmOn == true) {
if (millis() % 250 == 0) {
ledColor = random(0, 6); }

And here, still in your if statement, put the whole switch case of led's. Make sure to close it off with another curly brace.

To end this tutorial, we want to make sure that your Serial monitor keeps showing the time once you set your alarm. Do this by this simple code and then close off your loop.

if (timeIsSet == true) {
// print elke keer de tijd af die verkregen wordt uit time_t t1 = rtc.get()
sprintf(regel,"time: %02d:%02d:%02d\n",hour(t1),minute(t1),second(t1));
Serial.print(regel); }

Done!