LEDs flicker when switches are pressed

Status
Not open for further replies.

AdmiralCrunch

Well-known member
Hi guys,

I have 8x RGB-LEDs connected to 3x 74HC595 and I use the ShiftPWM-Libary.
I have also 8x tactile-switches which are polled through a CD4051..

everything seems to work fine.. except when I press one of the switches, all LEDs flicker short... take a look: https://youtu.be/eQFKnv90_SM


in a other thread, Paul suggested that the most common reason for flickering are thin-cables, poor-breadboard, etc.?
could it also be in my case? or could this be a other problem? .. I have read somewhere, that generally one should connect a 10nF capacitor to every voltage input of a IC.. can someone confirm that?
 
Please upload a schematic for your design so we can know what could cause the problem.
And yes, you should put a decoupling capacitor with 100~10nF On every IC.
Do you use any sort of switch debounce?
 
Please upload a schematic for your design so we can know what could cause the problem.
And yes, you should put a decoupling capacitor with 100~10nF On every IC.
Do you use any sort of switch debounce?

Hi

oh ok, I will make and upload a shematic..

I use the bounce-lib for switches .. but no capacitors.

For decoupling, should I put a 100nF capacitor only to the Vin-pins of a IC? or really to EVERY pin that is connected to voltage? (on the 74HC595 the VCC would have a decoupling capacitor, but the SRCLR-pin (pin10) is also connected to voltage.. should there be a decoupling capacitor, too?)
 
Hi

oh ok, I will make and upload a shematic..

I use the bounce-lib for switches .. but no capacitors.

For decoupling, should I put a 100nF capacitor only to the Vin-pins of a IC? or really to EVERY pin that is connected to voltage? (on the 74HC595 the VCC would have a decoupling capacitor, but the SRCLR-pin (pin10) is also connected to voltage.. should there be a decoupling capacitor, too?)

The decoupling capacitor should only be connected between VCC and GND, close to these pins physically.
A way to confirm that the switches are signed correctly would be to send a serial message to the PC every time they are pressed. If you see multiple messages for one press, then the problem can be in the debounce.
 
The decoupling capacitor should only be connected between VCC and GND, close to these pins physically..
so do you mean:

like this? https://raw.githubusercontent.com/MiguelPynto/ShiftDisplay/master/extras/input.png



A way to confirm that the switches are signed correctly would be to send a serial message to the PC every time they are pressed. If you see multiple messages for one press, then the problem can be in the debounce.
aaah.. okay, I have tested it before I have implemented the bounce-libary and in fact there was this behaviour before, but after implementing the Bounce-lib, every press is also considered as one.
anyway.. how would I debounce a switch with a capacitor?
 
so do you mean:

like this? https://raw.githubusercontent.com/MiguelPynto/ShiftDisplay/master/extras/input.png




aaah.. okay, I have tested it before I have implemented the bounce-libary and in fact there was this behaviour before, but after implementing the Bounce-lib, every press is also considered as one.
anyway.. how would I debounce a switch with a capacitor?


- Yes, this is the way you want to connect it - and as I said put the capacitor as close as possible to the pins.
- If there is no problem with the debouce then you don't have to change it from software to hardware (i.e. electrical components instead of code).
- The common way a switch is debounced is by adding a low pass R/C filter before the digital input. This article covers this nicely. Scroll down to find circuits for both active-high and active-low switches.

A full schematic (and code would be nice to have too) will make it easier to find the source of this issue.
 
Decoupling matters the most for chips that have widly varying loads, so noise from within the chip does not propogate as varying VCC to other ICs, and as free bonus stabilizes the supply to the IC. So normally priority is MCUs/logic chips, anything driving power and less critically low current logic ICs. In your case the question here, is this flickering electrical in nature caused by signals from the buttons interfering with the output to the LEDs, or is it actually within your code, where inputs are blocking updates to the LEDs.

A look at the code would be helpful, as would doing some tests doing things like running with the keys connected but the code to read the commented out.

