The front panel of RAIN-PSC serves three essential purposes:
- Show the status of each node
- Show the load on each node
- Look really cool
The panel is actually eight individual control panels (one for each node in the cluster). Each panel consists of five LEDs and a toggle switch. The switch selects between two display modes: status and load.
When the switch is in the status position, each LED indicates the following:
boot(on when the os has booted successfully)
network(on when the node has successfully connected to the network)
temp(on when the node temperature is too high to run at full-speed)
user 2(used to indicate custom status selected by the programmer)
When the switch is in the load position, the LEDs behave as a bar-graph displaying the unix load of the node.
To provide this display the software needs to be able to:
- Poll the status of each monitored subsystem (os, network, etc.)
- Read the system load
- Read the toggle switch position
- Turn the LEDs on and off
When I started putting the electronics together, I used some command-line tools to interact with the LEDs and switches (I think it’s possible to write do all of the above in a shell script). In the long-run, I’ll probably write this in something faster/more efficient (Rust?) but for now, I’m going to use Python to get the hang of talking to the new hardware.
I’m installing a few things on top of the base Armbian to make this happen:
The source code for the current version of the software can be found here.
The script can be broken-down into three primary components:
- Functions to gather system information
- Functions to read and update the front panel components
- A loop to periodically update the display
Gathering system information using Python is a pretty well-worn path, so I won’t discuss that in detail here.
Reading the position of the toggle switch and turning the LED’s on and off is done using the smbus Python package. This package interacts with the bus in much the same way as the command-line i2c tools.
The hardest part of this for me is coming up with the best way to translate between the binary representation (the pins themselves), the boolean/decimal values I’m used to working with and the hexadecimal values that glue the two together. What I settled on was using hexadecimal internally to the functions which generate the display (
display_load()) and boolean/decimal values everywhere else. At some point I’ll abstract all this away into a library or a module, but since I don’t plan on using Python for this long-term I’ll probably hold-off on that for now.
Finally, the main loop simply loops forever, calling
toggle_on() to determine the position of the status/load switch and then calling
display_status() accordingly. Once the display is updated the loop
sleep()s for one second and then starts over. In its final form this will need to update the panel much faster than once-per-second (potentially leveraging interrupts as well), but for this version this is probably fast enough.