Welcome, Guest. Please Login or Register
YaBB - Yet another Bulletin Board
09.02.2010 at 20:03:04
News: Server upgrade went fine, you are now at the new system


Pages: 1 
Interfacing Arduino with 74HC595 and a 7-Seg (Read 2737 times)
SpikedCola
Full Member
***
Offline

Arduino rocks!

Posts: 119
North York, Ontario
Gender: male
Interfacing Arduino with 74HC595 and a 7-Seg
15.07.2009 at 05:19:26
 
Some of you may recognize me from the thread about interfacing an HD44780 display and DS18S20 temperature sensors. It was a great learning experience! Thanks to everyone that helped me get it working Smiley

For my next project, Ive picked up some CC 7-seg displays and some 74HC595 shift registers. Id like to do the same thing (read the temperature) and display it to the 7-seg's (I started with the LCD because saying lcd.write(temp); was easier than learning how to shift data Wink).

Ive connected ST_CP to pin 8, SH_CP to pin 12, and DS to pin 11. I have Q0 connected to the 'a' segment (I dont know if I labelled properly, but I started with 'a' being the top segment, and 'b' being the top-right segment, and continuing on in a clockwise rotation) all the way up to 'g' connected to Q7.

Im using the following code from the shiftOut tutorial, modified a bit (explained later):

Code:
//**************************************************************//
//  Name    : shiftOutCode, Predefined Array Style              //
//  Author  : Carlyn Maw, Tom Igoe                           //
//  Date    : 25 Oct, 2006                                      //
//  Version : 1.0                                               //
//  Notes   : Code for using a 74HC595 Shift Register           //
//          : to count from 0 to 255                            //
//****************************************************************

//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;

//holders for infromation you're going to pass to shifting function
byte data;
byte dataArray[8];

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

  //Arduino doesn't seem to have a way to write binary straight into the code
  //so these values are in HEX.  Decimal would have been fine, too.
  dataArray[0] = 0x00; // off
  dataArray[1] = 0x01; // a
  dataArray[2] = 0x02; // b
  dataArray[3] = 0x04; // c
  dataArray[4] = 0x08; // d
  dataArray[5] = 0x10; // e
  dataArray[6] = 0x20; // f
  dataArray[7] = 0x40; // g

  //function that blinks all the LEDs
  //gets passed the number of blinks and the pause time
  blinkAll(2,500);
}

void loop() {


  for (int j = 0; j < 10; j++) {
    //load the light sequence you want from array
    data = dataArray[j];
    //ground latchPin and hold low for as long as you are transmitting
    digitalWrite(latchPin, 0);
    //move 'em out
    shiftOut(dataPin, clockPin, data);  
    //return the latch pin high to signal chip that it
    //no longer needs to listen for information
    digitalWrite(latchPin, 1);
    delay(1000);
  }
}



// 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);
}


//blinks the whole register based on the number of times you want to
//blink "n" and the pause between them "d"
//starts with a moment of darkness to make sure the first blink
//has its full visual effect.
void blinkAll(int n, int d) {
  digitalWrite(latchPin, 0);
  shiftOut(dataPin, clockPin, 0);
  digitalWrite(latchPin, 1);
  delay(200);
  for (int x = 0; x < n; x++) {
    digitalWrite(latchPin, 0);
    shiftOut(dataPin, clockPin, 255);
    digitalWrite(latchPin, 1);
    delay(d);
    digitalWrite(latchPin, 0);
    shiftOut(dataPin, clockPin, 0);
    digitalWrite(latchPin, 1);
    delay(d);
  }
}
 



Ive modified the array at the start to contain the different segments, and how I have them hooked up:

Code:
Qx - seg -- bin -- dec - hex
Q0 - a - 00000001 - 01 - 01
Q1 - b - 00000010 - 02 - 02
Q2 - c - 00000100 - 04 - 04
Q3 - d - 00001000 - 08 - 08
Q4 - e - 00010000 - 16 - 10
Q5 - f - 00100000 - 32 - 20
Q6 - g - 01000000 - 64 - 40
Q7 - open -----------------
 



And so far, its working great! However, I plan on having four 7-seg displays per sensor (one per number, and two more at the end hard-wired to "°C"). Does this mean I will need four shift registers per sensor? I picked up four just in case (and if I dont need them Im sure I will use them in the future). What is the best way for me to connect all four displays? Other than the chip count, shift registers seem like a good way as I only need three wires per group of display. Im not looking for blocks of code at this point (however, if you have any I would definately appreciate them!); Im looking for ideas and suggestions. Please keep in mind that I do have a small programming background, but Im more of a hardware guy (Im in Uni for Electrical Engineering Tech), so you will most likely need to be basic with me for a little longer when it comes to code, until I catch on Wink Thanks!
Back to top
 
 
View Profile | MSN   IP Logged
EmilyJane
Senior Member
****
Offline



