or "How I learned to stop worrying and love staying up all night web programming again"

I've finally had some time to write up a bit more of a technical description of how Place Matrix works, following my introduction a few months ago.

I had a great time building this project because it was such an opportunity to learn about things with which I don't normally spend a lot of time tinkering. While I spend my days working as an operating systems engineer, I'm pretty familiar with building reliable and high performance software, but was a bit out of my element building a web application. It was certainly my goal to build a robust and reliable system, but it was hard to know all of the best practices, let alone implement them in a weekend hack. Some places this shows through. Nonetheless, I'm proud of the result and what I was able to build in a day and a couple of evenings of coding, and wanted to share some of the problems and solutions I encountered. I'm happy to get feedback on this article, both about the project and the presentation here.

System Architecture

There are several major components to the Place Matrix system. First, there is a web application hosted on Amazon AWS. It is a Flask app written in Python, and hosted via Amazon's Elastic Beanstalk. EB set up a frontend load balancer and some other stuff automatically. There's an Amazon RDS hosted MySQL database that handles all of the persistent data, such as logins and the current state of the display. On the frontend, it's really just a bit of HTML and Javascript. I used Google Sign-In to support authentication functionality. Second, the hardware is implemented with a Photon Particle controlling The Matrix project from Boldport Club, which utilizes the AS1130 LED driver chip. Finally an iPad Pro streams video to an iMac, which relays the video to YouTube for streaming.


Hardware

The primary motivation for this project was to do something neat with The Matrix, a project I received as part of my membership to Boldport Club. The community, especially the Slack channel, is inspiring in what they do with each month's project. After soldering 120 LEDs and that tiny SSOP-28 packaged AS1130 chip, I just had to find something worthwhile to do with it. Reddit's Place project seemed like the perfect inspiration. I used a hot-air pencil and solder paste with a stencil to solder all of the LEDs, and drag-soldered the chip on the back. At first all of the LEDs seemed to light up, but many were dim. I had figured I had overheated the LEDs when soldering, but the real problem was poor soldering of the chip. I suspect some unconnected, or perhaps a short (but maybe not dead short?) on the AS1130 pins could have caused this. Re-soldering the chip, followed by thorough cleaning with a Q-tip and isopropyl alcohol fixed it.

It was easy to wire this board to a Particle Photon that I had on hand. I crimped some pins for a Molex KK connector and used a solderless breadboard as a base on which I wired up power and SDA/SCL pins from The Matrix to the Photon. I had to shave the latching tabs off of the connector with an X-Acto knife to fit the connector housing.

Embedded Software

The first step to writing embedded software was getting a development environment working. I like the Particle platform because it allows easy OTA firmware updates, but in this instance I got off on the wrong foot. I wedged two separate units such that they wouldn't be recognized by the Particle web IDE and exhibited the dreaded "dim blue LED" symptom. One of them would get physically hot, and the other just wouldn't seem to respond to commands to download code. The hot one appears to have been previously physically damaged, but the other just needed a fresh firmware download in DFU or Safe mode.

I didn't keep a perfect record of what commands were necessary to recover the Photon with the dim blue LED, but I believe it was as follows. Might have also used Safe Mode instead of DFU before running the "particle update" command.

  • Download Photon Command Line Tools & native IDE
  • Use Homebrew to install dfu-util
  • brew install dfu-util
  • Connect Photon to Mac via USB
  • put Photon into DFU mode.
  • particle update
  • build sketch from the IDE against the latest FW version
  • put particle into DFU mode again
  • particle flash --usb <compiled_file_name.bin>

Writing the embedded application was pretty easy and ended up being less than 100 lines of code. I used the LRAS1130 library to talk to the hardware. The application consists of two functions, one takes a 4 character string that encodes a coordinate and toggles an LED. The second takes a Base64 encoded string, which represents a bit-array to write to the whole display. Both of these functions are bound to the Particle Cloud, so I can call them via a rest API, making integration with the backend very simple. I needed Base64 encoding to efficiently pack the 120 bits of data into the argument string length limit of 63 characters. I had first implemented the dead simple toggle function, but realized I needed to be able to write the whole display for consistency and resilience to power outages and the like in the real application. Before the project was done, I also added an LED test function to the API so I could verify my soldering.

Once on camera, I also found the Particle status LED distracting, so I suppressed it in the nominal state using the following code:

void loop() {
    if (Particle.connected()) {
        if (!RGB.controlled()) {
            RGB.control(true);
            RGB.color(0, 0, 0);
        }
    } else {
        if (RGB.controlled()) {
            RGB.control(false);
        }
    }
}

The night before I launched the project, I figured I should try to cleanup some solder joints. I spent quite a while resoldering that SSOP-28 package until I got consistently bright output. It was useful to look at the wiring diagram in the AS1130 datasheet, which The Matrix adheres to, in order to figure out which pin on the chip was improperly soldered.

Unfortunately no matter what I did I found the bottom two LEDs in the second column would not light. I resorted to probing signals at the LEDs with my oscilloscope, and though it was hard to interpret what was going on, I got the sense they were electrically connected but just weren't being commanded to turn on. At my wit's end, I tried using the LEDTest example included with the LRAS1130 library and was surprised to find all of the LEDs lit. After quite a bit of head scratching, I noticed user @tardate had committed a bug-fix to the library addressing a corruption issue. After pulling down that latest version, everything worked great. I'm so greatful to Lucky Resistor and contributors to the library, as it allowed me to focus on the app, rather than implement the protocol talk to chip. Couple of hours spent there, but I was happy to finally have success!

Source available below.

Backend

By far, the majority of the work went into the Flask web application. I picked Flask because I was already comfortable with Python and had previously built some simple server apps using Python. As an added bonus, the templating engine was familiar from my experience with Liquid, which I've used with Jekyll on this website.

I started by following an arbitrarytutorial to get the app up and running and talking to a database. It was pretty easy to rapidly iterate by running the development server locally, and talking directly to the MySQL database hosted on AWS, which let me avoid setting up a local database server, or having a different configuration for production. It also allowed me to just manually do database migrations as the datamodel changed.

I added a couple of REST endpoints that were easy to call from javascript on the page via XMLHttpRequests. I stripped out the existing functionality of the tutorial and my friend Charlie Deets helped me design the button grid and layout the content on the page. It took some work, but I managed to create a simple database model that would log each toggle request.

While I was reticent to require login, it was the easiest path to prevent abuse of the system. I let Google handle the authentication, then eventually when I needed to block misbehaving users, it was easy to uniquely identify users and revoke access as necessary. I couldn't have built a competitive system without seriously rat-holing down some abuse prevention path.

At one point, i broke the app and hadn't been doing a good job of separating my work into separate commits. I thought I had messed up the configuration, or something on the server was broken—later I found it was a programming error. The problem was I tried to delete my EB instance, but found it wouldn't get recreated, because the security group which the tutorial suggested I setup, depended on the instance. It wouldn't restart until I removed the instance from the security group. It seems like there was another way to setup a DB instance for the EB application—rather than set it up independently like the tutorial recommended, but I didn't have the experience to try it another way. Add a code snippet of HTTPS redirect. Security Groups. RDS hopefully handles the load? SQLAlchemy frustrates me. monitoring visitors with Google Analytics and AWS dashboards. Forcing SSL. Secret operator page (screenshot, encoding of google User IDs) which provides transcript of transactions. Did database migration by adding

video streaming

Air Server. iPad App. Youtube Embeddign options in iFrame API.

Accessories (the clock)

Performance, operations, and stats so far. Include part about creating a block list. feature, etc. I did a database migration by just modifying the SQL live. I hear this is not best practice:(http://imgur.com/y7Hm9?full) Over 500 users on April 14th.

I plan on eventually publishing the source to the web application and backend, however cannot publish the software running on the Particle, due to the fact that it uses a GPLv3 licensed library, and am unwilling to release software that I wrote under that license. It's pretty simple though, so should be easy to recreate.

Source Download