The County Stadium Scoreboard Project, Part 1: History, Inspiration & Coding

HISTORY

Thursday, April 10, 1980

Despite it being your standard, bitter cold Opening Day at Milwaukee County Stadium — 43 degrees — optimism for the stadium’s primary tenant, the Milwaukee Brewers, was unusually high. After two 90-win seasons under George Bamberger to round out the 70’s, along with a second-place divisional finish in 1979, Brewer fans had reason to believe the 80’s were going to be a big decade for the club. 

Over the off-season, the home of the Brewers received a major face lift to help stoke the excitement: A distinctive, brand-new scoreboard that, at the time, was the largest in the world. 

It came with controversy. The company that built it, Omega, paid to fly a number of Brewers officials to Saudi Arabia to show them what one of their installs could do, a sales pitch bordering on a bribe. Then there was debate between the Brewers and Milwaukee County in 1979 as to who would pay the $1 million for the new install. Both groups wanted to own the board to get the revenue generated by the billboards and video ads it was capable of showing. Ultimately, the Brewers won out and got the board built, getting the profits while donating the physical structure to the county. Later, Omega would be sued by another company for violating patents with the board they created. For a message board that would later go on County Stadium’s exterior facade, the Brewers turned away from Omega, instead contracting with Chicago’s White Way Signs. 

Issues aside, the new board was impressive. Paul Junio — a name that will come up a few times in this note — was there for the first game. “They showed us the video capabilities by putting on Days of Our Lives,” Junio said, “as that was what was showing on Channel 4 [WTMJ, Milwaukee’s NBC affiliate] right then. So there we were, 50,000 freezing baseball fans, watching Days of Our Lives before the opener.” 




Of course, that was just one story from the day. Bamberger, recovering from heart surgery, gave a taped video message to the fans over the board encouraging fans to have a beer on him. A few hours later, the board showed replays of Sixto Lezcano hitting a walk-off grand slam to cap a 9-5 Brewers victory over the Boston Red Sox. 

The board was an electromechanical marvel, especially when you consider it was constructed atop the skeleton frame of the previous board. The complexity of the board required as many as 11 people to operate it. The only means of showing moving pictures prior to the board were movie-theater-like projection — difficult in a well-lit, large space like a stadium, as was proven when an attempt at a projection screen atop Shea Stadium’s scoreboard was quickly abandoned in the early 60’s — or cathode-ray tubes, which were limited in size to about 40 inches. In an innovative new solution, the scoreboard conveyed images by using over 30,000 Edison light bulbs, each capable of one of eight levels of brightness. This allowed for video and animations to appear in warm hues of amber. Numerous stadiums through the 1960s and 70s had scoreboards that could show dot-matrix animations and pictures, namely the Astrodome’s center field board and wild “Home Run Spectacular,” but County Stadium’s board truly ushered in moving pictures. 

It was the world’s finest piece of large-scale crowd entertainment technology. 

And yet, it would only hold that title for three whole months before quickly being badly outclassed. 

From state-of-the-art to a state of disrepair

Mere months after County Stadium’s scoreboard debut, at the 1980 MLB All-Star Game, Mitsubishi and the Los Angeles Dodgers put Omega and the Brewers to shame, unveiling the first full-color video replay board at Dodger Stadium. The dawn of the JumboTron was at hand. Given the choice between color or, essentially, black-and-white, there was no way teams were going with the latter. Almost less than a year after it debuted, the County Stadium scoreboard was already behind the times. 

That would have been fine if Milwaukee’s scoreboard hadn’t cost so much, been so complex or had been in a facility showing less age than County Stadium, whose rusty girders served as a setting for a 1988 movie, Major League, centered on an owner who wanted to move her team because its stadium was so decrepit. But circumstances ended up forcing the Brewers and Milwaukeeans to live with the board for 21 agonizing seasons while waiting patiently for the arrival of Miller Park. 