Posts: 455
Dallas, Texas
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #1 - 15.07.2009 at 05:44:16
 
Hey again! It looks like you are still having a good time!

You can get away with just one shift register if you want to multiplex the display. If you switch the common cathodes to ground for, say, 1/60 of a second in a round robin fashion, shifting the new character in before you switch, your eye will think the display is constant.

The way you calculate the value of the anode resistors is to assume 4 times the required current since at 25% duty cycle the average current will be Imax/4.

That should give you plenty to think about for a while. Smiley
Back to top
 
 
View Profile   IP Logged
SpikedCola
Full Member
***
Offline

Arduino rocks!

Posts: 119
North York, Ontario
Gender: male
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #2 - 15.07.2009 at 14:31:00
 
Thanks for the reply. After school, Ill start working on having it flash the displays, one by one. However, if I have four segments per sensor, and one shift register, that means Im going to need (4+3=) 7 wires per set of four displays. And since Id like to have two, that puts me up to 14 wires, which doesnt leave much room for anything else. Any ways of further reducing the amount of pins Ill need to use?
Back to top
 
 
View Profile | MSN   IP Logged
Grumpy_Mike
God Member
*****
Offline

Solder is electric
glue

Posts: 5198
Manchester (England England)
Gender: male
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #3 - 15.07.2009 at 14:46:08
 
Use a demultiplex chip like the 74LS42, this will give you 8 output wires for only 3 address lines. Use these to switch the power on the anodes while pulling down the cathodes with the shift register.
An example of using the 74LS42 is to be found at:- http://www.thebox.myzen.co.uk/Hardware/Econo_Monome.html
Back to top
 
 
View Profile | WWW   IP Logged
EmilyJane
Senior Member
****
Offline



Posts: 455
Dallas, Texas
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #4 - 15.07.2009 at 15:28:45
 
That looks backwards to me, Mike. Are you sure about that?
Back to top
 
 
View Profile   IP Logged
SpikedCola
Full Member
***
Offline

Arduino rocks!

Posts: 119
North York, Ontario
Gender: male
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #5 - 15.07.2009 at 15:52:21
 
I was thinking the same thing. I chose common-cathode displays so I could turn them on with a 1. What you describe sounds like i would need to enable the displays with something like 1110 instead of 0001 which would make things more difficult for me.
Back to top
 
 
View Profile | MSN   IP Logged
Grumpy_Mike
God Member
*****
Offline

Solder is electric
glue

Posts: 5198
Manchester (England England)
Gender: male
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #6 - 15.07.2009 at 16:38:57
 
Quote:
That looks backwards to me,

Not sure what you are referring to but the schematic works so it must be right.  Wink

Quote:
enable the displays with something like 1110 instead of 0001


Yes that is more convenient because you need to use that signal to switch the power with a PNP transistor or P-channel FET. These require logic 1 to turn them off so they are suited to the output of the 74LS42.
Back to top
 
 
View Profile | WWW   IP Logged
EmilyJane
Senior Member
****
Offline



Posts: 455
Dallas, Texas
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #7 - 15.07.2009 at 17:08:38
 
Quote:
Not sure what you are referring to but the schematic works so it must be right.  


Science can't explain it but it happens! Wink

Yes, your LED matrix works fine, I'm sure, but OP has common cathode LED 7-segment displays. He is interested in driving the individual anode segments from the active high outputs of his 74HC595 shift register. Your suggestion would work if he used the 7442 to drive the common cathode connection for each digit, since the 7442 has active low outputs. Driving the anode segments with the 7442, on the other hand would take some pretty fast segment multiplexing or else would be pretty boring with only one segment lit per digit. You could use base 7 for your output. Two digits would be plenty for Celsius.  Cheesy

Leaving that for Mike to sort out for the moment, you could use a 4511 BCD to 7-segment decoder + the 7442 and service up to 8 digits with 7 digital out pins.
Back to top
 
 
View Profile   IP Logged
SpikedCola
Full Member
***
Offline

Arduino rocks!

Posts: 119
North York, Ontario
Gender: male
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #8 - 15.07.2009 at 20:51:30
 
Good, there's been some discussion while I was gone Smiley While I was in class I drew up some stuff. Here goes:

Table showing segment/Qx association/bin/hex conversion:


Table showing hex value for the numbers 0-9 (tested and working! Smiley)


