Malfunction of a Simple Button Code

Hi everyone.

I’ve got a problem with functioning the push button.
The code is the same and simple as other push button code.

int buttonPin1 = D4;     // the number of the pushbutton pin
int buttonPin2 =  D5;      // the number of the pushbutton pin
int redPin = D0;
int greenPin = D1;
int bluePin = D2;

int buttonState1 = 0;         // variable for reading the pushbutton status
int buttonState2 = 0;  
int speakerPin = D3;

void setup()
{
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT); 
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  
  // declare pin 9 to be an output:
  pinMode(speakerPin, OUTPUT);
  beep(50);
  beep(50);
  beep(50);
  delay(1000);
}

void loop()
{
    
  buttonState1 = digitalRead(buttonPin1);
  buttonState2 = digitalRead(buttonPin2);
  
  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (buttonState1 == HIGH) {
    // turn LED on:
  setColor(255, 0, 0);  // red
  delay(1000);
  
  beep(1000); 
  }
  if (buttonState2 == HIGH) {
    // turn LED on:
  setColor(0, 255, 255);  // aqua
  delay(1000);
  
  beep(1000); 
  }
  else {
    // turn LED off:
  setColor(0, 0, 0); 
  }
}
void beep(unsigned char delayms){
  analogWrite(speakerPin, 20);      
  delay(delayms); 
  analogWrite(speakerPin, 0);
  delay(delayms);   
}

void setColor(int red, int green, int blue)
{
  analogWrite(redPin, red);
  analogWrite(greenPin, green);
  analogWrite(bluePin, blue);  
}

I have two buttons, one RGB LED, and one buzzer.
The system should be run according to the code, but it does not follow the code.
Supposedly when button1 is pressed red light will appear and when button2 is press aqua light will appear. But the system run without the IF/ELSE function. it just lights up the red and aqua color without me pushing the buttons.

So, is there any guide that I can use, to use the push button and make it follow my instruction?

Are you sure when you press the button its state goes high, and not the other way around ?
If not, print the state of both buttons in that loop to verify what you think is happening is actually happening.

I’ve always had buttons go LOW when pressed. I always wire buttons between Ground and the GPIO pin and use the following code.

#define BUTTON D0
pinMode(BUTTON, INPUT_PULLUP);

if (!digitalRead(BUTTON)) {
    Serial.println("BUTTON PRESSED");
}

Yes,
Because I’ve also have done it in both ways (HIGH, LOW) just to test.
And the output is still the same.

Still, print the button states before your if statements. You need to confirm they are actually changing state.
Also, your beep(1000); value is larger than your “void beep(unsigned char delayms)” can accept.
unsigned char is only 255.

Is it like this that you want me to show?

Above picture, shows the state that is running without me push the button.

:persevere:

You should pay attention to @nrobinson2000’s advice.

The symptoms you describe are typical for floating pins.

Yes…I am.

Here is the new code for testing.

#define BUTTON D5

int redPin = D0;
int greenPin = D1;
int bluePin = D2;

void setup()
{
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT); 
  pinMode(BUTTON, INPUT_PULLUP);
  delay(1000);
}

void loop()
{      
  Particle.publish("Before If statement...");
    if (!digitalRead(BUTTON)) {
        Particle.publish("BUTTON PRESSED");
        setColor(0, 255, 255);  // aqua
    }
  else {
    // turn LED off:
  setColor(0, 0, 0); 
  }
}
void beep(unsigned char delayms){
  analogWrite(speakerPin, 20);      
  delay(delayms); 
  analogWrite(speakerPin, 0);
  delay(delayms);   
}

void setColor(int red, int green, int blue)
{
  analogWrite(redPin, red);
  analogWrite(greenPin, green);
  analogWrite(bluePin, blue);  
}

It’s still not working. Here is what it’s like in the console.

It’s looping without tracking the If statement…

Sorry,
This is the new test.

How have you got the button(s) wired?

Your current code is violating the rate limit for Particle.publish()

I didn’t mean print in that way. Keep it simple at first to verify the buttons are wired correctly. When using INPUT_PULLUP, you will need to wire your button with one end going to D5 and the other to gnd.

#define BUTTON D5
int val;

void setup()
{
  pinMode(BUTTON, INPUT_PULLUP);

    Serial.begin(115200);
    Serial.printf("System Ready...\n");

}

void loop()
{      
    val = digitalRead(BUTTON);
    Serial.printf("Button Value is: %d\n", val);
    delay(250);
}

@Syerlac, not sure why you want to reinvent button push detection since your code doesn’t even address debounce. I suggest you look at proven button libraries available on the web IDE such as “debounce” and “clickButton”. One is interrupt driven, the other is polled and both will serve you well. :wink:

1 Like

Yup, there are libraries that will save you some (a lot) work, but you still should understand how to do things properly and if the wiring isn’t done correctly the best of libraries won’t help much.

3 Likes

https://build.particle.io/libs/Debounce/0.0.1/tab/example/example.ino

4 Likes

Here is the result of the code.

It seems not working… because I didn’t push the button yet.

Ok.

I’ll try that.

Sir, I’ve tried your suggestion using the ClickButton.
Yes, the button functioning well. But when I re-code the code like below,

#include <clickButton.h>


int buttonPin1 = D4;     // the number of the pushbutton pin
int redPin = D0;
int greenPin = D1;
int bluePin = D2;
int speakerPin = D3;

// variables will change:
ClickButton button1(buttonPin1, LOW, CLICKBTN_PULLUP);

// Button results 
int functionB1 = 0;

void setup()
{
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  pinMode(D4, INPUT_PULLUP);

  // Setup button timers (all in milliseconds / ms)
  // (These are default if not set, but changeable for convenience)
  button1.debounceTime   = 20;   // Debounce timer in ms
  button1.multiclickTime = 250;  // Time limit for multi clicks
  button1.longClickTime  = 1000; // time until "held-down clicks" register
  
  // declare pin 9 to be an output:
  pinMode(speakerPin, OUTPUT);
  beep(50);
  beep(50);
  beep(50);
  delay(1000);
}

void loop()
{
    
  // Update button state
  button1.Update();
  
  // Save click codes in LEDfunction, as click codes are reset at next Update()
  if(button1.clicks != 0) functionB1 = button1.clicks;
  
  if(functionB1 == 1) Particle.publish("SINGLE click");
 {
  setColor(255, 0, 0);  // red
  delay(1000);
  }
  if(functionB1 == 2) Particle.publish("DOUBLE click");
  {
  setColor(0, 255, 0);  // green
  delay(1000);
  }
  
  functionB1 = 0;
  delay(5);
}

void beep(unsigned char delayms){
  analogWrite(speakerPin, 20);      // Almost any value can be used except 0 and 255
                           // experiment to get the best tone
  delay(delayms);          // wait for a delayms ms
  analogWrite(speakerPin, 0);       // 0 turns it off
  delay(delayms);          // wait for a delayms ms   
}

void setColor(int red, int green, int blue)
{
  analogWrite(redPin, red);
  analogWrite(greenPin, green);
  analogWrite(bluePin, blue);  
}

It still not functions when I push the button. But the LED is running without me pushing the button.

If this is the polled library, you need to call the update often. The button cannot process your click if the code is in delay.

Use the interrupt version or use timestamps instead of delays.

You have a typo here ^

Try this…

if(functionB1 == 1)
{
    Particle.publish("button", "SINGLE click", PRIVATE, WITH_ACK);
    setColor(255, 0, 0);  // red
    delay(1000);
}
else if(functionB1 == 2)
{
    Particle.publish("button", "DOUBLE click", PRIVATE, WITH_ACK);
    setColor(0, 255, 0);  // green
    delay(1000);
}
2 Likes