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

Contact
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

Lightweight Sliding Door Automator
Intermediate
  • 1,535
  • 7

Work in progress

Automate the opening and closing of a lightweight sliding door (e.g. a screen door), including remote controls on your phone.

Christmas Gift Box
Intermediate
  • 3,633
  • 595

Full instructions

Christmas Gift Box plays music and sends an email when it is opened.

Carbon Fiber Vacuum Chamber
Intermediate
  • 2,905
  • 94

Full instructions

Our project is a carbon fiber vacuum chamber that is monitored by multiple particle photons and various sensors.

ConnectTheDots with Particle Azure IoT Hub Integration
Intermediate
  • 841
  • 8

Protip

This project will allow you to connect your Particle device into an Azure IoT Hub for viewing data in real-time through an ASP.NET web app!

What should I wear outside?
Intermediate
  • 5,044
  • 67

Full instructions

A whimsical weather clock powered by Particle and forecast.io

Garage Door Opener with Blynk
Intermediate
  • 366
  • 2

Open, close and monitor a garage door opener with a smart phone using a Particle Photon and the Blynk application.

Add projectSign up / Login