Intro | Building the Device | Arduino Code | Desktop Application | Download & More
The Arduino program continuously reads the virtual COM port for incoming stats from the Windows desktop application. The values are averaged and displayed on the meters using PWM. As of May 2018 I've released "version 2" of the program which has several improvments over my original program. More on that later.
The COM port is continuously checked for incoming stats. The data format consists of a single letter identifier, followed by the reading and then a line break. Here is an example:
In this example, CPU load is at 15% and memory usage is 45%. The format allows for additional stats to be added, each using a single character as an identifier.
The program updates the meters every 100ms, or 10 times per second. Values are continuously added to an array which stores 20 values for each stat, resulting in them being averaged over the last 2 seconds (100ms * 20 = 2 seconds). This combination of updating multiple times per seconds and averaging the values provides a smooth movement of the needles so they don't appear "jumpy".
The LEDs are bicolor, with two anodes: one for green, and one for red. Each anode is wired to a separate output on the Arduino. When a stat is below 80% then the corresponding green LED is lit, and when it's 80% or higher red is lit instead.
If the program goes for more than two seconds without valid data to parse, it enters a "screen saver" mode where it moves the needles of the meter back and forth in opposing directions to show that it's running but not receiving valid data.
The Arduino's analogWrite function is used to set the needle position of the meters. The maximum value is 255, which gives an output of 5v. However, this may not be the "true" max value for the meters, depending on various circumstances.
In the meter I built, the first issue is the meters and resistors. If I had used 0-5V meters, they could be wired directly to the Arduino and no further circuitry would be required. But I used 0-1mA meters instead, which measure current. So a resistor is needed to create that current. At 5V, a 5kΩ of resistance is needed to get 1mA of current:
5V / 5,000Ω = 0.001A, or 1mA
So the ideal resistor to use would be a 5kΩ resistor with 1% accuracy or better. But that's not common, and it could be pricey. So I used 4.7kΩ 5% resistor instead, which are common. Less resistance means more current:
5V / 4,700Ω = 0.00106A, or approximately 1.1mA
So setting analogWrite to 255 will slightly overdrive the meter. In addition to this problem, it's also possible the meters aren't 100% accurate (they're very inexpensive) so it's good to have a way to adjust the output. That's what the constants METER_A_MAX and METER_B_MAX are for - they can be adjusted to match a specific meter/resistor combination.
The original program I wrote worked well, but there's always room for improvement! With version 2 I've made several changes to how the program is structured, including additional use of subroutines, arrays, and avoiding blocking functions like Delay and Serial.readBytesUntil. But the biggest improvement I made is better smoothing of the needle movement on the meters.
In the original program, I only updated the meters when a new value was received. Since the Windows app sends updates every 500ms, the meters updated every 500ms. That's only twice per second and it resulted in jerky movements, especially when the need had far to travel. I did average the CPU reading over the last four readings (so, the last 2 seconds of readings), which helped. But the time interval was still an issue.
The new program updates the meters every 100ms, regardless of how often data is received. The stats are still averaged over 2 seconds to reduce the effect of sudden jumps in CPU Load or Memory usage. The result is significantly smoother movement of the needles. I finally feel like the PC Meter functions the way I had always hoped it would.
Thanks to Hayden Thring for sharing his take on the PC Meter project, which inspired many of the improvements I made to version 2 of my Arduino program.
Back to Electronics Projects | Back to Main Menu