What I am doing is connecting 3 buttons on 1 analog pin while reading the incoming values on A0. This value determines what button has been pushed.
The problem is that I need to count how many times that button has been pushed but with this code it keeps counting as long as but button has been pushed.
How can I tackle this? By creating some sort of "changestatus" code?
Please some advise.
void loop()
{
Serial.print("Knop 1: ");
Serial.println(button1Value);
Serial.print("Knop 2: ");
Serial.println(button2Value);
Serial.print("Knop 3: ");
Serial.println(button3Value);
buttonValue = analogRead(A0); //Read in the button value
if (buttonValue>=925 && buttonValue<=935){ // Set button 1 Value
//button1Value = 1;
digitalWrite(ledPin, HIGH);
if (button1Value>=0 && button1Value<=4){
button1Value=button1Value+1;
}
else button1Value=0;
}
You need to detect when the value read enters the range being tested rather than when it is in the range being tested.
The StateChangeDetection example in the IDE shows how to do this with digital inputs. It should not be difficult to adapt it for use with analogue inputs.
I used a tuto from site and changed the conditions to my setup.
However it keeps counting while i hold the button. What am I missing?
// this constant won't change:
const int buttonPin = 2; // the pin that the pushbutton is attached to
const int ledPin = 10; // the pin that the LED is attached to
// Variables will change:
int buttonPushCounter = 0; // counter for the number of button presses
int buttonState = 0; // current state of the button
int lastButtonState = 0; // previous state of the button
void setup() {
// initialize the button pin as a input:
pinMode(buttonPin, INPUT);
// initialize the LED as an output:
pinMode(ledPin, OUTPUT);
// initialize serial communication:
Serial.begin(9600);
}
void loop() {
// read the pushbutton input pin:
buttonState = analogRead(A0);
// compare the buttonState to its previous state
if (buttonState != lastButtonState) {
// if the state has changed, increment the counter
if (buttonState>=925 && buttonState<=935) {
// if the current state is HIGH then the button went from off to on:
buttonPushCounter++;
Serial.println("on");
Serial.print("number of button pushes: ");
Serial.println(buttonPushCounter);
} else {
// if the current state is LOW then the button went from on to off:
Serial.println("off");
}
// Delay a little bit to avoid bouncing
delay(50);
}
// save the current state as the last state, for next time through the loop
lastButtonState = buttonState;
// turns on the LED every four button pushes by checking the modulo of the
// button push counter. the modulo function gives you the remainder of the
// division of two numbers:
if (buttonPushCounter % 4 == 0) {
digitalWrite(ledPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
}
}
The digital version of the program relies on the fact that the state of the input can only be HIGH or LOW and it detects when the value has changed since the last time that it was read and tests what it is now
However, using an analogue input there are no HIGH/LOW values to test so you must do something else. Maybe something like this (untested)
Now you have variable that will tell you whether the button is pressed or not that you can use to determine whether it became pressed since the last time you looked
I dont have the code at hand right now but the range check I have to do 3 times, in 1 IF statement.
I also need to track the state and counter of all 3 so at this point it is setup fairly simple. Maybe I could put the buttons in an array and do it with 1 check.
Do you know if I can put those ranges in variables? ;
RangeButton1 = 995 - 1005;
if (buttonValue = RangeButton1)
Button1State=HIGH;
Something like that, can that be done?
For responsetimes purposes (RC CAR) I dont want to use While, For and delay. Or at least as little as possible.
The buttons are meant for navigation in a menu displayed on a LCD or Oled screen. I have 12 pages to navigate to. These pages are indexed in a 4x4 matrix array. So when it is 0 (through switch case) I get main menu etc etc. With the first two buttons I fill the query to get menu[1][2].
All this is to program the arduino that sits in a fully waterproof enclosure in the RC car. I can turn data logging on or of, GPS on or of, max brake power.
And also read max speed, session duration, acceleration time, max RPM etc.
The arduino (or atmega only) will only come out of the care if reaaally needed. All other parameters will be programmed with this display.
So, ambitious as it is, I first want it to work before I experiment with the code. Unless I run into some other issues and have time to spare.
This is the code that I now use for testing. Because I can find tutorials for individual things, I cannot find it for smarter programming. So please, advise
// this constant won't change:
const int ledPin = 10; // the pin that the LED is attached to
const int valuePin = A0; // the pin that the Buttons are attached to
// Variables will change:
int button1PushCounter = 0; // counter for the number of button 1 presses
int button2PushCounter = 0; // counter for the number of button 2 presses
int button3PushCounter = 0; // counter for the number of button 3 presses
int button1State = 0; // current state of button 1
int button2State = 0; // current state of button 2
int button3State = 0; // current state of button 3
int lastButton1State = 0; // previous state of button 1
int lastButton2State = 0; // previous state of button 2
int lastButton3State = 0; // previous state of button 3
int buttonValue=0; // Waarde op Pin A0
int maxButton1=5; // Maximaal aantal pushes tot terug naar 0;
int maxButton2=4; // Maximaal aantal pushes tot terug naar 0;
int maxButton3=4; // Maximaal aantal pushes tot terug naar 0;
//String menu1 = "Voltage";
//String menu2 = "Temperatuur";
//String menu3 = "Remmen";
//String menu4 = "Prestaties";
//String menu5 = "Iets Anders";
char *myMenus[] = {"Hoofdmenu", "Temperatuur", "Voltage",
"Remmen", "Prestaties", "Iets Anders"
};
void setup() {
// initialize the LED as an output:
pinMode(ledPin, OUTPUT);
// initialize serial communication:
Serial.begin(9600);
}
void loop() {
// read the pushbutton :
//Serial.println(buttonValue);
buttonValue = analogRead(valuePin);
//Set buttons High or Low
if (buttonValue>=925 && buttonValue<=935){
button1State = HIGH;
}
else button1State = LOW;
if (buttonValue>=985 && buttonValue<=993){
button2State = HIGH;
}
else button2State = LOW;
if (buttonValue>=1015 && buttonValue<=1055){
button3State = HIGH;
}
else button3State = LOW;
//************************ Button 1 **********************************
//Serial.print("number of button pushes: ");
// Serial.println(buttonPushCounter);
// compare the buttonState to its previous state
if (button1State != lastButton1State) {
// if the state has changed, increment the counter
if (button1State == HIGH) {
if (button1PushCounter>=0 && button1PushCounter<maxButton1){
button1PushCounter++;
//buttonValue = 0;
}
else button1PushCounter=0;
// if the current state is HIGH then the button went from off to on:
//button1PushCounter++;
//Serial.println("on");
switch (button1PushCounter) {
case 1:{
Serial.println (myMenus[button1PushCounter]);
break;
}
case 2:{
Serial.println (myMenus[button1PushCounter]);
break;
}
case 3:{
Serial.println (myMenus[button1PushCounter]);
break;
}
case 4:{
Serial.println (myMenus[button1PushCounter]);
break;
}
case 5:{
Serial.println (myMenus[button1PushCounter]);
break;
}
case 0:{
Serial.println("Hoofdmenu");
break;
}
}
//Serial.print("number of button 1 pushes: ");
//Serial.println(button1PushCounter);
} else {
// if the current state is LOW then the button went from on to off:
//Serial.println("off");
}
// Delay a little bit to avoid bouncing
delay(50);
}
// save the current state as the last state, for next time through the loop
lastButton1State = button1State;
//************************ Button 1 **********************************
//************************ Button 2 **********************************
//Serial.print("number of button pushes: ");
// Serial.println(buttonPushCounter);
// compare the buttonState to its previous state
if (button2State != lastButton2State) {
// if the state has changed, increment the counter
if (button2State == HIGH) {
// if the current state is HIGH then the button went from off to on:
button2PushCounter++;
Serial.println("on");
Serial.print("number of button 2 pushes: ");
Serial.println(button2PushCounter);
Serial.println(buttonValue);
} else {
// if the current state is LOW then the button went from on to off:
Serial.println("off");
}
// Delay a little bit to avoid bouncing
delay(50);
}
// save the current state as the last state, for next time through the loop
lastButton2State = button2State;
//************************ Button 2 **********************************
//************************ Button 3 **********************************
//Serial.print("number of button pushes: ");
// Serial.println(buttonPushCounter);
// compare the buttonState to its previous state
if (button3State != lastButton3State) {
// if the state has changed, increment the counter
if (button3State == HIGH) {
// if the current state is HIGH then the button went from off to on:
if (button3PushCounter>=0 && button3PushCounter<maxButton3){
button3PushCounter++;
//buttonValue = 0;
}
else button3PushCounter=0;
Serial.println("on");
Serial.print("number of button 3 pushes: ");
Serial.println(button3PushCounter);
Serial.println(buttonValue);
} else {
// if the current state is LOW then the button went from on to off:
Serial.println("off");
}
// Delay a little bit to avoid bouncing
delay(50);
}
// save the current state as the last state, for next time through the loop
lastButton3State = button3State;
//************************ Button 3 **********************************
// turns on the LED every four button pushes by checking the modulo of the
// button push counter. the modulo function gives you the remainder of the
// division of two numbers:
if (button1PushCounter % 4 == 0) {
digitalWrite(ledPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
}
}
I would put the values for each button in a struct and put the structs in an array
Something (untested) to get you started :
struct dataDefinition
{
const byte pinNumber;
const int lowerValue;
const int upperValue;
boolean previouslyPressed;
byte count;
};
dataDefinition data[] =
{
{A0, 500, 600, false, 0}, {A1, 600, 700, false, 0}, {A2, 700, 800, false, 0}
};
void setup()
{
Serial.begin(115200);
}
void loop()
{
for (int inputNumber = 0; inputNumber < 3; inputNumber++)
{
boolean buttonIsPressed = false;
int inputValue = analogRead(data[inputNumber].pinNumber);
if (inputValue >= data[inputNumber].lowerValue && inputValue <= data[inputNumber].upperValue)
{
buttonIsPressed = true;
}
else
{
buttonIsPressed = false;
}
//code here to test whether the button has become pressed and to act on it if it has
//do this by testing the previouslyPressed value against the current value
//update the count if has become pressed
}
}
You need to put in the correct pin numbers and lower/upper values and add code where indicated
Thanks but your code assumes that every button has its own pin. Mine (4pcs) are all connected to a0. The only way the code can see the difference in the buttons is the resistance and thus value on A0 that the button creates. Each button has its own resistor.
EDIT: I see what you did, sorry. But how fast is this FOR loop? I really want to avoid FOR and while as much as possible.
Throughout the sketch the arduino is receiving signals from my RC receiver and has to put that signal out again with the least of delay.
Probably the slowest part of the code is the analogRead(). If you are worried about that being in a for loop then don't use one, use the fact that loop() repeats and check for just one range of input values each time through loop() by incrementing an index variable.
I apologise if my example code using an array of structs has confused things but you seem to have grasped the principle of such an array.
To use an array of structs with one pin the first thing to do us to change the data in the struct as the pin number is not needed. I will leave you to write the actual program but the principle will be as follows
start of loop()
read the analogue pin
for each level in the array check to see if the value read is in the target range
if the value is in range of the current level of the array
check whether the state has changed and the button is now pressed
if the button has become pressed
take whatever action is required such as moving a servo, changing the state of an LED etc
end if
save the current button state as the previous state
end if
end of for loop
end of loop()
If you don't want to use a for loop then use loop() to do the looping for you so that you can deal with the RC signals between checking for button presses
Where do you change the state of previously pressed? I cant find it in the code?
Well spotted, the code did not save the previous state
I will try and implement your tips. The only challenge I have is to map the analog input to a certain button. I will start out by testing one button and work my way further.
IF I can figure it out I will also have way to identify the throttle lever on my remote to be in Neutral, Forward, Brake or Reverse state.