I chose the word “electromechanical” when describing the board for a reason. Unlike early color installs that relied moreso on better-than-the-past projection or emerging LED technology, the County Stadium board used old-fashioned filament light bulbs. The massive amount of power required caused the board to have an audible whirr, disconcerting fans in the nearby bleachers. Less than a decade out from its construction, it was plagued by burned-out bulbs and occasional full outages. It sometimes necessitated a scoreboard borrowed from a recreational county park diamond to be positioned beneath it while it sat dark and needing repair. By the 90s, only one Omega employee was able to service the board in full, and he had to be flown in from Switzerland whenever there were issues. 

As installs like SkyDome’s giant, center field-spanning video board
became the rage, County Stadium’s scoreboard appeared relic-like. However, with a new ballpark on the way as of 1995, and the economics of 90s baseball working against a struggling small-market team, the Brewers could only afford to limp the board along until the Stadium closed, a year later than expected due to a construction accident, in 2000. 
 
The final iteration of County Stadium saw the Brewers place an advertisement for the team’s website on one of the scoreboard’s billboard panels. The irony of the premiere emerging communication technology of the 21st century being touted on what was perhaps Milwaukee’s most ambitious, but quickly outmoded, piece of 20th century communications technology, was apparent. When the scoreboard toppled during County Stadium’s demolition, the milwaukeebrewers.com ad was the last part to hit the ground. 

A kid’s fascination

When I tell people I was born on June 1, 1982, I like to add that the Brewers not only won that night, but fired manager Buck Rodgers after the win and replaced him with Harvey Kuenn, whose installation sparked the Brewers’ 1982 turnaround and resulted in the team’s only pennant to date. I even joke my arrival surely inspired the managerial change, as general manager Harry Dalton must have said, “Dan Pfeifer’s here now; we gotta clean up our act.” 

Accordingly, County Stadium was a place of awe and wonder for me, all the way up until my final game there with my parents at age 18 in 2000. The scoreboard was a big part of that fascination. To see thousands of lights, instantly coordinating to show fun animations like the sausage race, video features and upcoming promotions, seemed like one of the most amazing things I had ever seen. Of course, after attending games at the Bradley Center, with its full-color video display, and seeing most other stadiums with something, anything, better, even I conceded by the 90’s that County Stadium’s scoreboard was ancient, outdated tech. 

Even today, though, I think about how complex that board was, even relative to massive displays in the present day. Modern boards are, basically, just large computer screens, even ones that take odd shapes like the oculus boards in Atlanta’s Mercedes-Benz Stadium or the soon-to-open SoFi Stadium in Los Angeles. That doesn’t mean what they do isn’t amazing. But their operation isn’t groundbreaking anymore, or connected-up all that differently than the monitor on someone’s work desktop.

The County Stadium Omega board was a singular advancement in technology: A one-of-a-kind item because of how innovative and complex it was, how quickly it was outclassed, and how long it was around to remind us of its nature. It was its own one-off piece of communication history: An intermediary step in what has become a huge part of sports entertainment, given how visible the videoboard has become in new stadiums, as well as a cautionary tale of how quickly technology can go from hi-tech to undesirable. 

If I were to go back to my mom’s house, I’m sure I’d find childhood drawings of the board, done with crayon, marker or even on our first home computer, where I know I did at least one iteration as a Macintosh start-up screen. I got to be on the real thing twice as a kid: Once when I was a winner in the Brewers’ Major League Moment contest in 1995, and again in 1997, when I was selected to take part in the USPS Brew Crew Kids Weekend. I made a point to save a picture with my name on there. 

In the meantime, I’ve remained a big baseball fan. I’ve added a UWM Computer Science degree to my arsenal in the Miller Park era, in addition to doing some freelance media work that’s allowed me to get close with some Brewers employees, like Dave DeGrace, who was a part of the County Stadium board ops team for most of the Omega’s existence. Part of me always believed, if I was ever to get some electrical engineering training to add to my CS, I might want to go into designing or making scoreboards, even if the big ones aren’t nearly as interesting now as they used to be. 

Then, one boring night during a pandemic, the idea to bring that old County Stadium board back to life, 20 years after its death, literally just scrolled onto my screen. 

INSPIRATION

Wednesday, July 8, 2020

Quarantining for COVID-19 has resulted in a few new installations in my house. Since March, a few feet from where the scoreboard is now, there’s been a small folding table with three monitors, all of which were previously on my day-job desk at Marquette University for the purposes of working with alumni engagement and fundraising data. For better or worse, because the table is within view of our living room television, I end up surfing the internet on it quite a bit when I’ve decided my time looking at data is done for the day and my time looking up whatever else is on my mind has begun. 

