8 buttons from 4 buttons and a potentiometer

Hello all!


(This code does function.)
So I have been trying to get a servo door lock with an LCD screen and 4 buttons. I WAS running into quite a bit of trouble with the keypad of the lock. I needed it to provide me with at least 6 keys. I thought I could get it to press two keys at once but it wasn't working whatever I tried. I was ending up with either only the two button combo or the two button combo doesn't exist. I came up with what I thought would be an easy and ingenious way to convince the Arduino to print the correct information using the 4 buttons and a trimpot on an analog pin, which would give me a value from 0-1023. I did not need to press two buttons at once, I just had a technical limitation of 4 physical buttons

I couldn't get it to work but typing it out here made me realize I had put my "return" clause in the wrong spot, so thank you to all of you for being my rubber duck.

In terms of the breadboard, it's just the 4 buttons on their own circuits, not as a matrix, a potentiometer on its own, analog circuit, and an LCD. I couldn't get mine working in a way it was readable with pin 3 of the LCD being either full or no voltage, but one 330 ohm resistor inserted between the track the power is on to the track pin 3 of the LCD made it legible and I'm assuming two 330 ohm resistors would be perfect. I'd show my breadboard but its a disaster zone because this is one small part of a project.

Here's my code (togglekeys and togglekey are from the troubleshooting phase): THE DELAYS ARE LEFTOVERS FROM A TROUBLESHOOTING STEP

 #include <LiquidCrystal.h>

LiquidCrystal lcd(13,12,11,10,9,8);

int potPosition;

int key[] = {3,4,5,6};

int type;

void setup() {
  potPosition = analogRead(A0);
  Serial.begin(9600);

  lcd.begin(16,2);
  lcd.clear();

  pinMode(key[0], INPUT_PULLUP);
  pinMode(key[1], INPUT_PULLUP);
  pinMode(key[2], INPUT_PULLUP);
  pinMode(key[3], INPUT_PULLUP);
  


}

void loop() {
  potPosition = analogRead(A0);
  //togglekey();
  togglekeys();
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.println(type);
  delay(1000);
}

//-----toggle----

void togglekey (){
  if ((digitalRead(key[0] == LOW)) && (potPosition <= 512)){
    type = 1;
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.println(type);
    Serial.println(type);
    return 1;
  }
    else if ((digitalRead(key[0] == LOW)) && (potPosition > 512)){
      type = 5;
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.println(type);
      Serial.println(type);
      return 5;
  }
    else if ((digitalRead(key[1] == LOW)) && (potPosition <= 512)){
      type = 2;
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.println(type);
      Serial.println(type);
      return 2;
  }
    else if ((digitalRead(key[1] == LOW)) && (potPosition > 512)){
      type = 6; 
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.println(type);
      Serial.println(type);
      return 6;
  }
    else if ((digitalRead(key[2] == LOW)) && (potPosition <= 511)){
      type = 3;
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.println(type);
      Serial.println(type);
      return 3;
  }
    else if ((digitalRead(key[2] == LOW)) && (potPosition >= 512)){
      type = 7;
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.println(type);
      Serial.println(type);
      return 7;
  }
    else if ((digitalRead(key[3] == LOW)) && (potPosition <= 511)){
      type = 4;
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.println(type);
      Serial.println(type);
      return 4;
  }
    else if ((digitalRead(key[3] == LOW)) && (potPosition >= 512)){
      type = 8;
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.println(type);
      Serial.println(type);
      return 8;
  }
    else {
      delay(1000);
    }
}

//-----

void togglekeys (){
  if (analogRead(A0) <= 511){
    if (digitalRead(key[0]) == LOW){
      type = 1;
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.println(type);
      Serial.println(type);
      return 1;
    }
      else if (digitalRead(key[1]) == LOW){
        type = 2;
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.println(type);
        Serial.println(type);
        return 2;
      }
      else if (digitalRead(key[2]) == LOW){
        type = 3;
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.println(type);
        Serial.println(type);
        return 3;
      }
      else if (digitalRead(key[3]) == LOW){
        type = 4;
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.println(type);
        Serial.println(type);
        return 4;
      }
  }
    else if (analogRead(A0) >= 512){
      if (digitalRead(key[0]) == LOW){
        type = 5;
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.println(type);
        Serial.println(type);
        return 5;
      }
        else if (digitalRead(key[1]) == LOW){
          type = 6;
          lcd.clear();
          lcd.setCursor(0,0);
          lcd.println(type);
          Serial.println(type);
          return 6;
        }
        else if (digitalRead(key[2]) == LOW){
          type = 7;
          lcd.clear();
          lcd.setCursor(0,0);
          lcd.println(type);
          Serial.println(type);
          return 7;
        }
        else if (digitalRead(key[3]) == LOW){
          type = 8;
          lcd.clear();
          lcd.setCursor(0,0);
          lcd.println(type);
          Serial.println(type);
          return 8;
        }
    }
    else {
      delay(1000);
    }
}

