Help Understanding Shiftout

Hello,

I'm new to the whole Arduino/ Coding thing and a concept I need to use in my project keeps confusing me. I came across this topic (xxx.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1235795499/0) which describes how to use a M5451 (with 35 outputs) to drive all my LED's. I tried going through the code and I'm completely lost. Are there a few core concepts I can review to have a better understanding of what's going on with this tutorial?

Also, from what I gathered, this code was meant to affect all the LED's connected to the chip. What I want to do is drive sets of LEDs independently. In other words I want a group of 10 LEDs to do one thing ( lets say a chaser strip) while 2 more LEDs blink n and off, and lets say another 6 light up another way. How can you create these sets of LEDs and assign specific functions to them? Hopefully I was't too confusing on what I'm trying to accomplish. If you want me to clarify, just ask. Thanks everyone!

p.s. sorry had to add "xxx" to the link cause it wouldn't let me link.....such a noob.

What you want to do with this chip is completely possible and relatively easy. What is it you are having difficulty with? The M5451 is essentially just a big Shift Register and operates the same as a 595 chip. See the ShiftOut tutorial which explains it quite well.

I guess what I'm having a hard time trying to understand is how the arduino code actually the tells the chip which pin to turn on. I'm not sure how to even explain it but This is kinda what I don't understand:

Your arduino is hooked up to the shift register. Lets say you shift register has 8 out puts labeled 0-7. Now how does the arduino communicate to the chip OK, turn on pin 0, now leave pin 0 on and turn on pin 1, leave pin 0 and 1 on turn on pin 2, leave pin 0,1, and 2 turn on 3 etc. then reverse that turn off pin 7 but leave 6-0 on and so on...? What would the code look like?

It would seem like you would have to define each output on the shift register ( pins 0-7) so that the arduino knows which out put you want to do something on. I guess I'm confused on how the arduino code associates each pin and knows OK, I'm sending this signal to pin 0 and this signal to pin 0 and 1 etc. If this makes sense. Sorry I'm not an electronics expert so I'm not sure of correct terms for a lot of things yet.

http://arduino.cc/en/Tutorial/ShftOut23 This kinda makes a little sense to me particularly these lines:

dataArrayRED[0] = 0xFF; //11111111
dataArrayRED[1] = 0xFE; //11111110
dataArrayRED[2] = 0xFC; //11111100
dataArrayRED[3] = 0xF8; //11111000
dataArrayRED[4] = 0xF0; //11110000
dataArrayRED[5] = 0xE0; //11100000
dataArrayRED[6] = 0xC0; //11000000
dataArrayRED[7] = 0x80; //10000000
dataArrayRED[8] = 0x00; //00000000
dataArrayRED[9] = 0xE0; //11100000

this i assume this is where the chip is defined and the possible output pins are listed in array where 0xFF is pin 0's physical address and the arduino is being told to refer to it as dataArrayRED[0] anytime it is to be used in the code.