On the night of July 8, as we awaited the return of most professional sports that didn’t involve auto racing or golf, I was in front of my computer with little better to do. Because I had been watching a lot of NASCAR’s ProInvitationalSeries and return to regular racing during the early pandemic, there were odd, auto-racing topics catching my fancy. During a virtual race at a recreated version of North Wilkesboro Speedway, discussion of NASCAR’s longtime use of Union 76 signage for track officials came up. Once upon a time, 76 was the official fuel of NASCAR, and every track had at least one orange 76 ball on a tall pole that served dual purpose as both advertising and a spotter stand for NASCAR staff.

Reading about that made me wonder about the other place I remembered seeing 76 signs as a kid — the scoreboards at Dodger Stadium. 

My research revealed something I hadn’t previously known: Unocal 76, California’s arm of Union Oil, was influential in the Dodgers’ move to Los Angeles. Walter O’Malley couldn’t afford to build Dodger Stadium by himself, so Unocal filled in the financial gaps, with a return promise of exclusive stadium signage and a still-standing gas station in the outfield parking lot. For years, Dodger Stadium’s distinctive, hexagonal scoreboards had a 76 ball logo on top, as well as on auxiliary scoreboards along the walls in foul territory. 

As I searched Google Images with the terms 76, Dodger Stadium and field scoreboard, serendipity rose from the bottom of my screen: 


My brain did a dance. “Woah, what is that?!? Is that a homemade, functional scoreboard? I’ve always wanted to make something like that! How’d he do that!?!” 
 
Clicking through to the reddit thread revealed yes, that’s exactly what it was. The best part, though, was finding the part of the thread that explained it was an open-source coded project and a non-programmer could do it

“A non-programmer could do it?” I thought. “I’m a programmer! Mostly SQL code and SSRS nowadays, but that’s programming! If a non-programmer could do it, surely I could do it!” 

The excitement was palpable as I processed all of this. I knew what the Raspberry Pi was: A small, bare-bones computer marketed as something kids and makers could use to create little programming projects. I knew Github was a place where a lot of free code was, but I didn’t know much more than that. The big thing was, I knew this would be affordable. The Pi was marketed as cheap, both so kids/schools could get their hands on it and to encourage tinkerers to not feel afraid to destroy one by accident. If you did? Eh, a $40 mistake with a Pi was better than a $500 one with a Windows box. 

I didn’t know much more than that, but didn’t feel like I needed to. After all, a non-programmer could do it. 

I had investigated the cost for commercial sports tickers for our house’s rec room before. The most basic model I saw set you back close to $1,000, plus a monthly service fee, for a small, clunky, green-and-red LED device that looked straight out of 1978. I got an estimate for this ticker model in 2019: $5,000 plus a monthly data subscription fee. In 2018, the trade-in value of my car was estimated at $2,500, and I can't drive the ticker to work.That’s prohibitively expensive for something I wasn’t sure my wife would even allow me to put on our wall. 


After reading up on the source materials for the Dodger Stadium board, though, as well as poking around the code on Github and even searching for some other installs (of which you can see a few more on Google images), I realized the net cost could be as little as $100 for a simple install with no monthly fees. 

My mind was made up: I had to do this. 

To cement the thought, I did what I do when there’s something tremendously sports-geeky on my mind: Message Junio, who has been a great friend through the years as one of my groomsmen, my spotter and statistician for high school football broadcasts on The Big 920 - WOKY, and the official scorer to my public address announcer/music coordinator for the Lakeshore Chinooks collegiate summer baseball team the past two years. 

“I think I’ve found a new passion project,” I said, sending him a link. 

Junio didn’t deny it was cool, but said he had limited room for something like that on the wall of his own house. I was more determined, though. 

“I can do it, damn it,” I said. 

“Damn it” is strong language in the Dan Pfeifer dictionary. I don’t say that unless I mean it. 

The project was happening. 

How simple became complicated

