basic shiftpwm/shiftout questions /standard leds

Hi everyone,

after fiddeling with the TLC5940 a bit I had to try the 74HC595, because it uses just one timer and leaving the other timer to drive a servo. But frankly I have no real clue of what I am doing here.
What I want to achive is this very simple (but not to me) thing: I want to control a bunch of standard leds, lets say 25 all together. But I need to start with something more simple to test out everything. So I have this setup with an Arduino, 74HC595 and Leds on the first 5 outputs. Taking the basic shiftpwm example … what do I need to do, to fade on all Leds on pins 1-3 at the same time and have the Leds on Pins 4 and 5 do something else (lets say just fade on and stay on, while the other leds keep blinking).
I have tried using code from my TLC experiments to put ledPins in a group and apply a fade to the whole group at once, but it seems this won´t work with shift registers.

const int ShiftPWM_latchPin=8;

const int ShiftPWM_dataPin = 11;
const int ShiftPWM_clockPin = 12;

// If your LED's turn on if the pin is low, set this to true, otherwise set it to false.
const bool ShiftPWM_invertOutputs = false; 

// You can enable the option below to shift the PWM phase of each shift register by 8 compared to the previous.
// This will slightly increase the interrupt load, but will prevent all PWM signals from becoming high at the same time.
// This will be a bit easier on your power supply, because the current peaks are distributed.
const bool ShiftPWM_balanceLoad = false;

#include <ShiftPWM.h>   // include ShiftPWM.h after setting the pins!

unsigned char maxBrightness = 100;
unsigned char pwmFrequency = 75;
int numRegisters = 1;
int numRGBleds = numRegisters*8/3;
int ledPins[] = {0,1,2};
int pinCount = sizeof(ledPins)/sizeof(int);

void setup(){

  // Sets the number of 8-bit registers that are used.

  // SetPinGrouping allows flexibility in LED setup. 
  // If your LED's are connected like this: RRRRGGGGBBBBRRRRGGGGBBBB, use SetPinGrouping(4).
  //ShiftPWM.SetPinGrouping(3); //This is the default, but I added here to demonstrate how to use the funtion

void loop()
  // Turn all LED's off.
  //ShiftPWM.SetOne(0, 255);
  // For every led
  for (int thisPin = 0; thisPin < pinCount; thisPin++) {
    // Fade in
    for(unsigned char brightness = 0; brightness < 255; brightness++){
      ShiftPWM.SetOne(ledPins[thisPin], brightness);
    // Fade out
    //for(unsigned char brightness = 255; brightness > 0; brightness--){
    //  ShiftPWM.SetOne(pin, brightness);
    //  delayMicroseconds(2000);
   // }


Have a look at shiftOut() in the Arduino reference. You will see how a byte can be sent to a shift register to cause an LED connected to the output pins to be turned on or off. To achieve what you want to do you need to set the individual bits of the byte to be sent to the shift register before it is shifted out causing the LEDs to turn on/off.

Once you have got that principle working you can move on to fading the LEDs. A bit in a byte can only be on or off, of course, as can an LED, but if you turn a bit on/off for a varying length of time you get the appearance of the corresponding LED fading up/down.

The bitSet() function allows you to set a bit of a byte on or off so to fade an LED connected to bit 0 of the shift register you would do something like this pseudocode

set timeA to 1
set timeB to 255

start of loop
  set dataByte to B00000001;  //bit 0 turned on
  send dataByte to the shift register  //the LED will come on
  wait for timeA
  set dataByte to B00000000;  //bit 0 turned off
  send dataByte to the shift register  //the LED will turn off
  wait for timeB
  increment timeA
  decrement timeB
go back round the loop

As timeA gets longer and timeB gets shorter the LED will be on longer and off less so will fade up. Obviously you need to check when it reaches the lower/upper limits and stop incrementing. In practice you would control the bit by setting/clearing it individually rather than setting the the whole byte and would use only one time variable but this way you can see what is going on very easily.

So, how do you deal with more than one bit and more than one LED ? The first thing to do is to understand the BlinkWithoutDelay example which shows how to wait without using delay() Now, instead of 'wait for timeX' in the code you substitute 'is it time to change the state of the LED'. If so, you do it, if not keep going round the loop until the time is up. Now you can add more checks in the loop to see whether any other bits of the byte need to be changed and, if so, change just that bit and output the byte once at the start or end of the loop.

Thanks for the advice. I will go through the reference again. But somehow I start to believe that this stuff is way above me. In terms of time and everything. I wanted to achive an adjustable, remote controllable (at least this works somewhat easy by adapting the ShiftPWM example and using cases along with a BT Mate Silver) led switcher/blinker for model lighting purposes. Besides trying hard to learn Arduino I had to learn some electronics stuff to build the circuits I need. That worked out quite well. But this Arduino programming seems to be too demanding for me to learn inbetween a job, a hobby and a life. I will keep trying for a couple of days ...

Start simple and build on it. That is why I presented my suggestion in the way I did. There are neater, no doubt better ways to fade an LED using a shift register, but you need something that works first then you can think about making it more efficient.

Sometimes the more experienced members of the forum will suggest how they would do something rather than a more laboured but understandable way, perhaps with several steps where one would do, which is easier to understand. This comes from a natural desire to have things done the right way when to begin with what people want is for code to work even if it is not efficient.

Good luck with your project.