single led addressing and shif register

hello,
I finally discovered arduino a month ago and I just fall in love with it. I have a problem that I cannot resolve, I connected in cascade 4x74ls975 (ehm, 74HC595) as showed in the shiftout tutorial but I've not understand crearly how to address the cascaded ICs!
Another question is how to access individually every single led when different 74ls975 are cascaded.
I find a trick that wors well with one 74ls975 (74HC595) but not when 2 or more are connected.
Really appreciate your help. ;D

You keep images of the bits in variables, modify bits as required, then blat ALL bytes out to your shift registers. Only the changed bits will change.

http://www.arduino.cc/playground/Code/BitMath

As stated by Graynomad put the data in a variable then you can run bit math on it and then feed that variable to shift out. If you have one eight bit register you shift out 8 bits, two then 16 bits, three 24 bits and so on. You can keep a separate variable for each chip an shift out those variables in order to make it a little easier to keep track.

Uao! Thanks a lot for your replies!

About the ic's, I was wrong, really sorry for mistake. They are 74HC595 as mentioned above.
I'm very interested to the single led addressing because I'm building a box with lots of momentary push buttons that should act as switches (ON-OFF).
What I learned today is that every chip needs a shiftOut and first command address the last chip till the first.
For the experiment I connected on a breadboard 2 74HC595 cascaded and 16 leds.
All demos pde of the shiftOut tutorial works as expected. Now if I want try to access single led. I used this code?:

  digitalWrite(latchPin, 0);
  shiftOut(dataPin, clockPin, bytesdec[B00000000]);
  shiftOut(dataPin, clockPin, bytesdec[B00000001]);
  digitalWrite(latchPin, 1);

I'm sorry but I really need to understand well this thing and you guys are amazing helpful!

Now if I want try to access single led. I used this code?:

No using shift registers will ALWAYS access all the outputs at once. You have to have a variable that holds all the states of the LEDs. You always shift that out. To change a single LED you do an operation on that variable that just changes a single bit and then shift that out again.
You access single bits by doing bit manipulation of AND & OR operations.
See this page:-
http://www.arduino.cc/playground/Code/BitMath

Can you provide an really basic example like the one I've done (wrong) above?

::slight_smile:

shift1=0;
shift2=0;
  digitalWrite(latchPin, 0);
  shiftOut(dataPin, clockPin, shift2);
  shiftOut(dataPin, clockPin, shift1);
  digitalWrite(latchPin, 1);
//Set bit 3 in shift one
bitSet(shift1,3);
  digitalWrite(latchPin, 0);
  shiftOut(dataPin, clockPin, shift2);
  shiftOut(dataPin, clockPin, shift1);
  digitalWrite(latchPin, 1);

oh, thanks. I check the code on my arduino. I assume (tell me if I'm wrong) that the 2 variables shift1 and shift2 are bytes.
I had to add an argument to the shiftOut also, like this:

  byte shift1=0;
  byte shift2=0;
  digitalWrite(latchPin, 0);
  shiftOut(dataPin, clockPin, MSBFIRST, shift2);
  shiftOut(dataPin, clockPin, MSBFIRST, shift1);
  digitalWrite(latchPin, 1);
  //Set bit 3 in shift one

  bitSet(shift1,3);
  digitalWrite(latchPin, 0);
  shiftOut(dataPin, clockPin, MSBFIRST, shift2);
  shiftOut(dataPin, clockPin, MSBFIRST, shift1);
  digitalWrite(latchPin, 1);

The result on 16 leds are:
ON
ON
ON
ON
OFF
ON
ON
ON
OFF
ON
ON
ON
OFF
ON
ON
ON

Question: With 0 and 0 as shift1 and shift2 variables I was expecting all led off.
I finally understand the bitSet function to change one bit in a byte, very clever, but I still not understand the relation with byte and leds.
I was thinking that B00000001 means first led ON, so provide 2 byte (or 3 or 4, depends of the IC) for each variable it's enough, but now I'm lost.

My mistake!
I find that I was using the shiftOut function from arduino core. Using that one worked!

void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {

  int i=0;
  int pinState;
  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, OUTPUT);
  digitalWrite(myDataPin, 0);
  digitalWrite(myClockPin, 0);
  for (i=7; i>=0; i--) {
    digitalWrite(myClockPin, 0);
    if ( myDataOut & (1<<i) ) {
      pinState= 1;
    } 
    else {
      pinState= 0;
    }
    digitalWrite(myDataPin, pinState);
    digitalWrite(myClockPin, 1);
    digitalWrite(myDataPin, 0);
  }
  digitalWrite(myClockPin, 0);
}