Edit, checking the library, you are running code that pretty much bit bangs PWM output the hard way, see the info with ShiftPWM.PrintInterruptLoad() on the library page. So most likely guess here is that you have something that blocks the interupts that are running the PWM process and you are going to need to work out a different way to code things to reduce interrupt interference or find a LED drive solution that does not demand the CPU do all the heavy lifting.
 
Last edited:
Hi,

so now I have decoupled my shiftRegisters with 100nF.
does really EVERY IC need to be decoupled? I have done this with the 74HC4051, too, but then some wierd behaviour sometimes occur. I have removed the decoupling here and everything works normal again... oO

also I have made a shematic.. you can see it here: https://circuits.io/circuits/5878737-leds-flicker-once-when-pushbutton-are-pressed

In the datasheet for the 74HC4051 it says that 10nF is the recommended value.
What is the value of R25? from what I see it is a pull-up resistor but you don't want it to be too small.
In this schematic the 8 switches are connected to ground from both sides, so how do they change the state of the digital input?
What is the purpose of the 220Ω resistors near the switches?
And more importantly, what do you want the switches to control on? the schematic is hard to understand, when you draw schematics that will be viewed by other people be sure to make a VCC rail at the top of the circuit and GND at the bottom, make spacing between the lines and organize them.
But maybe the problem is in the code? please post it so we can eliminate the option of a problematic code and focus on the circuit itself, (or eliminate the option of a problematic circuit)
 
Thiscould easily be some hardware issues as mentioned.

But I also wonder if maybe it might be some software issue? Example if the code that is outputting the data is timing specific and the code reading the switches is looping inside it, not allowing the main code to output properly to the leds... But again hard to say much as there is no code to look at.
 
What is the value of R25? from what I see it is a pull-up resistor but you don't want it to be too small.
it is 220Ohm, just like on the other switches

In this schematic the 8 switches are connected to ground from both sides, so how do they change the state of the digital input?
no, the one side is connected to the 4051 and to the 220Ohm Resistor, the other to 5V. (sorry I know the shematic is a disgrace)

What is the purpose of the 220Ω resistors near the switches?
I have read that this has to be.. I am a complete noob at this, please correct me if those resistors shouldn't be there

And more importantly, what do you want the switches to control on?
I try to build a custom midi-controller.. so there are those 8 switches, and this one switch, which is the "shift-button".. in the end the 8 switches will control midi-messages and with shift + one of the switches pressed, should get me a menu where I can adjust midi-messages to the button pressed.

the schematic is hard to understand, when you draw schematics that will be viewed by other people be sure to make a VCC rail at the top of the circuit and GND at the bottom, make spacing between the lines and organize them.
But maybe the problem is in the code? please post it so we can eliminate the option of a problematic code and focus on the circuit itself, (or eliminate the option of a problematic circuit)
yes I know, I am sorry for this.. circiuts.io does not allow to color the connection-lanes.. maybe you could suggest a good tool for shematics?


as for the code.. it is a little big.. I don't know if it is not too much.. I post it anyway.. if I should shorten it, just say..
I should also mention, that I am at the very beginning of all this, so at some points I wrote notices like "send midi" but the function itself is not written yet..at other points there are functions that are not in use, yet..

so here it is..

this is my main sketch.ino

