Strange Button behaviour

Status
Not open for further replies.

sevEnil2

Active member
Hi @all
Another Friday passed (i usually work on friday on my project) and after the problems with the IDE are solved i wanted to test some code.
Actually quite easy code read the button state on a pin and if the button is pressed it should trigger a relais to turn of or on depending on the previous state.
So wired up everything and instantly the relays went amok(turning of and on 3-6 times a second). So my first guess was that i receive all the time button state 1 so it tries to turn of and on every loop.

so i wired a little lamp into the circuit so see what happens. And the behaviour this lamp showed i made a video of it because i couldn't explain what happens.
https://goo.gl/photos/rtbu3QevH6r5LkUT6
(so no teensy included in this circuit) As you can see after the first 3 times it starts to delay or something, sometimes the lamp even stopped going on for several pushes. Anyone a idea whats going on here?

So i had the thing already once tested on a breadboard. (because i'm a completely beginner)
https://goo.gl/photos/RYwmQoQbiYfYpNnh8
there everything worked as expected... but i actually lost my code from past there...

So the funny thing was yesterday that if i wired the button to the pin 19 i always received state 1 on the serial monitor. if i wired it to the 23 i firstly didn't get any output so i would expect 0 until the first time i pressed the button from then on it kept it state to 1 independent of time and other button pushes. Did use the wrong method to read the pin?

Code:
#define USE_OCTOWS2811
#include "Table.h"
#include<OctoWS2811.h>
#include<FastLED.h>

#define NUM_LEDS_PER_STRIP 164
#define NUM_STRIPS 8
int numOfTopLeds= 168;
int numOfFrontLeds= 0;
int numOfLeftLeds= 0;
int numOfRightLeds= 0;
int numOfBackLeds= 0;
int numOfFeetLeds= 7;

const int maxBrightness=150;
int currentBrigthness =130;
Table table = Table();

//TODO need to check the pins in reality. these are just some random numbers.
//pin 18 is the airpump
int buttonMutePumpPin = 23;
int buttonBrightnessPin = 19;
int buttonNextAnimationPin =20;
int buttonUnknownsPin=21;
bool isButtonTogglePumpPressed =false;
bool isButtonBrightnessPressed=false;
bool isButtonNextAnimationPressed=false;
bool isButtonUnknownPressed=false;




CRGB leds[NUM_STRIPS * NUM_LEDS_PER_STRIP];

Table::Table() {
	// TODO Auto-generated constructor stub



}
Table::~Table() {
	// TODO Auto-generated destructor stub
}

void setup() {
LEDS.addLeds<OCTOWS2811>(leds, NUM_LEDS_PER_STRIP);
  //LEDS.addLeds(leds, 164);
  LEDS.setBrightness(currentBrigthness);
  FastLED.setBrightness(currentBrigthness);
  pinMode(buttonMutePumpPin, INPUT);
  pinMode(buttonBrightnessPin, INPUT);
  pinMode(buttonNextAnimationPin, INPUT);
  pinMode(buttonUnknownsPin, INPUT);


}


void Table::updateButtonStates(){
	isButtonTogglePumpPressed=0;
	bool isButtonTogglePumpPressed =digitalRead(buttonMutePumpPin);
	bool isButtonBrightnessPressed=digitalRead(buttonBrightnessPin);
	isButtonNextAnimationPressed=digitalRead(buttonNextAnimationPin);
	isButtonUnknownPressed=digitalRead(buttonUnknownsPin);
	if(isButtonTogglePumpPressed){
		//table.airpump.toogleAirpumpState();
		Serial.println(isButtonTogglePumpPressed);

	}
	if(isButtonBrightnessPressed){
		currentBrigthness = currentBrigthness + 15;
		if(currentBrigthness > maxBrightness){
			currentBrigthness =10;

		}
		LEDS.setBrightness(currentBrigthness);
		FastLED.setBrightness(currentBrigthness);
	}

}

void someAnymation() {
	static uint8_t hue = 0;
	for (int i = 0; i < NUM_STRIPS; i++) {
		for (int j = 0; j < NUM_LEDS_PER_STRIP; j++) {
			leds[(i * NUM_LEDS_PER_STRIP) + j] = CHSV((32 * i) + hue + j, 192,
					255);
		}
	}
	// Set the first n leds on each strip to show which strip it is
	for (int i = 0; i < NUM_STRIPS; i++) {
		for (int j = 0; j <= i; j++) {
			leds[(i * NUM_LEDS_PER_STRIP) + j] = CRGB::Red;
		}
	}
	hue++;
}

void loop() {
  someAnymation();
	//Fire2012();
  LEDS.show();
  LEDS.delay(10);
  table.updateButtonStates();
}


and by the way whats the difference between digitalRead and digitalReadFast?

regards sev
 
Last edited:
if your not using any pullup resistors for your buttons you should be using INPUT_PULLUP for pinMode, NOT INPUT.
digitalWriteFast uses alot less CPU cycles to change pin state.
 
Hi tonton81

thanks for your reply
I'm using those buttons: https://www.reichelt.com/Eingabetas...I2440d1b91a8594b18213154b77e84117&LANGUAGE=EN

What would be the right pullup resistors? i have a the issue here that there are no Electronic stores anymore so no guy to ask behind the Desk either....
the only way left the get components is over the internet... so as example if i buy a capacitor for 48 cents i still have to pay 7 franks delivery fee.

So i guess i didn't do that the first time either... and so far i understand the resistor is to ensure no Preue happens...
But that would result in multiple 1 until the 0 appears again not? So not infinite 1 or 0 until the first time pressed and afterwards infinite 1.

And whats the downside of digitialReadFast?
 
You probably don't need to buy resistors, since the Teensy already has them
https://www.arduino.cc/en/Reference/pinMode and related links
So using pinmode(INPUT_PULLUP); and having your buttons connect to gnd is all that is required. Then have your code look for a low to detect when button is pressed.

At the moment your buttons are acting as antenna's and picking up random noise, the pullups prevent that.


No real downside to digitalReadFast in writing your own code. Only reason there is any non fast option is to maintain compatibility with Arduino Uno code.
 
Hi GremlinWrangler

Thanks for the link and the hint that teensy already has them.

But now we come to the point i don't understand.
If i understand you correctly the reason why i get allways a signal is that my cable/button picks up noises which are comming from the air and the teensy is without pullup resistors sensibel enought to detect those as a input signal. right? and thats a reason why i get allwas a high on my pin.
would also explain why i

so now you are telling me that after the changes to INPUT_PULLUP i have to detect for a low and that i don't understand. I would still expect a HIGH as soon i press the Button. Why does the state change?

Did you watch the first video with the lamp? Why does the lamp act so strange? is this something different?
 
usually you pull the pin HIGH with a pullup resistor or the internal pullup and you wait until you read a LOW from the button
like GremlinWrangler said you dont need the pullup resistor, just change your pinMode from INPUT to INPUT_PULLUP and check if button went LOW.
IF your doing the opposite, and your button is giving a HIGH side trigger (which according to your sketch it should be) you can also do the reverse, by doing a
pinMode INPUT_PULLDOWN, which will keep the pin at 0 until button is pressed
 
For reasons of convenience and easy design most chips provide onboard pullups, and you connect switches to ground and your program goes 'high state switch open, low state switch closed' and works from there.
https://en.wikipedia.org/wiki/Pull-up_resistor
The Teensy is a more capable chip and also offers pull downs as Tonton notes if that makes your code seem more sensible. Just be aware that not all devices support them if using something other than a teensy later.

Also if you are starting out be aware of switch bounce:
https://en.wikipedia.org/wiki/Switch#Contact_bounce
Which is a big thing in any code dealing with a physical switch, so always assume that within 100ms of a switch change there will be one or more other changes that you need to deal with. Your polling method with delay(10) will probably do the job, but wouldn't be impossible to get a double tap in that time scale.

Also complicating life is that 100 times a second you are checking the buttons and doing things. You possibly need to add code to check if button was just pressed, or if it's still down from the last loop through the code and you shouldn't change the value again.

A recomended tool is the debounce library:
https://www.pjrc.com/teensy/td_libs_Bounce.html
Which handles bounce and can be used to only trigger on button down or button up, not every time the button is down during loop()
 
Ah thanks GremlinWrangler
now it starts to make sense... (because until now i had it wired from + to the Button to the teensy). and i was expecting the teensy to be the ground. And i get a high as soon i close the button.
If i understand it right the circuit turns around as soon i use INPUT_PULLUP. so ground to button to teensy which is +.

Yeah i heard about Bounce issues with the buttons. But i wanted to deal later with it. because i also need to figure out how to check the buttons while a animation gets played... otherwise i will miss some state changes...

But still can someone explain me the behaviour on the first video?
 
Code:
void someAnymation() {
	static uint8_t hue = 0;
	for (int i = 0; i < NUM_STRIPS; i++) {
		for (int j = 0; j < NUM_LEDS_PER_STRIP; j++) {
			leds[(i * NUM_LEDS_PER_STRIP) + j] = CHSV((32 * i) + hue + j, 192,
					255);
		}
	}
	// Set the first n leds on each strip to show which strip it is
	for (int i = 0; i < NUM_STRIPS; i++) {
		for (int j = 0; j <= i; j++) {
			leds[(i * NUM_LEDS_PER_STRIP) + j] = CRGB::Red;
		}
	}
	hue++;
}

void loop() {
  someAnymation();
	//Fire2012();
  LEDS.show();
  LEDS.delay(10);
  table.updateButtonStates();
}

the for loops are blocking code, essentially causing a delay in your code from reading the button in realtime.
This is why you need to use interrupts for buttons for realtime access if you have that kind of code blocking, like that.

my last led project i stopped the for/while loops, it drags the processor and not efficient. I prefer to increment the code per loop cycle using optional variables and millis() (for delayed non blocking updates) and it never slowed down the rest of the code.
 
Last edited:
Tonton81 i'm aware of this issue and i did completly understand it... if there would be mutlithreading i would probably solve it that way but there is none ;) As i said i will start dealing with that kind of problems when they occure..


because i can only test code on friday (project is a half hour drive far away) i ask again.

Did someone check the first video? that freaked me out a bit ;) because that was only Supply 5v+ -> button->lamp->gnd teensy.
https://goo.gl/photos/rtbu3QevH6r5LkUT6
or have troubles to watch it ?
 