Is the Hex naming scheme typical with all chips? How do they come up with 0xFF as the "0" pin and so on ( If I'm assuming correctly)? Is there a chart? I know this is probably core work, IC 101 but I'm trying to learn by doing. Thanks.

@MikeMc -- are you saying the M5451 works EXACTLY the same as the 595 (ignoring the physical differences of course)? That would be interesting because it would mean that my arduino M5451 library would also work with the 595s...

No the M5451 is slightly different in how it expects data to go in but it is only a minor difference to a 595. if you read the datasheet for the two you will see they are almost identical except the M5451 has a much larger register.

idtjes3:

I don't know if you have figured it out by now, but you basically got it all wrong. You don't adress individual pins on a shiftregister directly like that in which you assumed (from the code snippet you showed).

It's actually simpler, as in more primitive.

The shiftOut() function takes a byte (8 bits) and shuffle it out one bit at a time. To do this it need two output pins on the Arduino, one for clock, which basically says the bit is ready to be read, and one for the bits (data).

The function shiftOut() does this automagically on all 8 bits (the hole byte) :slight_smile:

A shiftregister just receives these bits one bit at a time. Hence the first bit it receives, will pass through all its outputs until it reaches its destination, closely followed by the other bits (unless the shiftregister have an enable or latch or similar. In which case it wont show on its outputs until told to).

"shiftOut" shifts them out either from left to right (MSB first - Most Significant Byte), or right to left (LSB first - Least Significant Byte).

shiftOut(dataPin, clockPin, bitOrder, value)
http://arduino.cc/en/Reference/ShiftOut

The code snippet you show is just an array of values, not adressable to any individual bits on the shiftregister like you said. If you use shiftout on them, they will show up on the shiftregister eventually (it's pretty fast), but all the bits in any one of the dataArrayRED[] will be on the shiftregister.

So

shiftOut(dataPin, clockPin, MSBFIRST, dataArrayRED[0]);

If dataArrayRED[0] = 0xFF, which is binary 11111111 (the same thing) -> All the bits on the shiftregister will be 1's.

If instead it had ben 0xFE, which is binary 11111110 -> All the bits except the last one will be 1's (or the first, depending on the direction you shift them out - MSBFIRST of LSBFIRST)

There is a loop in the code you refer to which runs through the dataArray*.*
You can read more on that in arrays and control structures in the language reference page http://arduino.cc/en/Reference/Extended

Thanks raron for your detailed response. I guess that makes sense if your trying to light an LED one at a time or go from say pin 1 to pin 2 to pin..etc. but what doesn't make sense to me is say you have a 15 LED light setup and you want LED 1 and 15 to be lit then 2 and 14 while still having 1 and 15 lit and so on until the LEDs meet in the center (kinda like a bar graph) how would you show that in the code? How does the arduino tell the shift register which pins should be on and that it wants to go in that direction?

For this instance should I define an array in the pattern I want the lights to go ( in hex) then call the array in the code?

Sorry for the late response. I didn't check this thread for a while. (+ it doesnt seem to be subscription of threads here?).

What you say about storing the pattern in an array is correct (not that it's the only way, but it certainly is one way of doing it).

If you have a 16 bit shiftregister, or two 8-bit shiftregisters chained, you need to use the shiftOut() function twice. If you store the pattern as an int (2 bytes), you need to extract one byte at a time from it and feed the shiftOut() function.

If you don't strobe the leds while doing the shiftOut, they will lit up briefly (not visible I'd guess, as it is pretty quick. But I haven't tried this yet in fact) as the bits shift to their position.

Then, after 16 bits are shifted out, you just wait a time equal to some preset framerate. Let's say about 30 frames pr. second, you wait about 1/30 second until you shift out the next pattern.

Or I guess that's far too quick for this purpose when I think about it.. say 1/5th of a second maybe, and you wait about 200 ms until the next pattern. Just experiment with the timings.

Pseudo-ish code:

int dataPin = 12;
int clockPin = 13;

int patterns = 8 ;
unsigned int pattern[] = {b1000000000000001,
              b1100000000000011,
              b1110000000000111,
              b1111000000001111,
              b1111100000011111,
              b1111110000111111,
              b1111111001111111,
              b1111111111111111 };


void setup()
{
}

void loop()
{

  for (int i=0;i<patterns;i++)
  {
    uint8_t lowByte = (uint8_t)pattern[i] & 0x00FF:
    uint8_t highByte = (uint8_t)(pattern[i] >> 8 ) & 0x00FF;

    shiftOut(dataPin, clockPin, MSBFIRST, highByte);
    shiftOut(dataPin, clockPin, MSBFIRST, lowByte);

    delay(200); // milliseconds
  }
}

(Basically wrote the hole thing there?:stuck_out_tongue: Primitive waiting though, but it works)
Not sure uf the typecasting of (uint8_t) is neccessary together with the masking though (masking = AND'ing with 0x00FF = just keep the lowest byte). Experiment :slight_smile:

Ah, Thanks raron. I'll have to try this when I get home tonight. To me, this method makes more sens cause I can see the actual pattern in front of me. Thanks again everyone for your help.

No problem :slight_smile:

A couple of erratas though:

Seems the binary prefix is a "B", not "b", and that it's only possible for byte values ( B10101010) Integer Constants - Arduino Reference

As it says in the example:

The binary formatter only works on bytes (8 bits) between 0 (B0) and 255 (B11111111). If it is convenient to input an int (16 bits) in binary form you can do it a two-step procedure such as:

myInt = (B11001100 * 256) + B10101010; // B11001100 is the high byte

Also, I might have confused the left and right direction in the description of shiftOut and MSB / LSB. If so, I ment your left and right :wink:

doesnt seem to be subscription of threads here?

at the top and bottom of each page there is a line that has

Reply | Add Poll | Notify of replies | Send Topic | Print | Mark as Unread

You can use that e-mail notification for a kind of a subscription.

Also, on the page where you type a reply, the same thing is in a checkbox just under the row of smilies:

Notify of replies: Check this if you wish to be notified of replies to this topic.

Hope that helps.

Thanks!
(How could I miss those? :-[ )

How could I miss those?

They're not red in their original version. :wink: :wink:

They're not red in their original version.

Thats it! :stuck_out_tongue: