Build a Simple Binary to Decimal Converter Box
2022-05-26 | By Maker.io Staff
License: See Original Project Switches
Learn how to build a straightforward binary-coded-decimal (BCD) to decimal number converter box by following this beginner-friendly article. The final product contains eight switches that let users input a number between zero and 255 by setting the individual bits of a byte. A custom-built microcontroller board then interprets the input before converting it to its decimal representation to display the result in a more human-friendly format using a standard 16x2 character liquid crystal display (LCD).
This image shows the final product. The LCD shows the input switch states and the decimal equivalent.
BOM
Part/Qty
- 16MHz Quartz - 1
- 22pF Ceramic Capacitor - 2
- 10K Resistor - 1
- 100µF Electrolytic Capacitor - 1
- Arduino UNO - 1
- SN74HC165 Shift Register - 1
- 16x2 Character LCD - 1
- SPDT Switches - 8
- 10K Potentiometer - 1
- Project Box - 1
- Prototyping Perfboard - 1
- DIP-28 IC Socket - 1
- 16-pin Header - 1
Building the Project Using as Few Digital I/O Pins as Possible
Although the schematic diagram of this project may look complicated at first, it only comprises a handful of simple-to-use components:
This image shows the schematic diagram of the project.
The character LCD and the 10K potentiometer are the most prominent parts of the schematic. The display uses six general-purpose input/output (GPIO) pins of the ATMega328PU microcontroller (IC1). Note that the BOM for this project lists an Arduino UNO board. However, the finished build only uses the microcontroller (MCU) of the Arduino board. You can use the Arduino board as a convenient way to program the MCU and then pull the microcontroller out of the development board and plug it into this project’s board.
As this project utilizes only the MCU without the rest of the Arduino UNO, you’ll have to add a few external components that ensure that the IC functions as intended. The 16MHz crystal and the two 22pF capacitors feed the MCU’s clock input. The 10K pull-up resistor prevents the MCU from resetting itself, and the 100µF electrolytic capacitor helps prevent brown-out issues that would also lead to the MCU resetting itself erroneously.
Besides these components, the finished project also contains eight toggle switches that allow users to input a binary coded number. Instead of connecting the switches directly to the MCU’s GPIO pins, I added an SN74HC165 shift register between the switches and the microcontroller. This digital logic chip converts eight parallel inputs to a single serial line, which frees up five GPIO inputs of the MCU. Therefore, the eight switches interface the inputs A through H of the shift register, where A is the least significant bit (the rightmost switch on the finished device). Finally, I connected two control signals and the serial output line to the MCU.
Tips and Tricks for Simplifying the Assembly Process
Start the build by thinking about where you want to place the components in the project box. You can use masking tape and a pen to draw guidelines that help you make straight cuts. Then, create a cutout for the LCD and drill four holes to mount the display to the case using four screws. Then, drill eight holes for the switches and another for the potentiometer. Next, solder the male pin header that comes with the LCD to the display PCB pins. You can later add the female pin header to the perfboard to effortlessly connect the display to the rest of the circuit. Finally, mount the switches, the potentiometer, and the LCD in the enclosure.
Your device should look similar to this once you add all the components. I used a smaller potentiometer that I directly soldered to the perfboard inside the project box.
Next, assemble the circuit on a piece of perfboard. I recommend you start with the IC socket for the ATMega328PU microcontroller, as this part has the largest footprint, then place the female pin header close to the IC socket. Next, connect the other components according to the schematic above. Lastly, tie the switches to the shift register IC using longer, flexible wires. Repeat this process for the external potentiometer.
Connect all the switches to the shift register. The pin headers let you easily disconnect the circuit from the LCD.
Understanding the Device’s Firmware
Similar to the schematic diagram above, the project's firmware may look complicated at first. However, you can break it down into three main tasks, as illustrated by the following flow chart:
This flowchart illustrates the main tasks of the firmware.
The yellow box outlines the setup function’s primary task: initializing the necessary GPIO pins and the LCD. The firmware for this project uses the standard Arduino LiquidCrystal library that comes with recent versions of the Arduino IDE:
void setup()
{
pinMode(SH_LD, OUTPUT);
pinMode(CLK, OUTPUT);
pinMode(QH, INPUT);
digitalWrite(CLK, LOW);
lcd.begin(16, 2);
}
As you can see, the setup function initializes the three control lines connected to the shift register. In addition, the method also pulls the clock low to disable the serial output of the external storage IC. Finally, a special function, which I discuss below, sends clock signals to the shift register when the Arduino is ready to receive the input bits.
The green boxes in the flowchart highlight the primary responsibilities of the loop function. The loop method first resets the cursor position. It then prints some characters and requests the current state of the eight toggle switches from the external IC. Next, the loop function converts the eight input bits to a decimal number before it sends the result to the LCD:
void loop()
{
unsigned long currentMillis = millis();
if(currentMillis - lastMillis > REFRESH_DELAY)
{
lcd.setCursor(0, 0);
lcd.print("BIN: ");
readShiftRegisterValue();
// Write the bit values to the LCD
for(int i = 0; i < 8; i++)
lcd.print(bits[i], DEC);
lcd.setCursor(0, 1);
lcd.print("DEC: ");
lcd.print(getDecimalValue(), DEC);
lcd.print(" ");
lastMillis = currentMillis;
}
}
Converting the eight input bits from a binary-coded decimal to a single integer value is a straightforward task. There are various methods you can employ to achieve the same effect. However, this program loops over all eight bits and multiplies each bit with the appropriate power of two. The resulting sum is the decimal representation of the encoded number:
int getDecimalValue(void)
{
int ret = 0;
int base = 1;
for(int i = 7; i >= 0; i--)
{
ret += bits[i] * base;
base = base * 2;
}
return ret;
}
Requesting Bits from the External Shift Register
The program’s main loop needs to request eight bits from the external shift register. The MCU can accomplish this by setting the three control lines to the correct values:
void readShiftRegisterValue(void)
{
// Pull SH_LD low to latch the switch values
digitalWrite(SH_LD, LOW);
delay(5);
// Pull SH_LD high to enable bit shifting
digitalWrite(SH_LD, HIGH);
delay(5);
for(int i = 0; i < 8; i++)
{
bits[i] = digitalRead(QH);
sendShiftRegisterClockPulse();
}
}
The code snippet above demonstrates how to read eight bits from the SN74HC165 shift register using an Arduino. The MCU first pulls the SH_LD line low to make the shift register latch the switch values. Then, after a short delay, the Arduino sets the SH_LD output high again to enable the register’s shift mode. Doing so makes the shift register output the previously latched bit values using the QH line with every positive clock pulse. To read all eight bits, the for loop first reads and stores the current state of the QH line before sending a positive clock pulse that makes the shift register output the next bit value on its QH line. The program repeats the loop eight times and stores the input bits in an array that the other program parts can access.
Download the Source Code
You can download the complete source code here.
Summary
This image shows the finished product.
This beginner-friendly project lets you build an intriguing BCD to decimal converter that’s perfect for learning how to use the binary system for counting. Eight toggle switches allow users to flip each of the eight bits of a byte. A display shows the input combination and the decimal equivalent of the input values.
As the display already uses quite a few GPIO lines of the microcontroller, I added a parallel-to-serial shift register. Instead of using eight additional GPIO inputs by directly connecting the switches, this approach only occupies three data lines of the ATMega328PU. The firmware instructs the shift register to latch all eight switch states once the MCU is ready to read the following values. Once done, the MCU individually requests each bit from the shift register by reading the QH output and then sending a single clock burst to the shift register. This single rising clock edge lets the register IC know it should output the next bit in the sequence.
Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.
Visit TechForum