i saw it but theres so many things there i refered to your sketch as being the delay for the lamp to turn on

"Supply 5v+ -> button->lamp->gnd teensy. " i hope your not sourcing the ground from the teensy itself. thats a big no-no. you should be using a mosfet at that point to trigger it.
 
Hi tonton

probably i did a no go... but pls be patient ;)

the teensy is powered by the powersupply and not over USB so for me the ground output on the octows2811 seems to be the same...so no connection to any pin and no sketch running.
That was a lab setup to just test if i wired the button correctly or if there is allways current. So this setup is gone allready...

But pls explain me the nogo what is the bad thing i did or probably did or could have done because i'm totaly not aware of it...
 
"Supply 5v+ -> button->lamp->gnd teensy. " <-- which teensy ground? i dont / cant really see how you have things wired in that video, but if i think what your doing is true by pushing the button the 5 v goes to the lamp and while that happens the lamp draws GND from the teensy's gpio, which is what i hope your not doing, unless you want the teensy to end up dead, your button should be only for the teensy and not the lamp in-between, you should, i hope also, be using a 5v tolerant teensy as well according to the quote layout
 
gpio is general purpose input out put. In this case any of the pins on a teensy that have digital functions. Comes from the days when you had output pins and input pins and they were all fixed, until somebody designed a way to make them interchangable by the software. And to differentiate from specific input our output pins (serial,SPI, PWM etc). From your point of view a GPIO label means it's a pin you can digital read from and digital write to.

