Scoreboard Construction



With the availability of powerful and cheap micro controllers, it’s relatively easy to design and build an electronic scoreboard. The Raspberry Pi micro controller has everything that is needed. The internet is full of design examples, code snippets and programming libraries.

Initially, I wanted to build a simple scoreboard to only display the summed up runs, innings and balls/strikes/outs. But let’s face it – a complete scoreboard with all innings is so much cooler. So my small project grew from this


to this:


The following descriptions are not intended to be a step by step instruction. See them as a source of inspiration. Where possible, I’ve published my documentation and files. Especially for the the mechanical design and the housing I didn’t always document the construction, as I mostly went forward using what I had available and improvising.

Everything here is made available free of charge, under coverage by the GNU General Public License. However, if you do use the information to build your own scoreboard, please make sure that the Erding Mallards are mentioned.

You can contact me through the contact form.

Anders Lind, Erding, January 2016

Basic Design

LED Numbers

The digits for the innings (1-9 and X) and the error counters, a total of 22, can display a number between 0 and 19. Runs and hits use two 7 segment digits each for a possible count of 99. The digits for runs have the double amount of LEDs for better visibility. Balls, strikes and outs are displayed using smaller dots made of 12 LED segments each. The Guest 8 digit has a colon for the time display.


The i2c protocol is a simple serial interface, only requiring two wires (plus ground): data and clock. It’s intended for connecting ICs on a single PCB, but by using amplifiers one can implement longer distances. I choose the IC MCP23017, which can control 16 signals. Using 15 such drivers, a total of 240 segments can be controlled. Since the MCP23017 only has 3 address pins, the maximum number of drivers on a single i2c bus is 8.

The Raspberry Pi, model B, revision 2, has one i2c interface available through the GPIO pin header. However, a second i2c bus is available, one only has to solder a 2×8 pin header to the board. You can find a description here.

To operate the scoreboard, a WLAN access point is incorporated and the operation is done using a standard web browser.

Driver Board


I didn’t want to spend money on a professional layout software. Using the free version of Eagle, a PCB of the size 10 x 8 can be designed, so that’s the size I chose. Instead of one large I made 15 small double-sided PCBs, each one holding a MCP23017. Each board is powered by 12V and generates its own 5V supply using a simple 7805 voltage regulator. The Raspberry Pi is powered from one of the driver boards, which gets a pin compatible switching power converter instead of a 7805, which otherwise would require a large cooling flange. The LED strips are switched using STP16NF06L power MOSFETs, which have a particularly low resistance and thus require no cooling.

Schematic (click for a PDF file):


Board mounting layout (click for a PDF file):


Zip file with manufacturing data

PCB table of content (PDF file)

Each board drives two digits. As the digits for runs and hits only require 7 signals instead of 8, the additional 8 signals are used to drive the lamps for balls, strikes and outs, as well as the colon.

Driver usage (click for a PDF file):


I ordered and built 16 boards, so that I have one in reserve in case one breaks.

For the programming and testing, I included two 7-segment displays on the boards. This proved to be very useful, as I could assemble the entire control system on a plywood board with 1 m length and could check everything out without having the large LED digits and the housing available. The displays can be de-activated through jumpers.

The board also has a socket for an i2c repeater of type P82B96, which is only mounted on the first board of each i2c bus string. Each board has two pull-up resistors for the bus, which can be activated or deactivated through a jumper. This proved to be important, as I had to try out various combinations of pullup resistors before the buses were stable. At the end, around every second board had to have a pull-up.

To simplify the assembly, I chose to use connectors and receptors from AKL. One could also use skrew terminals, but it would be a bit of a pain having to connect 240 individual wires at once. I also use connectors for the 12V power supply connections.

After soldering all the components to the boards, I cleaned them (including the Raspberry Pi) thoroghly, covered all the jumpers and sockets with tape, and coated them with enamel. After drying, I removed the tape and inserted the ICs in the sockets.


The Raspberry Pi’s operating system is the Linux variant Raspbian Wheezy. The standard programming language is Python, so I implemented most of the programming using Python and Javascript.


I’m using direct bus commands to control the i2c bus in the various Python functions. Each change of the display status of a digit is done by supplying commands similar to this: „i2cset -y 0 0x20 0x14 0x3F“. The arguments are i2c-Bus (0 or 1), i2c-Address (0x20 through 0x27), i2c-Register (0x14 or 0x15) and finally what will be displayed as Hex-code.


By default, the two i2c buses run with a clock frequency of 400kHz. This proved to be much too fast for the relatively primitive wiring in the system. By trial and error, I determined the highest usable frequency to be 10kHz. A complete refresh of the scoreboard takes around 500ms, which makes it look like the board is wiped from left to right. The bus frequency is set in the system file /boot/config.txt with the entries “dtparam=i2c0_baudrate=100000” and “dtparam=i2c1_baudrate=100000“.


The programming library WebIOPI has everything needed to implement a control system using http with a dedicated web server. The library of course also has functions to manipulate the various GPIO pins of the Raspberry Pi, however I only use the http control functions. The system consists of only 7 files, stored in the directory /home/pi/scoreboard:


This is the web site URL that is accessed when making a WLAN network connection. The javascript script is called from here, which controls the rest of the communications.


The javascript file is pretty large, as there are many control buttons. The user interface has both acrive buttons for controlling things like runs, outs, balls, etc., and others that are used to display status information like counters for runs, balls, strikes or current inning. I’m sure the program could be optimized, but it runs fast enough on a modern smart phone or laptop (remember, javascript functions are running on the client, i.e. on the equipment where the wep page is opened from).


The Cascading Stylesheet file contains the settings for the graphical appearence like colors, borders, spacings, etc.


JPEG file with the header picture.

This is the main Python program. It’s called by the WebIOPi server daemon after the Raspberry Pi has booted. It’s basically an endless loop, using pre-defined calls from the WebIOPi library.

This file contains the definitions and default values of global variables used by the various Python functions. These are things like the current run, hit and error counts, the display mode, etc.

The function library. Most of the progamming effort was spent here. The 40-odd functions are either called by the main program, when an action is triggered by the Javascript program, or from other functions.

Program Files (ZIP-archive) (updated to version 3, April 14, 2017)

Power Supply

Most LED strips are made for 12V, so that was chosen as system voltage. Then the question arise, how to get power to the scoreboard which is located behind the outfield fence. I didn’t want to dig a trench for a 200m long cable, so I opted for using solar power. Amazon sells sets intended for campers or caravans and I picked one rated for 300W offered by Offgridtec. It consists of three solar panels, cabling and a power controller. I mounted a switch to be used when assembling the panels, and for season beginn and end. I take out the rechargable batteries for the winter.

I placed the power controllers and the two batteries in two steel cabinets. I originally planned for only one, but the battery wouldn’t quite fit so I had to separate them. Now there’s a 17Ah battery in the upper cabinet, together with the power controller, power switch and an 80mm cooling fan; the lower cabinet holds a 30Ah battery. The fan is switched on and off by a thermal switch (30 °C) connected directly to the 12V supply. The air is sucked in through a filter at the bottom of the lower cabinet and led to the upper cabinet through a plastic tube.

I applied some margin when dimensioning the cabling. The single display segments are connected using speaker cables (in black/red) with a diameter of 2 x 0.5mm², purchased on 100m rolls – around 250m were used. The PCB supplies are made with 2.5mm² cables. To connect the mounting plate with the housing’s terminal block I used spare 6mm² solar cables; between the power cabinet and the terminal block I used a 5 x 4mm² mains cable. Two strands are used for ground and switched 12V, one carries a permanent 12V for the cooling fans of the scoreboard.

Bill-of-material driver PCB (PDF file)

LED Numbers

Usually, scoreboards and other signes use red numbers. I purchased a 5m roll of red LED strips using 3528 diodes (i.e. diodes with an emitting surface of 3.5×2.8 mm), glued them to a plywood plate and tried it out. It looked OK at home, but when I tested it on the field in sunlight, it turned out that the numbers were only visible at a distance of 50 or 60 meters. The light output was simply too weak. I could of course opt for larger 5050 diodes, but that would exceed my power budget.

Luckily, the human eye is much more sensitive to green light than to red, by a factor of around 10. A new trial using green LEDs was successful, this time I could easily read the number across the entire field.

Each number was built on a 4mm thick phenolic plywood sheet. I drilled a lot of holes to fasten the LED strips with cable ties, in case the adhesive should weaken over time. I used strips with 60 LEDs per meter, which corresponds to 3 LEDs for every 5 cm. The strips are sealed with silicone for weather protection. Each segment of a number consists of 3 segments, i.e. 9 LEDs. Soldering the segments to their cables was a lot of work:

  1. Remove the silicone coating at one end using a sharp knife.
  2. Clean the soldering surfaces from remaining silicone.
  3. Apply solder tin to the surfaces.
  4. Strip the cables to around 4 mm and apply solder.
  5. Press the cables to the soldering surfaces and solder them in place.
  6. Strip the other end of the cable and use a 9V battery to test the connection.
  7. Cut shrink sleeving to10mm length and shrink it in place to seal the connection.

Before that, I cut all the cables to the correct length.

Signal cabling (click for PDF file):


After mounting the LED strips to the sheets, I fastened the cables on the rear using cable ties, at the same time mounting the cable ties holding the LED strips. I then used more cable ties to form a bundle with equal cable lenghts, and then stripped the ends again and use the 9V battery to identify the segments. I used self-adhesive cable markers. Finally, I crimped sleeves to all cable ends.

Bill-of-material mounting plate (PDF file)

Drill drawing of the digit sheets (click for PDF file): Bohrzeichnung


TP-Link TL-WA7210N is used as WLAN access point, configured to act as DHCP server. A simple LAN cable connects it with the Raspberry Pi. The system forms a closed network with no external access. Such an access could be done in theory to feed a live ticker, but would require additional programming of safety features and filters.

Mechanical Construction

The driver boards and the micro controllers are mounted on a 10mm strong plywood plate. The plate has several rectangular cutouts for the cabling. Two power rails and the power splitter for the WLAN module are also mounted here.

I designed the scoreboard for a width of 3.46 meters. This allowed me to use 4m beams for the roof construction, the longest length available at the hardware store. In retrospect, an additional 1/2 m would have been better, since I find the digits to be a bit to close to each other for perfect visibility.

As main support for the digits I joined two 16mm thick phenolic plywood sheets together. I cut out large openings to both save weight and for easier assembly of the cabling. I made wooden spacers, 10mm thick by drilling a hole through knothole fillers – much cheaper than plastic spacers. But I had to drill around 160 of them. Using the spacers, the digits were screwed on to the main support using black screws. The plywood plate came on the rear side.

The housing was constructed of 12mm thick phenolic plywood sheets on a wooden frame. I hadn’t quite accounted for the weight, the entire think requires two persons to carry. One could surely do thing differently, depending on the local requirements. I chose a variant where the main support is attached to the bottom surface and the entire thing is inserted from below. Two aluminium profiles are used to guide the assembly. For service, the mounting screws can be removed and the entire assembly be slid out, without having to dismantle the entire housing. Two steel wires prevent that the assembly falls to the ground. Two persons are definitely needed to assemble and disassemble it though.

The front consists of two 3mm thick acrylic glass sheets. They are not screwed in place, since acrylic glass has a high therman coefficient and will shrink and grow with the ambient temperature. One has to account for 5mm per meter. So I used aluminium profiles and regular window insulation (P-profile) to squeeze them in place.

To avoid too high temperatures in the housing, I attached two 120mm fans in the upper corners. They are attached to 12V through a 40 °C thermal switch. Fresh air is sucked into the housing through filtered vents in the bottom side.

Mounting and Weather Protection

The mounting assembly is constructed of 10x10cm thick wooden beams. Two vertical beams are bolted to two 3m long steel U-beams (U120), set 1m deep in concrete. Shorter beams angle out at around 2m height to support the roof construction. Four 8 x 12cm beams form the roof support. The roof itself is made of corrugated bitumen sheets, fastened with nails. Another 10 x 10cm beam is fastened between the vertical beams, holding the scoreboard with 4 angle irons. The scoreboard is also fastened with 2 angle irons on each side.

Drawing of the side assemblies (click for PDF file):



First the power must be switched on. The main switch is located on the upper power cabinet and has a detachable knob acting as key. The Raspberry Pi boots and initiates the WebIOPi software. When the boot sequence is finished, a welcome message is displayed on the scoreboard.

The scoreboard operator, using a tablet, smartphone or laptop, connects to the WLAN network provided by the access point and then opens the control page. This is only accessble by entereing the correct IP address. Each time the page is refreshed, the system time of the scoreboard is synchronized with the time on the client.

This is what the control page looks like:


It’s divided into four sections. On the top, the main control buttons for Innings, Runs, Hits, Errors, Balls, Strikes, Outs and Next Batter are located. The current Balls/Strikes/Outs are indicated as colored circles. The innings counter shows the current half-inning as a text. The innings counter begins with “Pre-Game”, at which stage the other buttons are inactive. By clicking on “Inning +” and “Inning -“, the corresponding half-inning run digit is activated. When Hits or Errors are updated, the digits will flash 5 times. Up to the 7th inning, an “A” for Away and a “H” for Home is shown in the 9th inning column. A dash in column 8 and X indicate which team is at bat. In the 8th inning, only the “A” and “H” are displayed in the X column.

The next section has three buttons, controlling the display mode:

  • Baseball: all counters are active
  • Tossball: Hits, Errors, Balls and Strikes are inactive and not displayed
  • Uhrzeit: The current time is shown
  • HOMERUN: shown as a marquee (new in version 3)

The operator can switch between the modes anytime without any loss of data.

In the third section, the individual innings with their Runs, the summed up Hits and Errors are shown. This area can be used to adjust the results without having to step through the innings with the main buttons.

Further down, there are 4 buttons:

  • Neues Spiel beginnen: Start a new game. After confirming the popup, all counters are reset and a new game started.
  • Zeit stellen: Should the automatic time synchronization fail, this can be used to set the time.
  • Scoreboard neu starten: This will reboot the Raspberry Pi. All counters ar reset. The scoreboard will display “reboot” during the reboot process.
  • Scoreboard abschalten: This button is used to turn off the scoreboard after the end of the last game. The display will show “Turn off” to remind the operator, that the main switch must be turned off.

New in version 3:

I have added a new section, where information about the 18 batters can be entered. If information was entered (the test is if the jersey number is anything else than 0), the player information is displayed for 10 seconds when the “Next Batter” button is clicked. Under the “Next Batter” button, I added an additional button, which displays the next batter information. By clicking this button, the user can scroll backwards through the batting order. Entry fields:

  • Jersey number
  • Given name
  • Family name
  • Field position
  • Hits
  • At Bats

This was largely implemented using Javascript. The player entires are stored in the browser session and retained, until the browser session is closed. The entry fields are color coded:

  • White: data is present, but possibly not yet sent to the scoreboard. This can happen, if the scoreboard is restarted.
  • Green: the data has been sent, using the “OK” button.
  • Red: new data was input and not yet sent.


July 2016

Sometime between July 3 and July 9, the power regulator failed. I noticed this after powering on the scoreboard for a Saturday game when there was no WLAN signal. The welcome message was still displayed correctly, though. After the game, I had a look and the display of the regulator was dead and the large battery resembled a football. I don’t know if it was caused by lightning or a spontaneous self-destruct, but the result was that the voltage from the solar panels went straight to both the batteries and the 12V supply output. This first destroyed the fan, and when the scoreboard was powered on, the WLAN module got the full 27V or more and was destroyed. The Raspberry survived thanks to the robust on-board power regulators. The LEDs also apparently took no damage. I ordered new parts for around 300 € and could replace them in time for the next weekend’s games. This time I used a better regulator as well.

October 2016

The first groups of LEDs – around 8 of them – are showing signs of failure. Some have started blinking, some are considerably dimmer, others rally and work again after a while. Always in groups of 3 LEDs, as they are wired together that way. It doesn’t seem to be caused by moisture, as it happens both at the solder and the cutoff ends. I’ll keep an eye on it, if it gets too obvious I’ll have to replace the failing strips. I wonder if the overvoltage in July might have caused more damage than I thought?

April 2017

The LEDs work better when the temperature rises. I tested them when it was +6°C warm, and had 21 failed segments. Two weeks later, at balmy +20°C, only 3 or 4 were dead. I suspect that the cable ties that I used to fasten the cables and the strips, are causing too much mechanical stress. I therefore cut all of them, hoping to avoid further dead LEDs. The resistors are OK, when pressing on the LEDs of a failed segment, they light up.

In April, I updated the programming, adding several new functions:

  • The clock finally works
  • HOMERUN marquee
  • Entry and display of batter information (number, name, position and hits-at bats)