ShiftPWM library with press button

Hi, I have a program that is using the ShiftPWM library (http://www.elcojacobs.com/shiftpwm/) and I am have some using press button in my program. When the

ShiftPWM.Start(pwmFrequency,maxBrightness);

is commented, the press button work otherwise, it don't. Is there an incompatibility ? What are the solutions ?

Thanks

William

What are the solutions ?

The problem is probably in the program that you did not post or the hardware that you did not describe but I can't tell, and nor can anyone else.

Here is my code:

const int ShiftPWM_latchPin=9;
const bool ShiftPWM_invertOutputs = true; 
const bool ShiftPWM_balanceLoad = false;
#include <ShiftPWM.h>  
byte red, green, blue;
unsigned char maxBrightness = 255;
unsigned char pwmFrequency = 100;
int numRegisters = 4;
int numRGBleds = 10;
int pin13 = 13;
int led[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,}; // Assign the pins for the leds
int leftChannel = 0;  // left channel input
int left, i, ii, signal;
int nbech = 10;  // nombre d"échantillon de son a moyenner
int w =0;
//unsigned long hex[8] = {0xa336a3, 0x99ff00, 0x6142de, 0xc46ec4,	0xeeff00, 0x00ffdd, 0xffffff, 0xc46ec4};
int R[10] = {0, 0, 0, 0, 0, 255, 255, 255, 255, 255};
int G[10] = {0, 255, 255, 255, 255, 255, 255, 180, 50, 0};
int B[10] = {255, 180, 50, 0, 0, 0, 0, 0, 0, 0};


//new mode
const int sensitivityPin = A2;  // Analog input pin that the potentiometer is attached to
const int audioPin = A0;        // Analog input pin that the audio channel is attached to
const int ledCount = 10;        // The number of LEDs in the bar graph
const int numReadings = 20;     // Number of samples to keep track of (for smoothing)
const int buttonPin = 13;
int counter=0;
int audioValue;                 // Analog value read from audio channel
int maxAudioValue = 0;          // Maximum analog value read from audio channel
int sensitivityValue;           // Analog value read from potentiometer
int ledLevel;                   // Value to map to the output LEDs

int readings[numReadings];      // the readings from the analog input
int index = 0;                  // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average

int ActiveMode;

void setup()
{
  Serial.begin(9600);
  ShiftPWM.SetAmountOfRegisters(numRegisters);
  ShiftPWM.SetPinGrouping(1); 
  
  ShiftPWM.Start(pwmFrequency,maxBrightness);  
  
  for (i = 0; i < 10; i++)  // Tell the arduino that the leds are digital outputs
  pinMode(led[i], OUTPUT);
  
   for (int thisReading = 0; thisReading < numReadings; thisReading++)
    readings[thisReading] = 0; 
}

void loop()
{

  int ledPins[]  = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    //int ledPins[]  = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
  audioValue = analogRead(audioPin);
  if (audioValue > maxAudioValue)
    maxAudioValue = audioValue;  

 // //sensitivityValue = analogRead(sensitivityPin);
 sensitivityValue = 250;
  ledLevel = map(audioValue, 0, 1023, 0, sensitivityValue/2);
  if (ledLevel > ledCount) {
    ledLevel = ledCount;
  }
  
  for (int thisLed = 0; thisLed < ledCount; thisLed++) 
  {
    pinMode(ledPins[thisLed], OUTPUT); 
    if (thisLed < ledLevel){
    //  digitalWrite(ledPins[thisLed], HIGH);
     ShiftPWM.SetRGB(ledPins[thisLed],R[ledPins[thisLed]],G[ledPins[thisLed]],B[ledPins[thisLed]]);
   delay (10);
    }
  

 else{
  ShiftPWM.SetRGB(ledPins[thisLed],0,0,0);
      //ShiftPWM.SetRGB(ledPins[thisLed],0,0,0);
 }
  }
  
  delay(1);        // delay in between reads for stability

}

For my hardware it’s an arduino uno and I am using the TLC5940 shift registrer.

I can't at first sight see where in the code you read a button or switch input.

God ! I’m so distracted, I sent you the code that I’m am using right now. Here is one of the code that I have try with the button. I have try a lot of variation, but I think this is the last one I have test:

const int ShiftPWM_latchPin=9;
const bool ShiftPWM_invertOutputs = true; 
const bool ShiftPWM_balanceLoad = false;
#include <ShiftPWM.h>  
byte red, green, blue;
unsigned char maxBrightness = 255;
unsigned char pwmFrequency = 100;
int numRegisters = 4;
int numRGBleds = 10;
int pin13 = 13;
int led[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,}; // Assign the pins for the leds
int leftChannel = 0;  // left channel input
int left, i, ii, signal;
int nbech = 10;  // nombre d"échantillon de son a moyenner
int w =0;
//unsigned long hex[8] = {0xa336a3, 0x99ff00, 0x6142de, 0xc46ec4,    0xeeff00, 0x00ffdd, 0xffffff, 0xc46ec4};
int R[10] = {0, 0, 0, 0, 0, 255, 255, 255, 255, 255};
int G[10] = {0, 255, 255, 255, 255, 255, 255, 180, 50, 0};
int B[10] = {255, 180, 50, 0, 0, 0, 0, 0, 0, 0};


//new mode
const int sensitivityPin = A2;  // Analog input pin that the potentiometer is attached to
const int audioPin = A0;        // Analog input pin that the audio channel is attached to
const int ledCount = 10;        // The number of LEDs in the bar graph
const int numReadings = 20;     // Number of samples to keep track of (for smoothing)
const int buttonPin = 13;
int counter=0;
int audioValue;                 // Analog value read from audio channel
int maxAudioValue = 0;          // Maximum analog value read from audio channel
int sensitivityValue;           // Analog value read from potentiometer
int ledLevel;                   // Value to map to the output LEDs

int readings[numReadings];      // the readings from the analog input
int index = 0;                  // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average

int inPin = 3;         // the number of the input pin

int state = HIGH;      // the current state of the output pin
int reading;           // the current reading from the input pin
int previous = LOW;    // the previous reading from the input pin

// the follow variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long time = 0;         // the last time the output pin was toggled
long debounce = 200;   // the debounce time, increase if the output flickers





void setup()
{
  Serial.begin(9600);
  ShiftPWM.SetAmountOfRegisters(numRegisters);
  ShiftPWM.SetPinGrouping(1); 
  pinMode(inPin, INPUT);
 // ShiftPWM.Start(pwmFrequency,maxBrightness);  
  
  for (i = 0; i < 10; i++)  // Tell the arduino that the leds are digital outputs
  pinMode(led[i], OUTPUT);
  
   for (int thisReading = 0; thisReading < numReadings; thisReading++)
    readings[thisReading] = 0; 
}

void loop()
{

reading = digitalRead(inPin);

// if the input just went from LOW and HIGH and we've waited long enough
// to ignore any noise on the circuit, toggle the output pin and remember
// the time
if (reading == HIGH && previous == LOW && millis() - time > debounce) {
  Serial.println('HIGH');

  time = millis();    
}


 
  delay(1);        // delay in between reads for stability
  previous = reading;

}

I have base the code directly from the arduino page: http://www.arduino.cc/en/tutorial/switch

int inPin = 3;         // the number of the input pin
  pinMode(inPin, INPUT);
int led[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,}; // Assign the pins for the leds
  for (i = 0; i < 10; i++)  // Tell the arduino that the leds are digital outputs
  pinMode(led[i], OUTPUT);

Do you have an LED or a switch on pin 3 and is it an input or an output ?

I changed the pin of the button to the pin 10. Now, I'm receiving the serial print in kind of a random way. In the last code that I posted, the ShiftPWM line is commented:

 // ShiftPWM.Start(pwmFrequency,maxBrightness);

When it's not the case, I don't receive anything...

Thanks !

If you're using the SPI version of ShiftPWM, it initializes Uno pins 13 and 11 as shift register clock and data outputs. I notice that you've got a button on pin 13... Your code also doesn't seem to actually use ShiftPWM. For that matter, the TLC5940 offers hardware PWM, so I'm not sure why you'd want ShiftPWM in the first place.

Best, Michael

I guess it was from previous testing. I clean up the code a little bit. I realize that by trying to be clear (deleing a unuseful part of the code) , I did the opposite. So Here is the code that I ultimately want to work

#include <ShiftPWM.h>  

const int ShiftPWM_latchPin=9;
const bool ShiftPWM_invertOutputs = true; 
const bool ShiftPWM_balanceLoad = false;
byte red, green, blue;
unsigned char maxBrightness = 255;
unsigned char pwmFrequency = 100;
int numRegisters = 4;
int numRGBleds = 10;

int led[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,}; // Assign the pins for the leds
int leftChannel = 0;  // left channel input
int left, i, ii, signal;
int nbech = 10;  // nombre d"échantillon de son a moyenner
int w =0;

int R[10] = {0, 0, 0, 0, 0, 255, 255, 255, 255, 255};
int G[10] = {0, 255, 255, 255, 255, 255, 255, 180, 50, 0};
int B[10] = {255, 180, 50, 0, 0, 0, 0, 0, 0, 0};


const int sensitivityPin = A2;  // Analog input pin that the potentiometer is attached to
const int audioPin = A0;        // Analog input pin that the audio channel is attached to
const int ledCount = 10;        // The number of LEDs in the bar graph
const int numReadings = 20;     // Number of samples to keep track of (for smoothing)

int counter=0;
int audioValue;                 // Analog value read from audio channel
int maxAudioValue = 0;          // Maximum analog value read from audio channel
int sensitivityValue;           // Analog value read from potentiometer
int ledLevel;                   // Value to map to the output LEDs

int readings[numReadings];      // the readings from the analog input
int index = 0;                  // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average

int ButtonPin = 10;         // the number of the input pin
int ButtonCount = 1;
int state = HIGH;      // the current state of the output pin
int reading;           // the current reading from the input pin
int previous = LOW;    // the previous reading from the input pin
long time = 0;         // the last time the output pin was toggled
long debounce = 200;   // the debounce time, increase if the output flickers


void setup()
{
  Serial.begin(9600);
  ShiftPWM.SetAmountOfRegisters(numRegisters);
  ShiftPWM.SetPinGrouping(1); 
  pinMode(ButtonPin, INPUT);
  ShiftPWM.Start(pwmFrequency,maxBrightness);  
  
  for (i = 0; i < 10; i++)  // Tell the arduino that the leds are digital outputs
  pinMode(led[i], OUTPUT);
  
   for (int thisReading = 0; thisReading < numReadings; thisReading++)
    readings[thisReading] = 0; 
}

void loop()
{

reading = digitalRead(ButtonPin);

if (reading == HIGH && previous == LOW && millis() - time > debounce) {
  Serial.println("HIGH");
  ButtonCount = ButtonCount + 1;
  time = millis();    
}

if(ButtonCount == 1){
    Serial.println("Mode 1"); 
  int ledPins[]  = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  audioValue = analogRead(audioPin);
  if (audioValue > maxAudioValue)
    maxAudioValue = audioValue;  
    
   sensitivityValue = 250;
  ledLevel = map(audioValue, 0, 1023, 0, sensitivityValue/2);
  if (ledLevel > ledCount) {
    ledLevel = ledCount;
  }
  
  for (int thisLed = 0; thisLed < ledCount; thisLed++) 
  {
    pinMode(ledPins[thisLed], OUTPUT); 
    if (thisLed < ledLevel){
     ShiftPWM.SetRGB(ledPins[thisLed],R[ledPins[thisLed]],G[ledPins[thisLed]],B[ledPins[thisLed]]);
   delay (10);
    }
  

 else{
  ShiftPWM.SetRGB(ledPins[thisLed],0,0,0);
 }
  }

  delay(1);        // delay in between reads for stability

}
  
  
  //------ Mode 2 ------//
  if (ButtonCount == 2) {
  Serial.println("Mode 2"); 
  int ledPins[]  = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
   for (int thisLed = 0; thisLed < ledCount; thisLed++)
     pinMode(ledPins[thisLed], OUTPUT);
  audioValue = analogRead(leftChannel); 
  if (audioValue > maxAudioValue)
    maxAudioValue = audioValue;  
    
   sensitivityValue = 250;
  ledLevel = map(audioValue, 0, 1023, 0, sensitivityValue/2);
  if (ledLevel > ledCount) {
    ledLevel = ledCount;
  }
  for (int thisLed = 0; thisLed < ledCount; thisLed++) 
      {
    if (thisLed < ledLevel){
      ShiftPWM.SetRGB(ledPins[thisLed],R[ledPins[thisLed]],G[ledPins[thisLed]],B[ledPins[thisLed]]);
  delay (10);  
  }
    else
      ShiftPWM.SetRGB(ledPins[thisLed],0,0,0);

      delay(1);   
      }
}

 
  delay(1);        // delay in between reads for stability
  previous = reading;

}

The shift registrer are because I need to control multiple RGB leds

Thanks !

Thanks. This is a quick shot in the dark (I'm at work now and can't really dig into it), but your PWM frequency looks awfully high at 100. (I never was able to run anything faster than 75hz & some things not even that fast.) You might try reducing it by half and see what you get. You can also reduce load by lowering maxBrightness. --Michael

I've try cutting in half the the PWM frequency, nothing had change (not event the led control by the shift registrer). What is it supposed to change ?For the maxBrightness, I can't really get it down.

Thanks William

I'm confused. In the examples on http://www.elcojacobs.com/using-shiftpwm-to-control-rgb-leds-with-arduino/ they show only 3 pins being used to drive LEDs. However, in your code, you are also dedicating 10 pins to it. What are you doing?

Assuming you're using it correctly on that front...

Does shiftpwm send anything to the registers when shiftpwm is called?

Could it be power problems? Do the LEDs briefly flash at any point? Disconnect the registers and see if it reproduces - if it runs with the registers disconnected, that points toward an insufficient power supply and/or insufficient filtering on the power.

Add a serial.println() with some text on both sides of that call. See what it's doing. Is it hanging? Continually resetting itself? Do the messages make it through?

As DrAzzy says, there seems to be some confusion about your use of the hardware. You''ve got pin assignments for leds on your arduino. You have another set of assignments for "ledPins" further down in your sketch. These are also initialized as outputs.

You have ShiftPWM sending to shift register pins (out of Uno pin 13 for the shift register's clock, pin 11 for data, and pin 8 for latch, yes?), apparently trying to activate outputs identified by this second set of assignments. If so, you should not set them as outputs. They are values sent to the shift register. They represent outputs of your TLC5940 not your arduino.

And again, if you're not using the PWM capabilities built into the TLC5940 (instead of ShiftPWM), you might as well have bought the much cheaper 74HC595s.

I don't think I can make sense of your code until this is cleared up. Am I missing something?

best, Michael

PS, Changing ShiftPWM maxBrightness from 255 to (say) 200 will lower the load on the arduino (it works hand-in-hand with the pwmFrequency in this respect) and will be a minimally visible difference.

DrAzzy, I’m not so sure to understand what you mean there:

Could it be power problems? Do the LEDs briefly flash at any point? Disconnect the registers and see if it reproduces - if it runs with the registers disconnected, that points toward an insufficient power supply and/or insufficient filtering on the power.

About the 10 pins declare for the output, it might be a mistake. Is was declaring led as output, but they use the shift registrer and not the pins itself. I test it and it work fine without the output assignment.

mjward about the 2 led pins assignment, it was residue from previous code. I clean up again my code, I think I have been able to delete every unusefull line of code.
About the maxBrightness, the projet really need it a full potential, but I’m still gonna try. What lowering the maxBrightness will change ?

#include <ShiftPWM.h>  

const int ShiftPWM_latchPin = 9;
const bool ShiftPWM_invertOutputs = true; 
const bool ShiftPWM_balanceLoad = false;
byte red, green, blue;
unsigned char maxBrightness = 255;
unsigned char pwmFrequency = 100;
const int numRegisters = 4;
const int numRGBleds = 10;


int R[10] = {0, 0, 0, 0, 0, 255, 255, 255, 255, 255};
int G[10] = {0, 255, 255, 255, 255, 255, 255, 180, 50, 0};
int B[10] = {255, 180, 50, 0, 0, 0, 0, 0, 0, 0};

const int leftChannel = 0;  // left channel input
const int sensitivityPin = A2;  // Analog input pin that the potentiometer is attached to
const int audioPin = A0;        // Analog input pin that the audio channel is attached to
const int ledCount = 10;        // The number of LEDs in the bar graph
const int numReadings = 20;     // Number of samples to keep track of (for smoothing)

int counter=0;
int audioValue;                 // Analog value read from audio channel
int maxAudioValue = 0;          // Maximum analog value read from audio channel
int sensitivityValue;           // Analog value read from potentiometer
int ledLevel;                   // Value to map to the output LEDs

int readings[numReadings];      // the readings from the analog input

int ButtonPin = 10;         // the number of the input pin
int ButtonCount = 1;
int state = HIGH;      // the current state of the output pin
int reading;           // the current reading from the input pin
int previous = LOW;    // the previous reading from the input pin
long time = 0;         // the last time the output pin was toggled
long debounce = 200;   // the debounce time, increase if the output flickers


void setup()
{
  Serial.begin(9600);
  ShiftPWM.SetAmountOfRegisters(numRegisters);
  ShiftPWM.SetPinGrouping(1); 
  pinMode(ButtonPin, INPUT);
  ShiftPWM.Start(pwmFrequency,maxBrightness);  
  
   for (int thisReading = 0; thisReading < numReadings; thisReading++)
    readings[thisReading] = 0; 
}

void loop()
{

reading = digitalRead(ButtonPin);

if (reading == HIGH && previous == LOW && millis() - time > debounce) {
  Serial.println("HIGH");
  ButtonCount = ButtonCount + 1;
  time = millis();    
}

if(ButtonCount == 1){
    Serial.println("Mode 1"); 
  int ledPins[]  = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  audioValue = analogRead(audioPin);
  if (audioValue > maxAudioValue)
    maxAudioValue = audioValue;  
    
   sensitivityValue = 250;
  ledLevel = map(audioValue, 0, 1023, 0, sensitivityValue/2);
  if (ledLevel > ledCount) {
    ledLevel = ledCount;
  }
  
  for (int thisLed = 0; thisLed < ledCount; thisLed++) 
  {
  //  pinMode(ledPins[thisLed], OUTPUT); 
    if (thisLed < ledLevel){
     ShiftPWM.SetRGB(ledPins[thisLed],R[ledPins[thisLed]],G[ledPins[thisLed]],B[ledPins[thisLed]]);
   delay (10);
    }
  

 else{
  ShiftPWM.SetRGB(ledPins[thisLed],0,0,0);
 }
  }

  delay(1);        // delay in between reads for stability

}
  
  
  //------ Mode 2 ------//
  if (ButtonCount == 2) {
  Serial.println("Mode 2"); 
  int ledPins[]  = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
 //  for (int thisLed = 0; thisLed < ledCount; thisLed++)
   //  pinMode(ledPins[thisLed], OUTPUT);
  audioValue = analogRead(leftChannel); 
  if (audioValue > maxAudioValue)
    maxAudioValue = audioValue;  
    
   sensitivityValue = 250;
  ledLevel = map(audioValue, 0, 1023, 0, sensitivityValue/2);
  if (ledLevel > ledCount) {
    ledLevel = ledCount;
  }
  for (int thisLed = 0; thisLed < ledCount; thisLed++) 
      {
    if (thisLed < ledLevel){
      ShiftPWM.SetRGB(ledPins[thisLed],R[ledPins[thisLed]],G[ledPins[thisLed]],B[ledPins[thisLed]]);
  delay (10);  
  }
    else
      ShiftPWM.SetRGB(ledPins[thisLed],0,0,0);

      delay(1);   
      }
}

 
  delay(1);        // delay in between reads for stability
  previous = reading;

}

Thanks both of you guys !

If your code is working with your present maxBrightness and pwmFrequency settings, then fine, don't worry about it. ShiftPWM puts a pretty heavy load on the arduino, depending on the refresh frequency, the number of brightness levels the processor is keeping track of, and the number of shift registers you are feeding.

My own project using ShiftPWM fed a chain of 30 8-bit shift registers which drove 240 leds, and for some of my more complicated display routines, the processor would bog down. I found values that worked by trial and error, adjusting pwmFreq and max Brightness. The ShiftPWM library includes a function to measure load at runtime and print to serial, ShiftPWM.PrintInterruptLoad().

As for what lowering maxBrightness, specifically, does, here's how I understand it (I'm pretty new to this myself). With a setting of 255, at whatever pwm frequency, you are setting your shift register's output to a pwm duty cycle of 100% (ie, there is no gap between output pulses to your led). With a setting of 200, the duty cycle is proportionately less (ie, the gaps between output pulses is proportionately greater). I found for my purposes that the difference was all but imperceptible to the naked eye.

--Michael

Thank you for the information ! I test a couple of things according with what your were saying and sadly the button is still not working... Any other idea ?

OK. To confirm regarding your cleaned-up code--if in setup() you comment-out the line "ShiftPWM.Start(pwmFrequency, maxBrightness);" your button does what's expected? (BTW, you don't need the for loop that follows; globally declared arrays are initialized to zero by the compiler.)

I might better be able to help if you'll give a step by step explanation of what your code does (or is meant to do).

Have you tried inserting serial debug statements at each key section of your code to find out where the failure occurs?

--Michael

It appears I misled you a little about maxBrightness. From the ShiftPWM page:

This sets the number of brightness steps. More brightness steps will give a higher load on you program. The maximum you can use is 255, because the brightness for each LED is stored as a byte. The value you choose here means fully on. Choosing a lower value only decreases the number of steps, not the actual brightness.

--Michael