David McLaughlin
Published © CC BY-NC

LED Reflection Clock

Using 60 LED's facing a suitable wall, the time is projected in colour.

IntermediateWork in progress5 days4,327
LED Reflection Clock

Things used in this project

Hardware components

Spark Core
Particle Spark Core
×1
Anodised Aluminium Front Panel
×1
Perspex Panel & LED clamp
×1
NEOpixel 60 LED ring
×1

Software apps and online services

Particle Development System

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Custom parts and enclosures

Front and rear panels

Front Panel Express Files

Schematics

Schematic PDF

PDF file

Fritzing Breadboard View

Altium Designer Files

PCB files for Altium Designer

Code

LED Clock Driver

C/C++
Use Particle Dev to build the code to run on your spark or photon core.
Requires Neopixel driver from the Particle libraries
#include "neopixel.h"

// IMPORTANT: Set pixel COUNT, PIN and TYPE
#define PIXEL_COUNT 60
#define PIXEL_PIN D4
#define PIXEL_TYPE WS2812B

// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
//               note: if not specified, D2 is selected for you.
// Parameter 3 = pixel type [ WS2812, WS2812B, WS2811, TM1803 ]
//               note: if not specified, WS2812B is selected for you.
//               note: RGB order is automatically applied to WS2811,
//                     WS2812/WS2812B/TM1803 is GRB order.
//
// 800 KHz bitstream 800 KHz bitstream (most NeoPixel products ...
//                         ... WS2812 (6-pin part)/WS2812B (4-pin part) )
//
// 400 KHz bitstream (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//                   (Radio Shack Tri-Color LED Strip - TM1803 driver
//                    NOTE: RS Tri-Color LED's are grouped in sets of 3)

Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);

// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel.  Avoid connecting
// on a live circuit...if you must, connect GND first.

uint16_t Hours = 4;
uint16_t Mins = 18;
uint16_t Seconds = 0;

#define ONE_DAY_MILLIS (24 * 60 * 60 * 1000)
unsigned long lastSync = millis();
uint16_t LastSeconds;

void setup()
{
    Serial.begin(57600);

    strip.begin();
    strip.clear();
    strip.show();

    strip.setBrightness(64);
    //
    // startup sequence
    //
    delay(500);
    colorWipe(strip.Color(255, 0, 0), 20); // Red
    colorWipe(strip.Color(0, 255, 0), 20); // Green
    colorWipe(strip.Color(0, 0, 255), 20); // Blue
    delay(500);

    LastSeconds = 61;   // Cause update on first run of the loop

    Time.zone(+7);
}

void loop()
{
    if (millis() - lastSync > ONE_DAY_MILLIS)
    {
        //
        // Request time synchronization from the Particle Cloud
        //
        Spark.syncTime();
        lastSync = millis();
    }
    //
    // Get the current time
    //
    Hours = Time.hourFormat12();
    Mins = Time.minute();
    Seconds = Time.second();

    if(Seconds != LastSeconds)
    {
        if(Seconds == 0 && Mins == 0)   // Do a sequence every hour
        {
            hourSequence();
        }
        strip.clear();

        setHours(Hours);
        setMins(Mins);
        setSeconds(Seconds);

        strip.show();

        LastSeconds = Seconds;
    }
    delay(100);
}

void setHours(int hours)
{
    int16_t out;

    out = 60 - (hours * 5);

    if(out == 60)
        out = 0;

    Serial.println(Hours);
    Serial.println(out);

    strip.setPixelColor(getOffset(out - 2), 20, 0, 0);
    strip.setPixelColor(getOffset(out - 1), 50, 0, 0);
    strip.setPixelColor(out, 255, 0, 0);
    strip.setPixelColor(getOffset(out + 1), 50, 0, 0);
    strip.setPixelColor(getOffset(out + 2), 20, 0, 0);
}

void setMins(int mins)
{
    int16_t out;

    out = 60 - mins;

    if(out == 60)
        out = 0;

    strip.setPixelColor(getOffset(out - 1), 0, 50, 0);
    strip.setPixelColor(out, 0, 255, 0);
    strip.setPixelColor(getOffset(out + 1), 0, 50, 0);
}

void setSeconds(int seconds)
{
    uint16_t out;

    out = 60 - seconds;

    if(out == 60)
        out = 0;

    strip.setPixelColor(out, 0, 0, 255);
}

uint16_t getOffset(int16_t in)
{
    int16_t out = in;

    if(in < 0)
    {
        out = 60 + in;
    }
    else if(in > 59)
    {
        out = in - 59;
    }
    return out;
}

//
// Fill the dots one after the other with a color
//
void colorWipe(uint32_t c, uint8_t wait) {
    for(int16_t i=(strip.numPixels() - 1); i >= 0; i--) {
        strip.setPixelColor(i, c);
        strip.show();
        delay(wait);
    }
}

void hourSequence()
{
    strip.clear();

    colorWipe(strip.Color(255, 0, 0), 20); // Red
    colorWipe(strip.Color(0, 255, 0), 20); // Green
    colorWipe(strip.Color(0, 0, 255), 20); // Blue
    delay(500);
}

LEDClockSource.zip

C/C++
No preview (download only).

Credits

David McLaughlin

David McLaughlin

1 project • 10 followers
Self taught electronics engineer with hardware and software design experience. Building & programming various home and commercial designs for the last 35 years.
Thanks to Peter Scargill.

Comments