Introduction: RGB LED Clock
Our team decided to make a digital clock that also has RGB LED lights built into the display. This project combines the functionality of a clock with the cool multicolor function of RGB LEDs to create a fun product.
Supplies
Items / Modules
- Arduino Uno
- male to male jumper wires
- real time clock
- coin cell battery
- RGB LED Display
- 2 pushbuttons
- 2 * 10K resistors for active low pushbutton circuit
- 2 breadboards
- 12V 2A wallwart
- plastic box casing
- diffuse sheets
- Tape
Tools:
- Soldering iron
- Solder
- Wire strippers/cutters
- Scissors
Step 1: Ready the Outer Shell
Take out the plastic casing and diffuse sheets. Cut one sheet so that it fits to cover the bottom, front, and top of the rectangular prism shaped casing. Then cut a sheet to cover the left side, front and right side of the prism shaped casing. Leave the back open. Alternate between the two sheet shapes until you have six to eight layers of diffuse sheet in the front and three to four layers on top bottom and sides. Apply tape as needed.
The idea is that since more diffuse sheets will be in front your eyes will mostly see the numbers displayed by the RGB display. Meanwhile the sides shine more with whatever color you desire and the back projects a lot of light out and against the wall behind the clock. This creates a cool halo affect around the clock while at the same time not hurting your eyes when you are trying to read the time.
Step 2: Wire the Electronics
Real Time Clock Module: *Note the real time clock will need a 3V external battery to work.
RTC VCC --> Breadboard +5V
RTC GND --> Breadboard GND
RTC SDA --> Arduino A4
RTC SCL --> Arduino A5
LED Display Module:
LED Display VCC --> Breadboard +5V
LED Display GND --> Breadboard GND
LED Display DIN --> Arduino A0
Buttons:
Brightness Button --> Arduino D4
Color Button --> Arduino D6
Step 3: Test the Electronics
Upload the code for each part to your Arduino Uno
Make Sure you have the following libraries installed in your Arduino IDE:
FastLED
Real Time Clock Code:
The display should display the current time of day.
Display Brightness Code:
The display should brighten with each click of your designated display brightness button, until it resets to the initial brightness.
Display Color Code:
The display should change colors with each click of your designated display color button, until it resets to the first color.
All of the code is attached in the INO file but I also added the code as a code snippet below.
Note: The setSegment method was taken from the ESPixel Library.
#include <FastLED.h>
#include <time.h>
#include <Wire.h>
#include <I2C_RTC.h>
CRGBPalette16 currentPalette;
TBlendType currentBlending;
const long gmtOffset_sec = -18000; //Eastern Time
const int daylightOffset_sec = 3600;
static DS1307 RTC;
#define DATA_PIN A0 //Data Pin for 7 segments LED's
#define BRT_PIN 4 //Change Brightness Button Pin
#define COL_PIN 6 //Change Color Button Pin
#define LED_TYPE WS2812
#define COLOR_ORDER GRB
#define NUM_LEDS 86
int BRIGHTNESS = 10;
int COLOR = 0;
#define FRAMES_PER_SECOND 100
uint8_t pps = 3; // number of Pixels Per Segment
CHSV segBlack(0, 0, 0); //black
CRGBArray<NUM_LEDS> leds;
// Name segments and define pixel ranges.
// 1....2....3....4
// AAA
// F B
// GGG
// E C
// DDD
CRGBSet seg1A( leds(pps * 0, pps - 1+(pps * 0) ));
CRGBSet seg1B( leds(pps * 1, pps - 1+(pps * 1) ));
CRGBSet seg1C( leds(pps * 2, pps - 1+(pps * 2) ));
CRGBSet seg1D( leds(pps * 3, pps - 1+(pps * 3) ));
CRGBSet seg1E( leds(pps * 4, pps - 1+(pps * 4) ));
CRGBSet seg1F( leds(pps * 5, pps - 1+(pps * 5) ));
CRGBSet seg1G( leds(pps * 6, pps - 1+(pps * 6) ));
CRGBSet seg2A( leds(pps * 0+(1 * 7 * pps), pps - 1+(pps * 0)+(1 * 7 * pps) ));
CRGBSet seg2B( leds(pps * 1+(1 * 7 * pps), pps - 1+(pps * 1)+(1 * 7 * pps) ));
CRGBSet seg2C( leds(pps * 2+(1 * 7 * pps), pps - 1+(pps * 2)+(1 * 7 * pps) ));
CRGBSet seg2D( leds(pps * 3+(1 * 7 * pps), pps - 1+(pps * 3)+(1 * 7 * pps) ));
CRGBSet seg2E( leds(pps * 4+(1 * 7 * pps), pps - 1+(pps * 4)+(1 * 7 * pps) ));
CRGBSet seg2F( leds(pps * 5+(1 * 7 * pps), pps - 1+(pps * 5)+(1 * 7 * pps) ));
CRGBSet seg2G( leds(pps * 6+(1 * 7 * pps), pps - 1+(pps * 6)+(1 * 7 * pps) ));
CRGBSet seg3A( leds(pps * 0+(2 * 7 * pps), pps - 1+(pps * 0)+(2 * 7 * pps) ));
CRGBSet seg3B( leds(pps * 1+(2 * 7 * pps), pps - 1+(pps * 1)+(2 * 7 * pps) ));
CRGBSet seg3C( leds(pps * 2+(2 * 7 * pps), pps - 1+(pps * 2)+(2 * 7 * pps) ));
CRGBSet seg3D( leds(pps * 3+(2 * 7 * pps), pps - 1+(pps * 3)+(2 * 7 * pps) ));
CRGBSet seg3E( leds(pps * 4+(2 * 7 * pps), pps - 1+(pps * 4)+(2 * 7 * pps) ));
CRGBSet seg3F( leds(pps * 5+(2 * 7 * pps), pps - 1+(pps * 5)+(2 * 7 * pps) ));
CRGBSet seg3G( leds(pps * 6+(2 * 7 * pps), pps - 1+(pps * 6)+(2 * 7 * pps) ));
CRGBSet seg4A( leds(pps * 0+(3 * 7 * pps), pps - 1+(pps * 0)+(3 * 7 * pps) ));
CRGBSet seg4B( leds(pps * 1+(3 * 7 * pps), pps - 1+(pps * 1)+(3 * 7 * pps) ));
CRGBSet seg4C( leds(pps * 2+(3 * 7 * pps), pps - 1+(pps * 2)+(3 * 7 * pps) ));
CRGBSet seg4D( leds(pps * 3+(3 * 7 * pps), pps - 1+(pps * 3)+(3 * 7 * pps) ));
CRGBSet seg4E( leds(pps * 4+(3 * 7 * pps), pps - 1+(pps * 4)+(3 * 7 * pps) ));
CRGBSet seg4F( leds(pps * 5+(3 * 7 * pps), pps - 1+(pps * 5)+(3 * 7 * pps) ));
CRGBSet seg4G( leds(pps * 6+(3 * 7 * pps), pps - 1+(pps * 6)+(3 * 7 * pps) ));
CRGBSet col(leds(84, 85)); //colon
int count = 8888; // keeps track of what number to display
int a = 0;
bool colon;
//---------------------------------------------------------------
void setup() {
Serial.begin(9600);
pinMode(BRT_PIN, INPUT);
pinMode(COL_PIN, INPUT);
RTC.begin();
RTC.setDateTime(__DATE__, __TIME__);
RTC.startClock(); //Start the Clock
colon = true; //make sure the colon is visible
FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalSMD5050);
FastLED.setBrightness(BRIGHTNESS);
currentPalette = RainbowColors_p;
currentBlending = LINEARBLEND; //blend the pallet linearly
FastLED.clear(); // Initially clear all pixels
}
//---------------------------------------------------------------
void loop()
{
FastLED.delay(1000/FRAMES_PER_SECOND);
int actual = 0; //initiate actal variable
actual = (RTC.getHours() * 100) + (RTC.getMinutes()); //get the time from the RTC module
//Check if brightness button is pressed
if (digitalRead(BRT_PIN) == 0) {
if (BRIGHTNESS >= 35) {
BRIGHTNESS = 0; //if brightness is at maximum, reset it back to zero
}
else {
BRIGHTNESS += 5; //Increase brightness by 5 each time button is pressed
}
FastLED.setBrightness(BRIGHTNESS); //update the led's brightness
delay(300); //delay 0.3 seconds
}
//Check if color button is pressed
if (digitalRead(COL_PIN) == 0) {
if (COLOR > 4) {
COLOR = 0; //if color is greater than 4, set it back to the first color option
}
else {
COLOR++; // increment through all of the color options
}
switch (COLOR) { //Fast LED has some built in color pallets that we will be using
case 0: currentPalette = RainbowColors_p; break; //set the led color pallet to rainbow color pallet
case 1: currentPalette = CloudColors_p; break; //set the led color pallet to cloud color pallet
case 2: currentPalette = PartyColors_p; break; //set the led color pallet to party color pallet
case 3: currentPalette = ForestColors_p; break; //set the led color pallet to forest color pallet
case 4: currentPalette = OceanColors_p; break; //set the led color pallet to ocean color pallet
}
//Pallet is set durring the setSegments method so no need to set it here
delay(300); // delay 0.3 seconds
}
setSegments(actual, 1); //display the time on the clock
}
//This method is taken from the ESPixel clock library
//---------------------------------------------------------------
void setSegments(int count, uint8_t colorIndex) {
// Based on the current count set number segments on or off
uint8_t c1 = 0; // Variable to store 1s digit
uint8_t c10 = 0; // Variable to store 10s digit
uint8_t c100 = 0; // Variable to store 100s digit
uint8_t c1000 = 0; // Variable to store 100s digit
int c;
CHSV segCOLOR(0, 0, 0);
c1 = count % 10;
c10 = (count / 10) % 10;
c100 = (count / 100) % 10;
c1000 = (count / 1000) % 10;
uint8_t brightness = 255;
for ( int i = 0; i < NUM_LEDS; i++) {
leds[i] = ColorFromPalette( currentPalette, colorIndex, brightness, currentBlending);
colorIndex += 3;
}
//next block of if statements sets segments to black to form digits
segCOLOR = segBlack; //unused segment color
if (c1000 == 0) {
seg1G = segCOLOR;
}
if (c1000 == 1) {
seg1A = seg1D = seg1E = seg1F = seg1G = segCOLOR;
}
if (c1000 == 2) {
seg1C = seg1F = segCOLOR;
}
if (c1000 == 3) {
seg1E = seg1F = segCOLOR;
}
if (c1000 == 4) {
seg1A = seg1D = seg1E = segCOLOR;
}
if (c1000 == 5) {
seg1B = seg1E = segCOLOR;
}
if (c1000 == 6) {
seg1B = segCOLOR; //B
}
if (c1000 == 7) {
seg1D = seg1E = seg1F = seg1G = segCOLOR;
}
if (c1000 == 8) { }
if (c1000 == 9) {
seg1D = seg1E = segCOLOR;
}
if (c100 == 0) {
seg2G = segCOLOR;
}
if (c100 == 1) {
seg2A = seg2D = seg2E = seg2F = seg2G = segCOLOR;
}
if (c100 == 2) {
seg2C = seg2F = segCOLOR;
}
if (c100 == 3) {
seg2E = seg2F = segCOLOR;
}
if (c100 == 4) {
seg2A = seg2D = seg2E = segCOLOR;
}
if (c100 == 5) {
seg2B = seg2E = segCOLOR;
}
if (c100 == 6) {
seg2B = segCOLOR; //B
}
if (c100 == 7) {
seg2D = seg2E = seg2F = seg2G = segCOLOR;
}
if (c100 == 8) { }
if (c100 == 9) {
seg2D = seg2E = segCOLOR;
}
if (c10 == 0) {
seg3G = segCOLOR;
}
if (c10 == 1) {
seg3A = seg3D = seg3E = seg3F = seg3G = segCOLOR;
}
if (c10 == 2) {
seg3C = seg3F = segCOLOR;
}
if (c10 == 3) {
seg3E = seg3F = segCOLOR;
}
if (c10 == 4) {
seg3A = seg3D = seg3E = segCOLOR;
}
if (c10 == 5) {
seg3B = seg3E = segCOLOR;
}
if (c10 == 6) {
seg3B = segCOLOR; //B
}
if (c10 == 7) {
seg3D = seg3E = seg3F = seg3G = segCOLOR;
}
if (c10 == 8) { }
if (c10 == 9) {
seg3D = seg3E = segCOLOR;
}
if (c1 == 0) {
seg4G = segCOLOR;
}
if (c1 == 1) {
seg4A = seg4D = seg4E = seg4F = seg4G = segCOLOR;
}
if (c1 == 2) {
seg4C = seg4F = segCOLOR;
}
if (c1 == 3) {
seg4E = seg4F = segCOLOR;
}
if (c1 == 4) {
seg4A = seg4D = seg4E = segCOLOR;
}
if (c1 == 5) {
seg4B = seg4E = segCOLOR;
}
if (c1 == 6) {
seg4B = segCOLOR; //B
}
if (c1 == 7) {
seg4D = seg4E = seg4F = seg4G = segCOLOR;
}
if (c1 == 8) { }
if (c1 == 9) {
seg4D = seg4E = segCOLOR;
}
if (colon) {
// col = colON; //comment out to use palette color
} else {
col = CRGB::Black; //turns off colon to make it blink
}
}
Attachments
Step 4: Connect Everything Together
Place the display flush against the wall of the casing already covered in diffuse sheets with the LEDs facing outward. There should be about six to eight layers of sheets between the display lights and the wall of the casing. Tape the display down.
Once that is done add your Arduino Uno and breadboards with real time clock and buttons on them to the inside of the casing. Make sure to tape everything down so that it doesn’t shift around.
After that is done make a nest of your LED light strand and place it inside the casing.
Makes sure everything is wired into the right places.
Finally take your wallwart barrel connector and plug it into the Arduino.
The clock is complete! You can now plug the wallwart into a wall outlet and your clock should turn on. on.