256 Kilobytes

[Raspberry Pi] How to Add a Seven-Segment Display to a Robot

The only thing more retarded than 7-bit signed ASCII is the idea of using a dot-matrix display. If you don’t like microwaves and/or digital clocks, then get the fuck out. This post is not for you. Seven-segment character displays (pictured below) are the only legitimate way of displaying numbers and characters.

Four seven-segment displays.

These displays contain seven LEDs, which can each be lit up independently to create various numbers, letters, and symbols. They are commonly controlled by microprocessors (such as Arduinos) or microcomputers (such as the Raspberry Pi). They can also be incoporated into this previously-discussed robot.

Parts

Note that all links to Amazon here are affiliate links; you can click them if that's something that you want to do. There are potentially cheaper deals if you search for Chinese companies that will ship directly to you.

The Seven-Segment Display

The specific seven-segment display model that is being used here is a single-digit display from Digi-Key with the part number MAN71A. Alternate models could be used here instead, as the various models of seven-segment display are similar. Pick whichever common cathode and/or common anode models that you prefer (both types are used in this article). Note that, while the term “seven-segment display” is used consistently throughout this article, there are also a number of similar variations on this type of display, such as:

  • Nine-segment displays, which (most commonly) have two diagonal segments from the display’s bottom left up toward the top right.
  • Fourteen segment displays, which:
    • Have diagonal segments from each of the corners up to the middle;
    • Split the segment in the middle of the display into two halves; and
    • Add two vertical segments in the middle of the display (just look at the picture in the Wikipedia article)
  • Sixteen segment displays, which are the same as fourteen segment displays, but which also split the segments at the top and bottom of the display into two separate segments
  • Any of the previously mentioned display types may have one or two decimal points available as additional LED pins (the seven-segment display that we’re using here has two)

There are also displays that are physically larger than this one, that support multiple digits, and so on.

Other Parts

To work with the seven-segment display, these parts were also used:

This excludes the parts used for building the Raspberry Pi robot, which are listed in the linked article.

Identifying Your Model’s Design

A seven segment display will have “a bunch” of pins sticking out of it. In the case of the MAN71A model that we’re using here, there are eleven. Before setting up the wiring, it’s probably a good idea to identify what these pins actually do.

Locating Your Seven-Segment Display’s Pin Diagram

Pinout diagrams for displays may differ between different seven-segment display models. Looking up your model number should allow you to find the exact documentation and a datasheet/user manual for your specific model. For example, the data sheet for the MAN71A is available as a PDF. Once you have this documentation, you can start to figure out how to set up your circuit.

Determine Your Model’s Setup

There are three basic types of setup for a seven-segment display:

  • Common anode. Power flows in through one point of entry; power flows out through many ground wires (one ground wire per LED segment). 
  • Common cathode. Power flows out through one point of exit (i.e., a ground wire); power flows in through many power wires (one power wire per LED segment). 
  • No common anode/cathode. Multiple input power wires and multiple output power wires.

Note that while you should only need one power/ground wire for displays that use a common anode/cathode setup, there may be multiple pins that can serve as that common anode/cathode input/output point.

Find the Common Anode

First, identify the common anode, which is where power will be passed into the device through. This term explains itself if you break it down:

  • The term “anode” refers to the point where current flows into a device
  • Common means, you know, common. As in, shared between the various pins.

Basically, this is the pin that power will flow in through, which can then be used to power any of the segments. This is what we’re using here, which can be seen in the image below, which is a screenshot pulled from the PDF data sheet linked previously:

MAN71A Pin Diagram and Documentation with Common Anode Highlighted

This model has two (one on each side), although it is only necessary to provide power to one.

Common Cathode

Some displays may have a common cathode rather than a common anode. For example, the MAN74A, which is a similar model, uses a common cathode instead. If your model has a common cathode, the concept is the same as a common anode, but reversed; there are many power input points and one outgoing ground wire, rather than the other way around. 

