A Simple Binary Counter on the Arduino Uno

In the last few months I've gotten back into working with electronics. This was the initial project I built when my Arduino Uno arrived in the mail.

The idea behind the circuit is straightforward – we'll use the digital I/O pins on the Arduino to both accept push-button input from the user, and to display the current counter value.

The diagram is as follows:

The LEDS

The digital output pins on the Arduino Uno from 1 to 6 will be used to power our 6 display resistors. Each LED will need a resistor after it to to limit current flow through the resistor, which protects the LED from damage, as well as the Arduino which needs to supply the current.

We'll use 4.7 kΩ resistors: by Ohm's law, 5 v / 4700 Ω = 1.06383 mA, which will mean out LEDs are visible while keeping our current well below the ~20mA current they're rated at.

The Buttons

When reading from the input pins on the Arduino, we'll need to keep some things in mind.

First, the input pins are digital, so the Arduino expects ~5V, which we'll provide from the 5V rail. You could get away with down to around 3.5V, but after that the Arduino isn't likely to consistently read the input pin as a logical 1.

Second, you might be tempted to neglect the 10kΩ resistors between the input pins and ground, but you'd figure out soon enough why they are important. They're "pull-down" resistors, and allow the input pin to settle at logical 0 (ground). With nothing attached to the pin, any transient voltage could easily cause the pin to read as a logical 1.

Third, buttons, like all electrical components are imperfect. Our simple push button has a spring inside it, and when we release it after pressing it, it's likely to vibrate, or "bounce" a little before opening back up. We'll need to make sure to add some debounce in our code to account for this.

The Code
const int ledPins[] = {1, 2, 3, 4, 5, 6};  
const unsigned int numLeds = 6;

// keep button state in one place
struct button  
{
  int pin;
  int state;
  int prevState;
};

button make_button(int pin)  
{
  // we'll need to set the pin to accept input before
  // reading it
  pinMode(pin, INPUT);
  return button{pin, 0, 0};
};

button upButton;  
button downButton;  
long unsigned counter = 0;

// write a number (in binary) to the output pins
void write_bin(int num)  
{
  // for each output pin get the least significant digit 
  // of the counter, write to the pin, then shift right
  for (int i = 0; i < numLeds; i++) {
    digitalWrite(ledPins[i], num & 1);
    num >>= 1;
  }
}

bool read_button(button &but)  
{
 // read the pushbutton input pin:
  but.state = digitalRead(but.pin);

  // compare the buttonState to its previous state
  if (but.state != but.prevState) {
    // if the state has changed, increment the counter
    if (but.state == HIGH) {
      return true;
    } else {
      // if the current state is LOW then the button
      // wend from on to off:
      return false;
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state,
  //for next time through the loop
  but.prevState = but.state;
  if (but.state) {
    return true;
  } else {
    return false;
  }

}

void setup()  
{
  // initialize all LEDs to output
  for (int ledIndex = 0; ledIndex < numLeds; ledIndex++) {
    pinMode(ledPins[ledIndex], OUTPUT);
  }

  // setup buttons
  upButton = make_button(11);
  downButton = make_button(12);
}

void loop()  
{
  if (read_button(upButton))
  {
    if (counter < 63) {
      counter += 1;
    }
    delay(200);
  }
  else if (read_button(downButton))
  {
    if (counter > 0) {
      counter -= 1;
    }
    delay(200);
  }
  write_bin(counter);
}
The Result