Code:
  #include <Bounce.h>  
  #include <cfg.h>  

  cfg cfg;
  
  const int ShiftPWM_latchPin = 8;
  #define SHIFTPWM_NOSPI
  const int ShiftPWM_dataPin = 11;
  const int ShiftPWM_clockPin = 13;
  const bool ShiftPWM_invertOutputs = false; 
  const bool ShiftPWM_balanceLoad = true;

  #include <ShiftPWM.h>    
  #include <btnTrackSelect.h>      
  
  
  btnTrackSelect btnTrackSelect[16];  
  
  Bounce btnShift = Bounce(cfg.btnShiftPin, 10);  // 10 ms debounce
  
  
  // ################## SETUP
  
  void setup() {
    // 4051 - CTRL
    pinMode(cfg.muxPin1, OUTPUT);
    pinMode(cfg.muxPin2, OUTPUT);
    pinMode(cfg.muxPin3, OUTPUT);
    
      
    // 4051 - INPUT PINS
    pinMode(cfg.btnTrackSelectPin, INPUT);     
    pinMode(cfg.faderTrackVolumePin, INPUT);
  
    // SHIFT
    pinMode(cfg.btnShiftPin, INPUT_PULLUP);  
     
    Serial.begin(9600);      
    while ( !Serial && (millis()<4000) ) {
      Serial.println("LOADING SERIAL PORT ...");  
    }
    Serial1.begin(9600);
    while ( !Serial1 && (millis()<4000) ) {
      Serial1.println("LOADING Serial1 PORT ...");  
    }
    
    Serial.println("SERIAL PORT INITIALIZED"); 
    Serial.println("Serial1 PORT INITIALIZED");   

    // LIGHT
    ShiftPWM.SetAmountOfRegisters(3);
    ShiftPWM.SetPinGrouping(8);
    ShiftPWM.Start(cfg.pwmFrequency,cfg.maxBrightness);    
    ShiftPWM.SetAll(0);
  }




  // ################## MAIN LOOP
  
  void loop() { 
     
    if(cfg.modus != cfg.modusNext) {
      Serial.println("MODUS CHANGED: "); Serial.print(cfg.modus);
      Serial1.write("aaa");
      cfg.modus = cfg.modusNext;    
    }
  
     if (cfg.modus == "EDIT") {          
      readMenuEncoders();
    }  
  
    for (int i = 0; i <= 7; i++) {    
      // count through MUX    
      cfg.MuxBit1 = bitRead(i,0);
      cfg.MuxBit2 = bitRead(i,1);
      cfg.MuxBit3 = bitRead(i,2);   
      digitalWrite(cfg.muxPin1, cfg.MuxBit1);
      digitalWrite(cfg.muxPin2, cfg.MuxBit2);
      digitalWrite(cfg.muxPin3, cfg.MuxBit3);
      
      pollShift();
      pollMuxDigital(i, "btnTrackSelect", cfg.btnTrackSelectPin);     
            
    
    } 
     
  }



/*
 * Polls Shift-Button and sets Status-Var
 */
void pollShift() {
    if (btnShift.update()) {
      if (btnShift.fallingEdge()) {                 
          cfg.shiftStatus = false;                    
      } else {               
          cfg.shiftStatus = true;
      }
    }  
}


/*
 * Polls 4051 with digital Input-Sources
 */
void pollMuxDigital(int i, String element, int digitalPin) {   
  btnTrackSelect[i].btnStatus = digitalRead(digitalPin); 
      
  if(btnTrackSelect[i].btnStatus == HIGH && btnTrackSelect[i].btnStatusOld != btnTrackSelect[i].btnStatus) {     

    if(btnTrackSelect[i]._state == 0) {
      Serial.print(i); Serial.print(" - PRESSED .. "); Serial.println();  
      if(cfg.shiftStatus == true) {
         // EDIT
        edit(i, element);
        btnTrackSelect[i].setBtnState(2);                       
      } else {
        // SEND MIDI 
        btnTrackSelect[i].setBtnState(1);            
      } 
       
    } else if(btnTrackSelect[i]._state == 1) {
      Serial.print(i); Serial.print(" - PRESSED AGAIN.. "); Serial.println();  
      if(cfg.shiftStatus == true) {
         // EDIT
        edit(i, element);
        btnTrackSelect[i].setBtnState(2);                        
      } else {
        // SEND MIDI 
        btnTrackSelect[i].setBtnState(0);            
      } 
    } else if(btnTrackSelect[i]._state == 2) {
       
      if(cfg.shiftStatus == true) {
        Serial.print(i); Serial.print(" - RESET EDIT.. "); Serial.println(); 
        // EDIT
        edit(i, element);
        btnTrackSelect[i].setBtnState(2);                        
      } else {
        Serial.print("reset "); Serial.print(cfg.editCtrlNr); Serial.print(" to "); Serial.print(btnTrackSelect[cfg.editCtrlNr]._state_prev); Serial.println();
        btnTrackSelect[cfg.editCtrlNr].setBtnState(0);  
        cfg.editCtrl = "";
        cfg.editCtrlNr = 0;
        cfg.modusNext = "";
        
        // SEND MIDI 
        btnTrackSelect[i].setBtnState(0);            
      } 
    }



    Serial.print("#SET COLOR# "); 
    Serial.print((i+1)); Serial.println();
    Serial.print(btnTrackSelect[i]._rgb[0]); Serial.println();
    Serial.print(btnTrackSelect[i]._rgb[1]); Serial.println();
    Serial.print(btnTrackSelect[i]._rgb[2]);Serial.println();
    Serial.println();
    
    ShiftPWM.SetRGB(i,btnTrackSelect[i]._rgb[0],btnTrackSelect[i]._rgb[1],btnTrackSelect[i]._rgb[2]);   
        
  } 
  

 btnTrackSelect[i].btnStatusOld = btnTrackSelect[i].btnStatus;  



  
  if(btnTrackSelect[i].btnStatusOld == HIGH && btnTrackSelect[i].btnStatus == LOW) {
    Serial.print(i); 
    Serial.print(" - UN - statusOld : "); Serial.print(btnTrackSelect[i].btnStatusOld); 
    Serial.println();  
  } 
 
  
}