No Common Anode/Cathode

Some displays may not use a common cathode/anode setup. If this is the case, then figure out which cathodes and anodes go together and wire accordingly. These seem to be less common than the other setups.

Identifying Display Pins

At this point, there are two basic ways to figure out which pin goes with what:

  • Look at the documentation (lmao); or
  • Create a basic circuit connecting a power/ground wire to the common anode/cathode and then connect power/ground wires to the other pins to figure out which pins go with which segments.

If you do decide to look at the documentation, the segments will most likely be labeled A-G, starting with the top segment and going clockwise around the display (with G being the middle segment). This is shown in the diagram below:

Standard segment labels A-G and DP for a seven-segment display.

If you’re winging it, it’s generally fairly easy to figure out which pin goes with which segment, since the pins generally go to segments that are close to the pin location.

Creating Basic Seven-Segment Display Circuits

Once you've familiarized yourself with your model's documentation and design, the first thing to do is to set up a basic circuit to make sure that everything works as you expect.

Powering All Segments

With all of the above in mind, we can now set up a basic circuit. The image shown below uses a seven-segment display with a common anode.

A basic circuit for powering a seven-segment display.

In the image above, all of the ground wires are connected, lighting up all of the lights and both of the decimal points.

Powering Specific Segments

Removing those ground wires (or otherwise breaking circuits) can be used to specify which segments should and should not light up. For example, the image below shows the same circuit from the “Powering All Segments” section above with one wire removed:

A basic seven-segment display with one segment not powered.

As shown, one segment is now turned off.

Adding an 8-Pole DIP Switch

By controlling which exact combinations of segments are powered, various letters, numbers and symbols can be created. However, manually plugging and unplugging wires to change between symbols is clearly not a viable solution for any even marginally-useful circuit. One basic concept is to use an 8-pole DIP switch (a set of eight switches that can be toggled on and off) to allow the wiring to stay in place and to toggle the segments on and off by toggling switches. This is shown in the image below:

The digit 4 created with an 8-pole DIP switch.

As shown, by toggling a specific set of switches, the standard configuration for a number “4” has been created. Very nice.

Limitations of Basic Circuits

However, this is still bullshit, primarily because there is no abstraction. When you flip the switches, they turn individual segments on and off. What the fuck is that bullshit? If you want to display the set of segments needed to display “4” that should be doable with a single button push (or other action), rather than having to figure out what the specific combination of switches is needed for each individual letter.

There are two basic ways to abstract from handling individual segments to working with full digits: Abstraction with circuitry and abstraction with computer code (via a Raspberry Pi, in this case).

Abstraction with Circuitry

Basic Example

In the image below:

  • Green and blue ground wires are connected to the cathodes used to light the LEDs used to create the letter “E”
  • White ground wires are connected to the cathodes used to light the LEDs used to create the digit “1”

Then, rather than connect those wires directly into the main circuit, they are plugged into their own row and column. This way, all that needs to be done is connect a single ground wire to the desired row/column to instantly complete the full circuit for the digit of choice.

A concept for abstracting away segments micromanagement to full digits.

As shown in the image above, when the yellow wire (which is also a ground wire) is used to connect the blue/green ground wires, a full “E” is created; when the yellow wire is used to complete the circuit with the white ground wires, a full “1” is created.

Handling More Digits and Combinational Logic Circuits

Using the general concept of abstraction, this can be taken further to create circuit inputs and outputs that can be used to abstract away the process of creating various digits. One way to do this is by creating a combinational logic circuit that reads in from binary input to create hexadecimal characters as output. This is discussed in the video below (created by Ben Eater):

There are also follow videos in that series, starting with “Using an EEPROM to replace combinational logic.”

However, for our use case, fuck all of that shit. Since this seven-segment display is going to be used as part of a Raspberry Pi robot, an easier solution is to instead write this logic as code that is then run by the Raspberry Pi.