Idea 1: Connecting the displays with only shift registers (for a total of 3 wires per group of displays):


Idea 2: Connecting the displays with a shift register and either a 2-to-4 line decoder (for multiplexing the displays) which would need five wires, or using a transistor (missing resistors - just a block diagram) for each display, for a total of seven wires per group of displays:



Now, some of these ideas may not even work, I was just trying to come up with ideas, to prove that Im serious about doing this (and not just trying to con you guys into doing my work for me!). So far, Idea 1 with one shift register per display seems the best, as the coding would be the easiest - I expect it would go something like this:

temp * 100 // remove the decimal (decimal hardwired on second display)
for each number in temp, starting with the 1's value
 look up hex in table // if we need a 0, shift out 0x3F, etc
 shift out

may be completely off, but hey, Im trying!
Back to top
 
 
View Profile | MSN   IP Logged
EmilyJane
Senior Member
****
Offline



Posts: 455
Dallas, Texas
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #9 - 15.07.2009 at 22:01:05
 
Those are all good ideas. Did you say the two displays on the right were displaying constant degree symbol and the "C"? In that case you could hard wire the characters although you'd have to fiddle with resistance to get the same brightness as your live digits. Probably a little too much "refining" as you might want to use those digits in the future.

Think about the code for the case where you have only one shift register. What do you have to do to maintain a reading in your live displays before the next refresh?

Think about the case where you have a shift register for each live digit. Ask yourself the same question.

What about if you have a chip that turns decodes BCD into 7 segment (4511)? Does that give you more or less time for other processing than the other two cases? Which strategy of multiplexing gives you least time to do other things? Which one affects the quality of the display the most or least if you stop doing it for a moment?

This is starting to sound too much like a homework assignment and it's supposed to be fun! Cheesy
Back to top
 
 
View Profile   IP Logged
SpikedCola
Full Member
***
Offline

Arduino rocks!

Posts: 119
North York, Ontario
Gender: male
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #10 - 15.07.2009 at 22:21:44
 
Quote:
Those are all good ideas. Did you say the two displays on the right were displaying constant degree symbol and the "C"? In that case you could hard wire the characters although you'd have to fiddle with resistance to get the same brightness as your live digits. Probably a little too much "refining" as you might want to use those digits in the future.

Yes, there will be two more displays to the right of these four, which will display "°C". I was planning on using a 1k pot and adjusting the brightness to match the others.


Quote:
Think about the code for the case where you have only one shift register. What do you have to do to maintain a reading in your live displays before the next refresh?

To be honest, I havent even put any thought into this method, other than just 'can it be done'. Being as new as I am to writing code for a uC, Im planning on staying away from multiplexing for now, as that adds another element of unknown to my code, and I already dont know what Im doing as it is Wink


Quote:
Think about the case where you have a shift register for each live digit. Ask yourself the same question.

Unless Im misunderstanding you, wouldnt I just have to not start shifting until I poll the sensor? The shift register is going to keep the digit lit to whatever I have loaded into the latch until I load something else, right?


Quote:
What about if you have a chip that turns decodes BCD into 7 segment (4511)? Does that give you more or less time for other processing than the other two cases? Which strategy of multiplexing gives you least time to do other things? Which one affects the quality of the display the most or least if you stop doing it for a moment?

Here, let me delve deep into my knowledge of multiplexing... The first kind Smiley I know the idea behind it (switching displays on and off quickly to trick the mind into thinking theyre on all time), but Ive never seen it implemented in code or looked at the various methods.


Quote:
This is starting to sound too much like a homework assignment and it's supposed to be fun! Cheesy

Ive never had a homework assignment like this! Tongue Mine consisted of "create a circuit that uses a one-shot multivibrator to turn a 50kHz 80% duty cycle square wave into a 50kHz 50% duty cycle square wave." This sounds more like a big term project Wink
Back to top
 
 
View Profile | MSN   IP Logged
EmilyJane
Senior Member
****
Offline



Posts: 455
Dallas, Texas
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #11 - 15.07.2009 at 22:39:55
 
As far as the decoder goes, you have to write the BCD code into the decoder for each displayed digit and then write the cathode for that digit low for your multiplex time. The digital out pins provide the latch function during the "on" time.

I think you will agree that out of the methods you've considered, the one with a shift register for each digit has the lowest overhead in terms of % of available processing time.

Another method would be use one shift register driving two BCD to 7 segment decoders where the shift register contains the two BCD digits instead of segment data. Just a different way, I don't suggest that it is better or worse.

Wow, you've got it easy. Smiley
Back to top
 
 
View Profile   IP Logged
Mike Mc
God Member
*****
Offline

Go! Go! Arduinoooo
!!!

Posts: 913
London, England
Gender: male
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #12 - 15.07.2009 at 22:41:35
 
Quote:
I was thinking the same thing. I chose common-cathode displays so I could turn them on with a 1. What you describe sounds like i would need to enable the displays with something like 1110 instead of 0001 which would make things more difficult for me.


Why would it make life more difficult?

Turning 0001 into 1110 is easy, you just use a logical NOT symbol, i.e. a ~ before your variable and it inverts it.
Back to top
 
 
View Profile | WWW | MSN   IP Logged
SpikedCola
Full Member
***
Offline

Arduino rocks!

Posts: 119
North York, Ontario
Gender: male
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #13 - 15.07.2009 at 22:51:42
 
Ahh cool, like I said, I dont consider myself anything of a program, I didnt know ~ would invert it Tongue Still, its just one fewer thing that Id have to do.
Back to top
 
 
View Profile | MSN   IP Logged
EmilyJane
Senior Member
****
Offline



Posts: 455
Dallas, Texas
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #14 - 15.07.2009 at 22:58:34
 
Mike's example was using FET inverters as anode drivers which required an active low to enable. OP already has common cathode displays and he is driving the anodes directly from the HC595. Agreed that he could just as easily drive those same anodes with FETs and negative logic from those same shift registers. He would not use 7442s to do that, however.

Maybe the difficulty would come from having to wire up all those extra transistors.
Back to top
 
 
View Profile   IP Logged
SpikedCola
Full Member
***
Offline

Arduino rocks!

Posts: 119
North York, Ontario
Gender: male
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #15 - 15.07.2009 at 23:03:07
 
Im sure Id forget to invert the output in my first few tries, so that would likely screw me up too haha.

So far so good:
http://www.facebook.com/photo.php?pid=7887757&l=907350c731&id=536725214
Back to top
 
 
View Profile | MSN   IP Logged
EmilyJane
Senior Member
****
Offline



Posts: 455
Dallas, Texas
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #16 - 15.07.2009 at 23:07:13
 
Looks plenty bright. What is your segment current? Are you multiplexing the one digit?
Back to top
 
 
View Profile   IP Logged
SpikedCola
Full Member
***
Offline

Arduino rocks!

Posts: 119
North York, Ontario
Gender: male
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #17 - 15.07.2009 at 23:35:45
 
They are running at 5v and have a 510Ω resistor per segment, so each segment is getting (5v / 510Ω =) 9.8mA.

Ive just got the CC grounded and Im using the following code:
Code:
#include <Debounce.h>
#include <Button.h>

//**************************************************************//
//  Name    : shiftOutCode, Predefined Array Style		  //
//  Author  : Carlyn Maw, Tom Igoe				   //
//  Date    : 25 Oct, 2006						  //
//  Version : 1.0							     //
//  Notes   : Code for using a 74HC595 Shift Register	     //
//	    : to count from 0 to 255				    //
//****************************************************************

//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;

//holders for infromation you're going to pass to shifting function
byte data;
byte dataArray[10];
Button button = Button(10,PULLUP);

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

  //Arduino doesn't seem to have a way to write binary straight into the code
  //so these values are in HEX.  Decimal would have been fine, too.
  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);
  //move 'em out
  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()
{
  if (button.uniquePress())
  {
    if (j < 10)
    {
	data = dataArray[j];
	//ground latchPin and hold low for as long as you are transmitting
	digitalWrite(latchPin, 0);
	//move 'em out
	shiftOut(dataPin, clockPin, data);
	//return the latch pin high to signal chip that it
	//no longer needs to listen for information
	digitalWrite(latchPin, 1);
	j++;
    }
    else if (j == 10)
    {
	j = 0;
	data = dataArray[j];
	//ground latchPin and hold low for as long as you are transmitting
	digitalWrite(latchPin, 0);
	//move 'em out
	shiftOut(dataPin, clockPin, data);
	//return the latch pin high to signal chip that it
	//no longer needs to listen for information
	digitalWrite(latchPin, 1);
    }
    delay(200);
  }

  /*
  for (int j = 0; j < 10; j++) {
   //load the light sequence you want from array
   data = dataArray[j];
   //ground latchPin and hold low for as long as you are transmitting
   digitalWrite(latchPin, 0);
   //move 'em out
   shiftOut(dataPin, clockPin, data);
   //return the latch pin high to signal chip that it
   //no longer needs to listen for information
   digitalWrite(latchPin, 1);
   delay(1000);
   }
   }
   */
}

// 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);

}
 



