Go Down

Topic: Intermittent problem reading many buttons on one analog read. (Read 791 times) previous topic - next topic

John_S

Hi,
I have an intermittent problem when I have 8 push buttons on one analog pin. The issue is when I press button 5, the software will think I pushed button 6. Sometimes. Or I push button 2, and it thinks I pushed button 3 or 4. I've searched a lot, and tried all the solutions I've found, but the problem is still persistent, albeit intermittently. It works 100% only 99% of the time. I can't make a simple sketch that replicates the problem because if its "intermittent-ness".

The circuit is attached.

I have the switch code in a function. It reads the analog input, and decides which switch is pressed. The function will return which switch is pressed. If no switch is pressed, it will return 0. If you hold down the switch, there are 3 speeds that it will repeat the "button press" at, depending how long you hold down the switch (for increasing variables or scrolling quickly).
Code: [Select]
int Pushbutton(){
  int TheButton;

  if (millis() - buttontimeout >40){  //don't read the buttons any faster than every 40 ms
    buttontimeout = millis();
    buttonread = analogRead(buttonpin);
    buttonread = analogRead(buttonpin);  //use a second reading to let the ADC stabilize
    // Button 1 = ~651  //ADC readings
    // Button 2 = ~681
    // Button 3 = ~730
    // Button 4 = ~816
    // Button 5 = ~203
    // Button 6 = ~291
    // Button 7 = ~340
    // Button 8 = ~372   
    // Off = 512
    if (buttonread <661 && buttonread>641) TheButton = 1; //LH Button 1 is pushed
    else if (buttonread <691 && buttonread>671) TheButton = 2; //LH Button 2 is pushed
    else if (buttonread <740 && buttonread>720) TheButton = 3; //LH Button 3 is pushed
    else if (buttonread <826 && buttonread>806) TheButton = 4; //LH Button 4 is pushed
    else if (buttonread <213 && buttonread>193) TheButton = 5; //RH Button 1 is pushed
    else if (buttonread <301 && buttonread>281) TheButton = 6; //RH Button 2 is pushed
    else if (buttonread <350 && buttonread>330) TheButton = 7; //RH Button 3 is pushed
    else if (buttonread <382 && buttonread>362) TheButton = 8; //RH Button 4 is pushed
    else TheButton = 0;

    if (TheButton != oldbutton){ //button has changed
      oldbutton = TheButton;
      if (TheButton !=0){ //button is pressed
        buttonpressed = millis();
        newbrightness = brightness;
        analogWrite(backlightpin, brightness);
        lighttime = millis();
        return TheButton;
      }
    }

      if (millis()- buttonpressed > 3000){   //wait 3000 ms before repeating button extra fast speed
        if (millis() - repeatbutton > 40){ //repeat button every 40ms
          repeatbutton = millis();
          return TheButton;
        }
      }
      else if (millis()- buttonpressed > 1800){ //wait 1800 ms before repeating button high speed
        if (millis() - repeatbutton > 150){ //repeat button every 120ms
          repeatbutton = millis();
         
          return TheButton;
        }
      }
      else if (millis()- buttonpressed > 500){   //wait 500 ms before repeating button slow speed
        if (millis() - repeatbutton > 300){ //repeat button every 300ms
          repeatbutton = millis();
          if (TheButton == 1){
            flashlight = !flashlight;
            buttonpressed = millis();
            return 0;
          }
          else if (TheButton == 8){
            return 9;
          }
            else
            {
            return TheButton;
          }
        }
      }
   
    else return 0;
  }
}


Throughout my code, I call the Pushbutton function like this:
Code: [Select]
button = Pushbutton();

if (button == 2){
  //do stuff
  //...
}
if (button == 3){
  // do stuff
  //...
}
if (button == 4){
  //do stuff
  //ect...
}


In an attempt to rectify the problem due to noise/decoupling, I have a 10uF before the voltage regulator, and a 10uF cap after the voltage regulator. I have 0.1 uF caps on the AVCC, VCC, and AREF pins on the '328. I have 0.1uF caps beside each microchip on the circuit board. I even have a 0.1uF cap beside each bank of buttons. I'm at a loss here to solve my problem.

I'm not even sure if it's a hardware or software problem. Any help would be appreciated.

This is for the project linked to in my signature. I'd like to fix it and have happy customers.
http://jsrintervalometers.blogspot.ca

dhenry

The hardware setup is more complicated than necessary.

For the software, I would do some thing like this:

  Key = readadc();
  If (key > key1_threshold) return 1;
  If (key > key2_threshold) return 2;
  If (key > key3_threshold) return 3;
  ...

Where the threshold goes from the highest to the lowest ( key1_threshold > key2_threshold > key3_threshold ...).
 
For your application, you can simply use a switch / case structure to process it.

John_S

The reason the hardware is the way it is, if you look at the final product, there are 2 banks of 4 buttons. Each bank is on it's own PCB. The PCBs are identical, and can be rotated 180 degrees to go on the left or right. It's for ease of manufacturing.

Also the software you suggested is too simple. I tried something like what you have, but you'd tap the button, and it returns a press 10 or 20 times. I need something that presses once when you want once, and also to scroll through a hundred selections quickly.
http://jsrintervalometers.blogspot.ca

tylernt

John, see the sketch at http://arduino.cc/forum/index.php?topic=129234.0

It shows a method of both preventing multiple "hits" on a single press, as well as better accuracy by double-sampling. The code itself is untested but I think it contains the principles you're looking for.

Go Up