Issue with trying to use a lamp to indicate button state is that the teensy input is pretty close to open circuit, since it's sensing the voltage, not the current. What you could do is use a resistor + LED as a pullup/pull down. So

+3.3V-----
|
button
|
---teensy input
|
LED
|
300-1000 ohm resistor (whatever is to hand)
|
gnd----------------

Circuit will go high when button is pressed, and pull low when off and the LED should only light when button is down. how well it works depends a bit on the diode leaking a bit when the switch is up to still function as a pull down.
 
Hi thanks for this well detailed explanation.
1.So just for my understanding i didn't use a gpio to get gnd so my setup was fine and i didn't do any nogo...right?
2.The problem is that a lamp takes to much current and will kill the chip if i would use a gpio, it doesnt matter if i would use a gpio configured as input or output in both ways it would just be to much current.
3. Probably my english is the issue i'm sorry for that... i did the setup with the lamp only to "debug" my components because i didn't understand why i get allways a high on teensy. So i was expecting that i did solder something wrong on the button and i bypassed the button. So to test if i did that i just added a lamp and i was expecting it to light up immediately as son i turn the power on. The only reason i mention it was the strange light up behavior i got which was delayed somehow and i couldn't explain. There was no gpio involved in that setup. And thanks for providing a solution but i don't need a lamp in my final circuit. ;)
 
