I originally made my Word Clocks using PICAXE micro-controllers, some LED drivers, and plain, white, LEDs.
A while ago, I decided to upgrade them to colour LEDs; specifically the WS2812B type of LEDs which are serially addressable, and can be controlled directly from a micro-controller. I also changed the micro-controller to an Arduino. I originally built two of these clocks, and in the updated versions one is using an Arduino UNO, and the other an Arduino Nano – the same micro-controller, but in different formats.
The clock continuously, randomly, fades the colour of each word from one colour to another.

Word Clock in time mode

Word Clock in test mode
/* Project: 3x3x3 Mono LED Cube (r3).
* File: MVLightning.cpp
* Description:
* Movie -- mv_Lightning
* Dark clouds, and occasional flashes of lightning.
*
* Copyright (C) 2014 Marc Symonds
* All rights reserved.
*
* This software may be used and redistribtued, with or without
* modification, as long as it is understood that this software
* is provided as-is without any explicit or implied warranties
* of merchantablity or fitness of purpose.
*/
#include "Arduino.h"
#include "Movies.h"
#include "DisplayFrame.h"
void mv_Lightning()
{
unsigned long ts, m;
unsigned long tl, tf;
byte i, p, y, z, mode, cnt;
Light cloud[9];
Point l1, l2;
y = 0;
z = 0;
for (i = 0 ; i < 9 ; i++)
{
p = POS(2, y, z);
displayFrame[p] = random(1, 3);
cloud[i].up = (displayFrame[p] < 2);
cloud[i].t = millis() + random(250, 750);
if (++y > 2)
{
y = 0;
++z;
}
}
ts = millis() + (DEF_MOVIE_TIME * 3);
tl = millis() + random(2000, 5000);
mode = 0;
y = 0;
z = 0;
i = 0;
m = millis();
while (m < ts)
{
if (m > cloud[i].t)
{
p = POS(2, y, z);
displayFrame[p] += (cloud[i].up ? 1 : -1);
if (displayFrame[p] < 2)
cloud[i].up = true;
else if (displayFrame[p] > 1)
cloud[i].up = false;
cloud[i].t = m + random(250, 750);
}
if (mode > 0)
{
if (m > tf)
{
if (mode == 1)
{
displayFrame[l1.Pos()] = 7;
displayFrame[l2.Pos()] = 7;
mode = 2;
}
else
{
displayFrame[l1.Pos()] = 0;
displayFrame[l2.Pos()] = 0;
if (--cnt < 1)
{
mode = 0;
tl = millis() + random(2000, 5000);
}
else
mode = 1;
}
tf = m + 30;
}
}
else if (m > tl)
{
l1.x = 1;
l1.y = random(0, 3);
l1.z = random(0, 3);
l2.x = 0;
do
{
l2.y = l1.y + random(0, 3) - 1;
} while (l2.y > 2);
do
{
l2.z = l1.z + random(0, 3) - 1;
} while (l2.z > 2);
mode = 1;
cnt = random(5, 8);
tf = m;
}
if (++y > 2)
{
y = 0;
if (++z > 2)
z = 0;
}
if (++i > 8)
i = 0;
m = millis();
}
df_fadeOut();
}
/* Project: 3x3x3 Mono LED Cube (r3).
* File: MVBoxy.cpp
* Description:
* Movie -- mv_Boxy
* Randonly display a growing and shrinking box.
* (as well as you can do in 3x3x3).
*
* Copyright (C) 2014 Marc Symonds
* All rights reserved.
*
* This software may be used and redistributed, with or without
* modification, as long as it is understood that this software
* is provided as-is without any explicit or implied warranties
* of merchantablity or fitness of purpose.
*/
#include "Arduino.h"
#include "Movies.h"
#include "DisplayFrame.h"
void mv_Boxy()
{
unsigned long ts;
unsigned long tbox = 1; // 0xB000000000000000000000000001;
unsigned long sbox = 13851; //0XB000000000000011011000011011;
unsigned long lbox = 129948655; //0XB111101111101101101111101111;
int spd;
POSTransFPtr trans;
trans = GetPOSTrans(random(0, 8));
ts = millis() + (DEF_MOVIE_TIME / 2);
while (millis() < ts)
{
spd = random(50, 90);
df_DisplayMonoFrame(trans, tbox);
delay(spd);
df_DisplayMonoFrame(trans, sbox);
delay(spd);
df_DisplayMonoFrame(trans, lbox);
delay(spd * 4);
trans = GetPOSTrans(random(0, 8));
df_DisplayMonoFrame(trans, sbox);
delay(spd);
df_DisplayMonoFrame(trans, tbox);
delay(spd);
df_clear();
delay(spd);
}
}
/* Project: 3x3x3 Mono LED Cube (r3).
* File: Movies.h
* Description: Definitions for movie functions.
*
* Copyright (C) 2014 Marc Symonds
* All rights reserved.
*
* This software may be used and redistributed, with or without
* modification, as long as it is understood that this software
* is provided as-is without any explicit or implied warranties
* of merchantablity or fitness of purpose.
*/
#ifndef Movies_h
#define Movies_h
#define DEF_MOVIE_TIME 10000
void mv_TwinkleAll();
void mv_Glitter();
void mv_Pulse();
void mv_Jitter();
void mv_EdgeChase();
void mv_EdgeChase2();
void mv_Rain();
void mv_AllOn();
void mv_Flashy();
void mv_EdgeTumble();
void mv_Counter();
void mv_Snake();
void mv_Boxy();
void mv_Lightning();
#endif
/* Project: 3x3x3 Mono LED Cube (r3).
* File: MVTwinkleAll.cpp
* Description:
* Movie -- mv_TwinkleAll
* All LEDs are randomly faded in an out.
* Similar to mv_Flashy, but with a subtle difference.
*
* Copyright (C) 2014 Marc Symonds
* All rights reserved.
*
* This software may be used and redistributed, with or without
* modification, as long as it is understood that this software
* is provided as-is without any explicit or implied warranties
* of merchantablity or fitness of purpose.
*/
#include "Arduino.h"
#include "Movies.h"
#include "DisplayFrame.h"
void mv_TwinkleAll()
{
unsigned long ts;
byte x;
byte m[27];
ts = millis() + DEF_MOVIE_TIME;
for (x = 0 ; x < 27 ; x++)
m[x] = (displayFrame[x] == MAXBRIGHTNESSLEVEL);
while (millis() < ts)
{
for (x = 0 ; x < 27 ; x++)
{
if (m[x])
{
if (random(10) > 6)
{
if (--displayFrame[x] == 0)
m[x] = false;
}
}
else
{
if (random(10) > 4)
{
if (++displayFrame[x] >= MAXBRIGHTNESSLEVEL)
m[x] = true;
}
}
}
delay(50);
}
df_fadeOut();
}
/* Project: 3x3x3 Mono LED Cube (r3).
* File: MVSnake.cpp
* Description:
* Movie -- mv_Snake
*
* Copyright (C) 2014 Marc Symonds
* All rights reserved.
*
* This software may be used and redistributed, with or without
* modification, as long as it is understood that this software
* is provided as-is without any explicit or implied warranties
* of merchantablity or fitness of purpose.
*/
#include "Arduino.h"
#include "Movies.h"
#include "DisplayFrame.h"
#define SNAKELEN 4
void mv_Snake()
{
unsigned long ts, t;
int ss, sl, sp, i, j, k;
byte nx, ny, nz;
ts = millis() + DEF_MOVIE_TIME;
points[0] = Point((byte)random(0, 3), (byte)random(0, 3), (byte)random(0, 3));
sl = 1;
ss = 0;
displayFrame[points[0].Pos()] = MAXBRIGHTNESSLEVEL;
sp = random(100, 500);
while (millis() < ts)
{
t = millis() + sp;
do
{
nx = points[ss].x;
ny = points[ss].y;
nz = points[ss].z;
switch(random(0, 3))
{
case 0:
nx = nx + random(0, 3) - 1;
break;
case 1:
ny = ny + random(0, 3) - 1;
break;
default:
nz = nz + random(0, 3) - 1;
break;
}
} while (millis() < t && (nx > 2 || ny > 2 || nz > 2 || displayFrame[POS(nx, ny, nz)] != 0));
while (millis() < t)
;
if (nx > 2 || ny > 2 || nz > 2 || displayFrame[POS(nx, ny, nz)] != 0)
{
for (i = 0 ; i < 27 ; i++)
displayFrame[i] = MAXBRIGHTNESSLEVEL;
delay(50);
df_clear();
points[0] = Point((byte)random(0, 3), (byte)random(0, 3), (byte)random(0, 3));
sl = 1;
ss = 0;
displayFrame[points[ss].Pos()] = MAXBRIGHTNESSLEVEL;
}
else
{
i = ss;
for (j = 0 ; j < sl ; j++)
{
k = points[i].Pos();
if (displayFrame[k] > 0)
--displayFrame[k];
if (displayFrame[k] > 0)
--displayFrame[k];
if (i == 0)
i = SNAKELEN - 1;
else
--i;
}
if (++ss >= SNAKELEN)
ss = 0;
points[ss].Set(nx, ny, nz);
displayFrame[points[ss].Pos()] = MAXBRIGHTNESSLEVEL;
if (sl < SNAKELEN)
++sl;
}
}
df_clear();
}
/* Project: 3x3x3 Mono LED Cube (r3).
* File: MVRain.cpp
* Description:
* Movie -- mv_Rain
* A number of LEDs are lit on the top plane, and they
* then "fall down" the cude.
*
* Copyright (C) 2014 Marc Symonds
* All rights reserved.
*
* This software may be used and redistributed, with or without
* modification, as long as it is understood that this software
* is provided as-is without any explicit or implied warranties
* of merchantablity or fitness of purpose.
*/
#include "Arduino.h"
#include "Movies.h"
#include "DisplayFrame.h"
class Drop
{
public:
byte pos;
byte count;
unsigned long time;
byte spd;
void reset()
{
pos = POS(2, random(0, 3), random(0, 3));
count = 2;
spd = random(30, 100);
time = millis() + spd;
}
void displayDrop(boolean state)
{
displayFrame[pos] = state ? MAXBRIGHTNESSLEVEL : 0;
}
void drop()
{
if (millis() > time)
{
if (spd == 0)
{
reset();
displayDrop(true);
}
else
{
displayDrop(false);
if (count == 0)
{
spd = 0;
time = millis() + random(50, 100);
}
else
{
--count;
pos -= 3;
displayDrop(true);
time = millis() + spd;
}
}
}
}
};
void mv_Rain()
{
unsigned long ts;
byte y;
Drop drops[2];
ts = millis() + (DEF_MOVIE_TIME * 2);
for (y = 0 ; y < 2 ; y++)
{
drops[y].reset();
drops[y].displayDrop(true);
}
while (millis() < ts)
{
for (y = 0 ; y < 2 ; y++)
{
drops[y].drop();
}
}
df_clear();
}
/* Project: 3x3x3 Mono LED Cube (r3).
* File: MVPulse.cpp
* Description:
* Movie -- mv_Pulse
* Fade in and out all LEDs together.
*
* Copyright (C) 2014 Marc Symonds
* All rights reserved.
*
* This software may be used and redistributed, with or without
* modification, as long as it is understood that this software
* is provided as-is without any explicit or implied warranties
* of merchantablity or fitness of purpose.
*/
#include "Arduino.h"
#include "Movies.h"
#include "DisplayFrame.h"
void mv_Pulse()
{
unsigned long ts;
byte x, y;
ts = millis() + (DEF_MOVIE_TIME / 2);
while (millis() < ts)
{
for (y = 0 ; y <= MAXBRIGHTNESSLEVEL ; y++)
{
for (x = 0 ; x < 27 ; x++)
displayFrame[x] = y;
delay(50);
}
delay(100);
for (y = MAXBRIGHTNESSLEVEL - 1 ; y > 0 ; y--)
{
for (x = 0 ; x < 27 ; x++)
displayFrame[x] = y;
delay(50);
}
df_clear();
delay(500);
}
}
/* Project: 3x3x3 Mono LED Cube (r3).
* File: MVJitter.cpp
* Description:
* Movie -- mv_Jitter
* A single LED moves quickly and randomly around the
* cube.
*
* Copyright (C) 2014 Marc Symonds
* All rights reserved.
*
* This software may be used and redistributed, with or without
* modification, as long as it is understood that this software
* is provided as-is without any explicit or implied warranties
* of merchantablity or fitness of purpose.
*/
#include "Arduino.h"
#include "Movies.h"
#include "DisplayFrame.h"
void mv_Jitter()
{
unsigned long ts, t;
byte x, y, z, nx, ny, nz;
ts = millis() + DEF_MOVIE_TIME;
x = random(0, 3);
y = random(0, 3);
z = random(0, 3);
nx = x;
ny = y;
nz = z;
displayFrame[POS(x, y, z)] = MAXBRIGHTNESSLEVEL;
while (millis() < ts)
{
t = millis() + 80;
do
{
// Work out the next LED to light, adjacent to the current LED.
switch(random(0, 3))
{
case 0:
switch(random(0, 3))
{
case 0:
if (nx > 0)
--nx;
break;
case 2:
if (nx < 2)
++nx;
break;
}
break;
case 1:
switch(random(0, 3))
{
case 0:
if (ny > 0)
--ny;
break;
case 2:
if (ny < 2)
++ny;
break;
}
break;
default:
switch(random(0, 3))
{
case 0:
if (nz > 0)
--nz;
break;
case 2:
if (nz < 2)
++nz;
break;
}
break;
}
} while ( x == nx && y == ny && z == nz);
while (millis() < t)
;
displayFrame[POS(x,y,z)] = 0;
displayFrame[POS(nx,ny,nz)] = MAXBRIGHTNESSLEVEL;
x = nx;
y = ny;
z = nz;
}
displayFrame[POS(nx,ny,nz)] = 0;
}
/* Project: 3x3x3 Mono LED Cube (r3).
* File: MVGlitter.cpp
* Description:
* Movie -- mv_Glitter
* Lights random LEDs for short periods of time creating
* a "glitter" effect.
*
* Copyright (C) 2014 Marc Symonds
* All rights reserved.
*
* This software may be used and redistribtued, with or without
* modification, as long as it is understood that this software
* is provided as-is without any explicit or implied warranties
* of merchantablity or fitness of purpose.
*/
#include "Arduino.h"
#include "Movies.h"
#include "DisplayFrame.h"
void mv_Glitter()
{
unsigned long ts;
byte x;
byte m[3];
byte n[3] = {0, 0, 0};
ts = millis() + DEF_MOVIE_TIME;
while (millis() < ts)
{
for (x = 0 ; x < 3 ; x++)
{
if (n[x] == 0)
{
displayFrame[m[x]] = 0;
m[x] = random(0, 27);
n[x] = random(30, 50);
displayFrame[m[x]] = MAXBRIGHTNESSLEVEL;
}
else
--n[x];
}
delay(1);
}
for (x = 0 ; x < 3 ; x++)
displayFrame[m[x]] = 0;
}
Recent Comments