Abstraction with Computer Code

Another approach is to--rather than use circuitry for the abstraction--use a programmable power source instead of a battery. With the 9V Energizer battery shown in the previous photos, if a circuit’s wiring is complete, the battery will always provide power. In contrast, using something like a Raspberry Pi, we can write code that will tell the microcomputer when to provide power to the circuit and when to cut it off.

Rebuilding the Basic Circuit with a Common-Cathode-Based Display

Since the power will be coming from the Raspberry Pi, this setup will work better with many power wires rather than many ground wires. Rebuilding the basic circuit with a seven segment- display that uses a common cathode instead of a common anode should look something like this:

Basic circuit with a seven segment display using a common cathode.

Note that:

  • Yellow and orange wires are power wires;
  • The blue wire is a ground wire:
  • The resistors are 470 Ohm, 1k Ohm, and 2.2k Ohm resistors, which were used interchangeably. There seems to be no real difference in the brightness of the LEDs for any of these three resistor values. The only reason for the different values is that I had insufficient resistors on hand to use all 470 Ohm resistors.

Connecting the Circuit to a Raspberry Pi

When added to the breadboard from the Raspberry Pi robot created and documented previously, this circuit is identical with some other wires shown for the other parts of the robot.

A seven-segment display attached to a Raspberry Pi robot (top view).

The ground wire for the common cathode is plugged into the ground bus that was wired in the previous tutorial. The power wires are hanging over the side here, which will then be plugged into the Raspberry Pi, which is attached to the bottom of the robot with adhesive velcro strips. With a side view, the wiring that connects to the Raspberry Pi’s GPIO pins can be seen:

A seven-segment display attached to a Raspberry Pi robot (side/bottom view).

In this photo, white jumper wires are connected to the orange wires and green jumper wires are connected to the yellow wires. Ignore this color scheme; these wires “should” all be red, and they would if I had more red jumper wires.

Raspberry Pi GPIO Pins for Seven-Segment Displays

After referencing the Raspberry Pi pinout diagram for the Model 2B V1.1 (which is what we’re using here; your model may vary), this is how the GPIO pins used in the image above line up with the seven-segment display’s segments:

Segment GPIO Number Pin Number
A 16 36
B 20 38
C 21 40
D 6 31
E 13 33
F 19 35
G 26 37

 The exact GPIO pins used here could vary as needed or relevant.

Basic Test Code (Working with Individual Segments)

Now that the wiring is set up, power on the Raspberry Pi and SSH into it (see robot guide). Then, create a file called seven-segment-display.py, put the following code into it, and save the file.

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)

class Segment:
        def __init__(self, pin):
                self.pin=pin
                GPIO.setup(  self.pin, GPIO.OUT)
                GPIO.output( self.pin, False)

        def test_segment(self):
                print "PIN ON: "  + str(self.pin)
                GPIO.output(self.pin, True)
                time.sleep(1)
                GPIO.output(self.pin, False)
                print "PIN OFF: " + str(self.pin)

class SevenSegmentDisplay:
        # Replace these pin numbers with your actual pin numbers
        A = Segment(36)
        B = Segment(38)
        C = Segment(40)
        D = Segment(31)
        E = Segment(33)
        F = Segment(35)
        G = Segment(37)

        def test_all_segments(self):
                print "Testing all segments..."
                self.A.test_segment()
                self.B.test_segment()
                self.C.test_segment()
                self.D.test_segment()
                self.E.test_segment()
                self.F.test_segment()
                self.G.test_segment()
                print ""

try:
        display = SevenSegmentDisplay()
        while True:
                display.test_all_segments();
except KeyboardInterrupt:
        GPIO.cleanup()

Then, run the script with sudo python seven-segment-display.py. This will loop through the seven display segments with a brief delay between them. This is shown in the GIF below:

GIF of testing individual seven-segment display segments.

More Test Code (Working with Full Symbols)

