Interfacing Arduino with 74HC595 and a 7-Seg

Do you have two shift registers wired up? I'll assume you do and that you have Q7 from the first daisy-chained to DS of the second.

You'd call your shiftOut function twice first with 0x5b and then 0x7c or B01011011 and B01111100 or 91 and 124 or what ever you favorite base is. In your program you'll most likely call it with a variable each time.

What I was talking about is that when you are initializing variables or defining constants, you can use the B format if it makes visualizing your data any easier of more clear.

EDIT Would I need to join them together? Now that I think about it, I should just be able to shift out the LSByte, then the MSByte, right?

That's right. If you do want to concatenate them together into an integer it's pretty simple.

There are many ways but here are two:

unsigned int concat;
byte digit1;
byte digit2;

concat = digit1;
concat = (concat << 8) + digit2; // or
concat = (concat * 256) + digit2;

Thats correct, Ive got Q7' of the first chip connected to the DS of the second, and so on.

How do I assign the hex character for each character in the temperature? It sounds kind of confusing, so Ill try to show you what Im doing:

  toShift = 8454;

  dataArray[0] = 0x3F; // 0
  dataArray[1] = 0x06; // 1
  dataArray[2] = 0x5B; // 2
  dataArray[3] = 0x4F; // 3
  dataArray[4] = 0x66; // 4
  dataArray[5] = 0x6D; // 5
  dataArray[6] = 0x7C; // 6
  dataArray[7] = 0x07; // 7
  dataArray[8] = 0x7F; // 8
  dataArray[9] = 0x67; // 9

  [ some code here ]

  shiftOut(dataPin, clockPin, byte1);
  shiftOut(dataPin, clockPin, byte2);
  shiftOut(dataPin, clockPin, byte3);
  shiftOut(dataPin, clockPin, byte4);

--

where:
byte1 = 0x66; // 4
byte2 = 0x6D; // 5
byte3 = 0x66; // 4
byte4 = 0x7F; // 8

I was thinking of a foreach() loop but Im not sure if C has them, I tried typing foreach( and it didnt get highlighted. Any ideas?

In these situations, I use the "do what I mean" instruction.

Seriously though, I believe your array that indexes a number 0-9 into the 7 segment pattern is what you want to use. All you have to do is convert your decimal value 0-99 into two BCD digits. Then you use each BCD digit, 0-9 to index your array to return the proper 7 segment pattern.

Is that a big enough hint?

Hmm yes, that should definately help. Thanks!

EDIT I thought I got it when I read it, but I think Im trying to do it a different way. I was hoping to do something like this psudo-code:

  int toShift = 8424;
  byte digitstoShift[4];
  byte dataArray[10];

  dataArray[0] = 0x3F; // 0
  dataArray[1] = 0x06; // 1
  dataArray[2] = 0x5B; // 2
  dataArray[3] = 0x4F; // 3
  dataArray[4] = 0x66; // 4
  dataArray[5] = 0x6D; // 5
  dataArray[6] = 0x7C; // 6
  dataArray[7] = 0x07; // 7
  dataArray[8] = 0x7F; // 8
  dataArray[9] = 0x67; // 9

foreach (number n in toShift) // toShift = 8424
{
  int value = getValue(n); // n = 0 (for the first number, 8) and value = 8 , the value of the number at position n
  digitstoShift[n] = dataArray[value];
}

  shiftOut(dataPin, clockPin, digitstoShift[0]);   
  shiftOut(dataPin, clockPin, digitstoShift[1]);   
  shiftOut(dataPin, clockPin, digitstoShift[2]);   
  shiftOut(dataPin, clockPin, digitstoShift[3]);

Either that, or something that can take an int (eg 8421) and create an array with the four numbers in it (which I can then work with).

My apologies if none of that makes sense :slight_smile:

Take a look at this. This is not necessarily the most efficient way to make the conversion but it demonstrates number bases and the equivalent of a decimal shift.

int x = 5386; // number to convert
char m[4]; // individual digits
int n; // exponent 
int k; // 10 to power n

void setup()

{
  Serial.begin(9600);
  if (x < 10000) { 
  
    if (x >= 1000){ // first we need to find out how many digits are in our number.
      n = 3;
      k = 1000;
    }
    else if (x >= 100) {
      n = 2; 
      k = 100;
    }
     else if (x >= 10){
      n = 1; 
      k = 10;
    }
    else if (x >= 0) {
      n = 0;             // we'll use this for our array index as well so we'll start at zero 
      k = 1;
    }
   
    
  }
  else n = -1; // this can flag an error when you make this a function

  int temp = x; // don't destroy x
  
  for (int i = n; i >= 0; i--) // break the number apart 1 decade at a time
  {  
    m[i] = temp / k; // integer divide isolates MSD
    temp = temp - (m[i] * k); // remaining digits
    k = k / 10; // decrement decade
  }

Serial.println(m[3],DEC);
Serial.println(m[2],DEC);
Serial.println(m[1],DEC);
Serial.println(m[0],DEC);

}

void loop(){
}

Thank you so much! Thats exactly what I needed. I hope you dont mind, I borrowed a bit of your code (I kept you in there, of course!).

#include <DallasTemperature.h>
//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;
int j = 1;

int toShift = 0;
char m[4];

byte data;
byte dataArray[10];
DallasTemperature tempSensor;

void setup() {
  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
  Serial.begin(9600);
  tempSensor.begin(9);

  dataArray[0] = 0x3F; // 0
  dataArray[1] = 0x06; // 1
  dataArray[2] = 0x5B; // 2
  dataArray[3] = 0x4F; // 3
  dataArray[4] = 0x66; // 4
  dataArray[5] = 0x6D; // 5
  dataArray[6] = 0x7C; // 6
  dataArray[7] = 0x07; // 7
  dataArray[8] = 0x7F; // 8
  dataArray[9] = 0x67; // 9

  data = dataArray[0];
  //ground latchPin and hold low for as long as you are transmitting
  digitalWrite(latchPin, 0);
  shiftOut(dataPin, clockPin, data); // shift 0 four times to clear the display
  shiftOut(dataPin, clockPin, data);
  shiftOut(dataPin, clockPin, data);
  shiftOut(dataPin, clockPin, data);
  //return the latch pin high to signal chip that it no longer needs to listen for information
  digitalWrite(latchPin, 1);
}

void loop() 
{
  int n = 3; // exponent
  int k = 1000; // 10 to power n
  toShift = (tempSensor.getTemperature() * 100);
  Serial.println(toShift);

  // following code by EmilyJane of arduino.cc forums
  int temp = toShift; // don't destroy x
  for (int i = 3; i >= 0; i--) // break the number apart 1 decade at a time
  {
    m[i] = temp / k; // integer divide isolates MSD
    temp = temp - (m[i] * k); // remaining digits
    k = k / 10; // decrement decade
  }

  //ground latchPin and hold low for as long as you are transmitting
  digitalWrite(latchPin, 0);
  //move 'em out
  shiftOut(dataPin, clockPin, dataArray[m[0]]);   
  shiftOut(dataPin, clockPin, dataArray[m[1]]);   
  shiftOut(dataPin, clockPin, dataArray[m[2]]);   
  shiftOut(dataPin, clockPin, dataArray[m[3]]); 
  //return the latch pin high to signal chip that it 
  //no longer needs to listen for information
  digitalWrite(latchPin, 1);
}

// the heart of the program
void shiftOut(int myDataPin, int myClockPin, byte myDataOut) 
{
  // This shifts 8 bits out MSB first, 
  //on the rising edge of the clock,
  //clock idles low

  //internal function setup
  int i=0;
  int pinState;
  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, OUTPUT);

  //clear everything out just in case to
  //prepare shift register for bit shifting
  digitalWrite(myDataPin, 0);
  digitalWrite(myClockPin, 0);

  //for each bit in the byte myDataOut?
  //NOTICE THAT WE ARE COUNTING DOWN in our for loop
  //This means that %00000001 or "1" will go through such
  //that it will be pin Q0 that lights. 
  for (i=7; i>=0; i--)  {
    digitalWrite(myClockPin, 0);

    //if the value passed to myDataOut and a bitmask result 
    // true then... so if we are at i=6 and our value is
    // %11010100 it would the code compares it to %01000000 
    // and proceeds to set pinState to 1.
    if ( myDataOut & (1<<i) ) {
      pinState= 1;
    }
    else {      
      pinState= 0;
    }

    //Sets the pin to HIGH or LOW depending on pinState
    digitalWrite(myDataPin, pinState);
    //register shifts bits on upstroke of clock pin  
    digitalWrite(myClockPin, 1);
    //zero the data pin after shift to prevent bleed through
    digitalWrite(myDataPin, 0);
  }

  //stop shifting
  digitalWrite(myClockPin, 0);

}

Video:

Im very happy with this method! It does exactly what I want, and best of all, only uses four pins per temperature I want to display (3 for the shift registers and one for the sensor itself)! Thank you so much! ;D

Hey, very good! I'm glad I could help! Are you going to package it up somehow?

Yes, the two sets of displays are going to be soldered to some perf-board. I also plan on designing a menu-like interface for the LCD (I wanted the temperature to be visible at all times, thats why I did it with 7-seg's) and putting everything into a nice box to be mounted on a wall, so Im sure I will have more questions when I delve into that.

Thanks again!

You're welcome. Keep us posted.

Finally got 'er done! Even had it working on the first try. Oh boy, am I happy!

#include <DallasTemperature.h>

int bottomDataPin = 5; 
int bottomLatchPin = 6;
int bottomClockPin = 7;
int topLatchPin = 3;
int topClockPin = 4;
int topDataPin = 2;
int j = 1;
int toShift_Top = 0;
int toShift_Bottom = 0;
char m[4];
byte data;
byte dataArray[10];

DallasTemperature tempSensor0;
DallasTemperature tempSensor1;

void setup() {
  pinMode(topLatchPin, OUTPUT);
  pinMode(bottomLatchPin, OUTPUT);
  Serial.begin(9600);
  tempSensor0.begin(11);
  tempSensor1.begin(12);

  dataArray[0] = 0x3F; // 0
  dataArray[1] = 0x06; // 1
  dataArray[2] = 0x5B; // 2
  dataArray[3] = 0x4F; // 3
  dataArray[4] = 0x66; // 4
  dataArray[5] = 0x6D; // 5
  dataArray[6] = 0x7C; // 6
  dataArray[7] = 0x07; // 7
  dataArray[8] = 0x7F; // 8
  dataArray[9] = 0x67; // 9

  // clear both displays with 0's
  // top
  digitalWrite(topLatchPin, 0);
  shiftOut(topDataPin, topClockPin, dataArray[0]);
  shiftOut(topDataPin, topClockPin, dataArray[0]);
  shiftOut(topDataPin, topClockPin, dataArray[0]);
  shiftOut(topDataPin, topClockPin, dataArray[0]);
  digitalWrite(topLatchPin, 1);
  //bottom
  digitalWrite(bottomLatchPin, 0);
  shiftOut(bottomDataPin, bottomClockPin, dataArray[0]);
  shiftOut(bottomDataPin, bottomClockPin, dataArray[0]);
  shiftOut(bottomDataPin, bottomClockPin, dataArray[0]);
  shiftOut(bottomDataPin, bottomClockPin, dataArray[0]);
  digitalWrite(bottomLatchPin, 1);
}

void loop() 
{
  int k = 1000;
  toShift_Top = (tempSensor0.getTemperature() * 100);

  // the following code is by EmilyJane of arduino.cc forums
  int temp = toShift_Top;
  for (int i = 3; i >= 0; i--)
  {
    m[i] = temp / k;
    temp = temp - (m[i] * k);
    k = k / 10;
  }
  // end
  digitalWrite(topLatchPin, 0);
  shiftOut(topDataPin, topClockPin, dataArray[m[0]]);   
  shiftOut(topDataPin, topClockPin, dataArray[m[1]]);   
  shiftOut(topDataPin, topClockPin, dataArray[m[2]]);   
  shiftOut(topDataPin, topClockPin, dataArray[m[3]]); 
  digitalWrite(topLatchPin, 1);
  
  k = 1000;
  toShift_Bottom = (tempSensor1.getTemperature() * 100);
  // again, the following code is by EmilyJane of arduino.cc forums
  temp = toShift_Bottom;
  for (int i = 3; i >= 0; i--) 
  {
    m[i] = temp / k;
    temp = temp - (m[i] * k);
    k = k / 10;
  }
  // end
  digitalWrite(bottomLatchPin, 0);
  shiftOut(bottomDataPin, bottomClockPin, dataArray[m[0]]);   
  shiftOut(bottomDataPin, bottomClockPin, dataArray[m[1]]);   
  shiftOut(bottomDataPin, bottomClockPin, dataArray[m[2]]);   
  shiftOut(bottomDataPin, bottomClockPin, dataArray[m[3]]); 
  digitalWrite(bottomLatchPin, 1);
}

// the heart of the program
void shiftOut(int myDataPin, int myClockPin, byte myDataOut) 
{
  // This shifts 8 bits out MSB first, 
  //on the rising edge of the clock,
  //clock idles low

  //internal function setup
  int i=0;
  int pinState;
  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, OUTPUT);

  //clear everything out just in case to
  //prepare shift register for bit shifting
  digitalWrite(myDataPin, 0);
  digitalWrite(myClockPin, 0);

  //for each bit in the byte myDataOut?
  //NOTICE THAT WE ARE COUNTING DOWN in our for loop
  //This means that %00000001 or "1" will go through such
  //that it will be pin Q0 that lights. 
  for (i=7; i>=0; i--)  {
    digitalWrite(myClockPin, 0);

    //if the value passed to myDataOut and a bitmask result 
    // true then... so if we are at i=6 and our value is
    // %11010100 it would the code compares it to %01000000 
    // and proceeds to set pinState to 1.
    if ( myDataOut & (1<<i) ) {
      pinState= 1;
    }
    else {      
      pinState= 0;
    }

    //Sets the pin to HIGH or LOW depending on pinState
    digitalWrite(myDataPin, pinState);
    //register shifts bits on upstroke of clock pin  
    digitalWrite(myClockPin, 1);
    //zero the data pin after shift to prevent bleed through
    digitalWrite(myDataPin, 0);
  }

  //stop shifting
  digitalWrite(myClockPin, 0);

}



Wow! Beautiful job. Congratulations!