Go Down

Topic: LEDs activated using Shift-Register are less bright (Read 549 times) previous topic - next topic

elemakil

Apr 01, 2013, 06:28 pm Last Edit: Apr 01, 2013, 09:56 pm by elemakil Reason: 1
Hi,

I'm working on a project for a lamp based on RGB LEDs (common cathode). I use ten such RGB LEDs which I power using my Arduino Uno. My setup is based on the project presented here: http://blog.tkjelectronics.dk/2011/08/arduino-rgb-led-controller/

The project linked uses eight LEDs, however, I require ten. Therefore I decided to use a 74HC595 Shift register to activate eight of the ten LEDs. Thus My project contains an Arduino Uno, which is connected to one 74HC595 unit. The eight outputs of the shift register are connected to two ULN2003L darlington ICs (replace the ULN2803 in the project that I linked). Two additional Arduino pins are directly connected to two input nodes of the second ULN2003L unit. This yields ten (active) output nodes from the two ULN2003L units. I replaced the three BC557 transistors in the project I linked by three S9015 transistors (I'm pretty sure they have equivalent specs). The resistors connecting the three PWM pins with the three transistors are 1k resistors. For the LEDs I chose one 130 ohm resistors for Green and Blue (each) and one 68 ohm transistor for red.

When powering up the built, the two LEDs which are activated by the direct lines (i.e. not using the shift register) are quite significantly brighter than the other eight. I find this puzzling because I thought that the line(s) going to the Darlington array serve only as "activators", meaning that it does not matter whether I plug a shift register in between or connect them directly to my 5V digital pins...
From what I understand, the brightness of an LED is influenced by the PWM frequency and the current flowing:

a) PWM frequency: I assumed that the shift-register does not influence the PWM frequency because I assumed that it shifts "fast enough"
b) Current: Due to the setup (check the schematics in the project that I linked) the current flow shouldn't be influenced by any units placed (logically) before the Darlington array as long as the turn on voltage of the Darlington array is matched.

Are any of my assumptions plain wrong? I'd be really glad if you could help me understand why those eight LEDs are less bright... Thanks!

Edit: The code I'm running on the Arduino:

Code: [Select]

/*
* RAINBOW LAMP
*/

// = = = = = = = = = =
// Define constants
// = = = = = = = = = =

// number of LEDs (total)
const int numLEDs = 10;

// pins for accessing the RGB components of the RGB LEDs
const int redPin = 9;
const int greenPin = 10;
const int bluePin = 11;

// The 74HC595 can address only 8 outputs -> need two additional arduino pins to address all ten LEDs
const int numSoloLEDs = 2;
// number of such solo LEDs
const int soloLEDPins[] = { 5, 6 };

// pin connected to ST_CP of 74HC595
const int latchPin = 4;
// pin connected to SH_CP of 74HC595
const int clockPin = 2;
// pin connected to DS of 74HC595
const int dataPin = 3;

// this function generates a rainbow
// it requires the current rgb values as input and the current stage
// it modifies the curren rgb values
void rainbowStep( int & red, int & green, int & blue, int & stage, int stepSize = 1 ){
  switch( stage ) {
    case 0: {
      red = 255;
      blue = 0;
      if ( green <= 255 - stepSize ){
        green += stepSize;
        break;
      }
      else {
        green = 255;
        stage = 1;
        break;
      }
    }
    case 1: {
      blue = 0;
      green = 255;
      if ( red > stepSize ){
        red -= stepSize;
        break;
      }
      else {
        red = 0;
        stage = 2;
        break;
      }
    }
    case 2: {
      red = 0;
      green = 255;
      if ( blue <= 255 - stepSize ){
        blue += stepSize;
        break;
      }
      else {
        blue = 255;
        stage = 3;
        break;
      }
    }
    case 3: {
      red = 0;
      blue = 255;
      if ( green > stepSize ){
        green -= stepSize;
        break;
      }
      else {
        green = 0;
        stage = 4;
        break;
      }
    }
    case 4: {
      blue = 255;
      green = 0;
      if ( red <= 255 - stepSize ){
        red += stepSize;
        break;
      }
      else {
        red = 255;
        stage = 5;
        break;
      }
    }
    case 5: {
      red = 255;
      green = 0;
      if ( blue > stepSize ){
        blue -= stepSize;
        break;
      }
      else {
        blue = 0;
        stage = 0;
        break;
      }
    }
    default: {
      red = 255;
      green = 0;
      blue = 0;
      stage = 0;
      break;
    }
  }
}
 

