1
\$\begingroup\$

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

\$\endgroup\$

3 Answers 3

1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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);
\$\endgroup\$
0
\$\begingroup\$

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()

\$\endgroup\$
11
  • \$\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
    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
    Jan 15, 2014 at 18:00
  • \$\begingroup\$ Yes, when in the loop is the code from the second part of your answer. \$\endgroup\$
    – Nick
    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
    Jan 15, 2014 at 18:11
  • 1
    \$\begingroup\$ @Ricardo proteus \$\endgroup\$
    – alexan_e
    Jan 17, 2014 at 13:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.