Official website for Linux User & Developer
FOLLOW US ON:
May
24

Arduino CPU monitor

by Sean M Tracey

Get a Node.js-powered Arduino to display the current processor usage of a computer in real-time

In this article we’ll be using Node.js and the Duino library to get real-time CPU data and display it with a series of LEDs. We’ll also look into adjusting the brightness of those LEDs with a potentiometer, and running the app as a background process with Forever.js.

The normal process of programming an Arduino is you write a program (or sketch, as it’s called by nthusiasts), compile it, upload to your microcontroller and then let it run. If you don’t get the result you’re expecting, you amend the sketch, recompile and re-upload it. Though robust, this method is a tad cumbersome and long – and that’s before we even get into topics like wiring up shields, relays and extra bits of kit.

This is where Duino comes in. Rather than going through all of that, we upload a sketch that allows the Arduino to become a slave, of sorts, to another computer – an endpoint for data and instructions. This is done through a serial port connection and, in this instance, a Node.js library. The benefits of this approach are numerous, but primary among them is that we can use the calculating ability of a far more powerful computer to crunch problems and send only the result to the Arduino to enact a function or effect.

Resources

Node.js v0.10.17
NPM v1.3.8
Duino v0.0.9
Forever.js v0.10.11
Arduino Uno/Duemilanove
5 LEDs
Potentiometer
13 prototyping wires
Your favourite text editor
Arduino IDE 1.0.5

Step-by-step

Step 01 Prepare the project

The first thing we need to do to get this ball rolling is install Duino.js so that we can upload its software to our Arduino in order for the two to be able to communicate. Let’s start by cloning the GIT repo of Duino to our computer.

git clone https://github.com/ecto/duino.git

You should now have a folder called ‘duino’ on your system. Open the directory and find the ‘src’ folder. Found in this folder is a file called du.ino, which is the software that will let Duino talk to our microcontroller. Open this sketch in the Arduino IDE and click ‘Upload’. The sketch will upload to your Arduino, so that we’re now ready to start talking to it.

On your system, create a new project folder. You can name it anything you like, and then enter it. From the command line execute

npm install duino

This will create a folder called ‘node_modules’, which will include the Duino software and all of its listed dependencies. We’re now ready to start writing the program for the Arduino.

02 Prepare the app

Using your favourite text editor, create a new file ‘app.js’ and insert the following:

var arduino = require(‘duino’),
   board = new arduino.Board({debug : false}),
   spawn = require(‘child_process’).exec,
   pins = [3, 5, 6, 9, 10],
   //These pin numbers may vary across different versions of Arduino
   brightness = 255;

Here we’re including the Duino library and using it to create an instance of Board – the function that provides the methods for interacting with our Arduino. Because Node.js doesn’t have easy/direct access to our system’s CPU details, our app will use the Node.js child_process module to execute the shell programs vmstat and tail to get access to information about user CPU usage. This will be covered in detail in a few steps.

The pins array contains the numbers of the pins we’ll be using in this sketch. If you look at your Arduino, you’ll notice that all of these pins are capable of reading and writing both digital (HIGHLOW) and analog (0-255) data. A little later we’ll be adjusting the brightness of our LEDs by adjusting a potentiometer. In order to affect this change across the LEDs, we need to be able to control the amount of power that goes to them, so we’ll be writing analog values with PWM (which is what the ~ symbolises on the Arduino board) to reflect the potentiometer’s value.

03 Wire the Arduino

Before we proceed any further with coding, now would be a good time to wire up and then plug in the Arduinos. In the diagram included, each of our LEDs is powered by its own pin, but are all connected to the ground pin via the ground bus on the breadboard. The potentiometer is not connected to our digital pins, but to one of the free analog pins, it doesn’t matter which one, but this tutorial uses A0 as it’s the first free pin.

In order to get a reasonably stable reading from the potentiometer, you must connect it to the 5V power pin. This is done through the power bus or directly, as shown in the diagram. Once all of that is connected, you can plug in your Arduino. Nothing will happen right now as we’re yet to start controlling it. Let’s do that now.

04 Get the CPU data with Node.js child processes

Before we can start writing information to the board, we need to have information to send it, so let’s get the CPU data. Earlier, it was mentioned that Node.js doesn’t have direct access to CPU information. Depending on the version/flavour of Linux you’re running, the following may vary slightly. This tutorial was tested in Debian 7.2 but if your system runs vmstat and tail, it should be fine. If we were to check the CPU usage at every possible instance that we could, our program would begin to tax the CPU, which would affect the readings. Irony abounds! If we read the CPU usage values every half-second or so, we’ll get a useful value and a reasonably good measure of what’s happening inside the box without causing a measurable impact ourselves. We’ll achieve this by wrapping the following code in a setInterval().

setInterval(function(){

   spawn(“echo $[100-$(vmstat|tail -1|awk ‘{print $15}’)]”, function(error, stdout, stderr){

      var percentage = parseInt (stdout);

      displayUsage(percentage);
   });

}, 500);

Using the Node.js child_process module, we can dispatch Shell commands (among other things) and have the standard output passed to callback function. Because we’ve used a little command-line magic to shorten the output of vmstat, what will be passed through to the callback in this instance is the current user CPU usage value expressed as a percentage out of 100. Perfect. So let’s do something with that.

05 Display CPU usage

Let’s create the function displayUsage()
that we just passed the percentage to outside
of our interval loop. This part of our process isn’t
particularly time sensitive.

function displayUsage(percentage){

   var ledCount = ((percentage / 100) * 100) / (10 * (10 / pins.length));

}

Right now, all display usage will do is calculate an integer between zero and four. Why is this useful? If you look to the circuit you’ve wired, you’ll see that we have five LEDs. This is a deliberate choice; wiring ten LEDs and controlling them can become complicated and slow in short order, not to mention that we don’t have ten pins capable of sending PWM values on the Uno. The formula given will take the percentage expressed by vmstat and calculate exactly how many LEDs should be lit given that percentage. In this instance, each LED symbolises a 20 per cent block of CPU usage. If all five LEDs are lit, we’re running at 80 – 100 per cent, three LEDs and it’s somewhere between 60 to 80 per cent. Now that we understand what ledCount does, let’s use it.

06 Alternative ways of controlling LEDs

Add to displayUsage() the following…

function displayUsage(percentage){

   var ledCount = ((percentage / 100) * 100) / (10 * (10 / pins.length));

   for(var z = 0; z < pins.length; z ++){
      if(z < ledCount){
         board.analogWrite(pins[z], brightness);
      } else {
         board.analogWrite(pins[z], 0);
      }
   }
}

Remember the array of pin numbers we created earlier on? Here we’re looping through them and checking if the pin selected from the array represents a value low enough that it can be turned on. We can do this in a variety of ways. If, for example, we only wanted to toggle the pins on and off then we could do something like this…

var leds = [],
   pins = [3, 5, 6, 9, 10];

for(var x = 0; x < pins.length; x += 1){

   leds.push(
      new arduino.Led({
         board: board,
         pin: pins[x]
      })
   );

}

function displayUsage(percentage){

   var ledCount = ((percentage / 100) * 100) / (10 * (10 / pins.length));

   for(var z = 0; z < pins.length; z ++){

      if(z < ledCount){
         leds[z].on();
      } else {
         leds[z].off();
      }
   }
}

...But those methods, while really useful, don’t allow us to set the values being sent. They are HIGH or LOW because we want to be able to adjust the brightness of our LEDs based on user input, so we’re going to address the board directly with board.analogWrite(pins[z], brightness). The analogWrite method lets
us send an analog value between 0 and 255, 0 being off (or the analog equivalent of LOW) and 255 being on – full power (or, the analog equivalent of HIGH).

07 Adjust the brightness

If you run app.js with node app.js in the command line, assuming everything is wired correctly, you will now have a fully functioning CPU meter. To try it out, why not open a couple of taxing programs at the same time to see how it affects the measure? As more of the CPU time is used, the number of LEDs lit up should increase, and we could leave it there. But, that does mean that we’ve only covered writing values. If we want to read values, how do we do that? Head back over to your project file. Immediately after the variables where we set the board information, create a new variable called ‘potentiometer’. This will be the object that we use to listen for events and access data from the potentiometer.

var potentiometer = new arduino.Sensor({
   board: board,
   pin: ‘A0’
});

You will notice that when we create the arduino.Sensor object, we pass through an options object with a ‘board and ‘pin’ key. Feasibly, this means we can control more than one Arduino at a time, but we’re not going to look at that this time. Pin, of course, is the analog pin we’ll read data from.

As well as an initiator, ‘potentiometer’ is an event emitter. If we listen for a ‘read’ event on ‘potentiometer’, we’ll get a value somewhere between 0 and 1024, depending on the position of the dial. With a little bit of maths, we can turn that value into a percentage of 255. If we set the ‘brightness’ as we have done below, it will now turn the brightness of your LEDs up and down as we turn it.

potentiometer.on(‘read’, function(err, value) {
   value = (value / 1024) * 100;
   brightness = Math.round((value / 100) * 255);

});

08 Run it Forever... .js

And that’s our real-time CPU app. We’ve managed to quickly put together something pretty funky to use with our system but right now we’re running app.js manually in the CLI. CLI is awesome, but what good is a CPU meter that needs a window open to run? This is where Forever.js comes in.

Forever is, at its core, a daemon that lets your Node.js scripts run ‘forever’ in the background. Forever will try its best to keep your Node.js app running – it even handles app crashes and restarts. Installation is simple:

$ npm install forever -g

Notice the ‘-g’ flag at the end. This is a global install, meaning that if any Node.js app needed to call forever on this system, it wouldn’t need to be saved in the node_modules folder. After that’s completed installing we can now enter...

forever start [PATH TO OUR NODE.JS + UINO FILE]

...and the CPU meter is now a background process. If you want to check the apps you have running with forever, you can enter <code>forever list</code> and you’ll get an output that looks something like this.

info: Forever processes running
data: uid command script forever pid logfile uptime
data: [0] fwGv /usr/local/bin/ node app.js 96489 96490 /Users/seantracey/.forever/fwGv.log 0:0:1:13.707

If you want to stop a process, you can enter forever stop [PROCESS INDEX].

Step 09 Brief recount

Voila! So concludes our whirlwind tour of Arduino and Node.js. We’ve covered a lot in a short space of time. We now know how to read information from an analog source (our potentiometer), writing analog values to various pins, the difference between digital and analog signals, why we’ve used analog signals for this tutorial, executing child processes within a Node.js app to enhance our Node’s abilities and making an app run ‘forever’. This should be enough to get you excited about what Arduinos can do; now it’s time to start going out and making awesome bits and bobs – you can do so much with just a few wires and a microcontroller!

  • Tell a Friend
  • Follow our Twitter to find out about all the latest Linux news, reviews, previews, interviews, features and a whole more.
    • Andy Hillman

      would it be possible to display the output on a 16×2 LCD display instead of LED’s?