Click here to Skip to main content
Click here to Skip to main content
Go to top

Arduino and the Web using NodeJS and SerialPort2

, 18 Aug 2012
Rate this:
Please Sign up or sign in to vote.
This article focuses on how to listen for signals from an Arduino through the Serial Port (Linux, Mac) or COM Port for Windows using the SerialPort2 Node.JS module and serve signal data to the web in real time using Socket.IO.

Introduction

This article provides the necessary steps in allowing your Arduino board to be interfaced to the web using novel but Open Source technologies everyone can use. This has long been available but using other alternative ways of doing things by using LAN, or Zigbee modules/shields for Arduino, and they can be quite expensive. However, depending on the purpose, this simple solution may be sufficient enough.

You can watch this simple video as a simple demonstration of what can be done using your Arduino and the Web.

Background

Using the USB, the Arduino Board is connected to the PC serially to a certain COM port which the OS allocates. Node.JS, the asynchronous server side JavaScript engine then listens for the port using a Node.JS module called SerialPort2. When a signal is received, using the Node.JS Socket.IO module, data is then served also asynchronously to the web providing a real time feed of the Arduino signal.

The following are the key technologies being used to present the feasibility of this approach to the particular problem:

  • Arduino - A small electronics prototyping board. Available in multiple versions but in this article the one being used is the Arduino Mega 2560 Version 1. The same methods can be applied to other versions of the Arduino as long as it has means to output data serially.
  • NodeJS - A server side JavaScript interpreter.
  • NodeJS SerialPort2 - A Node.JS module for listening to COM ports.
  • NodeJS Socket.IO - A Node.JS module for serving async data to the web using technologies such as WebSockets.
  • NPM - Is a Node.JS package manager already included with the official installer of Node.JS.
  • jQuery - A JavaScript library for easier scripting.
  • Flot - Flot is a pure JavaScript plotting library for jQuery.
  • Apache - Used in this project for serving static content. The WAMP pack is the suggested package for easy installation. The user can also use the WAMP pack for hosting PHP and MySQL.

For Windows users, SerialPort2 requires the following for a successful build:

  • Python 2.7.3
  • Visual Studio 2010
  • Windows SDK 7.1

The Solution

It is considered that the user already has a working knowledge of an Arduino. For the purpose of this article, we will create a certain scenario for which we will create a solution. A potentiometer is connected to the Arduino board to Analog pin 0 (from now on referred to as A0). We will want to stream the analog signal levels to the web and view it using a web browser such as Google Chrome, Firefox, or Internet Explorer. The signal levels must update in real time as the potentiometer is rotated.

Preparation of the Arduino Board

You can refer to the following schematic in order to setup the potentiometer and your Arduino board.

Programming your Arduino

You can use the following code for you Arduino. The code is sufficiently commented. It is recommended that the reader understand how the code works with respect to the Arduino in order to fully understand the next steps.

const int analogInPin = A0;  // Analog input pin that the potentiometer is attached to

int sensorValue = 0;        // value read from the pot
int prevsensorValue = 0;

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600); 
}

void loop() {
  // read the analog in value:
  sensorValue = analogRead(analogInPin);
  
  // If the previous value is the same as the new one, the do not send to save
  // communication link between the Arduino and the PC. 
  if (prevsensorValue != sensorValue) {
    // print the results to the serial monitor:
    Serial.print("A"); // Print the letter A to signal the beginning of an Input
    Serial.print(sensorValue); // Send the sensor Value (this is an integer)
    Serial.print("B"); // Print the letter B to signal the end of an Input
    prevsensorValue = sensorValue; // Change the previous sensor value
  }
  // wait 100 milliseconds before the next loop
  // for the analog-to-digital converter to settle
  // after the last reading. If you are sending too fast
  // there is also a tendency to flood the communication line.
  delay(100);                     
}

Preparing Node.JS

You can download the official installer of Node.JS from its official website. The recommended version is Node.JS v0.7.8. Also, in order to successfully build SerialPort2 on Windows, you are required to install Python 2.7.3 and Microsoft Visual Studio 2010 with the Microsoft Windows SDK 7.1. The NPM module which is already a part of the Node.JS v0.7.8 will take care of the build process. However, to make things easier, you may need to add the python.exe directory path to the PATH environment variable.

