Quad seven segment display with shift register

I wanted to control a seven segment display but still have enough pins left to work my ultrasonic distance sensor.  The next step was to make my quad display work.   I carefully worked through what each pin did using a spreadsheet and found I could display any number I liked at any one time, but they would all show the same number.  Clearly the display needed to be refreshed in sequence somehow.  My eureka moment was realising that this is exactly how it works – you just switch them on and off, one after the other really really fast.  The eye can’t tell this is happening so you see it all as one display.  PENNY D….R….O….P….S.

I found Pial’s Blog about using a shift register to control a 4 segment display and after much fiddling got it to work once I realised that his display worked on common anode (having a voltage made it work) whereas mine was common cathode (no voltage makes things work).  I realised I had to make everything down where his was up and up where his was down.  I then got a beautiful negative display of the numbers (the segments I wanted off were on and visa versa) which confused me for a while.  I’d spotted a weird tilde ~ on the start of some variables and after a little research found that this made the binary numbers the “negative” (01000100 becoming 10111011).  I removed the ~ and bingo, I could control the numbers.  I found a minor bug in his digits too – his 5 made a 3 so I fixed that.

This code just prints random numbers at a fast flicker to prove I can change things on the fly.

/*
  Shift Register Example
 for 74HC595 shift register

 This sketch turns reads serial input and uses it to set the pins
 of a 74HC595 shift register.

 Hardware:
 * 74HC595 shift register attached to pins 2, 3, and 4 of the Arduino,
 as detailed below.
 * LEDs attached to each of the outputs of the shift register

 Created 22 May 2009
 Created 23 Mar 2010
 by Tom Igoe

 */

//Pin connected to latch pin (ST_CP) of 74HC595
const int latchPin = 8;
//Pin connected to clock pin (SH_CP) of 74HC595
const int clockPin = 12;
////Pin connected to Data in (DS) of 74HC595
const int dataPin = 11;

//http://www.pial.net/post/Arduino-controlling-a-4-digit-seven-segment-display.aspx
const int digitPins[4] = {2,3,4,5}; //pins to control the 4 common anode pins of the display
const byte digit[10] = //seven segment digit bits
{
  B00111111, //0
  B00000110, //1
  B01011011, //2
  B01001111, //3
  B01100110, //4
  B01101101, //5
  B01111101, //6
  B00000111, //7
  B01111111, //8
  B01101111  //9
};
int digitScan = 0; //to interate through the digits in the display
int digitBuffer[4] = {0}; // to?

void setup() {
  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT); 
  pinMode(clockPin, OUTPUT);
 
  for(int i=0;i < 4 br="" gt="" i="" nbsp="">    pinMode(digitPins[i],OUTPUT);
  }
 

}

void loop() {
 
  //if (Serial.available() > 0) {
    // ASCII ‘0’ through ‘9’ characters are
    // represented by the values 48 through 57.
    // so if the user types a number from 0 through 9 in ASCII,
    // you can subtract 48 to get the actual value:
    //int bitsToSend = Serial.parseInt();
    //Serial.println(“Wrote: ” + String(bitsToSend));
   
    //drop the latch
    //digitalWrite(latchPin, LOW);
   
    // shift the bits out:
    //shiftOut(dataPin, clockPin, MSBFIRST, bitsToSend);
 
      // turn on the output so the LEDs can light up:
    //digitalWrite(latchPin, HIGH);
  //}
  // wait for a bit
  //delayMicroseconds(400);
  delay(1000);
  refreshDisplay();
}

// Going to change the display
void refreshDisplay()
{
  // make all the display segments LOW
  for(byte k=0;k < 4 br=”” k=””>  {
    digitalWrite(digitPins[k], HIGH);
  }

  // the numbers I am outputting, need to link to sensor next
    digitBuffer[0] = random(0, 9);
    digitBuffer[1] = random(0, 9);
    digitBuffer[2] = random(0, 9);
    digitBuffer[3] = random(0, 9);
  // open the latch
  digitalWrite(latchPin, LOW); 
 
  // clear all the pins
  shiftOut(dataPin, clockPin, MSBFIRST, B00000000);
 
  // close the latch pin
  digitalWrite(latchPin, HIGH);
 
  // wait for a bit
  delayMicroseconds(400);
 
  // makes the right digit high
  digitalWrite(digitPins[digitScan], LOW);

  // open the latch
  digitalWrite(latchPin, LOW); 
  if(digitScan==0) // 0 is the first character – I want 3.123m
  {
    // write the number with the dp
    shiftOut(dataPin, clockPin, MSBFIRST, (digit[digitBuffer[digitScan]] | B10000000)); //inserting the dot
  }
  else
  {
    // write the number
    shiftOut(dataPin, clockPin, MSBFIRST, digit[digitBuffer[digitScan]]);
  }
  digitalWrite(latchPin, HIGH);
  digitScan++;
  if(digitScan>3) digitScan=0;
 
}


Next step is to link up to the distance sensor, but I now need to make a bug hotel with youngest.