Słomkowski's technical musings

Playing with software, hardware and touching the sky with paraglider.

Octoglow VFD - Orange Pi Zero board and software

Module which houses the brain of the Octoglow - the Orange Pi Zero single board computer. It also contains I2C DAC to drive analog gauges to show CPU usage in real time.

The last board in the collection, the brain. Its main component is Orange Pi Zero, a cheap Chinese alternative to Raspberry Pi Zero. Its main advantage is onboard Wi-Fi and Ethernet. The motivation for the very existence of this PCB is to hide the too modern layout of the single board computer from view and provide additional peripherals. Since the schematic is so simple, there’s not much to explain.

As seen in the photos, the board holds the Orange Pi by three screws and 2x13 header. It provides the required 5 V from system bus. Speaking of which, there are four 10-pin system bus connectors, just to make the whole thing future-proof. The MOSFET level shifter shifts 5 V to 3.3 V for I2C.

There is also I2C DAC5573 devised for controlling the external analog gauge meters. It is four-channel, but only two of the outputs are routed to external connectors. There are potentiometers RV1 and RV2 for fine-adjusting the gauge meters. Currently one channel is actually used, it displays the CPU usage. Quite a nice touch.

Switch SW3 is used to disconnect the system bus from Orange Pi and connect to external socket instead. It was put to simplify the development process. There is also SW2 switch which acts as programmatic shut down button. There is script which listens on appropriate GPIO pin to trigger system shutdown.

I put two system indicators too. Since I didn’t manage to find nice-looking LEDs, I stayed with miniature light bulbs. They are switched on by default, they go off only when respective GPIO is set as output and then set to 0. This way, when the boot sequence is complete and octoglowd daemon is running, they are all off.

Electrical wiring schematic.
Electrical wiring schematic.

↑ click to enlarge ↑

Software stack

The Pi has 16 GB MicroSD with Raspbian installed. It is connected to the home network by Wi-Fi. The central application which controls the whole device is octoglowd, described in detail in the following section. Octoglow daemon is a Java application. To have it run at startup, I use supervisord. It is convenient, because it also tries to restart the app after unexpected crashes. I also created Python script (software/running-proc-gpio-eventlistenter.py) to drive the light bulb associated with running daemon. Supervisor monitors the daemon, when it crashes, the light goes up automatically.

The other script software/reset-button-handler.sh constantly monitors the state of the button GPIO. If it detects state 0, it calls shutdown -h now. This is done to safely shut down the Linux system without the need to log into it via SSH.

Octoglow daemon

octoglowd (software/octoglowd) is a JVM application written in Kotlin. I made heavy use of coroutines, the Kotlin approach to concurrent programming. It provided me the great opportunity to learn them. I used some notable libraries:

It should be noted that this app is an second attempt to write Octoglow daemon. The previous one was done in Rust, but I suffered from steep learning curve and immature language. Lacking good async libraries also didn’t help. This abandoned code is archived in branch octoglowd-rust in the repository.

The architecture is all about standalone workers called daemons, which take care of all aspects of the functionality. Each daemon defines its pooling interval. Some more important daemons:

There is naturally code for communicating with each I2C device. I made an abstraction class I2CDevice, which wraps dvlopt library in coroutines nicely.

Front display daemon

FrontDisplayDaemon is the most complicated daemon because it accepts input from the dial and manages the pooling data from various devices and redraws the display. It is based on the concept of views. Each view is concerned with collecting data from single sensor or service and displaying it on the screen. The user cycles between the views by turning the knob. If there’s no input from the user for a prolonged time, the views are cycled automatically, by predefined interval. Each view can also define its own menu. You enter it by pressing the knob. For example, GeigerView has menu to enable or disable the magic eye.

Let’s describe the functionality taking CryptocurrencyView as example. Its task is to download exchange rates of three defined coins from coinpaprika.com and display them on the screen. Function poolStatusData() interacts with coinpaprika API and saves the result to the database. Function redrawDisplay() draws the data on the screen. Each exchange rate has its differential chart drawn to easily spot the trend. The differential chart functionality is used in many views. The resolution of the VFD display is limiting the amount of information which can be shown at once, but it does the trick nonetheless.

Some of the views which are implemented are shown below: