Things used in this project

Hardware components:
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:
09507 01
Soldering iron (generic)

Custom parts and enclosures

Front and rear panels
Front Panel Express Files
LEDclock.zip

Schematics

Schematic PDF
PDF file
Fritzing Breadboard View
Fritzing Breadboard View.fzz
Altium Designer Files
PCB files for Altium Designer
LEDclockDesignFiles.zip

Code

LED Clock DriverC/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.zipC/C++
No preview (download only).

Credits

Me2015
David McLaughlin

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.

Replications

Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Similar projects you might like

Blynk GPS Tracker
Intermediate
  • 41
  • 2

Full instructions

Simple GPS tracker using a Particle Photon (or Electron) and an EM406 GPS module with location visible on Blynk app map.

Pool Buddy
Intermediate
  • 1,619
  • 11

Work in progress

Monitor and log water quality (pH & ORP) and temperature from everywhere.

IoT Thermometer Using Python
Intermediate
  • 986
  • 8

Full instructions

How to develop a simple but powerful IoT thermometer using a Zerynth-powered single-board MCU and the Zerynth App.

Particle Photon Flip Dot Clock
Intermediate
  • 2,162
  • 31

Full instructions

The flip dot display uses an electromechanical dot matrix that spin from black to yellow to display text, numbers and more!

Patriot iOS App
Intermediate
  • 547
  • 9

Use an old iPhone device to control and display the status of your Patriot IoT devices.

Patriot iOS App

Team Patriot

What To Wear LCD
Intermediate
  • 48
  • 1

Ever wondered what to wear due to unpredictable weather??? Wonder no longer!

Add projectSign up / Login