A while back I started thinking about a way to display stationary bike race results that didn’t require either a projector or a really complicated mechanical assembly. The thing that came to mind was a race tree like at the drag races. I asked Amanda who has been running bike events in portland if she could get me 12 lights. I wound up with pile of Bike Planet lights which required about a weeks worth of surgery.
From one of our led driving discussions a few years back I wound up with a tube of 74hc595s which I wired up like so.
While there are examples using bit banging to drive shift registers with the arduino they ignore the built in hardware capabilities of the AVR family.
Using the built in spi greatly simplifies your code and is remarkably fast. In the code sample below there are 5 bytes which represent the 40 pins from 5 shift registers. The main loop just toggles the bits and sends them out the door.
byte outbytes[5]={0x55,0x55,0x55,0x55,0x55}; //uncomment this for a standard arduino //#define PIN_SCK 13 // SPI clock (also Arduino LED!) //#define PIN_MISO 12 // SPI data input //#define PIN_MOSI 11 // SPI data output#define PIN_HEARTBEAT 7 // added LED #define PIN_SCK 9 // SPI clock (also Arduino LED!) #define PIN_MISO 11 // SPI data input #define PIN_MOSI 10 // SPI data output #define PIN_SS 8 // SPI slave select void EnableSPI(void) { SPCR |= 1 << SPE; } void DisableSPI(void) { SPCR &= ~(1 << SPE); } byte SendRecSPI(byte Dbyte) { // send one byte, get another in exchange SPDR = Dbyte; while (! (SPSR & (1 << SPIF))) { continue; } return SPDR; // SPIF will be cleared } void RunShiftRegister(void) { byte bitBucket; int i; digitalWrite(PIN_SS,HIGH); EnableSPI(); // turn on the SPI hardware for (i=0; i<5; i++) { bitBucket = SendRecSPI(outbytes[i]); } DisableSPI(); // return to manual control digitalWrite(PIN_SS,LOW); } void setup() { pinMode(PIN_SCK,OUTPUT); digitalWrite(PIN_SCK,LOW); pinMode(PIN_SS,OUTPUT); digitalWrite(PIN_SS,HIGH); pinMode(PIN_MOSI,OUTPUT); digitalWrite(PIN_MOSI,LOW); pinMode(PIN_MISO,INPUT); digitalWrite(PIN_MISO,HIGH); SPCR = B01110001; // Auto SPI: no int, enable, LSB first, master, + edge, leading, f/16 SPSR = B00000000; // not double data rate } void loop(){ int i; RunShiftRegister(); for (i=0; i<5; i++){ outbytes[i]= ~outbytes[i]; } delay(1000); };
Simple fast and easy.