Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
7 years, 4 months ago.
Problem with using two buttons.
Hello! I have a program which receives input from two SPST buttons. I have tried using the onboard pull-up resistors AND my own external pullup resistors and either way, I receive an output which switches between the correct and incorrect output for each button. Essentially, if I press a button, there is about an 80% chance that it will do what it's supposed to do. Please see the serial monitor below as well as my code. If anyone has even the slightest idea of what I could do, please let me know! I'm using the STM Nucleo F446RE with the inputs: DigitalIn emergencyButton(PA_9); DigitalIn takeOverButton(PB_5); these buttons are connected to ground and their corresponding pins.
Code
#include "mbed.h" #include "OpenChair.h" //Define variables char str [80]; int i; int TO; //Open serial port Serial pc(SERIAL_TX, SERIAL_RX); //Initialise OpenChair OpenChair chair(PC_12,PD_2,PC_10,PC_11,60,150); //60,150 //Define Peripherals //DigitalIn emergencyButton(USER_BUTTON); DigitalIn emergencyButton(PA_9); DigitalIn takeOverButton(PB_5); AnalogIn potentiometerX(PA_0); AnalogIn potentiometerY(PA_1); DigitalOut notifierLED(PB_13); DigitalOut relay(PB_6); DigitalOut buzzer(PB_12); //led pb3 int main() { emergencyButton.mode(PullUp); takeOverButton.mode(PullUp); //State the variables which hold the data for the position of the potentiometers of the addon box. pc.baud(115200); double valueX; double valueY; //Turn on board and hold the power button after poweroff so that the release of it causes the motherboard to turn off. pc.printf ("Relay Starting\n"); wait(1); // Wait one second before beginning turn on sequence incase system startup is due to someone playing around with the switch. relay = 1; wait(0.5); relay = 0; wait(0.5); relay = 1; pc.printf ("Relay Finishing\n"); // Begin serial communication. pc.baud(115200); pc.printf ("Starting Loop\n"); while(1) { if (emergencyButton == 0) { pc.printf ("Emergency mode activated. Shutting down.\n"); //relay = 0; pc.printf ("Relay off\n"); /*while (1) { pc.printf ("Buzzer on\n"); buzzer = 1; wait(0.1); pc.printf ("Buzzer off\n"); buzzer = 0; wait(0.1); }*/ wait(0.2); }else if (takeOverButton == 0) { pc.printf ("Takeover button on\n"); TO = TO*-1; pc.printf ("Takeover button toggled\n"); wait(0.2); } else if (TO == 1) { pc.printf ("Takeover button variable activated and joystick drive enacted\n"); valueX= (double) (potentiometerX.read()*2-1); valueY= (double) (potentiometerY.read()*2-1); pc.printf("Potentiometer Values: %.02f %.02f\n",valueX,valueY); chair.drive(valueX, valueY, 1); wait_ms(50); } else if (TO == 0) { /* pc.scanf ("%s",str); //pc.printf ("%s\n",str,i); if (str[0] == 'F') { pc.printf ("Going forward\n"); chair.drive(1.00, 1.00, 1); wait_ms(50); continue; } else if (str[0] == 'B') { pc.printf ("Going back\n"); chair.drive(-1.00, -1.00, 1); wait_ms(50); continue; } else if (str[0] == 'L') { pc.printf ("Rotating left\n"); chair.drive(-1.00, 1.00, 1); wait_ms(50); continue; } else if (str[0] == 'R') { pc.printf ("Rotating right\n"); chair.drive(1.00, -1.00, 1); wait_ms(50); continue; } else {continue;}*/ } } // end while } //end main
3 Answers
7 years, 4 months ago.
Hello Andrew,
See below an example of using InterruptIn
for buttons (as suggested by Jan) with simple button debouncing (as suggested by Graham):
#include "mbed.h" //#include "OpenChair.h" //Define variables char str[80]; int i; bool TO = false; //Open serial port Serial pc(SERIAL_TX, SERIAL_RX); //Initialise OpenChair OpenChair chair(PC_12,PD_2,PC_10,PC_11,60,150); //60,150 //Define Peripherals InterruptIn emergencyButton(PA_9); volatile bool emergencyBtnEnabled = true; volatile bool emergencyBtnPressed = false; InterruptIn takeOverButton(PB_5); volatile bool takeOverBtnEnabled = true; volatile bool takeOverBtnPressed = false; AnalogIn potentiometerX(PA_0); AnalogIn potentiometerY(PA_1); DigitalOut notifierLED(PB_13); DigitalOut relay(PB_6); DigitalOut buzzer(PB_12); //led pb3 Timeout debounceBtn; // button bouncing Timeout // Enables Emergency button when bouncing is over void enableEmergencyBtn(void) { emergencyBtnEnabled = true; } // ISR handling Emergency button press event void onEmergencyBtnPressed(void) { if (emergencyBtnEnabled) { // disabled while the button is bouncing emergencyBtnEnabled = false; emergencyBtnPressed = true; debounceBtn.attach(callback(enableEmergencyBtn), 0.3); // debounce time = 0.3s } } // Enables TakeOver button when bouncing is over void enableTakeOverBtn(void) { takeOverBtnEnabled = true; } // ISR handling TakeOver button press event void onTakeOverBtnPressed(void) { if (takeOverBtnEnabled) { // disabled while the button is bouncing takeOverBtnEnabled = false; takeOverBtnPressed = true; debounceBtn.attach(callback(enableTakeOverBtn), 0.3); // debounce time = 0.3s } } int main(void) { emergencyButton.mode(PullUp); takeOverButton.mode(PullUp); emergencyButton.fall(callback(onEmergencyBtnPressed)); // attach ISR to handle button press event takeOverButton.fall(callback(onTakeOverBtnPressed)); // attach ISR to handle button press event //State the variables which hold the data for the position of the potentiometers of the addon box. pc.baud(115200); double valueX; double valueY; //Turn on board and hold the power button after poweroff so that the release of it causes the motherboard to turn off. pc.printf("Relay Starting\n"); wait(1); // Wait one second before beginning turn on sequence incase system startup is due to someone playing around with the switch. relay = 1; wait(0.5); relay = 0; wait(0.5); relay = 1; pc.printf("Relay Finishing\n"); // Begin serial communication. pc.baud(115200); pc.printf("Starting Loop\n"); while (1) { if (emergencyBtnPressed) { emergencyBtnPressed = false; pc.printf("Emergency mode activated. Shutting down.\n"); //relay = 0; pc.printf("Relay off\n"); } else if (takeOverBtnPressed) { takeOverBtnPressed = false; pc.printf("Takeover button on\n"); TO = !TO; pc.printf("Takeover button toggled\n"); } else if (TO == true) { pc.printf("Takeover button variable activated and joystick drive enacted\n"); valueX = (double)(potentiometerX.read() * 2 - 1); valueY = (double)(potentiometerY.read() * 2 - 1); pc.printf("Potentiometer Values: %.02f %.02f\n", valueX, valueY); chair.drive(valueX, valueY, 1); wait_ms(50); } else if (TO == false) { // ... } } // end while } //end main
7 years, 4 months ago.
There is another issue with the flag value T0. You multiply T0 by -1 presumably to flip it between 1 and -1. That means you should test T0 against either 1 or -1 as well. You currently test against 1 and 0. Also note that T0 should be initialised as either 1 or -1. Without initialisation it should be 0 in C++.
7 years, 4 months ago.
I wrote a Button library with debounce, auto-repeat, press, long press features. You can use it, or check source for ideas. https://developer.mbed.org/users/vargham/code/Button/
It's a bit unclear what you're trying to achieve here, but
posted by Jan Jongboom 04 Aug 2017TO
is undefined, thus can contain any value, so if you're relying on that variable, you will see issues. Declare it asint TO = 0;
. Also, if you want to respond to button presses, it's probably better to useInterruptIn
rather than polling, as using an interrupt you won't miss any events.It would probably help if you could provide the simplest possible example with one button that demonstrates the problem. I would try to decouple the button reading from taking action. Which is what Jan is suggesting by reading the button via interrupt.
Obviously an issue you always have to worry about with push buttons is debouncing. If it works 80% of the time that could be the issue. I've not used it, but you could try this library. At quick glance it looks like a pretty good strategy and similar to what I have done on my own before.
https://developer.mbed.org/users/AjK/code/DebounceIn/
posted by Graham S. 05 Aug 2017