Hello,

What do you think happens if you press a button during any of these?

Something which is overwhelmingly likely unless you hold a button pressed for ages.

Please read the forum guide, particularly the bit about posting code in code tags and providing a schematic of your circuit and some photos.

Thank you.

My photo didn't upload. My bad. one second. And the pressed button was pressed for ages, because my case required it. I had set it that high so I didn't get overrun with a bunch more copies of the same button press. The code was in code tags.

As I see it your problems are:

  • Trying to have 8 buttons using an unconventional method without first learning to read one button correctly.
  • Reading the state of a button and using that in your code, you should be reading when a button becomes pressed, not, as you are doing, reading when a button is pressed.
  • Slowing the code to a crawl with multiple delays.

There are lots of tutorials on how to read a button, here is mine, but there are plenty more:

There are also lots of topics about problems with buttons, many of which cover problems similar to yours.

It's hard to be sure, but if you are using a bought keypad, those are normally not designed to allow more than one press at the same time. Because the buttons are connected as a matrix, pressing more than one key at the same time can cause other keys to appear to also be pressed: "ghost" or "phantom" presses.

If you build your own matrix keypad from separate buttons, this problem can be avoided by placing a small diode in series with each key.

Hmm...
Unfortunately I am replying on a tablet, which makes checking things a pain. I'm also about to go out, this is likely to be my last reply for some time today. There are others here who will, I'm sure, offer their advice too.

Please read the tutorials about buttons.

Based on what you described and what you tried in code, pressing 2 buttons at the same time might not be possible with your current setup.

Right now in your code if you press the first button with pot value <= 512, you get 1, however even if you press another button, it will only register the first button as pressed. This is due to the if else statements not allowing the code to check the other buttons, while the one before it is pressed.

It would actually be easier to change the value (type) based on the position of the Pot and a button to append it to an array of entered values. Think of it like a dial on a safe. Doing this, you could just have 1 button instead of 4 and have values from 0-9 instead of 1-8.

You also should add debounce to your button(s) too and please look into the example sketch Blink Without Delay, it will help you with timing without the need for “delays()” in the code.

My issue was not that I needed two have two buttons pressed at the same time, as I just had a physical limitation at the time to 4 buttons. This potentiometer method allows me to have a full 4x4 key pad in the space of five buttons. The delays are leftovers from a troubleshooting step where I was getting overrun. Those are easy enough to change. I thought people would find this an interesting way to solve an issue. I wasn't having an issue with one button being read at a time. I know how to use python, this was the first on-my-own with a constraint placed on me in the Arduino code.
In the choice between getting two buttons worth of input to read correctly vs just turning a dial to give me more buttons, this was the path of least resistance. This code does actually run, even when I change the delays to be more reasonable.

I do very much resent that comment you left earlier about me not knowing how to read one button.

Using a button library would make the code so much easier to write and read.

There are many libraries to choose from such as Button in easyRun or OneButton or Toggle or EasyButton or Bounce2, ...

here is an example using Toggle (I could not test it in wokwi as the server was too busy)

but it's likely to work.

#include <Toggle.h>

class augmentedButton : public Toggle {
  public:
    byte bPin;
    const char* label1;
    const char* label2;
    augmentedButton(const byte p, const char* l1, const char* l2) : Toggle(p), bPin(p), label1(l1), label2(l2)  {}
    void begin() {Toggle::begin(bPin);}
};

const byte potPin = A0;

augmentedButton buttons[] = {
  {3, "yellow", "YELLOW"},
  {4, "blue", "BLUE"},
  {5, "red", "RED"},
  {6, "green", "GREEN"},
};

void setup() {
  for (auto& b : buttons)  b.begin();
  Serial.begin(115200);
}

void loop() {
  bool shifted = analogRead(potPin ) >= 512;
  for (auto& b : buttons) {
    b.poll();
    if (b.onPress()) {
      Serial.println(shifted ? b.label1 : b.label2);
    }
  }
}

Hello,
I'm back and I'm using my PC so it's a lot easier to see things. I see you did attempt code tags when you first posted and you've now sorted them out and got them working, thank you. I think the problem with your first attempt was not having <code> on a line of its own. Anyway, I'm pleased you sorted it.

Sure, but we only know what you post. I see you have amended your first post with a comment saying the code functions.

I was under the impression you were asking for help with your code, I didn't think you were posting an idea others might be interested in. However, yes, I like seeing imaginative ways to solve problems, so, yes, if that's what this is intended to be then thank you for sharing it.

OK... Why do you resent it? I mean, I probably could have expressed it better, not sure. It was intended to be helpful, maybe it was, maybe not, only you can judge that. But resent? I don't understand. You appeared to me to be asking for help, my reply was intended to help.

Given what you've now explained:

  • Do you want any (more) help?
  • Do you want any help from me?