I was thinking that B00000001 means first led ON

It depends on how you have wired it up. If you are using the shift register to sink current a 0 will turn it on, if you are using it to source current a 1 will switch it on.

It sounds like I'm doing kind of what you are doing. I'm only using one 74HC595 at the moment but the design is built for more to be added later. (7-seg leds)

I'm storing all the states in a byte array.

//Shift Register patterns
const byte b_[] = {
  B00000000, B10000000, B01000000, B00100000, B00010000, B00001000, B00000100, B00000010, B00000001};

Then I'm calling a function when I want to change something.

void ChangeLED(byte Data){
  digitalWrite(Latch_pin, LOW);
  shiftOut(Data_pin, Clock_pin, LSBFIRST, Data);
  digitalWrite(Latch_pin, HIGH);

This can be expanded to...

void ChangeLED(byte Data0, byte Data1){
  digitalWrite(Latch_pin, LOW);
  shiftOut(Data_pin, Clock_pin, LSBFIRST, Data1);
  shiftOut(Data_pin, Clock_pin, LSBFIRST, Data0);
  digitalWrite(Latch_pin, HIGH);

Then all you have to do is call the function when you want to change the leds around.

//ChangeLED(byte Data0, byte Data1)
ChangeLED(b_[4], b_[2])

That turns on led 4 on the first register and led 2 on the second one out.

Again this setup is intended for controlling a few 7-Segment leds. If you're using a lot of leds in a lot of different configurations then your array will be huge.

Guys, you save my day!!!
Just a question, why the core shiftOut function doesn't work as the one above? I have tryied with MSBFIRST and LSBFIRST as parameters but results are totally different from the core one.

I can only think it is to do with what edge of the clock the data is transferred on. There is a minimum data set up time and if you change the data too close to the active clock edge you will not get correct operation.

I just post my first complete code in arduino. I'm sure it's horrible and waste memory and resources but I'm really happy that works and helped me to understand many things, thank you guys!

/* basic and horrible code to drive single leds (or relay or whatever) in ON/OFF stile that use 74HC595 shift register ic's. it can handle 64 leds/relays.
*/
// 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;
//how many shift resisters IC's?
int shiftRegisters = 2;
// shift register temp containers
byte shiftIC1 = 0;//8
byte shiftIC2 = 0;//16
byte shiftIC3 = 0;//24
byte shiftIC4 = 0;//32
byte shiftIC5 = 0;//40
byte shiftIC6 = 0;//48
byte shiftIC7 = 0;//56
byte shiftIC8 = 0;//64
// max leds that can be addressed
int maxled = 8*shiftRegisters;
// led status container
int led_channels [] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};



void setup() {
  Serial.begin(9600);
  // reset all shift registers ic's
  shiftRegistersSend();
  for (int i=1;i<=maxled;i++) {//fill and create led status array
    led_channels [i] = 0;
  }
}

void loop() {
  for (int i=1;i<=16;i++){
    ledSwitch(i);
    delay(300);
  }
}

//shift register engine automatically fits the IC's fitted onboard
void shiftRegistersSend(){
  pinMode(latchPin, OUTPUT);
  digitalWrite(latchPin, 0);
  switch (shiftRegisters) {
  case 1:
    break;
  case 2:
    shiftOut(dataPin, clockPin, shiftIC2);
    break;
  case 3:
    shiftOut(dataPin, clockPin, shiftIC3);
    shiftOut(dataPin, clockPin, shiftIC2);
    break;
  case 4:
    shiftOut(dataPin, clockPin, shiftIC4);
    shiftOut(dataPin, clockPin, shiftIC3);
    shiftOut(dataPin, clockPin, shiftIC2);
    break;
  case 5:
    shiftOut(dataPin, clockPin, shiftIC5);
    shiftOut(dataPin, clockPin, shiftIC4);
    shiftOut(dataPin, clockPin, shiftIC3);
    shiftOut(dataPin, clockPin, shiftIC2);
    break;
  case 6:
    shiftOut(dataPin, clockPin, shiftIC6);
    shiftOut(dataPin, clockPin, shiftIC5);
    shiftOut(dataPin, clockPin, shiftIC4);
    shiftOut(dataPin, clockPin, shiftIC3);
    shiftOut(dataPin, clockPin, shiftIC2);
    break;
  case 7:
    shiftOut(dataPin, clockPin, shiftIC7);
    shiftOut(dataPin, clockPin, shiftIC6);
    shiftOut(dataPin, clockPin, shiftIC5);
    shiftOut(dataPin, clockPin, shiftIC4);
    shiftOut(dataPin, clockPin, shiftIC3);
    shiftOut(dataPin, clockPin, shiftIC2);
    break;
  case 8:
    shiftOut(dataPin, clockPin, shiftIC8);
    shiftOut(dataPin, clockPin, shiftIC7);
    shiftOut(dataPin, clockPin, shiftIC6);
    shiftOut(dataPin, clockPin, shiftIC5);
    shiftOut(dataPin, clockPin, shiftIC4);
    shiftOut(dataPin, clockPin, shiftIC3);
    shiftOut(dataPin, clockPin, shiftIC2);
    break;
  }
  shiftOut(dataPin, clockPin, shiftIC1);
  digitalWrite(latchPin, 1);
}

// handle leds and set status
// it just needs the led number
void ledSwitch(int led) {
  if (led == 0){// set all off
    for (int i=1;i<=maxled;i++) {//reset led status container
      led_channels [i] = 0;
    }
    // reset shift register containers
    shiftIC1 = 0;
    shiftIC2 = 0;
    shiftIC3 = 0;
    shiftIC4 = 0;
    shiftIC5 = 0;
    shiftIC6 = 0;
    shiftIC7 = 0;
    shiftIC8 = 0;
    shiftRegistersSend();
  } 
  else {
    if (led <= maxled){
      if (led >=1 && led <= 8) {
        if (led_channels[led] == 0){
          led_channels[led] = 1;
          bitSet(shiftIC1,led);
        } 
        else {
          led_channels[led] = 0;
          bitClear(shiftIC1,led);
        }
      } 
      else if (led >=9 && led <= 16) {
        if (led_channels[led] == 0){
          led_channels[led] = 1;
          bitSet(shiftIC2,led-8);
        } 
        else {
          led_channels[led] = 0;
          bitClear(shiftIC2,led-8);
        }
      } 
      else if (led >=17 && led <= 24) {
        if (led_channels[led] == 0){
          led_channels[led] = 1;
          bitSet(shiftIC3,led-16);
        } 
        else {
          led_channels[led] = 0;
          bitClear(shiftIC3,led-16);
        }
      } 
      else if (led >=25 && led <= 32) {
        if (led_channels[led] == 0){
          led_channels[led] = 1;
          bitSet(shiftIC4,led-24);
        } 
        else {
          led_channels[led] = 0;
          bitClear(shiftIC4,led-24);
        }
      } 
      else if (led >=33 && led <= 40) {
        if (led_channels[led] == 0){
          led_channels[led] = 1;
          bitSet(shiftIC5,led-32);
        } 
        else {
          led_channels[led] = 0;
          bitClear(shiftIC5,led-32);
        }
      } 
      else if (led >=41 && led <= 48) {
        if (led_channels[led] == 0){
          led_channels[led] = 1;
          bitSet(shiftIC6,led-48);
        } 
        else {
          led_channels[led] = 0;
          bitClear(shiftIC6,led-48);
        }
      } 
      else if (led >=49 && led <= 56) {
        if (led_channels[led] == 0){
          led_channels[led] = 1;
          bitSet(shiftIC7,led-56);
        } 
        else {
          led_channels[led] = 0;
          bitClear(shiftIC7,led-56);
        }
      } 
      else if (led >=57 && led <= 64) {
        if (led_channels[led] == 0){
          led_channels[led] = 1;
          bitSet(shiftIC8,led-64);
        } 
        else {
          led_channels[led] = 0;
          bitClear(shiftIC8,led-64);
        }
      }
      shiftRegistersSend();
    }
  }
}

// shiftOut main engine
void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
  int i=0;
  int pinState;
  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, OUTPUT);
  digitalWrite(myDataPin, 0);
  digitalWrite(myClockPin, 0);
  for (i=7; i>=0; i--) {
    digitalWrite(myClockPin, 0);
    if ( myDataOut & (1<<i) ) {
      pinState= 1;
    } 
    else {
      pinState= 0;
    }
    digitalWrite(myDataPin, pinState);
    digitalWrite(myClockPin, 1);
    digitalWrite(myDataPin, 0);
  }
  digitalWrite(myClockPin, 0);
}