Im working on getting the other three segments hooked up Smiley
Back to top
 
 
View Profile | MSN   IP Logged
EmilyJane
Senior Member
****
Offline



Posts: 455
Dallas, Texas
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #18 - 15.07.2009 at 23:57:52
 
Yay!

You can make binary constants. They are limited to type byte.

Code:
dataArray[0] = B111111; // 0  

Back to top
 
 
View Profile   IP Logged
SpikedCola
Full Member
***
Offline

Arduino rocks!

Posts: 119
North York, Ontario
Gender: male
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #19 - 16.07.2009 at 00:16:15
 
How do I string hex/binary together? Like if I want the two displays to display 62, Id have to shift out 0x7C5B (shifting 5B first, then 7C). In binary itd be 01111100 sent first, then 01011011, to fill the register like this:
Code:
 01011011 | 01111100
+---------+---------+
     6		2 



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?
Back to top
 
 
View Profile | MSN   IP Logged
EmilyJane
Senior Member
****
Offline



Posts: 455
Dallas, Texas
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #20 - 16.07.2009 at 00:32:06
 
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.
Back to top
 
 
View Profile   IP Logged
EmilyJane
Senior Member
****
Offline



Posts: 455
Dallas, Texas
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #21 - 16.07.2009 at 00:59:29
 
Quote:
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:
Code:
unsigned int concat;
byte digit1;
byte digit2;

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

Back to top
 
 
View Profile   IP Logged
SpikedCola
Full Member
***
Offline

Arduino rocks!

Posts: 119
North York, Ontario
Gender: male
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #22 - 16.07.2009 at 02:01:13
 
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:

Code:
  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?
Back to top
 
 
View Profile | MSN   IP Logged
EmilyJane
Senior Member
****
Offline



Posts: 455
Dallas, Texas
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #23 - 16.07.2009 at 02:23:41
 
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?
Back to top
 
 
View Profile   IP Logged
SpikedCola
Full Member
***
Offline

Arduino rocks!

Posts: 119
North York, Ontario
Gender: male
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #24 - 16.07.2009 at 04:12:25
 
Hmm yes, that should definately help. Thanks!
Back to top
 
« Last Edit: 16.07.2009 at 20:03:31 by SpikedCola »  
View Profile | MSN   IP Logged
SpikedCola
Full Member
***
Offline

Arduino rocks!

Posts: 119
North York, Ontario
Gender: male
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #25 - 16.07.2009 at 20:03:45
 
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:
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 Smiley
Back to top
 
 
View Profile | MSN   IP Logged
EmilyJane
Senior Member
****
Offline



Posts: 455
Dallas, Texas
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #26 - 16.07.2009 at 22:30:15
 
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.

Code:
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(){
}

 

Back to top
 
 
View Profile   IP Logged
SpikedCola
Full Member
***
Offline

Arduino rocks!

Posts: 119
North York, Ontario
Gender: male
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #27 - 17.07.2009 at 00:02:36
 
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!).


Code:
#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:
http://www.facebook.com/v/233411460214

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! Grin
Back to top
 
« Last Edit: 17.07.2009 at 02:28:11 by SpikedCola »  
View Profile | MSN   IP Logged
EmilyJane
Senior Member
****
Offline



Posts: 455
Dallas, Texas
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #28 - 17.07.2009 at 02:05:26
 
Hey, very good! I'm glad I could help! Are you going to package it up somehow?
Back to top
 
 
View Profile   IP Logged
SpikedCola
Full Member
***
Offline

Arduino rocks!

Posts: 119
North York, Ontario
Gender: male
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #29 - 17.07.2009 at 02:25:24
 
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!
Back to top
 
 
View Profile | MSN   IP Logged
EmilyJane
Senior Member
****
Offline



Posts: 455
Dallas, Texas
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #30 - 17.07.2009 at 02:37:11
 
You're welcome. Keep us posted.
Back to top
 
 
View Profile   IP Logged
SpikedCola
Full Member
***
Offline

Arduino rocks!

Posts: 119
North York, Ontario
Gender: male
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #31 - 24.07.2009 at 02:46:40
 
Finally got 'er done! Even had it working on the first try. Oh boy, am I happy!

Code:
#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);

} 





Back to top
 
 
View Profile | MSN   IP Logged
EmilyJane
Senior Member
****
Offline



Posts: 455
Dallas, Texas
Re: Interfacing Arduino with 74HC595 and a 7-Seg
Reply #32 - 24.07.2009 at 02:51:32
 
Wow! Beautiful job. Congratulations!
Back to top
 
 
View Profile   IP Logged
Pages: 1