Running LEDs using Shift Register with fade out.

Dear friends, I need some help on running LEDs using 74HC595. Yes, I did it but I would like to make it fade out. Any idea?

int SHCP_pin = 12;
int STCP_pin = 8;
int DS_pin = 11;

void setup()
{
  pinMode(DS_pin, OUTPUT);
  pinMode(STCP_pin, OUTPUT);
  pinMode(SHCP_pin, OUTPUT);
  writereg();  
}

boolean registers[32];

void writereg()
{
  digitalWrite (STCP_pin,LOW);
  for (int i=31;i>=0;i--)
  {
    digitalWrite (SHCP_pin, LOW);
    digitalWrite (DS_pin, registers[i]);
    digitalWrite (SHCP_pin, HIGH);
  }
  digitalWrite (STCP_pin, HIGH);
}
  
void loop()
{
  for (int i=0;i<32;i++) 
 {
    registers[i]= HIGH; 
    delay (50);
    writereg();
  }    
}

Please edit your post to use [code ] tags.

But what is the purpose of the program? At the moment you just turn on all led's or none...

But to help, you need to multiplex the outputs. You have to create code to PWM every output (so write the coresponding bit of the register to be 1 just for a % of time. 8bit is a bit hard to do but you can try to make 4-bit (16 levels) of PWM. And to make it consistant I would use a timer interrupt to update the registers.

And you can use shiftOut to do the job for you :wink:

I did a fake PWM once which might help in your case...

void noop() {}

/*
Percentage of HIGH time
Frequency of modulation in hertz
Relay pin configured as output
*/
void fakePWM(int percentage, int frequency, const int relayPin) {
  const unsigned long maxScale = (1000000 / frequency);
  unsigned long delayTime;
  unsigned long delayTimeMillis;
  
  digitalWrite(relayPin, LOW);
  delayTime = map(100 - percentage, 0, 100, 0, maxScale);
  delayTimeMillis = delayTime / 1000;
  delay(delayTimeMillis);
  delayTime - (delayTimeMillis * 1000) > 2 ? 
    delayMicroseconds(delayTime - (delayTimeMillis * 1000)) : noop();
  
  digitalWrite(relayPin, HIGH);
  delayTime = map(percentage, 0, 100, 0, maxScale);
  delayTimeMillis = delayTime / 1000;
  delay(delayTimeMillis);
  delayTime - (delayTimeMillis * 1000) > 2 ?
    delayMicroseconds(delayTime - (delayTimeMillis * 1000)) : noop();
  
}

It awefully confusing even for me, but I remembered it worked with leds.
I ended up not using it as I wanted to use it on a relay which was too slow to switch on higher frequencies

Yeay, I can tell you, you're not going to get anything useful when you use the delay() function to software PWM with shift registers... It will just hang the microcontroller.

To dim in 16 levels with a refresh rate of about 100Hz you need a interrupt frequency of around 16 x 100 = 1600Hz. Or a variable interrupt time with 4 values (1/1600s, 2/1600s, 4/1600s and 8/1600s)

septillion:
Please edit your post to use [code ] tags.

But what is the purpose of the program? At the moment you just turn on all led's or none...

But to help, you need to multiplex the outputs. You have to create code to PWM every output (so write the coresponding bit of the register to be 1 just for a % of time. 8bit is a bit hard to do but you can try to make 4-bit (16 levels) of PWM. And to make it consistant I would use a timer interrupt to update the registers.

And you can use shiftOut to do the job for you :wink:

Hi septillion. The purpose of the program is to make running LEDs. Yes, I did turn ON all the LEDs, from i=0 until i=32 with using 4*74HC595. But then, I would like to make it fade out from i=0 until i=32 after all LEDs turn ON completed after a few sec.

any idea?

evil-noxx:
I did a fake PWM once which might help in your case...

void noop() {}

/*
Percentage of HIGH time
Frequency of modulation in hertz
Relay pin configured as output
*/
void fakePWM(int percentage, int frequency, const int relayPin) {
 const unsigned long maxScale = (1000000 / frequency);
 unsigned long delayTime;
 unsigned long delayTimeMillis;
 
 digitalWrite(relayPin, LOW);
 delayTime = map(100 - percentage, 0, 100, 0, maxScale);
 delayTimeMillis = delayTime / 1000;
 delay(delayTimeMillis);
 delayTime - (delayTimeMillis * 1000) > 2 ?
   delayMicroseconds(delayTime - (delayTimeMillis * 1000)) : noop();
 
 digitalWrite(relayPin, HIGH);
 delayTime = map(percentage, 0, 100, 0, maxScale);
 delayTimeMillis = delayTime / 1000;
 delay(delayTimeMillis);
 delayTime - (delayTimeMillis * 1000) > 2 ?
   delayMicroseconds(delayTime - (delayTimeMillis * 1000)) : noop();
 
}




It awefully confusing even for me, but I remembered it worked with leds.
I ended up not using it as I wanted to use it on a relay which was too slow to switch on higher frequencies

Hi evil-noxx, thank for your reply. Its look complicated to me....any simplest way? i using 4 shift registers 74HC595 :slight_smile:

Ahhh, you don't try to fade the leds (dimming them) but to first turn on one, then two, three, four etc?

So people are sayingthat you don't really dim LEDs but turn them on rapdily then off, and the eye feels it is dimmer.

You could try to PWM your LEDs by using a simple C loop:

void dim(int on, const int pin) {
  for (int i = 0; i < 1024; i++) {
    if (i < on) {
      digitalWrite(pin, HIGH);
    } else {
      digitalWrite(pin, LOW);
    }
  }
}

I call the same digitalWrite() routine in both cases every time to keep timings consistent.
passing 512 should make the LED 1/2 as bright...

Without the shift that would work to dim a led. But after his last post I don't think he wants to do that, just make them run.

And although it will work if you don't do a lot of stuff on you're arduino it's far from consistent...

septillion:
Without the shift that would work to dim a led. But after his last post I don't think he wants to do that, just make them run.

And although it will work if you don't do a lot of stuff on you're arduino it's far from consistent...

Hi septilion. The reason why i using the shift register is to expand the nos. of LEDs, to make it running. Yes i did it. The next stage is, I want to make it slowly dim out after running LEDs completed from i=0 until i=40.

Did you try my little suggestion?
You'd call it in a loop until your on value is too low to be seen.

If that's too slow and flickers you could use the following, adjustin the max value of j:

void dim(int on, const int pin) {
  volatile int i;
  digitalWrite(pin, HIGH);
  for(int j=0; j < 500; j++)
    for (i = 0; i < on; i++);
  digitalWrite(pin, LOW);
  for(int j=0; j < 500; j++)
    for (i = on; i < 1024; i++);
  }
}

sonyhome:
So people are sayingthat you don't really dim LEDs but turn them on rapdily then off, and the eye feels it is dimmer.

You could try to PWM your LEDs by using a simple C loop:

void dim(int on, const int pin) {

for (int i = 0; i < 1024; i++) {
   if (i < on) {
     digitalWrite(pin, HIGH);
   } else {
     digitalWrite(pin, LOW);
   }
 }
}





I call the same digitalWrite() routine in both cases every time to keep timings consistent.
passing 512 should make the LED 1/2 as bright...

sonyhome:
So people are sayingthat you don't really dim LEDs but turn them on rapdily then off, and the eye feels it is dimmer.

You could try to PWM your LEDs by using a simple C loop:

void dim(int on, const int pin) {

for (int i = 0; i < 1024; i++) {
   if (i < on) {
     digitalWrite(pin, HIGH);
   } else {
     digitalWrite(pin, LOW);
   }
 }
}




I call the same digitalWrite() routine in both cases every time to keep timings consistent.
passing 512 should make the LED 1/2 as bright...

Hi sonyhome, thanks for your reply. I tried to compile your code with mine.
is it something like this?

int SHCP_pin = 12;
int STCP_pin = 8;
int DS_pin = 11;
int on;

void setup()
{
  pinMode(DS_pin, OUTPUT);
  pinMode(STCP_pin, OUTPUT);
  pinMode(SHCP_pin, OUTPUT);
  writereg();  
}

boolean registers[32];

void writereg()
{
  digitalWrite (STCP_pin,LOW);
  for (int i=31;i>=0;i--)
  {
    digitalWrite (SHCP_pin, LOW);
    digitalWrite (DS_pin, registers[i]);
    digitalWrite (SHCP_pin, HIGH);
  }
  digitalWrite (STCP_pin, HIGH);
}
  
void loop()
{
  for (int i=0;i<32;i++)
 {
    registers[i]= HIGH;
    delay (50);
    writereg();
    dim();
  }    
}

void dim() {
  for (int i = 0; i < 1024; i++) {
    if (i < on) {
      digitalWrite(registers[i], HIGH);
    } else {
      digitalWrite(registers[i], LOW);
    }
  }
}

need help.

lol! :smiley:

Nice try: "on" is a parameter of the function.

for (int brightness=1023; brightness--; brightness >0) {
  dim(brightness, SHCP_pin);
}
delay(1000);

sonyhome:
lol! :smiley:

Nice try: "on" is a parameter of the function.

for (int brightness=1023; brightness--; brightness >0) {

dim(brightness, SHCP_pin);
}
delay(1000);

I am beginner. ;D

int SHCP_pin = 12;
int STCP_pin = 8;
int DS_pin = 11;


void setup()
{
  pinMode(DS_pin, OUTPUT);
  pinMode(STCP_pin, OUTPUT);
  pinMode(SHCP_pin, OUTPUT);
  writereg();  
}

boolean registers[32];

void writereg()
{
  digitalWrite (STCP_pin,LOW);
  for (int i=31;i>=0;i--)
  {
    digitalWrite (SHCP_pin, LOW);
    digitalWrite (DS_pin, registers[i]);
    digitalWrite (SHCP_pin, HIGH);
  }
  digitalWrite (STCP_pin, HIGH);
}
  
void loop()
{
  for (int i=0;i<32;i++){
    registers[i]= HIGH;
    delay (50);
    writereg(); 
  }
   for (int brightness=1023; brightness--; brightness >0) {
    dim(brightness, SHCP_pin);
    delay(100);
  }
}

I still don't get it. :disappointed_relieved:

You also need to add the definition of dim, see message #11, and solve all the compilation errors.

Does that compile?!

If it did compile, replace the function name "dim" by "myDimmer".

Are you familiar with the ShiftPWM library? It lets you do that and more:
www.elcojacobs.com/shiftpwm/
--Michael

Edit: Apologies. It appears Elco's code is missing from both Google Code and Github. Fortunately, the estimable PJRC offers a download:

https://www.pjrc.com/teensy/td_libs_ShiftPWM.html/

Some problemw ith adding another URL to my post edit. Here's the PJRC/shiftPWM URL:
https://www.pjrc.com/teensy/td_libs_ShiftPWM.html

mjward:
Are you familiar with the ShiftPWM library? It lets you do that and more:
www.elcojacobs.com/shiftpwm/
--Michael

Edit: Apologies. It appears Elco's code is missing from both Google Code and Github. Fortunately, the estimable PJRC offers a download:

https://www.pjrc.com/teensy/td_libs_ShiftPWM.html/

Hi mjward, thanks for your reply. Just go through your link given. There are no pattern as I wanted on the youtube video. I just seen the ShiftPWM libs, it take some times for me to understand as I am beginner in Arduino.

sonyhome:
You also need to add the definition of dim, see message #11, and solve all the compilation errors.

Does that compile?!

If it did compile, replace the function name "dim" by "myDimmer".

I have modify and run on my arduino. There are no errors. Result: LEDs running but not fading out after all LEDs ON. any mistake on my coding?
Thanks for your help.

[i]int SHCP_pin = 12;
int STCP_pin = 8;
int DS_pin = 11;

void setup() 
{
  pinMode(DS_pin, OUTPUT);
  pinMode(STCP_pin, OUTPUT);
  pinMode(SHCP_pin, OUTPUT);
  writereg();  
}

boolean registers[32];

void writereg()
{
  digitalWrite (STCP_pin,LOW);
  for (int i=31;i>=0;i--)
  {
    digitalWrite (SHCP_pin, LOW);
    digitalWrite (DS_pin, registers[i]);
    digitalWrite (SHCP_pin, HIGH);
  }
  digitalWrite (STCP_pin, HIGH);
}
  
void loop()
{
  for (int i=0;i<32;i++){
    registers[i]= HIGH;
    delay (50);
    writereg();
  }
   for (int brightness=1023; brightness--; brightness >0) {
    myDimmer(brightness, SHCP_pin);
    delay(100);
  }
}

void myDimmer(int on, const int SHCP_pin) {
  for (int i = 0; i < 1024; i++) {
    if (i < on) {
      digitalWrite(SHCP_pin, HIGH);
    } else {
      digitalWrite(SHCP_pin, LOW);
    }
  }
}[/i]

for (int brightness=1023; brightness--; brightness >0)

change to:

for (int brightness=1023; brightness != 0; brightness--)

Remember, every word you write means something with a definite semantic.
The compiler understands only one way what you write.

Even though what you wrote was boggus I would have expected it to work.

Also:

I don't know what the pins you're using do so when I wrote:

digitalWrite(SHCP_pin, HIGH);

It could be that you need to write:

digitalWrite(DS_pin, HIGH);

Sorry I can't spend much time on this. You gotta understand what your progam is doing.
The loop I gave you tells you how to fake PWM somehow, you need to tell the LEDs to
turn on and off in it by calling the right function with the right parameters.