Well done :slight_smile:

You stuck to it and put in the effort. Great.

Thanks you guys!
I edited the code because was contain some error.
It's still horrible (if any suggestion will really welcome) but at list is working

Usage: ledSwitch(number of the led);
It will switch on. Calli it again it will bring off

/*
Really easy and horrible but working code for driving leds/relays
with shift register IC 74HC595 that automatically support from 8 to 64 channels (expandable)
Leds are drived by ON/OFF method and it's stored in an array for easy save in internal EEprom
*/

// define how many shift registers IC mounted
#define SR_IC 2 // 2 in this case
// define the led status array to store the led status (on/off)
// and set lenght accordly to the ic's mounted
int led_channels [8*SR_IC];
// max leds that can be addressed
int maxled = 8*SR_IC;
// 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;
// shift register temp containers (support 8 IC's)
byte shiftIC1 = 0;//8
byte shiftIC2 = 0;//16
byte shiftIC3 = 0;//24
byte shiftIC4 = 0;//32
byte shiftIC5 = 0;//40
byte shiftIC6 = 0;//48
byte shiftIC7 = 0;//56
byte shiftIC8 = 0;//64

void setup() {
  Serial.begin(9600);
  // reset all shift registers ic's
  shiftRegistersSend();
  Serial.println(led_channels [0]);
  Serial.println(led_channels [1]);
  Serial.println(led_channels [2]);
  Serial.println(led_channels [3]);
  Serial.println(led_channels [4]);
  Serial.println(led_channels [5]);
  Serial.println(led_channels [6]);
  Serial.println(led_channels [7]);
  Serial.println(led_channels [8]);
}