Because my projects always have a tendency to become more complex than I hope, as soon as I decided I wanted to do this someday (I wasn’t even convinced I wanted to start immediately), I tried to tell myself, “Dan, keep it simple. Get the board, get it working, maybe get some plywood to mount it on, paint it blue and green and put a Brewers & Packers logo on there. Don’t try and recreate the Miller Park scoreboard. Pam (my wife) might not want this in the house all the time, anyhow, so maybe it’s just something you dust off for our occasional game-watching parties.” 

The mistake I made, however, was starting to poke a little deeper around the code, specifically looking at the different sizes of board that were possible and the fonts those boards used. 

The code on Github allowed for one of four different sizes of LED boards: As small as 32×32 pixels, but also as big as 128×64. The bigger board allowed for full team names and more information to be shown. But the font on the sample of the 128×64 board felt decidedly terminal-like and blah. I wondered: What font is that? Can I swap in a new font? 

It turned out that font is in a format called BDF or “Glyph Bitmap Distribution Format.” It’s a sensible format for an LED board because, unlike more-modern fonts that utilize lines and shapes, BDF fonts just show which pixels should be “on” or “off” for every letter. That easily translates to LED lights being on or off for a character. 

Interestingly, BDF fonts are stored in a file that has a human-readable format rather than something compiled. I have the letter ‘A’ depicted at left and below. If you’re somewhat familiar with programming, you should recognize it as hexadecimal code. 

If you’re not, think of each row as a row of pixels, and each “character” representing four columns. Each of those four columns corresponds to a numerical value, in the following order: 

8 — 4 2 1

Each “on” pixel counts for its corresponding value.

For instance, for the “on” pixel atop the ‘A’, with a single pixel in the fifth column, the hexadecimal value for that row is ‘0800’, meaning “turn on the ‘8’ pixel in the second set of four pixels, and leave all the rest off.”

For the second row of pixels, “turn on the ‘1’ pixel for the first set of four columns, then, for the second set of four, turn on the value of pixels that adds up to 12, which is shown as ‘C’.” Why ‘C’? As you can see, the maximum possible value if you sum the four pixels there is 15 — 8+4+2+1. Rather than coming up with some weird way of determining what’s truly ‘15’ and what’s just a ‘1’ followed by a ‘5’, when the sum gets above 10, hexadecimal starts using letters instead: A equals 10, B 11, C 12, D 13, E 14 and F 15 (the ‘hexa’ in ‘hexadecimal’ is a prefix meaning ‘16’, as this has 16 different possible combinations from 0 to F). There’s only one possible way to add 8, 4, 2 and 1 to 12, or ‘C’, without duplicating digits: 8 + 4. So turn on the ‘8’ and ‘4’ pixels in the second set of columns, and leave the rest off. 

Once you get comfortable with the not-so-secret code, you can kind of even visualize how characters look just from the hex. However, there’s also a free tool called Fony that allows you to import fonts, look at their output and, of course, make changes. 

Before even ordering any of the components, I downloaded Fony, looked at the fonts in the code, and again thought ... “Meh.” I knew I wanted something a little more stylish. But what? 
What font does one use for a scoreb—

— it hit me.

Something I’ve always said about County Stadium: Whenever I see the a picture of the scoreboard, the fonts always seem to read in Bob Betts’ PA voice and it just kinda takes me there. 

I wondered: Could I recreate the County Stadium scoreboard fonts? 

The search was on for pictures, like this one of Brett Favre’s legendary final TD in County Stadium history. On a close enough viewing, you can tell which lights are on and off for many characters on the smaller font, while the bigger font had more than a few characters on that pic, too. There are quite a few pictures of the board online. 

I was able to change a few letters ... which turned into a few letters more ... then I started to realize, “The whole ‘don’t let this become a project’ thing is probably out the window, huh.” 

It took a few days, and even some missteps as I found new pictures and realized my guesses on some characters were wrong, in part because it was hard to tell what was intentional and what were burned-out bulbs. But, eventually, I had fully created two new fonts: CStadium.bdf (the smaller font, which was only ever used in all caps) and CStadiumB.bdf (the bigger font, with upper and lowercase letters). I also started to realize working on fonts was engaging enough for my geeky patoot that I needed to make sure I wasn’t going to bed too late, because there was always one more letter to do. 

The project went on pause for a few days because I had to finish my wife’s and my taxes, which were due on July 15 this year. But when it was clear we were getting a refund, the first thing I did was look at Github’s bill of materials and start ordering items. 

There was no longer any turning back. 

Pieces arrive

There wasn’t a whole lot I could do beyond the fonts without the actual stuff involved. Fortunately, through the magic of Amazon Prime, it only took a few days for key components to arrive, per what was on Github: 
  • A Vilros Raspberry Pi kit, including:
  • A Pi 3B+
  • A case for the Pi with heat-distributing elements
  • Some paste to work with the case to distribute heat
  • A 32 GB SD card with the Pi’s OS
  • An HDMI cable for connecting to a monitor (I already had plenty of these)
  • A power cord with a switch
  • A USB speaker, as I was hopeful I’d be able to also program up my board to show classic County Stadium videos, like the Two-Fisted Slopper and the first-ever sausage race
  • Some “standoffs”, which are supposed to help secure the Pi to the case (I only ended up using one)
  • A 5-volt, 10-amp power source for powering the LED board
Unfortunately, though, I had to wait on two key elements: 
  • An Adafruit RGB matrix “bonnet,” or device that attaches to the Pi that both powers the LED matrix and allows the Pi to send data signals to the matrix
  • The matrix itself
I decided the 128×64 LED board size, the largest the programming said could be used, was for me, but with a size where the board might still be able to fit in some 3D-printed cases that purportedly have designs on the internet someplace. That meant a 2.5 mm pixel “pitch,” or separation between the pixels, as many boxes were designed for the 64×32 board with a 5 mm pitch -- half the pixels, twice the separation.  

The “keep it simple” idea was still in my mind as a backup plan, but I was also starting to contemplate what this would look like if I built a County Stadium-like box for it, too. However, the only place I found the correctly sized LED board was through a Chinese dealer. Ordering through them meant a lengthy DHL ship time that had the potential to be even longer than usual, both mid-pandemic and in the middle of some political misgivings between our government and theirs. That meant waiting at least a couple weeks for that. The bonnet, meanwhile, was out of stock at Adafruit’s site and on Amazon. I found it through a third-party dealer in Nevada (there are brightly lit signs in Nevada? I’m stunned), but that, too, took some time to make its way to Wisconsin. 
In the meantime, I was able to hook the Pi up to a monitor, get it connected to our home Wi-Fi, figure out how to git (yes, git, as in Github) the code onto the device and even transfer the fonts. I also got to re-familiarize myself with Linux, the root for the Raspbian operating system, something I hadn’t worked with since my UWM days in the early 2000s. The college flashbacks were many. 

I was hopeful I could display the scoreboard info on a monitor, but it’s not set up to do that, not to mention, I found out the hard way the code expects a font named in a “#x#.BDF” format. CStadium.bdf had to become 10x11.BDF and CStadiumB.bdf got renamed to 12x18.BDF. I had to find all the places in the code where I had changed font names and, well, change them again. 

I did once run the code and have no errors appear, though with no LED board, I had no idea if it was doing the right thing or not. I paused then, realizing I had taken things as far as they would go without the board itself. 

CODING

Game Screen, Part I

By the time MLB teams were starting to play their final Summer Camp preseason games, the bonnet arrived. A few days later, so did the board. 

The Github instructions made a point to mention, for a 128×64 board, a small amount of soldering might be required — not as much with the Bonnet as other means to drive the LEDs, but one singular solder, connecting the bottom two gold boxes just above my thumb in the picture at left.

I put out an open call on Facebook to borrow a soldering iron and my buddy Peter Thomas came through. For safety’s sake, I actually did the soldering on our house’s pizza Pizazz, as it seemed like the safest metal surface to handle heat that wasn’t our range or oven.

My first attempt accidentally soldered all three boxes together. I hooked everything up, hoping it would still work, and, while it did power the board, one quarter of the board was duplicated on another quarter and shaky lines filled the rest of the screen. Back to the Pizzazz, where I heated up the solder and just moved what was on there around such that it was in the right place. 

I eagerly hooked everything together again, ran the code and ... it worked.  

