Digitally Combine Buttons (4 Bit Buttons)

Hi,

I am fairly new at electronics/arduino. I have an understanding of them, but am no where near an expert.

I have a project that I want to start working on and I am planning on using an arduino uno for this.

Basically, I need to consolidate as many buttons as I can on as few pins as possible. I haven’t done very much research on this, but I did come across some posts that say to use resistors on buttons attached to the same analog pins and read their value. I didn’t like this because of the safety issues involved in my project (cnc router). So I think I’ve come up with a safer way.

The reason for my posting this is to get suggestions/input/better way of doing it/has it been done before?. Anything helps. I drew out my design on autodesk circuts: https://circuits.io/circuits/2586967-4bit-buttons

The code on the Arduino is as follows:

int bitPin1 = 13; // Pin 13 connected to bit 1
int bitPin2 = 12; // Pin 12 connected to bit 2
int bitPin3 = 11; // Pin 11 connected to bit 3
int bitPin4 = 10; // Pin 10 connected to bit 4
int bin = 0000; // Declaring bin
int Pin9 = 9; // Setting test pin

void setup(){
  Serial.begin(9600);       // initialize serial communication at 9600 bits per second:
  pinMode(bitPin1, INPUT);  // Setting pin 13 to bit1
  pinMode(bitPin2, INPUT);  // Setting pin 12 to bit2
  pinMode(bitPin3, INPUT);  // Setting pin 11 to bit3
  pinMode(bitPin4, INPUT);  // Setting pin 10 to bit4
  pinMode(Pin9, OUTPUT);    // Setting pin 9 (test pin) to output
}

void loop(){
  int bitState1 = digitalRead(bitPin1);  // Read state of pin 13
  int bitState2 = digitalRead(bitPin2);  // Read state of pin 12
  int bitState3 = digitalRead(bitPin3);  // Read state of pin 11
  int bitState4 = digitalRead(bitPin4);  // Read state of pin 10
  
  byte bin=bitState1|(bitState2<<1)|(bitState3<<2)|(bitState4<<3);
  Serial.print(bin,BIN);
  Serial.print("\t");
  delay(1);
  
  if (bin == 1){  // If dec value of button depressed is 1 then pin 9 is high, not low (repeat for all dec values)
    digitalWrite(Pin9, HIGH);
  }
  else
  {
    digitalWrite(Pin9, LOW);  
  }

}

This design uses 15 buttons (16 depending on how you look at it), but only 4 arduino pins. Each button is assigned a binary byte of 4 bits. When one is depressed you will see the 4 red leds light up in accordance to its defined byte. The blue led is a test to make sure that pin 9 is active when the byte is equal to 0001. Hopefully all my terminology is correct and this all makes sense.

In my design, there are a bunch of diodes that I was wondering if there is anyway to get around. Also there is a mess of wires. Like I said, I’m pretty new at this and any suggestions would be appreciated.

You could use a shift register which is read by the Arduino.
Read this:
http://www.gammon.com.au/forum/?id=11979

You could also make a 16 to 4 diode matrix if you garrentee only one button is pushed at a time.
Similar to this:

I vote a parallel to serial shift register (16 bit). It can be constantly triggered untill at least one button is pressed...then delay for say 500ms, then take a final accepted reading (3 times to make sure ofc) which in that time button bouncing and if the user was trying to push more than one button will be read.

cmhigger:
but I did come across some posts that say to use resistors on buttons attached to the same analog pins and read their value. I didn’t like this because of the safety issues involved in my project (cnc router).

Why would that have safety issues?

If there needs to be a safety cut-out it should be implemented with a BIG RED SWITCH quite independently of an Arduino.

…R

Hi Larry and Johnny,

Thanks for the information I will definitely look into your suggestions.

Hi Robin,

This project is for a cnc machine. I do have an e-stop place directly on my machine. What I am trying to do is make a handheld pendant to jog the machine and have various other functions. It will plug directly into the computer (usb) and control it through software. I know I can just buy one online, but I like the theory of why buy it for $10 when you can make it for $100.

My concern with using analog and resistors (again I'm not very familiar with this) is that when the arduino reads the analog pin with a button depressed it would see a value that is "around" x. It wouldn't see a hard yes or no. With the digital way I feel like it is a hard yes or no answer. Please correct me if I am wrong in thinking this.

With a hard yes or no, I wouldn't have to worry about the arduino thinking I pressed a different button than I actually did and crashing an expensive tool into expensive material.

After thinking about it, I would have to change "safety issues" to more along the lines of money issues.

cmhigger:
it would see a value that is “around” x.

With a suitable choice of resistors “around X” would be totally different from “around Y” and there would be no confusion.

…R

Hey Robin,

I see what you are saying. If I were to use a resistor with a tight tolerance there should be no problem. Right?

I tried to think of other variables that could cause the arduino to miss read a button push and have another question you could maybe answer.

I doubt this is something I should be concerned about, but would help in resistor selection and programming. The 5v power supply on the arduino board, is there any fluctuation in the voltage? I know that it is a regulated 5v but does the regulator have a tolerance that is allowed through it? Such as +/-.1v.

The only thing that I could find on this subject was that it only allows for 5v.

Thanks for all the advice.

Sounds from your description that you will not be pressing more than one button at once? If that's true, you can read up to 20 buttons with 5 Arduino pins. No chips will be needed, but each button must be wired with a diode in series with it. The technique is called Charlieplexing.

cmhigger:
I see what you are saying. If I were to use a resistor with a tight tolerance there should be no problem. Right?

I don't think the tolerance really matters.

What is important is that the voltage seen by the ADC when one button is pressed is very different from the voltage when another button is pressed.

Suppose you have this
5v ------- 1k ----A--------X---- 1k --------Y-------- 1k ---------- GND

Suppose the ADC is connected at A and the switches are connected at X and Y and pressed connect that point to GND.

When no switch is pressed the ADC will see 3.3v. If switch X is pressed it will see 0v and is switch Y is pressed it will see 2.5v. It won't have any trouble distinguishing between them (E&OE).

...R