Now that the basic code is set up, it can be expanded on to abstract away the individual segments into specific characters. This is done below by using a Python dictionary to create a list of the characters to represent along with a series of seven True/False values to indicate which segments should be turned on for that character and which segments should be turned off.

import RPi.GPIO as GPIO
import time
import sys

GPIO.setmode(GPIO.BOARD)

class Segment:
        def __init__(self, pin):
                self.pin=pin
                GPIO.setup(  self.pin, GPIO.OUT)
                GPIO.output( self.pin, False)

        def test_segment(self):
                print "PIN ON: "  + str(self.pin)
                GPIO.output(self.pin, True)
                time.sleep(1)
                GPIO.output(self.pin, False)
                print "PIN OFF: " + str(self.pin)

class SevenSegmentDisplay:
        # Replace these pin numbers with your actual pin numbers
        A = Segment(36)
        B = Segment(38)
        C = Segment(40)
        D = Segment(31)
        E = Segment(33)
        F = Segment(35)
        G = Segment(37)

        # The hexadecimal characters from 0 to 15
        # Other 7-segment display letters, numbers, and symbols to abstract away
        # could be added here as well
        symbols = {
                 0: {'Char':'0', 'A':True , 'B':True , 'C':True , 'D':True , 'E':True , 'F':True , 'G':False },
                 1: {'Char':'1', 'A':False, 'B':True , 'C':True , 'D':False, 'E':False, 'F':False, 'G':False },
                 2: {'Char':'2', 'A':True , 'B':True , 'C':False, 'D':True , 'E':True , 'F':False, 'G':True  },
                 3: {'Char':'3', 'A':True , 'B':True , 'C':True , 'D':True , 'E':False, 'F':False, 'G':True  },
                 4: {'Char':'4', 'A':False, 'B':True , 'C':True , 'D':False, 'E':False, 'F':True , 'G':True  },
                 5: {'Char':'5', 'A':True , 'B':False, 'C':True , 'D':True , 'E':False, 'F':True , 'G':True  },
                 6: {'Char':'6', 'A':True , 'B':False, 'C':True , 'D':True , 'E':True , 'F':True , 'G':True  },
                 7: {'Char':'7', 'A':True , 'B':True , 'C':True , 'D':False, 'E':False, 'F':False, 'G':False },
                 8: {'Char':'8', 'A':True , 'B':True , 'C':True , 'D':True , 'E':True , 'F':True , 'G':True  },
                 9: {'Char':'9', 'A':True , 'B':True , 'C':True , 'D':True , 'E':False, 'F':True , 'G':True  },
                10: {'Char':'A', 'A':True , 'B':True , 'C':True , 'D':False, 'E':True , 'F':True , 'G':True  },
                11: {'Char':'b', 'A':False, 'B':False, 'C':True , 'D':True , 'E':True , 'F':True , 'G':True  },
                12: {'Char':'C', 'A':True , 'B':False, 'C':False, 'D':True , 'E':True , 'F':True , 'G':False },
                13: {'Char':'d', 'A':False, 'B':True , 'C':True , 'D':True , 'E':True , 'F':False, 'G':True  },
                14: {'Char':'E', 'A':True , 'B':False, 'C':False, 'D':True , 'E':True , 'F':True , 'G':True  },
                15: {'Char':'F', 'A':True , 'B':False, 'C':False, 'D':False, 'E':True , 'F':True , 'G':True  }
        }

        def clear_display(self):
                GPIO.output( self.A.pin, False )
                GPIO.output( self.B.pin, False )
                GPIO.output( self.C.pin, False )
                GPIO.output( self.D.pin, False )
                GPIO.output( self.E.pin, False )
                GPIO.output( self.F.pin, False )
                GPIO.output( self.G.pin, False )

        def show_symbol(self, x):
                print "Showing the symbol: " + self.symbols[x]['Char']
                GPIO.output( self.A.pin, self.symbols[x]['A'] )
                GPIO.output( self.B.pin, self.symbols[x]['B'] )
                GPIO.output( self.C.pin, self.symbols[x]['C'] )
                GPIO.output( self.D.pin, self.symbols[x]['D'] )
                GPIO.output( self.E.pin, self.symbols[x]['E'] )
                GPIO.output( self.F.pin, self.symbols[x]['F'] )
                GPIO.output( self.G.pin, self.symbols[x]['G'] )

        def test_all_symbols(self):
                for symbol in self.symbols:
                        time.sleep(1)
                        self.show_symbol(symbol)

        def test_all_segments(self):
                print "Testing all segments..."
                self.A.test_segment()
                self.B.test_segment()
                self.C.test_segment()
                self.D.test_segment()
                self.E.test_segment()
                self.F.test_segment()
                self.G.test_segment()
                print ""