/*
 * Enters Edit-Menu
 */
void edit(int zaehler, String element) {
  Serial.print("EDIT - "); Serial.print(element); Serial.print(" "); Serial.print(zaehler); Serial.println(); 

  cfg.editCtrl = element;
  cfg.editCtrlNr = zaehler;
  
  if(element == "btnTrackSelect") {     
        
    cfg.encoder1_oldPosition = btnTrackSelect[zaehler].ctrlChannel;
    cfg.encoder1_valRange[0] = btnTrackSelect[zaehler].ctrlChannel_valRange[0];
    cfg.encoder1_valRange[1] = btnTrackSelect[zaehler].ctrlChannel_valRange[1];
    /*
    cfg.encoder2_oldPosition = btnTrackSelect[zaehler].ctrlType;
    cfg.encoder2_valRange[0] = btnTrackSelect[zaehler].ctrlType_valRange[0];
    cfg.encoder2_valRange[1] = btnTrackSelect[zaehler].ctrlType_valRange[1];
    
    cfg.encoder3_oldPosition = btnTrackSelect[zaehler].ctrlNote;
    cfg.encoder3_valRange[0] = btnTrackSelect[zaehler].ctrlNote_valRange[0];
    cfg.encoder3_valRange[1] = btnTrackSelect[zaehler].ctrlNote_valRange[1];
    */
    encoder1.write(0);
    //encoder2.write(0);
   // encoder3.write(0);
      
    Serial.print("CHANNEL:"); Serial.print(btnTrackSelect[zaehler].ctrlChannel); 
    Serial.print(", - TYPE: "); Serial.print(btnTrackSelect[zaehler].ctrlType_values[btnTrackSelect[zaehler].ctrlType]); 
    Serial.print(", - NOTE/CC: "); Serial.print(btnTrackSelect[zaehler].ctrlNote_values[btnTrackSelect[zaehler].ctrlNote]); 
    Serial.println();   
    cfg.modusNext = "EDIT";      
  }
  
}



and here is the cfg.h

Code:
#ifndef cfg_h
#define cfg_h

#include "Arduino.h"



class cfg {
    
  public:  
    
    cfg();     
    
    // ########### PINS ###########
    
    // MUX CD4051
    int muxPin1 = 2;
    int muxPin2 = 3;
    int muxPin3 = 4;
    
    int btnShiftPin = 14;
    int btnTrackSelectPin = 15;     
    
    
    unsigned char maxBrightness = 255;
    unsigned char pwmFrequency = 75;    
   
    
    
    // ########### VARS ###########
    String modus = "";
    String modusNext = "";
   