void loop() {
  for (int i=0;i<15;i++){
    ledSwitch(i);
    delay(10);
  }
  //ledSwitch(0);
}

//shift register engine automatically fits the IC's fitted onboard
void shiftRegistersSend(){
  pinMode(latchPin, OUTPUT);
  digitalWrite(latchPin, 0);
  switch (SR_IC) {
  case 2:
    shiftOut(dataPin, clockPin, shiftIC2);
    break;
  case 3:
    shiftOut(dataPin, clockPin, shiftIC3);
    shiftOut(dataPin, clockPin, shiftIC2);
    break;
  case 4:
    shiftOut(dataPin, clockPin, shiftIC4);
    shiftOut(dataPin, clockPin, shiftIC3);
    shiftOut(dataPin, clockPin, shiftIC2);
    break;
  case 5:
    shiftOut(dataPin, clockPin, shiftIC5);
    shiftOut(dataPin, clockPin, shiftIC4);
    shiftOut(dataPin, clockPin, shiftIC3);
    shiftOut(dataPin, clockPin, shiftIC2);
    break;
  case 6:
    shiftOut(dataPin, clockPin, shiftIC6);
    shiftOut(dataPin, clockPin, shiftIC5);
    shiftOut(dataPin, clockPin, shiftIC4);
    shiftOut(dataPin, clockPin, shiftIC3);
    shiftOut(dataPin, clockPin, shiftIC2);
    break;
  case 7:
    shiftOut(dataPin, clockPin, shiftIC7);
    shiftOut(dataPin, clockPin, shiftIC6);
    shiftOut(dataPin, clockPin, shiftIC5);
    shiftOut(dataPin, clockPin, shiftIC4);
    shiftOut(dataPin, clockPin, shiftIC3);
    shiftOut(dataPin, clockPin, shiftIC2);
    break;
  case 8:
    shiftOut(dataPin, clockPin, shiftIC8);
    shiftOut(dataPin, clockPin, shiftIC7);
    shiftOut(dataPin, clockPin, shiftIC6);
    shiftOut(dataPin, clockPin, shiftIC5);
    shiftOut(dataPin, clockPin, shiftIC4);
    shiftOut(dataPin, clockPin, shiftIC3);
    shiftOut(dataPin, clockPin, shiftIC2);
    break;
  }
  shiftOut(dataPin, clockPin, shiftIC1);
  digitalWrite(latchPin, 1);
}



