My code:
#define MAX 50
const int LED1 = 2;
const int LED2 = 3;
const int LED3 = 4;
const int LED4 = 5;
int array[MAX];
int old_b = 0;
int val;
int counter = 0;
int i;
int temp;
int L1;
int L2;
void setup () {
pinMode (A5, INPUT_PULLUP);
Serial.begin(9600);
}
int readButtons (int pin) {
int b, c;
c = analogRead(pin);
Serial.print("analogRead = ");
Serial.println(c);
delay(100);
if (c > 1015) b = 0;
else if (c > 70 && c < 76) b = 1;
else if (c > 122 && c < 128) b = 2;
else if (c > 169 && c < 175) b = 3;
else if (c > 209 && c < 217) b = 4;
else if (c > 247 && c < 256) b = 5;
else if (c > 280 && c < 291) b = 6;
else b = 0;
if (b == old_b) {
return 0;
old_b = b;
} else {
return b;
old_b = b;
}
}
void loop () {
while ((val = readButtons(5)) != 5) {
if ((val == 1) || (val == 2) || (val == 3) || (val == 4)) {
array[counter] = val;
Serial.print("In ");
Serial.print(counter);
Serial.print(" saving ");
Serial.println(val);
delay(200);
counter++;
if (counter == MAX) {
counter = 0;
}
}
}
temp = counter;
counter = 0;
for (i = 0; i < temp; i++) {
if (array[i] % 2 == 0) {
L1 = 2;
L2 = array[i] / 3 + 3;
} else {
L2 = 5;
L1 = array[i] % 3 + 3;
}
if (readButtons(5) != 5) {
digitalWrite (L1, HIGH);
if (readButtons(5) != 5) {
digitalWrite (L2, HIGH);
delay(1000);
digitalWrite (L1, LOW);
digitalWrite (L2, LOW);
if (readButtons(5) == 5) {
i = temp;
}
} else {
digitalWrite (L1, LOW);
i = temp;
}
}
}
}
So I have a function which detects if a button was pressed. Prior to that, I have determined in which range are values for certain button and all buttons are connected on analog pin 5 like this, except I have them 6 and my resistors have 2200 ohms. In the while () {...}
loop, while the 5th button isn't pressed, Arduino is "looking" if any of first four buttons was pressed. If it was store it in an array and if not keep "looking". When 5th button is pressed, we brake out and store last known place in array in which value was stored and set the place counter to zero so when starting again, Arduino stores values in the first place of array. Then based on that what is stored I determine which pin/LED will light up. If at any time during blinking LEDs 5th button is pressed again, Arduino stops the blinking and again waits for the presses from first four buttons. That is how it is supposed to work in theory. In practice I still can't get it to stop blinking every time 5th button is pressed again. I have to press it multiple times, sometimes two or sometimes even more presses are necessary if I want it to stop blinking. I don't think using interrupts will help, since I don't know how I should implement them in my problem. Here is my circuit (except I have Arduino Duemilanove Atmega 168). LEDs go 1 to 4 from right to left:
Schematics
3 Answers 3
From your description, it seems you need to debounce the switch.
You can do this
Since you seem to be using some kind of resistive ladder to read multiple buttons on one ADC port, this will be a little more complicated.
This section of your code looks strange to me:
if (readButtons(5) != 5) {
digitalWrite (L1, HIGH);
if (readButtons(5) != 5) {
digitalWrite (L2, HIGH);
Your readButtons(5) function will return 0 unless a change has occurred in the button state.
So for the digitalWrite (L2, HIGH); code to be executed you would need to detect two button presses in very rapid succession.
I think this must be a bug, as I cannot think of any plausible reason for the code to be like this.
Maybe you intend to have presses separated by one second (for example)?
Then surely the code should be:
if (readButtons(5) != 5) {
digitalWrite (L1, HIGH);
delay(1000);
if (readButtons(5) != 5) {
digitalWrite (L2, HIGH);
I think the problem is the way you apply big delays that prevent the fast scan of the buttons.
In the following (untested) code I'm using small 1ms delays executed multiple times while the buttons keep being scanned
#define MAX 50
const int LED1 = 2;
const int LED2 = 3;
const int LED3 = 4;
const int LED4 = 5;
int array[MAX];
int old_b = 0;
int val;
int counter = 0;
int i;
int temp;
int L1;
int L2;
void setup()
{
pinMode(A5, INPUT_PULLUP);
Serial.begin(9600);
}
int readButtons(int pin)
{
int b, c;
c = analogRead(pin);
Serial.print("analogRead = ");
Serial.println(c);
//delay(100);
if(c > 1015)
{
b = 0;
}
else
if(c > 70 && c < 76)
{
b = 1;
}
else
if(c > 122 && c < 128)
{
b = 2;
}
else
if(c > 169 && c < 175)
{
b = 3;
}
else
if(c > 209 && c < 217)
{
b = 4;
}
else
if(c > 247 && c < 256)
{
b = 5;
}
else
if(c > 280 && c < 291)
{
b = 6;
}
else
{
b = 0;
}
if(b == old_b)
{
return 0;
old_b = b;
}
else
{
return b;
old_b = b;
}
}
void loop()
{
unsigned char counter_var = 0;
val = readButtons(5); // read the buttons
while(val != 5)
{
val = readButtons(5); // read the buttons
if(counter_var == 0)
{
if((val == 1) || (val == 2) || (val == 3) || (val == 4))
{
counter_var == 200; // to apply ~200ms delay
array[counter] = val;
Serial.print("In ");
Serial.print(counter);
Serial.print(" saving ");
Serial.println(val);
//delay(200);
counter++;
if(counter == MAX)
{
counter = 0;
}
}
}
else
{
counter_var--; // if delay>0 then this decrements and counts delay ms
delay(1);
}
}
counter_var = 0;
temp = counter;
counter = 0;
for(i = 0; i < temp; i++)
{
if(array[i] % 2 == 0)
{
L1 = 2;
L2 = array[i] / 3 + 3;
}
else
{
L2 = 5;
L1 = array[i] % 3 + 3;
}
if(readButtons(5) != 5)
{
digitalWrite(L1, HIGH);
if(readButtons(5) != 5)
{
digitalWrite(L2, HIGH);
delay(1000);
digitalWrite(L1, LOW);
digitalWrite(L2, LOW);
if(readButtons(5) == 5)
{
i = temp;
}
}
else
{
digitalWrite(L1, LOW);
i = temp;
}
}
}
}
The main change I have applied is in the following part ( start of loop() )
unsigned char counter_var = 0;
val = readButtons(5); // read the buttons
while(val != 5)
{
val = readButtons(5); // read the buttons
if(counter_var == 0)
{
if((val == 1) || (val == 2) || (val == 3) || (val == 4))
{
counter_var == 200; // to apply ~200ms delay
array[counter] = val;
Serial.print("In ");
Serial.print(counter);
Serial.print(" saving ");
Serial.println(val);
//delay(200);
counter++;
if(counter == MAX)
{
counter = 0;
}
}
}
else
{
counter_var--; // if delay>0 then this decrements and counts delay ms
delay(1);
}
}
and I have removed the delay(100)
from readButtons()
-
\$\begingroup\$ I have tired your code and unfortunately it didn't work. The one without the changes in loop would work perfectly, except it somehow always forgets to execute first pressed button command. For instance I press 1,2,2,3,4 it will execute like i have pressed 2,2,3,4. With the corrections in loop it doesn't recognizes presses of the 5th button that is it doesn't start/end blinking after pressing the 5th button. \$\endgroup\$Nick– Nick2014年01月15日 17:39:23 +00:00Commented Jan 15, 2014 at 17:39
-
\$\begingroup\$ @Mate so the cede for 1-4 buttons works and you only have a problem with button 5 detection in my code? \$\endgroup\$alexan_e– alexan_e2014年01月15日 18:00:35 +00:00Commented Jan 15, 2014 at 18:00
-
\$\begingroup\$ Yes, when in the loop is the code from the second part of your answer. \$\endgroup\$Nick– Nick2014年01月15日 18:05:58 +00:00Commented Jan 15, 2014 at 18:05
-
\$\begingroup\$ @Mate What you have used is the complete code of the first part of my reply, right? The second one is already a part of the first one and should be ignored. \$\endgroup\$alexan_e– alexan_e2014年01月15日 18:11:46 +00:00Commented Jan 15, 2014 at 18:11
-
1\$\begingroup\$ @Ricardo proteus \$\endgroup\$alexan_e– alexan_e2014年01月17日 13:33:47 +00:00Commented Jan 17, 2014 at 13:33
Explore related questions
See similar questions with these tags.