Table of Contents

USB System Monitor

Introduction

Some people like to fill the notification area of their GUI with all kinds of widgets that show them their CPU utilisation, memory usage, fan speed, network throughput, disk temperature and other information of dubious value in real time.

However, nothing beats an ugly plastic brick that looks like it escaped straight from an early 1980's computer hobbyist's basement to fulfil that function. For that purpose, I created the desktop USB system monitor. Plus, it was a really good excuse to get started with Microchip PICs.

Those were simpler times.

Description

In essence, this project is just two small analogue panel meters stuck in a box together with a microcontroller that drives them. The micro is connected to a PC via USB and enumerates as a USB CDC (i.e. virtual COM port), and outputs data received from the PC as values on the meters. The application as a system load monitor is arbitrary, and that functionality is entirely handled by a Python script running on the PC, which periodically reads the system status and sends it to the box.

Circuit and Components

The system monitor is built around a PIC16F1455 - a 14-pin microcontroller with a USB device peripheral and two PWM channels, which is exactly what is needed for this application.

Schematic of the system monitor.

The two PWM outputs of the PIC are used to drive the meters. In order to get a nice DC voltage for driving the meters, the PWM is first passed through as simple RC lowpass. Because the RC time constant is quite slow (~300ms), the response of the meters is also slowed sown a little, which I find visually more pleasing than an instant response. This DC voltage is then buffered by a LM324, and applied to the meter through a series resistor. The purpose of the series resistor is to scale the 0-3.3V range of the PWM output to the 0-100mV range of the meter.

One slightly curious aspect is the power supply: The PIC16F1455 can run off the 5V USB power supply - however, this would make driving the meters and particularly filtering the PWM a bit more tricky: Because the PWM output voltage range would be 0-5V, a rail-to-rail input and output opamp would be needed for buffering. Of course, the meters could be driven directly off the PIC pins, but then fairly large capacitors (1000s of μF) would be needed for smoothing the readings. In addition, the USB bus voltage is not well regulated, and so the maximum reading could change noticeably between different hubs and computers.

To get around those problems, the PIC has its own 3.3V regulator, while the LM324 is supplied directly from the 5V USB supply. This solves both of the aforementioned problems: The maximum reading is reasonably well controlled, and the signal can be buffered with an opamp, which means that the RC filter can be implemented using more reasonable components (or, in other words, components that I had at hand).

Apart from that, there is not much else to the circuit: A LED shows the USB status, and several headers on the board provide for USB, ICSP and meter connections. The USB connector on the outside of the case is a Bulgin PX0443 Mini-USB to Molex KK assembly.

Firmware and PC Software

The system monitor hardware is simply a box with two panel meters that shows values sent via USB. All the magic that turns it into a system load monitor is in the Python script that controls it.

I believe the PC software is pretty self-explanatory: It uses psutil to get the system information and sends it out to a specified (virtual) serial port. Since the firmware uses custom manufacturer and device ID strings, it is possible for the script to auto-detect the system monitor under Linux. Annoyingly, this doesn't work under Windows, because Windows insists on an INF file from which it reads the device ID strings (despite it being a CDC device). The whole trouble of a custom VID and PID and getting a signed INF is just not worth it, but I might look into a more active way of identifying the system monitor (*IDN?, anyone?)

The firmware running on the PIC is a very slight modification of Microchip's CDC demo project, which accepts messages containing numeric values and sets the PWM outputs accordingly. Again, it should be pretty self-explanatory once you take away the code that implements the CDC device.

The GitHub repo containing the firmware and PC software is located here

Pictures

Not a whole lot of room in the box, thanks to the meters.

Looks like there is plenty of room on the board…

…if it weren't for those connector on the bottom.