I have made a nifty "drag racing christmas tree" using 2 SIPO shift registers (connected back to back) to allow independant comtrol of all 14 LEDs ( 2xred 2xGreen 6xyellow and 4x blue - the staging and prestaging lights).
And for the LED control this only uses three pins (latch clock and data) on the Arduino.
I'll try make a video of this in action this weekend but here is the code
const unsigned int l_a1=11;
const unsigned int l_a2=8;
const unsigned int l_a3=9;
const unsigned int l_g=10;
const unsigned int l_r=14;
const unsigned int r_a1=3;
const unsigned int r_a2=0;
const unsigned int r_a3=1;
const unsigned int r_g=2;
const unsigned int r_r=6;
const unsigned int sw_l=3;
const unsigned int sw_r=2;
const unsigned int lst=12;
const unsigned int lps=13;
const unsigned int rst=4;
const unsigned int rps=5;
unsigned int reg_val=0;
unsigned int rndnum;
const int sr_latch = 11;
const int sr_clock = 10;
const int sr_data = 12;
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 display(15);
int count=0;
int finish=0;
int loffset=0;
int roffset=0;
int lelap;
int relap;
int lfinish;
int rfinish;
int swl;
int swr;
int repeat;
int lron=0;
int rron=0;
unsigned long msec, msecstart, ltime=0, rtime=0, lgtime, rgtime;
String stageing = String("no");
int l_staged=0;
int r_staged=0;
String tree_type = String("full");
// String tree_type = String("pro");
// int pro4=0;
int pro4=1;
void setup(){
pinMode(sr_data, OUTPUT);
pinMode(sr_clock, OUTPUT);
pinMode(sr_latch, OUTPUT);
Serial.begin(9600);
pinMode(sw_l, INPUT_PULLUP);
pinMode(sw_r, INPUT_PULLUP);
pinMode(A0, OUTPUT); // ????? needed???
writereg(65535);
delay(3000);
// get stageeing value
writereg(0);
bitWrite(reg_val, lps, HIGH);
writereg(reg_val);
msec=millis();
msecstart=msec;
dispint(count, 0x3d);
dispint(count, 0x3c);
while (msec - msecstart < 3000 ) { // 3 sec to stop stageing
if ( digitalRead(sw_l) == 0 ) {
count++;
// Serial.println(count);
dispint(count, 0x3c);
dispint(count, 0x3d);
delay(300);
msecstart=msec; }
else { msec=millis();}
}
if (count == 0) { stageing="yes"; }
else { stageing="no";
bitWrite(reg_val, rps, HIGH); }
writereg(reg_val);
delay(2000); // could put random delay here
count=0;
reg_val=0;
writereg(reg_val);
// get tree type
msec=millis();
msecstart=msec;
dispint(count, 0x3d);
dispint(count, 0x3c);
while (msec - msecstart < 3000 ) { // 3 sec to switch select tree
rndnum=random(65535);
writereg(rndnum);
if ( digitalRead(sw_l) == 0 ) {
count++;
// Serial.println(count);
dispint(count, 0x3c);
dispint(count, 0x3d);
delay(300);
msecstart=msec; }
else { msec=millis();}
}
if (count == 0) { tree_type = "full"; }
if (count == 1) { tree_type = "pro";
pro4=1; }
if (count == 2) { tree_type = "pro";
pro4=0; }
if (count > 2 ) {tree_type = "greens"; }
writereg(0);
delay(2000); // could put random delay here
}
void(* resetFunc) (void) = 0;//declare reset function at address 0
void loop() {
lgtime=30000;
rgtime=30000;
lfinish=0;
rfinish=0;
dispint(0, 0x3c);
dispint(0, 0x3d);
if (stageing == "yes" ) {
bitWrite(reg_val, lps, HIGH);
bitWrite(reg_val, rps, HIGH);
writereg(reg_val);
}
//stage players here
if (stageing == "yes" ) {
l_staged=0;
r_staged=0;
while ( (l_staged == 0 ) || ( r_staged == 0 ) ) {
swl=digitalRead(sw_l);
if (swl==0) {
l_staged=1;
bitWrite(reg_val, lst, HIGH);
writereg(reg_val);
}
swr=digitalRead(sw_r);
if (swr==0) {
r_staged=1;
bitWrite(reg_val, rst, HIGH);
writereg(reg_val);
}
}
}
rndnum=random(3000);
if (tree_type == "greens") {
lgtime=millis() + rndnum + 1000 ;
rgtime=lgtime;
}
if (tree_type == "full") {
lgtime=millis() + rndnum + 1500 + loffset;
rgtime=millis() + rndnum + 1500 + roffset;
}
if (tree_type == "pro") {
lgtime=millis() + rndnum + 400 + loffset;
rgtime=millis() + rndnum + 400 + roffset;
if (pro4==0) {
lgtime+=100;
rgtime+=100;
}
}
delay(rndnum);
msecstart=millis();
// Serial.print("starting ");
// Serial.println(count);
Serial.println();
Serial.println();
Serial.println();
while ( (lfinish == 0 ) || ( rfinish == 0 ) ) {
ltime = millis() - msecstart - loffset;
rtime = millis() - msecstart - roffset;
swl=digitalRead(sw_l);
if (swl == 0 && lfinish == 0 ) {
lfinish = 1;
lelap = millis() - lgtime;
// dispint(lelap, 0x3d);
bitWrite(reg_val, l_a1, LOW);
bitWrite(reg_val, l_a2, LOW);
bitWrite(reg_val, l_a3, LOW);
if (lelap < 0) {
bitWrite(reg_val, l_r, HIGH);
bitWrite(reg_val, lst, LOW);
bitWrite(reg_val, lps, LOW);
writereg(reg_val);
lron=1;
// Serial.print("Left redlighted ");
// Serial.println(lelap);
}
else {
// Serial.print("Left time is ");
// Serial.println(lelap);
bitWrite(reg_val, l_g, HIGH);
bitWrite(reg_val, lst, LOW);
bitWrite(reg_val, lps, LOW);
}
}
swr=digitalRead(sw_r);
if (swr == 0 && rfinish == 0 ) {
rfinish = 1;
relap = millis() - rgtime;
// dispint(relap, 0x3c);
bitWrite(reg_val, r_a1, LOW);
bitWrite(reg_val, r_a2, LOW);
bitWrite(reg_val, r_a3, LOW);
if (relap < 0) {
bitWrite(reg_val, r_r, HIGH);
bitWrite(reg_val, rst, LOW);
bitWrite(reg_val, rps, LOW);
writereg(reg_val);
rron=1;
// Serial.print("Right redlighted ");
// Serial.println(relap);
}
else {
// Serial.print("Right time is ");
// Serial.println(relap);
bitWrite(reg_val, r_g, HIGH);
bitWrite(reg_val, rst, LOW);
bitWrite(reg_val, rps, LOW);
}
}
writereg(reg_val);
if (tree_type == "full") {
if ( lfinish == 0 ) {
if ( ltime > 1500 ) {
if (lron==0 ){ bitWrite(reg_val, l_g, HIGH); }
if (lron==0 ){ bitWrite(reg_val, l_a3, LOW);}
}
else {
if (ltime > 1000) {
if (lron==0 && lfinish ==0) { bitWrite(reg_val, l_a3, HIGH);}
if (lron==0){ bitWrite(reg_val, l_a2, LOW); }}
else {
if (ltime > 500) {
if (lron==0) { bitWrite(reg_val, l_a2, HIGH);}
if (lron==0) { bitWrite(reg_val, l_a1, LOW); }}
else {
if (ltime >= 0 ) {
if (lron==0) { bitWrite(reg_val, l_a1, HIGH);}
}
}
}
}
writereg(reg_val);
}
if (rfinish == 0 ) {
if ( rtime > 1500 ) {
if (rron==0 ){ bitWrite(reg_val, r_g, HIGH);}
if (rron==0){ bitWrite(reg_val, r_a3, LOW);}
}
else {
if (rtime > 1000) {
if (rron==0 && rfinish ==0){ bitWrite(reg_val, r_a3, HIGH);}
if (rron==0){ bitWrite(reg_val, r_a2, LOW); }}
else {
if (rtime > 500) {
if (rron==0){ bitWrite(reg_val, r_a2, HIGH);}
if (rron==0){ bitWrite(reg_val, r_a1, LOW); }}
else {
if (rtime >= 0 ) {
if (rron==0){ bitWrite(reg_val, r_a1, HIGH);}
}
}
}
}
writereg(reg_val);
}
}
if (tree_type == "greens") {
if ( millis() >= lgtime) {
if (lron==0) { bitWrite(reg_val, l_g, HIGH);}
if (rron==0){ bitWrite(reg_val, r_g, HIGH);}
writereg(reg_val);
}
}
if (tree_type == "pro") {
if ( lfinish == 0 ) {
if (ltime + (pro4 * 100) > 500 ) {
if (lron==0){ bitWrite(reg_val, l_a1, LOW); }
if (lron==0){ bitWrite(reg_val, l_a2, LOW);}
if (lron==0){bitWrite(reg_val, l_a3, LOW);}
if (lron==0 && lfinish ==0){ bitWrite(reg_val, l_g, HIGH); } }
else {
if (ltime > 0 ) {
if (lron==0){ bitWrite(reg_val, l_a1, HIGH); }
if (lron==0){ bitWrite(reg_val, l_a2, HIGH);}
if (lron==0){ bitWrite(reg_val, l_a3, HIGH);} }
}
writereg(reg_val);
}
if (rfinish == 0 ) {
if (rtime + (pro4 * 100) > 500 ) {
if (rron==0){ bitWrite(reg_val, r_a1, LOW); }
if (rron==0){ bitWrite(reg_val, r_a2, LOW);}
if (rron==0){ bitWrite(reg_val, r_a3, LOW);}
if (rron==0 && rfinish ==0){ bitWrite(reg_val, r_g, HIGH); }}
else {
if (rtime > 0 ) {
if (rron==0){ bitWrite(reg_val, r_a1, HIGH); }
if (rron==0){ bitWrite(reg_val, r_a2, HIGH);}
if (rron==0){ bitWrite(reg_val, r_a3, HIGH); }}
}
writereg(reg_val);
}
}
}
bitWrite(reg_val, lps, LOW);
bitWrite(reg_val, rps, LOW);
writereg(reg_val);
dispint(lelap, 0x3d);
dispint(relap, 0x3c);
// light up winning lane
if (lelap > 0 ) {
if (relap < 0 || lelap <= relap) {
bitWrite(reg_val, lps, HIGH);
}
}
if (relap > 0 ) {
if (lelap < 0 || relap <= lelap) {
bitWrite(reg_val, rps, HIGH);
}
}
writereg(reg_val);
if (lelap < 0 && relap < 0) {
for (int i = 0; i < 10; i++) {
bitWrite(reg_val, lps, HIGH);
bitWrite(reg_val, rps, HIGH);
writereg(reg_val);
delay(300);
bitWrite(reg_val, lps, LOW);
bitWrite(reg_val, rps, LOW);
writereg(reg_val);
delay(300);
}
}
delay(2000);
//Serial.println("1111111 ");
repeat=0;
while (repeat==0) {
swl=digitalRead(sw_l);
if (swl==0) { repeat=1;}
swr=digitalRead(sw_r);
if (swr==0) { resetFunc(); }//call reset
}
//Serial.println("222222 ");
repeat=0 ;
lfinish=0;
rfinish=0;
swl=1;
swr=1;
lron=0;
rron=0;
reg_val=0;
writereg(reg_val);
delay(2000);
}
void dispint(int dint, char i2caddr) {
display.setTextSize(3);
display.setTextColor(WHITE);
display.begin(SSD1306_SWITCHCAPVCC, i2caddr);
display.clearDisplay();
display.drawRoundRect(0, 0, 127, 32, 8, WHITE);
display.setCursor(20, 4);
display.print(dint);
display.display();
}
void writereg(unsigned int val) {
digitalWrite(sr_latch, LOW);
for (int i = 0; i < 16; i++) {
boolean j = val%2;
val = val/2;
// Serial.print(i);
// Serial.print(" ");
// Serial.println(j);
digitalWrite(sr_clock, LOW);
digitalWrite(sr_data, j);
digitalWrite(sr_clock, HIGH);
}
digitalWrite(sr_latch, LOW);
digitalWrite(sr_latch, HIGH);
}