// handle leds and set status by just needs the led number
void ledSwitch(int led) {
  if (led <= maxled){ //if led out of range do nothing
    if (led >=0 && led <= 7) {
      if (led_channels[led] == 0){
        led_channels[led] = 1;
        bitSet(shiftIC1,led);
      } 
      else {
        led_channels[led] = 0;
        bitClear(shiftIC1,led);
      }
    } 
    else if (led >=8 && led <= 15) {
      if (led_channels[led] == 0){
        led_channels[led] = 1;
        bitSet(shiftIC2,led-8);
        delay(1);
      } 
      else {
        led_channels[led] = 0;
        bitClear(shiftIC2,led-8);
      }
    } 
    else if (led >=16 && led <= 23) {
      if (led_channels[led] == 0){
        led_channels[led] = 1;
        bitSet(shiftIC3,led-16);
      } 
      else {
        led_channels[led] = 0;
        bitClear(shiftIC3,led-16);
      }
    } 
    else if (led >=24 && led <= 31) {
      if (led_channels[led] == 0){
        led_channels[led] = 1;
        bitSet(shiftIC4,led-24);
      } 
      else {
        led_channels[led] = 0;
        bitClear(shiftIC4,led-24);
      }
    } 
    else if (led >=32 && led <= 39) {
      if (led_channels[led] == 0){
        led_channels[led] = 1;
        bitSet(shiftIC5,led-32);
      } 
      else {
        led_channels[led] = 0;
        bitClear(shiftIC5,led-32);
      }
    } 
    else if (led >=40 && led <= 47) {
      if (led_channels[led] == 0){
        led_channels[led] = 1;
        bitSet(shiftIC6,led-48);
      } 
      else {
        led_channels[led] = 0;
        bitClear(shiftIC6,led-48);
      }
    } 
    else if (led >=48 && led <= 55) {
      if (led_channels[led] == 0){
        led_channels[led] = 1;
        bitSet(shiftIC7,led-56);
      } 
      else {
        led_channels[led] = 0;
        bitClear(shiftIC7,led-56);
      }
    } 
    else if (led >=56 && led <= 63) {
      if (led_channels[led] == 0){
        led_channels[led] = 1;
        bitSet(shiftIC8,led-64);
      } 
      else {
        led_channels[led] = 0;
        bitClear(shiftIC8,led-64);
      }
    }
    shiftRegistersSend();
  }
}

// utility function that reset all leds and clear array
void allLedsOff(){
  // reset led status array
  for (int i=0;i<maxled;i++){
    led_channels[1] = 0;
  }
  // reset shift register containers
  shiftIC1 = 0;
  shiftIC2 = 0;
  shiftIC3 = 0;
  shiftIC4 = 0;
  shiftIC5 = 0;
  shiftIC6 = 0;
  shiftIC7 = 0;
  shiftIC8 = 0;
  shiftRegistersSend();
}

// shiftOut main engine
void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
  int i=0;
  int pinState;
  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, OUTPUT);
  digitalWrite(myDataPin, 0);
  digitalWrite(myClockPin, 0);
  for (i=7; i>=0; i--) {
    digitalWrite(myClockPin, 0);
    if (myDataOut & (1<<i)) {
      pinState= 1;
    } 
    else {
      pinState= 0;
    }
    digitalWrite(myDataPin, pinState);
    digitalWrite(myClockPin, 1);
    digitalWrite(myDataPin, 0);
  }
  digitalWrite(myClockPin, 0);
}