Wednesday 7 September 2011

48 bit Shift Register

One of the problems with running a model railroad from a microcontroller is the need for lots of digital output pins. There are a variety of things that need turning on and off - signals, track sections/blocks, house lights, even driving stepper motors!

This simple circuit uses 6 x 74LS595 chips to make a total of 48 bits of digital output using only 3 digital outs on my Arduino.

Here's video of it in action. I've hooked up my el-cheapo opto-isolated relay card to the lower 4 bits just to demonstrate it working.


You can see the entire setup above - the Arduino, the breadboard with the 6 chips and my relay board.
 Below you can see a little detail of the first few chips.

There is a really good Arduino tutorial here: http://www.arduino.cc/en/Tutorial/ShiftOut


The real pain in the a*#e is the amount of fiddly little wires I have had to cut, strip and place to make this work. It has to be made on a PCB before I do anything else!
And here is the source for my test program. I can feel an Arduino library coming one...


//Pin connected to ST_CP of 74HC595
int latchPin = 10;
//Pin connected to SH_CP of 74HC595
int clockPin = 11;
////Pin connected to DS of 74HC595
int dataPin = 9;

#define  BITS_PER_BYTE  8

#define  NUM_BYTES  4
byte  bitset[NUM_BYTES];

void
BitsetClear()
{
    int  i; 
   
    for (i = 0; i< NUM_BYTES; i++)
       bitset[i] = 0;
}
void
BitsetSet()
{
    int  i; 
   
    for (i = 0; i< NUM_BYTES; i++)
       bitset[i] = 0xFF;
}

void
BitsetSetBit(int  n)
{
    int  index;
    int  bit_num;
   
    index = n/BITS_PER_BYTE;
   
    bit_num = n % BITS_PER_BYTE;
   
    Serial.print("S: ");
    Serial.print(n);
    Serial.print(" : ");
    Serial.print(index);
    Serial.print(", ");
    Serial.println(bit_num);
   
    bitset[index] = bitset[index] | (0x01 << bit_num);
}

void
BitsetClearBit(int  n)
{
    int  index;
    int  bit_num;
   
    index = n/BITS_PER_BYTE;
   
    bit_num = n % BITS_PER_BYTE;
   
    Serial.print("C: ");
    Serial.print(n);
    Serial.print(" : ");
    Serial.print(index);
    Serial.print(", ");
    Serial.println(bit_num);
   
    bitset[index] = bitset[index] & ~(0x01 << bit_num);
}

void
BitsetDisplay()
{
    int  i; 
    for (i = NUM_BYTES; i > 0; i--)
    {
      digitalWrite(latchPin, LOW);
      // shift out the bits:
      shiftOut(dataPin, clockPin, MSBFIRST, bitset[i-1]); 
      //take the latch pin high so the LEDs will light up:
      digitalWrite(latchPin, HIGH);
     
      Serial.print(" ");
      Serial.print(bitset[i - 1], BIN );
     }
     Serial.println(".");
}



void setup() {
   
  Serial.begin(9600);
 
  //set pins to output so you can control the shift register
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
 
  BitsetSet(); 
  BitsetDisplay();
}

void loop() {

  int  i;
 
  int  num_bits = 4;// NUM_BYTES * 8;

  for( i = 0; i < num_bits ; i++)
  {
    if (i==0)
    {
      BitsetSetBit(num_bits - 1);
      BitsetClearBit(i);
      BitsetDisplay();
    }
    else
    {
      BitsetSetBit(i - 1);
      BitsetClearBit(i);
      BitsetDisplay();
    }
    delay(200);
  }
}

1 comment:

  1. ok, so you have an arduino, anyway, spare one here if you need it (along with soldering iron, breadboard and other paraphernalia) (see my previous comment).

    Sorry for commenting so much, but I'm supposed to doing something way more boring so this is suddenly a very important activity.

    ReplyDelete