try:
        # Initialize the seven segment display into a variable called "display"
        display = SevenSegmentDisplay()

        while True:
                display.test_all_symbols()
except KeyboardInterrupt:
        GPIO.cleanup()
except:
        GPIO.cleanup()
        print("Unexpected error:", sys.exc_info()[0])
        raise

With the updated code, rerun the script (sudo python seven-segment-display.py). The Raspberry Pi will loop through the sixteen hexadecimal digits with a brief delay between them. This is shown in the GIF below:

GIF of testing hexadecimal digits on a seven-segment display.

Note that while the GIF above suggests that the transitions between digits is sluggish/gradual, this seems to be caused by the GIF's low framerate, as the transitions are basically instantaneous.

Expanding on the Original Raspberry Pi Robot's Functionality

Now that the wiring is set up, it is probably a good idea to use the seven-segment display to actually display something useful, such as various status codes.

Updating the Script

The code written earlier in this post has been incorporated into the code from the original Raspberry Pi robot post. Additionally various other changes to the code from the original post have been made (specifically related to abstraction / moving functionality to various classes).

import RPi.GPIO as GPIO
import time
import sys
import random
import curses

# Read in the flags -w (test wheels) and -d (test display) for use later
import argparse
parser = argparse.ArgumentParser(description="Flip a switch by setting a flag")
parser.add_argument('-w', action='store_true')
parser.add_argument('-d', action='store_true')
args = parser.parse_args()

GPIO.setmode(GPIO.BOARD)

########## ##### Class/Function Definitions for Seven-Segment Display ##### ##########
class Segment:
        def __init__(self, pin):
                self.pin=pin
                GPIO.setup(  self.pin, GPIO.OUT)
                GPIO.output( self.pin, False)

        def test_segment(self):
                print "PIN ON: "  + str(self.pin)
                GPIO.output(self.pin, True)
                time.sleep(0.25)
                GPIO.output(self.pin, False)
                print "PIN OFF: " + str(self.pin)

