This is the code I made for my LED Ball. There's probably a couple of redundant parts - I started off with grandiose ideas and then had to hammer the routines to fit in the holes when the master plan didn't work so some bits aren't needed and I CBA to tidy the code up. There's nothing fancy in this - mostly standard routines for shift registers but i use the Output Enable to "rotate" the ball. This code does work with my Ball though and the Ball has been running continuously throughout the Christmas period.
Code: Select all
// Main Code for LED Ball v3.0
// all functional with PWM all planes tested
// added spiral, sine & Glow ball routines, 2way simplified fridgelight
// and this one WORKS, eh?
// by Graeme Park 2013. email - graemeSP@hotmail.com
// start of all setup structure............................
// define pins & vars etc
const int OEpin1 = 3; // Registers 1&5 Output Enable
const int OEpin2 = 5; // Registers 2&6 Output Enable
const int OEpin3 = 6; // Registers 3&7 Output Enable
const int OEpin4 = 9; // Registers 4&8 Output Enable
const int latchpin = 10; // pin for registers common latch
const int datapin = 11; // pin for registers common data
const int clockpin = 13; // pin for register common clock
const int resetpin = 7; // pin for registers common Master Reset
int UpperByte = 1; // initial setting of byte for upper registers
int LowerByte = 0; // initial setting of byte for lower registers
int del01 = 25; // set delay 1 to 25mS
int del02 = 500; // set delay 2 to 500mS
int del03 = 100; // set delay 3 to 100mS
byte var = 0; // counter for turnplane routine
byte OE1Var = 0; // set OE1 brightness high
byte OE2Var = 0; // ditto for OE2
byte OE3Var = 0; // ditto for OE3
byte OE4Var = 0; // ditto for OE4
byte turnstep = 0; // counter Spiral & Sines routines
// defs for fridgelight (case internal LEDs)
const int fridgelightPin1 = 14; // attach coloured LED & resistor
const int fridgelightPin2 = 15; // to these if yo
const int fridgelightPin3 = 16; // For case internals
int ledState = LOW;
// additional defs for NumeroDos
byte data2TOP;
byte data2BOTTOM;
byte dataArray2TOP[10];
byte dataArray2BOTTOM[10];
// additional defs for NumeroQuatro
byte dataTOP;
byte dataBOTTOM;
byte dataArrayTOP[15];
byte dataArrayBOTTOM[15];
// additional defs for SINES
byte sineTopArray[24];
byte sineBttmArray[24];
byte sineTop;
byte sineBtt;
void setup () {
pinMode(latchpin,OUTPUT);
pinMode(datapin,OUTPUT);
pinMode(clockpin,OUTPUT);
pinMode(resetpin,OUTPUT);
pinMode(OEpin1,OUTPUT);
pinMode(OEpin2,OUTPUT);
pinMode(OEpin3,OUTPUT);
pinMode(OEpin4,OUTPUT);
pinMode(fridgelightPin1, OUTPUT);
pinMode(fridgelightPin2, OUTPUT);
pinMode(fridgelightPin3, OUTPUT);
// reset the registers
digitalWrite(resetpin,LOW); // force MR low to reset both registers
delay(1); // hold it a while
digitalWrite(resetpin,HIGH); // now set MR high
Serial.begin(9600); // enable the Serial port for serial monitoring
// Array for upper register NumeroDos
dataArray2TOP[0] = 0xFF; //11111111
dataArray2TOP[1] = 0xFE; //11111110
dataArray2TOP[2] = 0xFC; //11111100
dataArray2TOP[3] = 0xF8; //11111000
dataArray2TOP[4] = 0xF0; //11110000
dataArray2TOP[5] = 0xE0; //11100000
dataArray2TOP[6] = 0xC0; //11000000
dataArray2TOP[7] = 0x80; //10000000
dataArray2TOP[8] = 0x00; //00000000
dataArray2TOP[9] = 0xE0; //11100000
//Array for lower register NumeroDos
dataArray2BOTTOM[0] = 0xFF; //11111111
dataArray2BOTTOM[1] = 0x7F; //01111111
dataArray2BOTTOM[2] = 0x3F; //00111111
dataArray2BOTTOM[3] = 0x1F; //00011111
dataArray2BOTTOM[4] = 0x0F; //00001111
dataArray2BOTTOM[5] = 0x07; //00000111
dataArray2BOTTOM[6] = 0x03; //00000011
dataArray2BOTTOM[7] = 0x01; //00000001
dataArray2BOTTOM[8] = 0x00; //00000000
dataArray2BOTTOM[9] = 0x07; //00000111
// Array for upper register NumeroQuatro
dataArrayTOP[0] = 0xF0; //10000000
dataArrayTOP[1] = 0x42; //01000010
dataArrayTOP[2] = 0x24; //00100100
dataArrayTOP[3] = 0x18; //00011000
dataArrayTOP[4] = 0x24; //00100100
dataArrayTOP[5] = 0x42; //01000010
dataArrayTOP[6] = 0x81; //10000001
dataArrayTOP[7] = 0x42; //01000010
dataArrayTOP[8] = 0x20; //00100000
dataArrayTOP[9] = 0x10; //00010000
dataArrayTOP[10] = 0x08; //00001000
dataArrayTOP[11] = 0x04; //00000100
dataArrayTOP[12] = 0x02; //00000010
dataArrayTOP[13] = 0x01; //00000001
dataArrayTOP[14] = 0x03; //00000011
dataArrayTOP[15] = 0x0F; //00001111
//Array for lower register NumeroQuatro
dataArrayBOTTOM[0] = 0x01; //00000001
dataArrayBOTTOM[1] = 0x00; //00000000
dataArrayBOTTOM[2] = 0x81; //10000001
dataArrayBOTTOM[3] = 0x42; //01000010
dataArrayBOTTOM[4] = 0x24; //00100100
dataArrayBOTTOM[5] = 0x18; //00011000
dataArrayBOTTOM[6] = 0x24; //00000011
dataArrayBOTTOM[7] = 0x42; //00000001
dataArrayBOTTOM[8] = 0x80; //10000000
dataArrayBOTTOM[9] = 0x40; //01000000
dataArrayBOTTOM[10] = 0x20; //00100000
dataArrayBOTTOM[11] = 0x10; //00010000
dataArrayBOTTOM[12] = 0x08; //00001000
dataArrayBOTTOM[13] = 0x04; //00000100
dataArrayBOTTOM[14] = 0xC0; //00000000
dataArrayBOTTOM[15] = 0xF8; //00000111
// array for sine top
sineTopArray[0] = 0x80; //10000000
sineTopArray[1] = 0x40; //01000000
sineTopArray[2] = 0x10; //00010000
sineTopArray[3] = 0x04; //00000100
sineTopArray[4] = 0x01; //00000001
sineTopArray[5] = 0x02; //00000010
sineTopArray[6] = 0x04; //00000100
sineTopArray[7] = 0x10; //00010000
sineTopArray[8] = 0x20; //00100000
sineTopArray[9] = 0x40; //01000000
sineTopArray[10] = 0x40; //01000000
sineTopArray[11] = 0x80; //10000000
sineTopArray[12] = 0x80; //10000000
sineTopArray[13] = 0x80; //10000000
sineTopArray[14] = 0x40; //01000000
sineTopArray[15] = 0x40; //01000000
sineTopArray[16] = 0x20; //00100000
sineTopArray[17] = 0x08; //00001000
sineTopArray[18] = 0x04; //00000100
sineTopArray[19] = 0x02; //00000010
sineTopArray[20] = 0x01; //00000001
sineTopArray[21] = 0x04; //00000100
sineTopArray[22] = 0x10; //00010000
sineTopArray[23] = 0x40; //01000000
// array for sine bottom
sineBttmArray[0] = 0x01; //00000001
sineBttmArray[1] = 0x02; //00000010
sineBttmArray[2] = 0x08; //00001000
sineBttmArray[3] = 0x20; //00100000
sineBttmArray[4] = 0x80; //10000000
sineBttmArray[5] = 0x40; //01000000
sineBttmArray[6] = 0x20; //00100000
sineBttmArray[7] = 0x08; //00001000
sineBttmArray[8] = 0x04; //00000100
sineBttmArray[9] = 0x02; //00000010
sineBttmArray[10] = 0x02; //00000010
sineBttmArray[11] = 0x01; //00000001
sineBttmArray[12] = 0x01; //00000001
sineBttmArray[13] = 0x01; //00000001
sineBttmArray[14] = 0x02; //00000010
sineBttmArray[15] = 0x02; //00000010
sineBttmArray[16] = 0x04; //00000100
sineBttmArray[17] = 0x10; //00010000
sineBttmArray[18] = 0x20; //00100000
sineBttmArray[19] = 0x40; //01000000
sineBttmArray[20] = 0x80; //10000000
sineBttmArray[21] = 0x20; //00100000
sineBttmArray[22] = 0x08; //00001000
sineBttmArray[23] = 0x02; //00000010
} // end of all setup structure ---------------------------------
// define the sketch operating routines
void AllPlanesOn() // enable output all planes
{
analogWrite(OEpin1,0);
analogWrite(OEpin2,0);
analogWrite(OEpin3,0);
analogWrite(OEpin4,0);
}
void AllPlanesOff() // disable output all planes
{
analogWrite(OEpin1,255);
analogWrite(OEpin2,255);
analogWrite(OEpin3,255);
analogWrite(OEpin4,255);
}
void fridgelight() // turn internal LEDS on and off
{ if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
// set the LED with the ledState of the variable:
digitalWrite(fridgelightPin1, ledState);
digitalWrite(fridgelightPin2, !ledState);
digitalWrite(fridgelightPin3, ledState);
}
void TurnPlanesCW() // rotate all planes CW
{
OneHigh();
delay(del03);
TwoHigh();
delay(del03);
ThreeHigh();
delay(del03);
FourHigh();
delay(del03);
AllPlanesOn();
}
void TurnPlanesAC() // rotate all planes ACW (yawn)
{
OneHigh();
delay(del03);
FourHigh();
delay(del03);
ThreeHigh();
delay(del03);
TwoHigh();
delay(del03);
AllPlanesOn();
}
void OneHigh() // subs for turnplanes
{
analogWrite(OEpin1,0);
analogWrite(OEpin2,255);
analogWrite(OEpin3,255);
analogWrite(OEpin4,255);
}
void TwoHigh()
{
analogWrite(OEpin1,255);
analogWrite(OEpin2,255);
analogWrite(OEpin3,255);
analogWrite(OEpin4,0);
}
void ThreeHigh()
{
analogWrite(OEpin1,255);
analogWrite(OEpin2,255);
analogWrite(OEpin3,0);
analogWrite(OEpin4,255);
}
void FourHigh()
{
analogWrite(OEpin1,255);
analogWrite(OEpin2,0);
analogWrite(OEpin3,255);
analogWrite(OEpin4,255);
}
void LightPlanes() { // all LEDS on
digitalWrite(latchpin, 0);
shiftOut(datapin, clockpin,MSBFIRST, 255);
shiftOut(datapin, clockpin,MSBFIRST, 255);
digitalWrite(latchpin, 1);
}
void DarkPlanes() { // all LEDS off
digitalWrite(latchpin, 0);
shiftOut(datapin, clockpin, MSBFIRST,0);
shiftOut(datapin, clockpin, MSBFIRST,0);
digitalWrite(latchpin, 1);
}
void DoNowt(int d) // all planes OFF - pause for d mS
{
AllPlanesOff();
delay(d);
AllPlanesOn();
}
// the LED display routines are here
void NumeroUno() // raindrops- each 16 LEDS in turn
{
AllPlanesOn();
for (int i=0; i < 15; i++)
{
digitalWrite(latchpin, 0);
shiftOut(datapin, clockpin,MSBFIRST, UpperByte);
shiftOut(datapin, clockpin,MSBFIRST, LowerByte);
digitalWrite(latchpin, 1);
delay(del01);
UpperByte <<= 1; // shift upper byte left
LowerByte <<= 1; // shift lower byte left
if (UpperByte > 128) { // pass the parcel to the lower register
UpperByte=0;
LowerByte=1;
}
if (LowerByte > 128) { // if at the end, the parcel hops to the top
UpperByte=1;
LowerByte=0;
}
}
}
void NumeroDos() // First array count
{
for (int j = 0; j < 10; j++) {
data2TOP= dataArray2TOP[j];
data2BOTTOM = dataArray2BOTTOM[j];
digitalWrite(latchpin, 0);
shiftOut(datapin, clockpin, MSBFIRST, data2BOTTOM);
shiftOut(datapin, clockpin, MSBFIRST, data2TOP);
digitalWrite(latchpin, 1);
delay(del01);
}
}
void NumeroTres() //Count up in binary routine, top & bottom
{
for (int j = 0; j < 128; j++) {
digitalWrite(latchpin, LOW);
shiftOut(datapin, clockpin, LSBFIRST, j);
digitalWrite(latchpin, HIGH);
delay(del01);
}
}
void NumeroCuatro() // Second array count
{
for (int j = 0; j < 15; j++) {
dataTOP = dataArrayTOP[j];
dataBOTTOM = dataArrayBOTTOM[j];
digitalWrite(latchpin, 0);
shiftOut(datapin, clockpin, MSBFIRST, dataBOTTOM);
shiftOut(datapin, clockpin, MSBFIRST, dataTOP);
digitalWrite(latchpin, 1);
delay(del03);
}
}
void NumeroCinco() // Rotate the "ball" CW
{
LightPlanes();
TurnPlanesCW();
TurnPlanesCW();
DarkPlanes();
}
void NumeroSeis() // Rotate the "ball" ACW
{
LightPlanes();
TurnPlanesAC();
TurnPlanesAC();
DarkPlanes();
}
void blinkAll_2Bytes(int n, int d) { // blinks n times, with d delay
digitalWrite(latchpin, 0);
shiftOut(datapin, clockpin,MSBFIRST, 0);
shiftOut(datapin, clockpin,MSBFIRST, 0);
digitalWrite(latchpin, 1);
delay(200);
for (int x = 0; x < n; x++) {
digitalWrite(latchpin, 0);
shiftOut(datapin, clockpin, MSBFIRST,255);
shiftOut(datapin, clockpin, MSBFIRST,255);
digitalWrite(latchpin, 1);
delay(d);
digitalWrite(latchpin, 0);
shiftOut(datapin, clockpin,MSBFIRST, 0);
shiftOut(datapin, clockpin,MSBFIRST, 0);
digitalWrite(latchpin, 1);
delay(d);
}
}
void Sines() // Third array - sine waves from top to bottom
{
AllPlanesOff();
DarkPlanes();
for (int i =0; i < 24; i++) // run this 24 times per cycle
{
// turn the planes one step each time
if (turnstep==0) {
OneHigh();
}
if (turnstep==1) {
FourHigh();
}
if (turnstep==2) {
ThreeHigh();
}
if (turnstep==3) {
TwoHigh();
}
turnstep++ ;
if (turnstep > 3) {
turnstep=0;
}
// load up from the array
sineTop = sineTopArray[i];
sineBtt = sineBttmArray[i];
// light the right LEDs
digitalWrite(latchpin, 0);
shiftOut(datapin, clockpin,MSBFIRST, sineTop);
shiftOut(datapin, clockpin,LSBFIRST, sineBtt);
digitalWrite(latchpin, 1);
delay(del03);
}
} // end of Sines
void Spirals() // drop one LED from top to bottom while rotating ball.
{
turnstep=0; // reset the turning counter
for (int i =0; i < 15; i++) // run this 16 times per cycle
{ // turn the planes one step each time
if (turnstep==0) {
OneHigh();
}
if (turnstep==1) {
FourHigh();
}
if (turnstep==2) {
ThreeHigh();
}
if (turnstep==3) {
TwoHigh();
}
turnstep++ ;
if (turnstep > 3) {
turnstep=0;
}
// light the right LED
digitalWrite(latchpin, 0);
shiftOut(datapin, clockpin,MSBFIRST, UpperByte);
shiftOut(datapin, clockpin,MSBFIRST, LowerByte);
digitalWrite(latchpin, 1);
delay(del03);
UpperByte <<= 1; // shift upper byte left
LowerByte <<= 1; // shift lower byte left
if (UpperByte > 128) { // pass the "parcel" to the lower register
UpperByte=0;
LowerByte=1;
}
if (LowerByte > 128) { // if at the end, parcel hops to the top
UpperByte=1;
LowerByte=0;
}
}
} // end of Spirals
void GlowBall()
{
AllPlanesOn();
LightPlanes();
delay(100);
for (int i=0; i < 255; i++)
{
analogWrite(OEpin1,i);
analogWrite(OEpin2,i);
analogWrite(OEpin3,i);
analogWrite(OEpin4,i);
delay(5);
}
for (int w=0;w < 5; w++)
{
for (int i=0; i < 255; i++) // cycle plane brightness using PWM
{
analogWrite(OEpin1,i);
analogWrite(OEpin2,255-i);
analogWrite(OEpin3,i);
analogWrite(OEpin4,255-i);
delay(2);
}
for (int i=0; i < 255; i++)
{
analogWrite(OEpin1,255-i);
analogWrite(OEpin2,i);
analogWrite(OEpin3,255-i);
analogWrite(OEpin4,i);
delay(2);
}
}
AllPlanesOn();
}
// end of GlowBall
void ByeBye() // a couple of blinks, brightball, fade to out, drops up and off.
{
LightPlanes();
delay(200);
for (int i=0; i < 255; i=i+10)
{
analogWrite(OEpin1,i);
analogWrite(OEpin2,i);
analogWrite(OEpin3,i);
analogWrite(OEpin4,i);
delay(25);
}
DarkPlanes();
AllPlanesOn();
for (int i=0; i < 15; i++)
{
digitalWrite(latchpin, 0);
shiftOut(datapin, clockpin,LSBFIRST, UpperByte); // from the bottom to the top
shiftOut(datapin, clockpin,LSBFIRST, LowerByte);
digitalWrite(latchpin, 1);
delay(del01);
UpperByte <<= 1; // shift upper byte left
LowerByte <<= 1; // shift lower byte left
if (UpperByte > 128) { // pass the "parcel" to the upper register
UpperByte=0;
LowerByte=1;
}
if (LowerByte > 128) { // if at the end, reset for next cycle UpperByte=1;
UpperByte=1;
LowerByte=0;
}
}
} // end of display routines
void loop()
{
fridgelight();
Serial.println("blink");
blinkAll_2Bytes(4,100);
fridgelight();
Serial.println("nowt");
DoNowt(1000);
fridgelight();
Serial.println("uno");
for (int count=0;count < 10;count++){
NumeroUno();
}
fridgelight();
Serial.println("dos");
for (int count=0;count < 5;count++){
NumeroDos();
fridgelight();
}
Serial.println("spirals");
for (int count=0;count < 5;count++){
Spirals();
fridgelight();
}
Serial.println("sines");
for (int count=0;count < 5;count++){
Sines();
fridgelight();
}
Serial.println("glowball");
for (int count=0;count < 2 ;count++){
GlowBall();
fridgelight();
}
Serial.println("tres");
for (int count=0;count < 2;count++){
NumeroTres();
fridgelight();
}
Serial.println("cuatro");
for (int count=0;count < 5;count++){
NumeroCuatro();
fridgelight();
}
Serial.println("cinco");
for (int count=0;count < 4;count++){
NumeroCinco();
fridgelight();
}
Serial.println("seis");
for (int count=0;count < 4;count++){
NumeroSeis();
fridgelight();
}
Serial.println("blink");
blinkAll_2Bytes(4,50);
fridgelight();
Serial.println("bye");
ByeBye();
fridgelight();
Serial.println("nowt");
DoNowt(2000);
}