Arduino Up/Down Counter with 74HC595 and 7-Segment Display

Overview:

The up/down counter is a classic project that could be applied in many applications. In this project, the 74HC595 and the 1-digit display tube (7-segment display) components of the Arduino Kit Upgraded Starter Kit are introduced. 

This acitivity explains how to use the 74HC595 to drive the 7-segment display, and to create Arduino functions.


Hardware Used:

Software Used:

  • Arduino IDE

Application Discussion:

Up/Down Counters are useful in various applications. They are especially effective as timers that whenever it reaches a certain number, (in most cases 9 or 0), a function occurs such as a lock opening or closing, a switch redirecting current, and other similar effects.

The 74HC595 IC

The 74HC595 is a serial-in, serial or parallel-out shift register with output latches. It is a popular IC used in the field of microcontrollers because of it's ability to lessen the number of pins used. It could be observed in this project, where instead of using eight arduino pins to drive the 7-segment display, it was lessened to three pins (data, latch, and clock).

Driving a 7-Segment Display 1-Digit Display Tube

The 7-Segment Display has 7 LEDS that is structured to form numbers from 0-9. The 7-Segment Display in the Upgraded Arduino Kit has the common cathode configuration. This means that the middle pins are to be connected to a common ground to power the LEDs. The LEDs could be lit up by adding current to specific pins and could be formed into shapes as shown in the table below:

a b c d e f g dp OUTPUT
1 1 1 1 1 1 0 0 0
0 1 1 0 0 0 0 0 1
1 1 0 1 1 0 1 0 2
1 1 1 1 0 0 1 0 3
0 1 1 0 0 1 1 0 4
1 0 1 1 0 1 1 0 5
1 0 1 1 1 1 1 0 6
1 1 1 0 0 0 0 0 7
1 1 1 1 1 1 1 0 8
1 1 1 1 0 1 1 0 9


In order to drive them, the 7-Segment Display, the following pins should be connected:

 74HC595 Arduino
pin 16 5V
pin 14 pin 2
pin 13 GND
pin 12 pin 4
pin 11 pin 7
pin 10 5V
pin 8 GND
 74HC595 7-Segment Display
pin 15 a
pin 1 b
pin 2 c
pin 3 d
pin 4 e
pin 5 f
pin 6 g
pin 7 dp

*middle pins of 7-Segment Display is connected to GND of the Arduino

Hardware Setup:

This is the breadboard configuration of the system. All parts are included in the Arduino Upgraded Starter Kit.

Software Setup:

Open the Arduino IDE and upload the code on the Arduino Uno Board.

Code:

The following is the Arduino code of the system. You can download the code in our GitHub page here or copy the code below.
const int dataPin = 2;  
const int latchPin = 4; 
const int clockPin = 7; 

const int upButton = 8;
const int downButton = 12;

int upButtonState = 0;
int downButtonState = 0;

int controlVar = 0; //0-upCount; 1-downCount

int countVar = 0;
 
void setup() {
  pinMode(dataPin, OUTPUT);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);

  pinMode(upButton, INPUT);
  pinMode(downButton, INPUT);
  
  byte bits = myfnNumToBits(countVar) ;
  myfnUpdateDisplay(bits);
  delay(1000);
}

void loop() {
  if (controlVar == 0){
    upCount();
  }
  if (controlVar == 1){
    downCount();
  }
}

void upCount(){
  countVar++;
  if (countVar > 9) {
    countVar = 0;
  }
  byte bits = myfnNumToBits(countVar) ;
  myfnUpdateDisplay(bits);
  delay(1000);
  buttonRead();
}

void downCount(){
  countVar--;
  if (countVar < 0) {
    countVar = 9;
  }
  byte bits = myfnNumToBits(countVar) ;
  myfnUpdateDisplay(bits);
  delay(1000);
  buttonRead();
}

void buttonRead() {
  upButtonState = digitalRead(upButton);
  downButtonState = digitalRead(downButton);
  if (upButtonState == HIGH) {
    controlVar = 0;
  }
  if (downButtonState == HIGH) {
    controlVar = 1;
  }
}

void myfnUpdateDisplay(byte eightBits) {
  digitalWrite(latchPin, LOW); 
  shiftOut(dataPin, clockPin, LSBFIRST, eightBits); 
  digitalWrite(latchPin, HIGH);
}

byte myfnNumToBits(int someNumber) {
  switch (someNumber) {
    case 0:
      return B11111100;
      break;
    case 1:
      return B01100000;
      break;
    case 2:
      return B11011010;
      break;
    case 3:
      return B11110010;
      break;
    case 4:
      return B01100110;
      break;
    case 5:
      return B10110110;
      break;
    case 6:
      return B10111110;
      break;
    case 7:
      return B11100000;
      break;
    case 8:
      return B11111110;
      break;
    case 9:
      return B11110110;
      break;
    default:
      return B10010010; // Error condition, displays three vertical bars
      break;   
  }
}

Code Breakdown:

  • setup()
This is a default Arduino function. In this function, the pins 2, 4 and 7 are set as OUTPUT, and the buttons using the pins 8 and 12 are set as INPUT.

byte bits = myfnNumToBits(countVar) ; myfnUpdateDisplay(bits);
delay(1000);

This line of code in particular is set to display the current countVar variable. This in turn will show '0' everytime the system starts.
  • loop()

This is also a default Arduino function. Any commands set here will be looped indefinitely. This function has an if statement that bases on the variable called controlVar.

  • upCount()

This function is called the moment the controlVar variable is set to 0. It is set to count up (count++) from the last number shown on the 1-digit display tube, and will keep doing so until it runs buttonRead() once again and the controlVar variable changes.

  • downCount()

This function is called the moment the controlVar variable is set to 1. It is set to count down (count--) from the last number shown on the 1-digit display tube, and will keep doing so until it runs buttonRead() once again and the controlVar variable changes.

  • buttonRead()

The moment this function is called, it identifies if the push buttons were pressed or not through the digitalRead() function. Once it identifies what button has been pushed through the (state) variables, it will assign the controlVar variable a number (0 for up, 1 for down).

  • myfnUpdateDisplay()

This function originated from Lester's code. It is the function that allows the 74HC595 to drive the 1-digit display tube. It takes the bits that were converted from the myfnNumToBits() function and updates the display.

  • myfnNumToBits()

Like myfnUpdateDisplay(), this function also originated from Lester's code. It turns the variable count to bits in the format that follows the table above.

Now try making a function!

Now that the code has been discussed, we see this instance repeat three times. One in setup(), another in upCount(), and finally in downCount().

byte bits = myfnNumToBits(countVar) ;
myfnUpdateDisplay(bits);
delay(1000);

As explained before, this set of code is used to allow the 7-Segment Display to show the current value of the countVar variable. In order to organize the code a bit more, it is best to make a new function for this code.

The new function can be named anything but for uniformity purposes, it will be named showCount(). Make sure not to input this inside any existing function.

 void showCount() {
byte bits = myfnNumToBits(countVar);
myfnUpdateDisplay(bits);
delay(1000);
}

Now that the function is made, it is time to call it. In setup, replace the code in this manner:

void setup() {
pinMode(dataPin, OUTPUT);
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(upButton, INPUT);
pinMode(downButton, INPUT);
showCount();
}

Now do the same in upCount() and downCount(). Running the program will produce the same results but with a much cleaner code.

Output:

 This is the video output of the project.

 

Conclusion:

Now that the basics of driving a 7-segment display and creating an Arduino functions have been discussed, this knowledge is useful in other applications. 

Projects that utlizes the idea of driving the 7-Segment Display is the Password-based Door Lock using 9g Servomotor, 4x4 Keypad, and 4-Digit Display Tube.

References:

https://create.arduino.cc/projecthub/meljr/7-segment-led-displays-102-using-a-shift-register-6b6976

7-segment display74hc595ArduinoArduino functionsArduino starter kitArduino unoPush buttonPushbuttons

Leave a comment

All comments are moderated before being published