class SevenSegmentDisplay:
        # Replace these pin numbers with your actual pin numbers
        A = Segment(36)
        B = Segment(38)
        C = Segment(40)
        D = Segment(31)
        E = Segment(33)
        F = Segment(35)
        G = Segment(37)

        # The hexadecimal characters from 0 to 15
        symbols = {
                 0 : {'Char':'0'    , 'A':True , 'B':True , 'C':True , 'D':True , 'E':True , 'F':True , 'G':False },
                 1 : {'Char':'1'    , 'A':False, 'B':True , 'C':True , 'D':False, 'E':False, 'F':False, 'G':False },
                 2 : {'Char':'2'    , 'A':True , 'B':True , 'C':False, 'D':True , 'E':True , 'F':False, 'G':True  },
                 3 : {'Char':'3'    , 'A':True , 'B':True , 'C':True , 'D':True , 'E':False, 'F':False, 'G':True  },
                 4 : {'Char':'4'    , 'A':False, 'B':True , 'C':True , 'D':False, 'E':False, 'F':True , 'G':True  },
                 5 : {'Char':'5'    , 'A':True , 'B':False, 'C':True , 'D':True , 'E':False, 'F':True , 'G':True  },
                 6 : {'Char':'6'    , 'A':True , 'B':False, 'C':True , 'D':True , 'E':True , 'F':True , 'G':True  },
                 7 : {'Char':'7'    , 'A':True , 'B':True , 'C':True , 'D':False, 'E':False, 'F':False, 'G':False },
                 8 : {'Char':'8'    , 'A':True , 'B':True , 'C':True , 'D':True , 'E':True , 'F':True , 'G':True  },
                 9 : {'Char':'9'    , 'A':True , 'B':True , 'C':True , 'D':True , 'E':False, 'F':True , 'G':True  },
                10 : {'Char':'A'    , 'A':True , 'B':True , 'C':True , 'D':False, 'E':True , 'F':True , 'G':True  },
                11 : {'Char':'b'    , 'A':False, 'B':False, 'C':True , 'D':True , 'E':True , 'F':True , 'G':True  },
                12 : {'Char':'C'    , 'A':True , 'B':False, 'C':False, 'D':True , 'E':True , 'F':True , 'G':False },
                13 : {'Char':'d'    , 'A':False, 'B':True , 'C':True , 'D':True , 'E':True , 'F':False, 'G':True  },
                14 : {'Char':'E'    , 'A':True , 'B':False, 'C':False, 'D':True , 'E':True , 'F':True , 'G':True  },
                15 : {'Char':'F'    , 'A':True , 'B':False, 'C':False, 'D':False, 'E':True , 'F':True , 'G':True  },

                # Additional characters for WASD 
                'W': {'Char':'Up'   , 'A':True , 'B':False, 'C':False, 'D':False, 'E':False, 'F':False, 'G':False },
                'A': {'Char':'Left' , 'A':False, 'B':True , 'C':False, 'D':False, 'E':False, 'F':False, 'G':False },
                'S': {'Char':'Down' , 'A':False, 'B':False, 'C':False, 'D':True , 'E':False, 'F':False, 'G':False },
                'D': {'Char':'Right', 'A':False, 'B':False, 'C':False, 'D':False, 'E':False, 'F':True , 'G':False }
        }

        def clear_display(self):
                GPIO.output( self.A.pin, False )
                GPIO.output( self.B.pin, False )
                GPIO.output( self.C.pin, False )
                GPIO.output( self.D.pin, False )
                GPIO.output( self.E.pin, False )
                GPIO.output( self.F.pin, False )
                GPIO.output( self.G.pin, False )

        # For example, the key value to show '0' is 0, value for 'E' is 14, etc.
        def show_symbol(self, key):
                print "Showing the symbol: " + self.symbols[key]['Char']
                GPIO.output( self.A.pin, self.symbols[key]['A'] )
                GPIO.output( self.B.pin, self.symbols[key]['B'] )
                GPIO.output( self.C.pin, self.symbols[key]['C'] )
                GPIO.output( self.D.pin, self.symbols[key]['D'] )
                GPIO.output( self.E.pin, self.symbols[key]['E'] )
                GPIO.output( self.F.pin, self.symbols[key]['F'] )
                GPIO.output( self.G.pin, self.symbols[key]['G'] )

        def test_all_symbols(self):
                for symbol in self.symbols:
                        time.sleep(0.25)
                        self.show_symbol(symbol)

        def test_all_segments(self):
                print "Testing all segments..."
                self.A.test_segment()
                self.B.test_segment()
                self.C.test_segment()
                self.D.test_segment()
                self.E.test_segment()
                self.F.test_segment()
                self.G.test_segment()
                print ""

########## ##### Function Definitions for Servos ##### ##########
class Wheel:
        def __init__(self, pin, forward_dc, backward_dc):
                self.pin=pin
                GPIO.setup(  self.pin, GPIO.OUT)
                GPIO.output( self.pin, False)

                self.forward_dc  = forward_dc
                self.backward_dc = backward_dc

        def test_wheel(self):
                p = GPIO.PWM(self.pin, 50)
                p.start(7.5)

                # Toward 90 degrees. Forward for right; backward for left
                p.ChangeDutyCycle(7.5)
                time.sleep(1) # sleep 1 second

                # Toward 0 degrees. Backward for right; forward for left
                p.ChangeDutyCycle(2.5)
                time.sleep(1) # sleep 1 second

                # Toward 180 degrees. [Also] forward for right; backward for left
                p.ChangeDutyCycle(12.5)
                time.sleep(1) # sleep 1 second

                p.stop()

        # direction > 1 is forward; direction < 0 is backward; direction == 0 is no movement
        def move(self, direction):
                print "Direction: " + str(direction)

                if   direction == 0:
                        return True

                self.pwm = GPIO.PWM(self.pin, 50)
                self.pwm.start(7.5)

                if   direction > 0:
                        self.pwm.ChangeDutyCycle( self.backward_dc)
                elif direction < 0:
                        self.pwm.ChangeDutyCycle( self.forward_dc )

        def stop(self):
                try:
                        self.pwm.stop()
                except:
                        pass
                        #print "self.pwn.stop failed for some reason"
                        #raise

class Robot:
        def __init__(self):

                # Initialize the seven segment display into a variable called "display"
                self.display = SevenSegmentDisplay()

                # This is the GPIO pin to control the wheel on the right side (closer to the 6V battery pack)
                self.r = Wheel(7, 7.5, 2.5)

                # This is the GPIO pin to control the wheel on the left side (closer to the Raspberry Pi power supply)
                self.l = Wheel(8, 2.5, 7.5)

        # Possible user inputs. For each input: 0 = remain stationary (0); 1 = spin forward; -1 = spin backward
        inputs = {
                'W': {'L': 1, 'R': 1, 'symbol_key':'W' },
                'A': {'L': 0, 'R': 1, 'symbol_key':'A' },
                'S': {'L':-1, 'R':-1, 'symbol_key':'S' },
                'D': {'L': 1, 'R': 0, 'symbol_key':'D' }
        }

        def handle_input(self, input_char):
                print "In handle_input"
                try:
                        self.display.show_symbol( self.inputs[input_char.upper()]['symbol_key'] )

                        self.r.move( self.inputs[input_char.upper()]['R'] )
                        self.l.move( self.inputs[input_char.upper()]['L'] )
                        time.sleep(0.05)
                        self.stop_wheels()
                except:
                        print input_char + " is an invalid input."
                        #print("Unexpected error:", sys.exc_info()[0])
                        #raise

        def stop_wheels(self):
                self.r.stop()
                self.l.stop()

########## ##### Definitions for Helper Functions ##### ##########
def get_input_without_enter(message):
    try:
        win = curses.initscr()
        win.addstr(0, 0, message)
        while True:
            ch = win.getch()
            if ch in range(32, 127): break
            time.sleep(0.05)
    except: raise
    finally:
        curses.endwin()
    return chr(ch)

########## ##### Main Loop / Execute the Code ##### ##########
try:
        # GPIO pin #10 powers the green "program is running" LED; turn this on while script is looping
        GPIO.setup(10,GPIO.OUT)
        GPIO.output(10, True)

        # Initialize the Robot object (which then initializes the various other classes as child objects)
        bot = Robot()


        # If -d flag set, test all of the segments and symbols for the display 
        if (args.d):
                # 1      = Testing/debugging segments and symbols from flag
                bot.display.show_symbol(1)
                time.sleep(3)
                bot.display.clear_display()

                bot.display.test_all_segments()
                bot.display.test_all_symbols()

        # If -w flag set, test both wheels
        if (args.w):
                # 2      = Testing/debugging wheels/servos from flag
                bot.display.show_symbol(2)
   
                bot.l.test_wheel()
                bot.r.test_wheel()


        while True:
                # 0      = Robot running in normal/main loop
                bot.display.show_symbol(0)

                print '...'
                input_char = get_input_without_enter("...")
                bot.handle_input( input_char )

                time.sleep(1.25)

except KeyboardInterrupt:
        # 12 (C) = Keyboard interrupt (CTRL+C) registered. Bot shutting down normally.
        bot.display.show_symbol(12)
        time.sleep(5)

        # If CTRL+C is pressed, clean up and shut off any GPIO settings/outputs.
        GPIO.cleanup()
except:
        # 14 (E) = Error
        bot.display.show_symbol(14)
        time.sleep(1.5)

        # If any non-deliberate error occurs, then make sure GPIO settings/outputs are still cleaned up
        GPIO.cleanup()
        print("Unexpected error:", sys.exc_info()[0])
        raise

This code will:

  • Show the digit "1" during the wheel/servo test cycyle (if the -w flag is set)
  • Show the digit "2" at the start of the display test cycle (if the -d flag is set)
  • Show the digit "0" while in the main loop and waiting for user input
  • Light up individual segments at the front, left, right, and rear of the display/robot when processing WASD inputs
  • Show the character "c"  on quit via keyboard interrupt (CTRL+C) (bot shutting down normally).
  • Show the character "E" on quit due to other errors.

Running the Upgraded Robot

A video of the robot running with the updated code is below. The command to run this robot is sudo python robot-7s.py -w -d, where the either or both of the two flags can be omitted to skip the debugging sections at the start of the script. 

Hell yeah. Pour up.

Conclusion

Other Applications for Seven-Segment Displays

There are a number of other applications for seven-segment displays, both in the context of this robot as well as for electroncis in general. These include, but are not limited to:

  • Building microwaves

In Conclusion

Hell yeah. What a great robot improvement using God’s chosen display.

Users Who Have Downloaded More RAM:
Scuffed Dog (3 months ago)
🐏 ⨉ 1
Posted by August R. Garcia 3 months ago

Edit History

• [2019-07-13 9:53 PDT] August R. Garcia (3 months ago)
• [2019-07-13 9:53 PDT] August R. Garcia (3 months ago)
• [2019-07-13 9:53 PDT] August R. Garcia (3 months ago)
🕓 Posted at 13 July, 2019 09:53 AM PDT

Profile Photo - August R. Garcia August R. Garcia LARPing as a Sysadmi... Portland, OR
🗎 192 🗨 947 🐏 287
Site Owner

Grahew Mattham

August Garcia is some guy who used to sell Viagra on the Internet. He made this website to LARP as a sysadmin while posting about garbage like user-agent spoofing, spintax, the only good keyboard, virtual assitants from Pakistan, links with the rel="nofollow" attributeproxiessin, the developer console, literally every link building method, and other junk.

Available at arg@256kilobytes.com, via Twitter, or arg.256kilobytes.com. Open to business inquiries based on availability.


Account created 10 months ago.
192 posts, 947 comments, and 287 RAMs.

Last active 10 hours ago:
Commented in thread Twitter video upload error "cannot read property 'code' of undefined"?

Post a New Comment

To leave a comment, login to your account or create an account.

Do you like having a good time?

Read Quality Articles

Read some quality articles. If you can manage to not get banned for like five minutes, you can even post your own articles.

View Articles →

Argue with People on the Internet

Use your account to explain why people are wrong on the Internet forum.

View Forum →

Vandalize the Wiki

Or don't. I'm not your dad.

View Wiki →

Ask and/or Answer Questions

If someone asks a terrible question, post a LMGTFY link.

View Answers →

Make Some Money

Hire freelancers and/or advertise your goods and/or services. Hire people directly. We're not a middleman or your dad. Manage your own business transactions.

Register an Account
You can also login to an existing account or recover your password. All use of this site is subject to terms outlined in the terms of service and privacy policy.