You can use GPIO as a gnd as long as you don't try to put to much current through it. So I have made mini projects by soldering a teeny button between pin 4 and 6 of a teensy, turning pullup on for pin 4 and setting pin 6 to gnd. Then read the button state at pin 4. Current there is limited by the pullup resistor to less than a mA so fine other than wasting a pin (space was more critical there).

Answering point two it would be fine to have that lamp as a pull up/pull down and sense the VOLTAGE across it as long as no CURRENT was flowing in or out of a pin, which in pinmode_input will only happen if you have massively out of spec voltages. Specifically the input is about 500k Ohms from memory. Ohms law says I =V/R = 3.3/500000 = 6.6 micro amps, regardless of how much current is flowing past it.

Re watching the video still not clear on how that happened, since it can't have been getting current through the Teensy with pinmode set to input so in theory current should have been 100% controlled by the button. Certainly didn't look like that was what was happening though.

Re threading, there are libraries that provide RTOS but you are probably more after
https://learn.adafruit.com/multi-tasking-the-arduino-part-1/overview
Which is the same approch as mentioned above basically:

check buttons
respond to presses
find ellapsed time
update animation based on time (not fixed cycle count) floor and moduli (%) are our friend here for turning times into cycles. So a bad but functional way to do it is:

unsigned long timeellapsed = millis(); //find time since run start in milliseconds
int animationstage=timeellapsed%10000; //gives remainder of a 10 second time interval
animationstage = animationstage/100; //divides down to get a more useful number for animation stages that is from 0-99 that progress once every 1/10 of a second.
 
3. i think you have still troubles to understand my setup due to the fact you are talking about pinmodes.
there was a cable to the button from 5v+ powersupply. another cable from the button to the teensy gnd (in the CheatSheet of teensy 3.2 also labeled GND) thats it.

But i see that no one can explain me why this happend or i didn't do what i'm telling you...
 
Yes, I think you may be right that we are having a hard time understanding your setup, if your setup is simply:
+5v -> Button -> lamp -> GND

And the +5v and GND are to the same power source, then in theory the light should be one either when the button is pressed or when it is not pressed. That is some switches are NO (Normally Open) and some are NC (Normally closed), so pushing the button should either make the circuit or break the circuit...

Some possible issues could include:

may be an issue that your lamp may be wanting more current or voltage than your power supply is designed to supply and maybe something is blinking it out.

Maybe some of your wires are not making very good contact and/or maybe have an internal break in the wiring..

Maybe the switch is defective and is making partial contact

Always hard to say when we can not see the actual setup.
 
so i tried to draw a shematic...

https://goo.gl/photos/n995HZRvd9TZXyMz8

the lamp is actually specified for 3.7 Volts ...but i would have expected it to just die and not doing some delayed lightups....
i would guess my supply is big enough with 40A 5v
so if i read now your list i would guess for broken wires/bad contacts... this could be a option because i setted up the test quickly... it was not ment to be long lasting. But i will try to document my setup better next Friday so for problems in the future my guess is i'm not done ;)

i'm fine to live with the mystery of the delayed lamp ;)
 
Last edited:
Hi a little question about the Bounce libary there seems to be a Bounce2. Is it recommendet to still use Bounce?
 
Status
Not open for further replies.
Back
Top