In order to install the required Node.JS modules using your command prompt, go to your working directory. The following command will download, build, and install the necessary Node.JS modules.

npm install serialport2 socket.io

You should have an output that will appear similar to this.

Preparing the Server Side

Create a file called server.js on the working directory.

The following lines of code prepares the necessary connections for Node.JS and the port. Data received is the global variable:

var SerialPort  = require('serialport2').SerialPort;
var portName = 'COM3';
...

Then the following code opens the serial port connection:

...
var sp = new SerialPort(); // instantiate the serial port.
sp.open(portName, { // portName is instatiated to be COM3, replace as necessary
   baudRate: 9600, // this is synced to what was set for the Arduino Code
   dataBits: 8, // this is the default for Arduino serial communication
   parity: 'none', // this is the default for Arduino serial communication
   stopBits: 1, // this is the default for Arduino serial communication
   flowControl: false // this is the default for Arduino serial communication
});
...

The following code is triggered only when the serial port is receiving messages from the specified port.

...
var cleanData = ''; // this stores the clean data
var readData = '';  // this stores the buffer
sp.on('data', function (data) { // call back when data is received
    readData += data.toString(); // append data to buffer
    // if the letters 'A' and 'B' are found on the buffer then isolate what's in the middle
    // as clean data. Then clear the buffer. 
    if (readData.indexOf('B') >= 0 && readData.indexOf('A') >= 0) {
        cleanData = readData.substring(readData.indexOf('A') + 1, readData.indexOf('B'));
        readData = '';
        /*
            More code here later...
        */
    }
});
...

We are now ready to send the clean data to the web. In order to do this, we must first setup the Socket.IO module. On the top part of the file, insert the instantiation of the Socket.IO module.

var SerialPort  = require('serialport2').SerialPort;
var portName = 'COM3';

var io = require('socket.io').listen(8000); // server listens for socket.io communication at port 8000
io.set('log level', 1); // disables debugging. this is optional. you may remove it if desired.
...

The next step is to turn on Socket.IO.

io.sockets.on('connection', function (socket) {
    // If socket.io receives message from the client browser then 
    // this call back will be executed.
    socket.on('message', function (msg) {
        console.log(msg);
    });
    // If a web browser disconnects from Socket.IO then this callback is called.
    socket.on('disconnect', function () {
        console.log('disconnected');
    });
});

The last step is to allow the server side Socket.IO to emit a message to all listening clients if there is new sensor data. In order to do this, insert the following line to sp.on('data').

...
io.sockets.emit('message', cleanData);
...

After updating the code, sp.on('data') will look like this:

...
var cleanData = ''; // this stores the clean data
var readData = '';  // this stores the buffer
sp.on('data', function (data) { // call back when data is received
    readData += data.toString(); // append data to buffer
    // if the letters 'A' and 'B' are found on the buffer then isolate what's in the middle
    // as clean data. Then clear the buffer. 
    if (readData.indexOf('B') >= 0 && readData.indexOf('A') >= 0) {
        cleanData = readData.substring(readData.indexOf('A') + 1, readData.indexOf('B'));
        readData = '';
        io.sockets.emit('message', cleanData);
    }
});
...

Your entire server side source code server.js will look like the following:

var SerialPort  = require('serialport2').SerialPort;
var portName = 'COM3';

var io = require('socket.io').listen(8000); // server listens for socket.io communication at port 8000
io.set('log level', 1); // disables debugging. this is optional. you may remove it if desired.

var sp = new SerialPort(); // instantiate the serial port.
sp.open(portName, { // portName is instatiated to be COM3, replace as necessary
   baudRate: 9600, // this is synced to what was set for the Arduino Code
   dataBits: 8, // this is the default for Arduino serial communication
   parity: 'none', // this is the default for Arduino serial communication
   stopBits: 1, // this is the default for Arduino serial communication
   flowControl: false // this is the default for Arduino serial communication
});

io.sockets.on('connection', function (socket) {
    // If socket.io receives message from the client browser then 
    // this call back will be executed.
    socket.on('message', function (msg) {
        console.log(msg);
    });
    // If a web browser disconnects from Socket.IO then this callback is called.
    socket.on('disconnect', function () {
        console.log('disconnected');
    });
});