    int shiftStatus;
    
    
    String editCtrl;
    int editCtrlNr;
    
    
    int MuxBit1;
    int MuxBit2;
    int MuxBit3;    

    
  private:
    
    
};

#endif
 
Sorry, I don't see anything obvious.

If it were me, I would maybe try to isolate to see if I remove most of the processing code that happens when the button is pressed, do I still see the flicker? If not, then add some more code back in and see when it starts to flicker, to see if maybe something like all the Serial.print statements is causing the timings to change, or maybe it is the setRGB call or ???
 
Hi

thanks for the review.. I have noticed, that when I press and hold one of the switches, all the LEDs dimm down and stay dimmed until I releasy the switch. I think I will do it like you wrote.. isolate part by part and see where the error occurs.
 
What happens if you change the resistors on the switches to a higher value around 1K~100K?
When the switch is pressed it connects between VCC and GND through the 220Ω resistor, which results in 5/220 = 0.022 mA current flowing, which is not so big but can be a problem when you power from usb which can have a max output of 100mA on some computers.
 
Is this on a UNO board and if you are using the 5vdc from the board, are you maxing out the 5vdc current. Are you possibly seeing the scan of the outputs of the IC's. Long ago on old portable vcr's, you could see the leds blink a little
 
https://www.pjrc.com/teensy/td_libs_ShiftPWM.html

With all the Serial.print commands, perhaps you are running up against the USB waiting to clear buffers. The docs for the ShiftPWM mentions a PrintInterruptLoad() function. It would show if you are running out of resources. I also notice there is a lack of a wait between changing the mux address lines and reading the switches. There is a function call to pollShift(), so that may not be an issue depending upon how quick pollShift returns.
 
What happens if you change the resistors on the switches to a higher value around 1K~100K?
When the switch is pressed it connects between VCC and GND through the 220Ω resistor, which results in 5/220 = 0.022 mA current flowing, which is not so big but can be a problem when you power from usb which can have a max output of 100mA on some computers.

Bro!! that seems to work!! :)))
I took 10K Resistors for the switches and it seems to solve the problem.. but I don't understand it.. you say, on some point the switch connects VCC/GND through the 220Ohm .. but how can this affect the LEDs which are at a total different point of the circiut?


but anyway.. many thanks man!! :)
 
Last edited:
Is this on a UNO board and if you are using the 5vdc from the board, are you maxing out the 5vdc current. Are you possibly seeing the scan of the outputs of the IC's. Long ago on old portable vcr's, you could see the leds blink a little

I don't understand.. UNO(?) .. this is a Teensy3.2 I'm running. How can I max out the 5vdc?
 
https://www.pjrc.com/teensy/td_libs_ShiftPWM.html

With all the Serial.print commands, perhaps you are running up against the USB waiting to clear buffers. The docs for the ShiftPWM mentions a PrintInterruptLoad() function. It would show if you are running out of resources. I also notice there is a lack of a wait between changing the mux address lines and reading the switches. There is a function call to pollShift(), so that may not be an issue depending upon how quick pollShift returns.

oh man.. this could be a issue in the future :/ .. I need to mux a ton of buttons and faders.. I also need to manage a display ..and with the PWM taking much performance.. could I run into tennsy-performance-issues here?
Maybe I should take a 3.6? Or take a Arduino UNO for the LEDs and send Information to the UNO via Serial?
 
Lets say your power (which is provided by the USB) has a max current output of 170mA (at 5V).
Assuming each of the LED's takes 20mA X 8 LED's = 160mA "taken" already (160mA are already flowing between VCC and GND).
Then, when you connect Between VCC and GND with a resistor, you get more current flowing, in this case 22mA which is equivalent to another LED.
So now your circuit "draws" 182mA which is above the maximum supply current, the result will probably be the voltage dropping from 5V to a lower one, and the LED's dim.
If you had completely shorted between VCC and GND, the LED's would shut off completely.
(of course these are made up figures, and they don't apply to your circuit)
If you want to learn more about this, search for theory of parallel circuits and Ohms law. I recommend this textbook.
 
Last edited:
Status
Not open for further replies.
Back
Top