Kinda. 


Any video of the board is probably going to show some flicker, but that doesn’t necessarily mean it’s visible in reality. With this test, though, it was. The Github project warned the board would use a lot of power, particularly if many lights were on at once, and especially with the 128×64 size. More reading revealed that yeah, flicker was going to happen for a few reasons: 
  • Lots of lights
  • A weak power source
  • An LED board that doesn’t transmit power well
I had all three. 

A part of me had wanted to set my board up to have an option for either color or “authentic County Stadium amber.” But with the team background colors causing a large amount of power pull, I knew amber was going to be a problem. I would also later determine my kit’s power supply was shorting out a little (the LED’s power supply can also power the Pi, but not enough to prevent flicker), and the fact that the 128×64 board I ordered probably should have taken two separate power inputs, yet only had one, meant flicker was going to happen if I didn’t make changes. 

I first decided the color option just wasn’t going to happen. Converting to all amber and black eliminated the flicker to a tolerable level. This meant taking the team color file in the code and eliminating all team colors, making everything default to amber. 

I was also able to change the background color boxes to instead be lines between the teams, giving the board a feel a little like what you see in Major League when the board is shown in that movie. I was happy with that. 

From there, I wanted to make the board look a little more like the real thing. 

The boxes for the outs were fine, but I wanted to show the count more like the real thing, with full ‘BALL’, ‘STRIKE’ and ‘OUT’ labels. This was a matter of trial and error — two steps forward, one step back, as I started to realize, all I could do was change the placement coordinates of text, start the board up, see how much something was off, then go back into the code and move it. It’s the kind of tedious thing computer programmers know they have to do, but also why a lot of people don’t want to be computer programmers. 
 
I got that to work, but then needed to reposition the inning, bases and baserunners. I decided on a different look for the bases — one similar to the diamond format the scoreboard showed during the starting lineups, with a full diamond and foul lines trailing into the outfield. This was putzy, as the coordinates for the bases are coded in a way that’s not initially intuitive, plus, I had to figure out how to draw the lines independently of the bases. I got there, but it took finagling. 

Once I got that, though, I was feeling confident enough to start actually trying to add some data to the display, namely team hits and errors. 

<note: super geeky coding stuff ahead, skip to next tag if you don’t want to get confused>

This meant first digging into the Python wrapper for the data in the mlbgame code that came with the mlb-led-scoreboard Github project. It turned out, the mlbgame data could provide team hits and errors, but those datapoints weren’t being pulled into any of the mlb-led-scoreboard code. This is where I had to start figuring out how the code worked. 

The mlb-led-scoreboard code is tremendously modular, which can be a good thing and a bad thing. The good part is, if one part breaks, it’s generally an isolated incident that’s easy to find. The bad part is, when you’re first trying to figure it out, so many things are split into different functions and files that it’s hard to know how they’re all interconnected.

Generally speaking, there are files in a directory called ‘data’ that work off a main file, data.py, that pulls information from mlbgame and distributes it into other, smaller data objects housed in other files, like inning.py for the inning number and arrow, pitches.py for the count, and so on. From there, another directory, ‘renderers’, has the code to take the data from those data files and display/render it and other key things, like the lines, to the board. It also looks at settings in yet other files, like a file in the ‘ledcoords’ folder, which houses a number of different settings for different-sized boards, and a config.json file in the main directory that has customizable board options. 

So I had to dig into the main data file, ask it to get the team hits and errors for both teams, then go into the the team names and data file, ask it to accept hits and errors for both teams, then go into the renderer file and tell it both to display the data and where it should go. 

<end tag for super geeky coding stuff> 

If you followed all that, you’re definitely a programmer. Not to mention, trust me when I say I didn’t figure all that out instantaneously. It took a lot of messing around. 

Nonetheless, here was the product. I was content. The labels evoked the real board, as did the arrow, even though it was for the inning and not the current batter in the order — there was nowhere near enough room for that on this board, which I quickly realized, at a little over 8,000 LEDs, only had one-quarter of the 30,0000 bulbs on the real thing. The bases looked good, too. 

About a week’s worth of work and testing was going well, though one thing was becoming apparent: I was only going to be able to work on this when games were going on, as there was no way to show balls, strikes and outs without an active game. The screen shows starting pitchers during pre-game and pitchers of record on a scroll after games have gone final. 

I set aside the game part of the board, then, and started working on what the board can do on off days. 

Ticker & Standings

The Github code came with two choices for offday displays: A setting for a news ticker, featuring a clock and weather, or league standings. You could turn the offday setting on or off for whether your preferred team (the Brewers for me, naturally) was off that day or all of baseball was off that day. 

After repositioning the game graphics, moving the ticker stuff around wasn’t difficult. 
I was able to learn a thing or two from the ticker, too, as it displayed a different icon for different types of weather, like a cloud for cloudy skies. I was able to lift that code to display other images. I Photoshopped up the MLB and Brewers logos to be in amber-and-black, drew some dividing lines in the manner I picked up from the game board, and voila: A nice(r) ticker screen. 



The standings, however, were where I realized the Github code had some issues. 

I mentioned mlbgame above. mlbgame was coded over three years ago and based off what was then MLB.com’s data API, or background data for its website. Unfortunately, in the time since, MLB.com has gone to a different API, and while they haven’t discontinued the old API, they are letting pieces of it die in time. While the game info is still working, one piece of the old API is officially deceased: The standings. 

Apparently, this happened just prior to the start of the abbreviated 2020 season, as a note about how people were getting errors from the standings board appeared in the Github project around the time I started looking at customizing the standings code. Others who work on the project quickly realized the old API would no longer support standings. 

There is a Python wrapper to help access MLB’s new API, called MLB-StatsAPI. But it works in a completely different way than the wrapper for the old API, which seems to have been abandoned by the guy who worked on it. For instance, in the old system, games were identified by a combination of codes related to the date and participants: Something like atlmlb-milmlb-20200819-01 or something like that. In the new code, this was dispatched in favor of a numeric game ID, like 654321, which could be found by using a function to search for an element of the game, like the road team and the date. 
Fortunately, the standings part didn’t work all that differently in the new system than they did in the old one, but I did have to figure out how to navigate sending the new API through the maze of files and functions to the scoreboard output. 

Already too-long story short: It took a few days and late nights, but I did get it figured out, even if my code definitely wasn’t pretty. The result, though, after I added a league watermark and a header line, looked really good. Given starting the move from mlbgame to MLB-StatsAPI was something the folks knowledgeable of the Github code for the two or three years were hoping to do, but hadn’t gotten around to yet, I was proud of this. 

In a later addition, I’d add in functionality such that the ticker actually shows the standings every five minutes. The off-day screens look really good. 

Video (and scary moments)

Feeling good after getting the standings to work, I next decided to try and see if I could get video on the board so I could show some of County Stadium’s epic animations. This nearly resulted in disaster. 

I’m decent with computer video editing, and I have a program, Power Director, able to convert YouTube videos to a smaller size and amber hues. I got the videos uploaded downloaded to my computer, edited, and uploaded to the scoreboard Pi with relative ease. 

The Github project’s code borrows from another project to display to the matrix, rgbmatrix, that includes a basic video viewer for the LED board; it just needs to be compiled for use and instructions can be found for that. I got the videos going through the video viewer, realized a few settings needed to be changed to make them look better, then got them there after some tinkering and reuploads. 

However, where things nearly went wrong was when I tried to figure out how to get audio to work. In the documentation for rgbmatrix, it says the Adafruit Bonnet, a device designed to snap snugly onto the Pi’s many output pins, precludes the Pi from putting out audio, as the output pins to power the LED board are also the ones usually used for sound. I, however, decided to try and see if there was some sort of internal setting I could change in the OS to get the USB speaker I ordered to work. 

A tip learned the hard way: Tinkering with an OS can have bad results. 

After a lot of Googling and changing settings in the root directory, I must have changed the wrong thing, or combination of things, or stopped a process in the middle of changing something. After one occurrence of the Pi seemingly stalling, after a restart, many commands I tried to run also caused the Pi to stall. I could usually log back on after subsequent restarts, but often, all but the simplest file commands continued to crash the computer. 

“Uh oh,” I thought. “I really messed this up.” 