var cleanData = ''; // this stores the clean data
var readData = '';  // this stores the buffer
sp.on('data', function (data) { // call back when data is received
    readData += data.toString(); // append data to buffer
    // if the letters 'A' and 'B' are found on the buffer then isolate what's in the middle
    // as clean data. Then clear the buffer. 
    if (readData.indexOf('B') >= 0 && readData.indexOf('A') >= 0) {
        cleanData = readData.substring(readData.indexOf('A') + 1, readData.indexOf('B'));
        readData = '';
        io.sockets.emit('message', cleanData);
    }
});

Preparing the Client Side

This is how we will want the client side to look like:

The progress bar is powered by jQuery. The graph output is powered by Flot. The value, progress bar, and graph updates in real time as shown in this video.

You must have the jQuery library, and an appropriate jQuery UI library on your working directory to make this work. Also, the Flot library is required to make the graph work.

Refer to the source code section for the exact coding of the index.html.

Final Step

Connect your Arduino to your PC using the USB and determine the correct port which it was assigned to. You can usually easily do this by using the Arduino programmer software and checking the available ports. For Windows, it is usually higher than COM Port 1.

Setup the Apache config to point to your working directory and have it serve the index.html for the clients.

Using the command prompt pointed at your working directory, you can run server.js by issuing the following command:

node server.js 

You can then rotate your potentiometer and see the potentiometer value, bar graph, and the line graph respond to changes in real time.

Recent Updates

NodeJS SerialPort2 is think now is merged with the original SerialPort project. You may check the projects here and the message by the author of those great modules here.

Points of Interest

Of course if you want an easier solution, you can buy the Ethernet Shield or the ZigBee shield for an even more sophisticated implementation.

History

  • Aug 19, 2012 01:03 AM PHT - Edited links and added some more information.
  • May 22, 2012 7:02 AM PHT - Submitted for posting.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Bangon Kali
Software Developer Kinalibangon Software
Philippines Philippines
Electronics and Communications Engineering student at our local university and a part time software developer for Kinalibangon Software.
Follow on   Twitter

Comments and Discussions

 
GeneralMy vote of 5 PinprofessionalLilanga28-Aug-14 23:57 
QuestionNot found event.js PinmemberMember 1036369427-Oct-13 14:53 
GeneralMy vote of 5 PinmemberAbinash Bishoyi9-Apr-13 6:02 
GeneralMy vote of 4 PinmemberAbinash Bishoyi21-Feb-13 20:07 
QuestionI need more help Pinmemberfrogeraie18-Feb-13 11:19 
QuestionAccess Denied error Pinmembernathalok25126-Sep-12 2:20 
AnswerRe: Access Denied error PinmemberBangon Kali30-Sep-12 8:07 
GeneralMy vote of 5 Pinmembercombust28-Aug-12 3:42 
GeneralGreat ! Pinmemberalwaysn00b20-Aug-12 21:22 
GeneralMy vote of 5 Pinmembervbfengshui19-Aug-12 5:12 
GeneralMy vote of 5 PinmemberCodingBruce18-Aug-12 11:47 
GeneralRe: My vote of 5 PinmemberBangon Kali18-Aug-12 13:36 
GeneralGreat article :) PinmemberUdesh Settinayake28-Jul-12 4:16 
GeneralRe: Great article :) PinmemberBangon Kali28-Jul-12 5:51 
GeneralRe: Great article :) PinmemberUdesh Settinayake28-Jul-12 8:57 
QuestionSimilar on going project... PinmemberRick Waldron (rwaldron)5-Jun-12 9:56 
AnswerRe: Similar on going project... PinmemberBangon Kali5-Jun-12 19:04 
GeneralRe: Similar on going project... Pinmemberrinie9-Jun-12 21:39 
Indeed serial-port has no windows support.
Also Firmata is much in use.
 
This is a nice complete sample, although enclosing the output between A and B seems like a kludge. Why not one output per line?
 
But it is nice to see a working nodejs/arduino example with a modern web frontend...
GeneralRe: Similar on going project... PinmemberBangon Kali9-Jun-12 23:14 
GeneralMy vote of 5 Pinmembersam.hill22-May-12 10:44 
GeneralRe: My vote of 5 PinmemberBangon Kali22-May-12 21:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140916.1 | Last Updated 18 Aug 2012
Article Copyright 2012 by Bangon Kali
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid