It was my birthday last month. Your lack of card and cake was noted, dear reader, but let’s not dwell on it…

One of the presents I was most eager to get to grips with was my new Raspberry Pi 2! (It’s a single-board computer roughly the size of a credit card) Now, I studied both GCSE and A-Level Electronics, but haven’t done anything remotely related since I left school, so I figured I should start with the basics. After setting up Raspbian and fitting the device into its snug little case I set about figuring out how to turn on a single LED.

I won’t bore you with that little exercise, this post is about how I wrote a 4-bit binary counter with a “heartbeat” made of 5 LEDs and some hastily (and probably shoddily) written Python.

Python 4-Bit LED Counter

Pasted below is the current version of the script I’ve written to count in binary - displayed by the LEDs - from 0 to 15. I am not an expert in writing Python scripts; in fact, it’s more accurate to describe me as a total novice. I’ve written in other languages before; things like HTML, PHP, Visual Basic, BASIC, C++, C#, etc. so I am familiar with basic programming concepts but I’m pretty rusty.

The Logic

Very roughly I approached the project by thinking about it like this:

  1. I need to count from 0 to 15 (i.e. 16 numbers).
  2. I need to convert that somehow from decimal into binary.
  3. I need to, bit by bit, figure out whether each LED should be 1 or 0 for each whole number.
  4. I need to turn the LEDs on, or off, based on the bit they represent (0, 2, 4, 8 or the heartbeat) for the current number in the count.

There is probably a very simple way to reduce the 4 steps above into 2 but I’m not that good, yet. I should admit that this isn’t the first stab, but the final steps after much thinking and experimenting. I decided to include a “heartbeat” LED to make it easier to identify when a number was incremented as the code currently builds the binary representation serially (i.e. one LED at a time) rather than in parallel (i.e. just flashing all 4 bits in one go). When I first ran the code I couldn’t figure out whether I was actually counting accurately or whether I’d just made a bunch of LEDs turn on and off at random!

This threw up a separate issue around timing. It’s well-known that the Raspberry Pi isn’t best suited to time-sensitive applications, even for something this simple. The delays are by no means accurate and it can vary. An extension to this project is to build an astable 555 timer circuit to remotely trigger 1 second intervals.

The Python Script

This is the code after having been through one round of refactoring (of sorts).

import RPi.GPIO as GPIO
import time

#Set up script to use the right pin configuration
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

#Define some variables
LED_counter = 0                     #The current number in decimal
bit_counter = 0                     #The current bit
current_num = ""                    #The current number in binary
LED_array = [[17,0],[22,0],[6,0],[26,0]]        #The LED configuration array

Pin_array = [17,22,6,26,4]

#Set all the pins to outputs
for index in range(len(Pin_array)):
    GPIO.setup(Pin_array[index], GPIO.OUT)

#Reset all the pins to 0
def resetPins():
    for index in range(len(Pin_array)):
        GPIO.output(Pin_array[index], 0)

    time.sleep(0.3)
    return

#Turn the LEDs on or off
def makeitso(theLEDs = [], *args):
    LED_counter = 0

    while LED_counter < 4:
        GPIO.output(theLEDs[LED_counter][0], theLEDs[LED_counter][1])
        LED_counter += 1
        time.sleep(.3)
    return

#Define the pin configuration by counting in binary and stripping out each bit, char by char.
while LED_counter <= 15:
    resetPins()
        
    current_num = bin(LED_counter)[2:].zfill(4)

        while bit_counter < 4:
            LED_array[bit_counter][1] = int(current_num[bit_counter])
            bit_counter += 1

        bit_counter = 0
    GPIO.output(Pin_array[4], 1)
    makeitso(LED_array)
    LED_counter += 1

GPIO.cleanup()

The Counter in Action

Here it is in action:

Next Steps

There are some things I’d like to do before I consider this project complete:

  • Get the code as efficient as possible. I know I'm doing things in a really convoluted way.
  • Improve the accuracy of the timing either through a remote astable 555 timer, or some other timing method.
  • Build and display the current number in parallel rather than displaying it a single LED at a time.