Fortunately, the file commands did still work, so I was able to hop on a computer, access the Pi remotely through an SSH connection and use SCP to download all the files I had already worked so hard on over the previous couple weeks. 

With everything backed up, and as I kept encountering hangs on the most basic of commands, I realized there was probably only one way to fix things: I had put faith in the backup and take the frightening step of clearing the SD card that served as the Pi’s storage and start from scratch with a completely clean OS install. Hopefully, I could then load the backup back onto the re-flashed card and wouldn’t have to totally start anew. 

To say this was scary was an understatement, but I went through with it. Much to my relief, though, after resetting the Wi-Fi settings and re-uploading my backup, I had the board back up and going in about an hour. Granted, this hour was at 4 a.m. on a weeknight, but I was too invested in the project by this point to go to bed without knowing I at least had undone any damage. 


So yes, the scoreboard can show the sausage race and Slopper, but with no audio. And while there may be another workaround to make audio work on a separate device, I still haven’t tried to install it. I will make sure another backup is in place before I do. 

Game Screen, Part II

Seeing how that went nowhere, I decided to try a less-risky experiment next. Having figured out how to get MLB-StatsAPI to work for the standings, I wondered if I could use it to add a little more useful information to the board. 

For all the information you can access in mlbgame, one piece of data the library doesn’t easily pass is current batter and pitcher. Yes, it has boxscore information, and you could probably use some sort of formula to calculate out the current batter by summing batters faced by all pitchers on the opposing team and hitting that spot in the batting part of the boxscore, plus any substitutions, and so on. That sounded dauntingly complicated. The current pitcher and batter, however, are easily accessible through the dictionaries produced by MLB-StatsAPI, as well as the on-deck batter and “in the hole” hitter. 

To get that data onto the game screen, I knew I’d have to connect the game information from MLB-StatsAPI to what was present from mlbgame ... somehow. This meant learning the functions to access the data in MLB-StatsAPI and coming up with a way to translate between the old and new game IDs. 

There were plenty of weird quirks to that, like having to translate between the old system’s team abbreviations and the new system’s use of numeric, somewhat nonsensical, “team ID” numbers. There’s no rhyme or reason to the team IDs. There’s also some outdated stuff in the old system, such as the fact the Los Angeles Angels’ team abbreviation is still ‘ana’, hearkening back to their days as the Los Angeles Angels of Anaheim or just the Anaheim Angels. I’m almost surprised it didn’t say ‘cal’.  

Adding to the mess was the fact that the new system is a dictionary of numerous lists and sub-lists, which means you have to dig through them all with a repeatedly-used “get” function. Furthermore still, in what was maybe my biggest programming challenge for the whole board, I simply couldn’t figure out why the code threw an error when it encountered a game that hadn’t started. It turned out, you needed to use error handling to deal with situations where the information wasn’t there, because, for instance, there were no lineups in place in the data yet. I knew how to do precisely none of this at the start of July, and there was a healthy amount of research involved in figuring out first what was wrong, then how to fix it. 

Nevertheless, I got there, even figuring out how to shorten player names to first initial and last name, unless the last name was too long, in which case, I skipped the initial. My first plan to do this was to get the player’s ID and hit a separate MLB-StatsAPI player database to get that info, but that slowed the board’s operation to a crawl because the player table literally includes every player ever to play Major League Baseball and getting timely data from there is a slog. I decided, instead, to parse the “fullName” field given, even manually programming in some exceptions. 

I was happy as a clam when, just before I was planning on visiting Junio about the construction phase of the project, I first got the data to simply display, meaning it was coming through the new data structures and renderers I had created correctly. Sure, it was all out of place, but that was fixable. 

After visiting Junio, I got everything moved around into the ultimate format I still have today. Later, I was even able to add the batters due up the following inning to a between-innings screen as well. I like the way it looks.  

The coding was definitely an adventure. I’d still say about 80 percent of the code is what it was on Github. But between the fonts, rearranging and the additional MLB-StatsAPI information, this is definitely a custom project now. Not bad for a guy who hadn’t ever seen the programming language a month earlier. 

Be on the lookout for Part 2 — talking about the carpentry, painting and decals for the board’s box, as well as its completion — coming soon

Comments