by on
Dorkbot

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.

Leave a Reply

  • (will not be published)