Arduino won't read the buttons - c

This program is intended to count the number of button1 presses and then break out of the loop with the button2 press. The button2 is like an enter key.
If I run what is inside the do while statement by itself without the do while it will count up each button push. I used this to verify that I have constructed my circuit correctly. but for some unknown reason if I put the same code into a do while or just a while then it does not read the pins. It will loop inside the do while but never exit to that done statement at the end. If I start the arduino as I press down either of the two buttons then it will register that a button is being pressed, but as soon as I let go then it will do nothing again. Please tell me what I am doing wrong.
My code
int ledpin = 11;
int button1pin = 7;
int button2pin = 2;
int button1counter = 0;
int button1state = 0;
int lastButton1state = 0;
int button2state = 0;
int lastButton2state = 0;
int button2counter = 0;
void setup() {
// initialize the digital pin as an output.
pinMode(button1pin, INPUT);
pinMode(button2pin, INPUT);
Serial.begin(9600);
}
void loop() {
button1state = digitalRead(button1pin);
button2state = digitalRead(button2pin);
do {
if (button1state != lastButton1state) {
if (button1state == HIGH) {
button1counter++;
Serial.print("number of button 1 pushes: ");
Serial.println(button1counter);
}
lastButton1state = button1state;
}
} while(button2state == LOW);
Serial.println("done");
}
Thanks I changed it and of course your right. However, I can't quite understand why your right. Let me comment the code with my understanding and please correct me if I'm wrong.
void setup() {
pinMode(button1pin, INPUT);//tells comp to make button 1 input
pinMode(button2pin, INPUT);//tells comp to make button 2 input
Serial.begin(9600);
}
void loop() {
button1state = digitalRead(button1pin);//tells comp to begin reading pin? but for how long?
button2state = digitalRead(button2pin);
do {

You read your button state outside of your while loop, so your button1state and button2state are never updated, that is why you enter in an infinite loop just do that little change:
void loop() {
do {
button1state = digitalRead(button1pin);
button2state = digitalRead(button2pin);
if (button1state != lastButton1state) {
if (button1state == HIGH) {
button1counter++;
Serial.print("number of button 1 pushes: ");
Serial.println(button1counter);
}
lastButton1state = button1state;
}
} while(button2state == LOW);
Serial.println("done");
}

Related

Arduino Teensy array of Bounce not actually updating

Im quite new to Arduino and C itself, but I can't figure out why the array does not work, while the sanity check does.
It seems to me that both should operate fine. I'm guessing I'm missing some small bit of crucial info with regards to how arrays in C work.
The entirity of the code:
#include <Bounce2.h>
#define BUTTON_AMOUNT 1
#define DEBOUNCE_INTERVAL 25
const int ledPin = LED_BUILTIN;
//Bounce *buttons[BUTTON_AMOUNT];
Bounce buttons[BUTTON_AMOUNT];
Bounce b1 = Bounce();
void setup() {
Serial.begin(31250);
pinMode(ledPin, OUTPUT);
for (int i = 0; i < BUTTON_AMOUNT; i++) {
Bounce b = Bounce();
b.attach(i, INPUT_PULLUP);
b.interval(DEBOUNCE_INTERVAL);
buttons[i] = b;
// buttons[i] = new Bounce();
// (*buttons[i]).attach(i, INPUT_PULLUP);
// (*buttons[i]).interval(DEBOUNCE_INTERVAL);
}
b1.attach(0, INPUT_PULLUP);
b1.interval(25);
}
void loop () {
for (int i = 0; i < BUTTON_AMOUNT; i++) {
// Serial.println("looping ...");
Bounce b = buttons[i];
b.update();
if (b.rose()) {
// Serial.println("rising edge");
digitalWrite(ledPin, LOW);
}
if (b.fell()) {
// Serial.println("falling edge");
digitalWrite(ledPin, HIGH);
}
}
// sanity check
b1.update();
if (b1.rose()) {
Serial.println("B1 - rising edge");
digitalWrite(ledPin, LOW);
}
if (b1.fell()) {
Serial.println("B1 - falling edge");
digitalWrite(ledPin, HIGH);
}
}
Your are copying Bounce objects into and out of the button array. E.g.
...
for (int i = 0; i < BUTTON_AMOUNT; i++) {
Bounce b = Bounce();
b.attach(i, INPUT_PULLUP);
b.interval(DEBOUNCE_INTERVAL);
buttons[i] = b; // <- bitwise copy
...
However, since Bounce doesn't implement means for copying objects buttons[i] = b simply copies b bitwise into the array which won't work.
Instead of copying the elements out of / into the array you can simply access them. Here working code showing how to do that.
#include "Bounce2.h"
constexpr int BUTTON_AMOUNT = 5;
constexpr int DEBOUNCE_INTERVAL = 25;
constexpr int ledPin = LED_BUILTIN;
Bounce buttons[BUTTON_AMOUNT]; // this already constructs the buttons in the array, you can use them directly
void setup() {
pinMode(ledPin, OUTPUT);
for (int i = 0; i < BUTTON_AMOUNT; i++) {
buttons[i].attach(i, INPUT_PULLUP); // directly access the Bounce objects in the array
buttons[i].interval(DEBOUNCE_INTERVAL);
}
}
void loop () {
for (int i = 0; i < BUTTON_AMOUNT; i++) {
buttons[i].update();
if (buttons[i].rose()) {
Serial.printf("rising edge B%u\n", i);
digitalWrite(ledPin, LOW);
}
if (buttons[i].fell()) {
Serial.printf("falling edge B%u\n", i);
digitalWrite(ledPin, HIGH);
}
}
}

Stopping and starting loops in arduino

I need a motor to cycle forward, then backward when the user pushes a once. the problem is, the arduino will run in loops after it is presses and wont stop.
How can i make it only cycle through once each time the button is pushed?
Ive tried exit(0), stop_it, etc, but those just exit the loop instead of starting back up when the button is pressed another time.
const int pwm_pin = 9;
const int dir_1a_pin = 8;
const int dir_2a_pin = 7;
int buttonPin = 2;
boolean on=false;
int buttonState = 0;
void setup() {
pinMode(buttonPin, INPUT);
pinMode(pwm_pin, OUTPUT);
pinMode(dir_1a_pin, OUTPUT);
pinMode(dir_2a_pin, OUTPUT);
}
void loop() {
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH){
if (on==true){
on=false;
} else{
on=true;
}
}
if(on == true){
digitalWrite(dir_1a_pin, HIGH);
digitalWrite(dir_2a_pin, LOW);
analogWrite(pwm_pin, 255);
delay (8000);
digitalWrite(dir_1a_pin, LOW);
digitalWrite(dir_2a_pin, HIGH);
analogWrite(pwm_pin, 255);
delay (12000);
}
}
You are making the logic too much complicated. Just read the button state in your loop and if it was HIGH do your motorcycle job. The next time loop runs as you haven't pressed the button it would become LOW and won't go into if statement.
const int pwm_pin = 9;
const int dir_1a_pin = 8;
const int dir_2a_pin = 7;
int buttonPin = 2;
void MotorCycle()
{
digitalWrite(dir_1a_pin, HIGH);
digitalWrite(dir_2a_pin, LOW);
analogWrite(pwm_pin, 255);
delay(8000);
digitalWrite(dir_1a_pin, LOW);
digitalWrite(dir_2a_pin, HIGH);
analogWrite(pwm_pin, 255);
delay(12000);
}
void setup()
{
pinMode(buttonPin, INPUT);
pinMode(pwm_pin, OUTPUT);
pinMode(dir_1a_pin, OUTPUT);
pinMode(dir_2a_pin, OUTPUT);
}
void loop()
{
// if button pressed
if (digitalRead(buttonPin) == HIGH)
{
MotorCycle();
}
}
I assume that the part you want to run once is in the section at the end in the if(on == true) section. If you don't want that to repeat, then how about setting on to false in that section. Then next time loop repeats it won't go into that section.

Arduino the void loop() function isn't looping

I'm new to Arduino and I wrote the beginning a code that is supposed to play games read stories and more on an LCD display.
Here's my code
#include <LiquidCrystal.h>
// Arduino pins number
const int SW_pin = 2; // digital pin connected to switch output
const int X_pin = 0; // analog pin connected to X output
const int Y_pin = 1; // analog pin connected to Y output
const int LCD_RS = 7;
const int LCD_Enable = 8;
const int LCD_D4 = 9;
const int LCD_D5 = 10;
const int LCD_D6 = 11;
const int LCD_D7 = 12;
LiquidCrystal lcd(LCD_RS, LCD_Enable, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
// Basic vars
int none = 0;
String Apps[2] = {"App selector","Credits"};
int CurrentApp = 0;
int Yaxis = 1;
int Xaxis = 1;
int HiCh = 0;
int button;
int JXaxis;
int JYaxis;
void Credits() { // CREDITS
Serial.print("- Credits app loading \n");
lcd.clear();
lcd.setCursor(3,0);
lcd.print("Credits app");
lcd.setCursor(0,1);
Serial.print("- Credits app loaded \n");
}
void setup() { // SETUP
Serial.begin(9600);
Serial.print("[2J");
Serial.print(" Serial Monitor opened \n \n");
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print("App selector");
Serial.print("- App selector menu \n");
pinMode(SW_pin, INPUT);
digitalWrite(SW_pin, HIGH);
lcd.setCursor(0,1);
lcd.print(Apps[0]);
}
void SelectApp() { // SELECTAPP
switch (HiCh) {
case (1):
CurrentApp = 1;
Credits();
break;
default:
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Error");
Serial.print("- App loading error \n");
}
}
void loop() { // LOOP
while (none == 0) {
button = digitalRead(SW_pin);
int JYaxis = analogRead(Y_pin) / 128;
int JXaxis = analogRead(X_pin) / 128;
if (CurrentApp == 0) {
for (;;) {
if (button == 0) {
SelectApp();
}
if (JYaxis <= 1) {
if (HiCh != 0) {
HiCh = HiCh - 1;
delay(300);
}
}
if (JYaxis >= 7) {
HiCh = HiCh + 1;
delay(300);
}
}
}
}
}
I am only using one joystick as the controller and I have an Arduino UNO R3 board
I know a lot of other people have written about this and a lot of people have fixed the issue too but I cannot find the problem in my code...
I'm sure it's an error during the execution of the script that blocks the rest but I can't find where it is.
Thank you in advance!
If you need any specifications ask them to me and I'll try to answer them.
That code has a couple of issues.
In the loop() function you wouldn't normally make an infinite loop, you just put one run of your loop. That is, remove the while.
On the other hand, using delay() is not a great idea, as the processing loop will stop there and continue after specified time. The behavior you're trying to achieve is better implemented using timer interrupts.

Arduino: detecting buttons pressed inside a while loop

I have been trying to write a code to basically add points to a score whenever I pressed a button while a certain amount of time is running down. The problem I am finding is that it doesn't detect when the button is pressed while the time is decreasing, in fact it can only detect when the time starts to decrease and then it doesn't matter at which state the button is it will continue to add to the score. Anyway here is the main code:
void loop() {
buttonState01 = digitalRead(button01);
buttonState02 = digitalRead(button02);
buttonState03 = digitalRead(button03);
if (buttonState01){
time = 3000;
while(time > 0){
if (buttonState02){
score += 10;
Serial.println(score);
}
time--;
Serial.println(time);
}
}
}
And here is the full code if needed:
int button01 = 4;
int button02 = 3;
int button03 = 2;
int buttonState01 = 0;
int buttonState02 = 0;
int buttonState03 = 0;
float time;
int score;
void setup() {
score = 0;
time = 0;
pinMode(button01, INPUT);
pinMode(button02, INPUT);
pinMode(button03, INPUT);
Serial.begin(9600);
}
void loop() {
buttonState01 = digitalRead(button01);
buttonState02 = digitalRead(button02);
buttonState03 = digitalRead(button03);
if (buttonState01){
time = 3000;
while(time > 0){
if (buttonState02){
Serial.println("Points");
}
time--;
Serial.println(time);
}
}
}
You should read the status of a button inside the while loop. Like this:
while(time > 0)
{
buttonState02 = digitalRead(button02);
if (buttonState02){
Serial.println("Points");
}
time--;
Serial.println(time);
}
And in your code, there is no logic to add points to the score.
A hardware interrupt would do exactly what you need.
Attach an interrupt routine to the pin your button is linked to, and get it to set the 'score' variable. Make sure you introduce some sort of timeout to avoid button-bounce (I.e. set LastTimeIncremented when you increase the score, and only increment score if LastTimeIncremented is more than 1 second ago)
This way the score will always be set regardless of what else the program may be doing.
Information on this can be found in the Arduino https://www.arduino.cc/en/Reference/attachInterrupt
The example on that page would do exactly what you want, just replace 'blink' with 'incrementScore' and you're pretty much done
const byte ledPin = 13;
const byte interruptPin = 2;
int score = 0;
int increment = 1;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), incScore, RISING);
}
void loop() {
digitalWrite(ledPin, state);
}
void incScore() {
score = score+increment;
// add anti-bounce functionality here
}

Confusing increment behaviour

int i = 1;
void setup() {
Serial.begin(9600);
}
void loop() {
if(i == 1){
Serial.print(i);
}
i++;
}
This is intended to only print the value of i once. Why does it keep printing 1 forever?
This code works properly only writing i once:
int i = 1;
void setup() {
Serial.begin(9600);
}
void loop() {
if(i == 1){
Serial.print(i);
}
i = 2;
}
Assuming loop() is called in a loop:
i will overflow in the first example.
In the second example it is fixed to the value of 2 after the first iteration.
You may also want to add some delay because sometimes you can miss the first Serial.println();.
Something like that:
int i = 1;
void setup() {
Serial.begin(9600);
delay(1000); //wait for one second
}
Hope it helps!
If you want your first example to work longer. Change "int" to "long".
int can only store 2 bytes. -32,768 to 32,767. You will reach this number really fast.
long can store 4 bytes. -2,147,483,648 to 2,147,483,647. This will take a whiiiile.

Resources