// the colours
int rollingRed = 255;
int rollingGreen = 0;
int rollingBlue = 0;
int rollingStage = 0;

unsigned char Prescaler = 0;
#define PrescalerOverflowValue 5
ISR(TIMER2_OVF_vect)
{
   if (Prescaler < PrescalerOverflowValue)
     Prescaler++;
   else {
     Prescaler = 0;
    sendRGBCode( rollingRed, rollingGreen, rollingBlue );
        rainbowStep( rollingRed, rollingGreen, rollingBlue, rollingStage, 1 );
   }
}

void setup(){
  // = = = = = = = = = =
  // set pin modes
  // = = = = = = = = = =
 
  // shift register pins
  pinMode( latchPin, OUTPUT );
  pinMode( clockPin, OUTPUT );
  pinMode( dataPin, OUTPUT );
 
  // solo LED pins
  for ( int i=0; i<numSoloLEDs; ++i ){
    pinMode( soloLEDPins[ i ], OUTPUT );
  }

  // colour pins
  pinMode( redPin, OUTPUT );
  pinMode( greenPin, OUTPUT );
  pinMode( bluePin, OUTPUT );
 
    // Enable Timer 2 interrupt (also used for PWM though)
   // This interrupt is divided by a prescaler, and takes care of the multiplexing
   TIMSK2 = 1<<TOIE2;

    sendRGBCode( rollingRed, rollingGreen, rollingBlue );
  for ( int i=0; i<numLEDs; ++i ){
    setLEDState( i, 1 );
  } 
}

void loop(){
    for ( int i=0; i<numLEDs; ++i ){
    setLEDState( i, 1 );
  } 
}

// this function sets the state of a certain LED
// the LED number here goes from zero to numLEDs, furthermore the pins addressed by the shift register occupy the front space
// i.e. LEDs [ 0 : numLEDs - numSoloLEDs - 1 ] are addressed by the shift-reg and LEDs [ numLEDs - numSoloLEDs, numSoloLEDs - 1 ] are solo LEDs
void setLEDState( int ledNo, int state ){
  if ( ledNo < numLEDs - numSoloLEDs ){
    registerWrite( ledNo, state );
  }
  else {
    digitalWrite( soloLEDPins[ ledNo - ( numLEDs - numSoloLEDs ) ], state );
  }
}

// this function sets the RGB pins to the values as specified
void sendRGBCode( int red, int green, int blue ){
  analogWrite( redPin, 255 - red );
  analogWrite( greenPin, 255 - green );
  analogWrite( bluePin, 255 - blue );
}

// this function sends the state "state" to the pin "pinNo" of the shift register
void registerWrite( int pinNo, int state ){
  // the bits you want to send
  byte bitsToSend = 0;

  // turn off the output so the pins don't light up
  // while you're shifting bits:
  digitalWrite( latchPin, LOW );

  // turn on the next highest bit in bitsToSend:
  bitWrite( bitsToSend, pinNo, state );

  // shift the bits out:
  shiftOut( dataPin, clockPin, MSBFIRST, bitsToSend );

  // turn on the output so the LEDs can light up:
  digitalWrite( latchPin, HIGH );
}

// this function switches all LEDs off
void goDark(){
    // solo LED pins
  for ( int i=0; i<numSoloLEDs; ++i ){
    digitalWrite( soloLEDPins[ i ], LOW );
  }
  // shift-reg LEDs
  for ( int i=0; i<numLEDs-numSoloLEDs; ++i ){
    registerWrite( i, 0 );
  }
}

fungus

What resistors are you using to limit the LED current?
No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

elemakil

As I wrote in my initial post, 68 ohm for the red LED contact and 130 ohm for green and blue (one resistor for each).

DVDdoug

Quote
a) PWM frequency: I assumed that the shift-register does not influence the PWM frequency because I assumed that it shifts "fast enough"
I'm just guessing, but I suspect this is your problem...  How fast are you clocking the shift register?   I dont think that's commonly done...  I haven't seen PWM used with a shift register unless there is a master PWM brightness level that affects all of the LEDs together.

You might have to synchronize the PWM with your shift register clock so that you can completely & accurately control (with software) the percentage of time each LED is on.   But again, I'm just guessing and I haven't really thought-through how that would work.

elemakil

#4
Apr 01, 2013, 08:44 pm Last Edit: Apr 01, 2013, 09:57 pm by elemakil Reason: 1
I'm using the registerWrite function as defined in this code snippet: http://arduino.cc/en/Tutorial/ShftOut12

How can I change the clock frequency of the shift register?

Edit: Added the code running on the Arduino (first post).

Go Up