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


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 

FastLED NeoMatrix 

Arduino GFX 

RTC 


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
  }
}

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.