
Node.js communicating with Arduino
This little demo I made shows that you can communicate with Arduino in a browser.
Arduino’s serial port is connected to Node.js trough the SerialPort module. SocketIO sends and recieves receives data from the browser.
How does it work ?
A big part of the Node.js application has the same setup that I described in a previous post, it contains:
- index.js, the starting component that connects all the files.
- server.js, initialize and handles http server, sockets and serial communication
- route.js, routes a request
- requestHandler.js, handles the request; sends a page to the browser
Node.js
When the HTTP Server is initialized in server.js, serial communication with Arduino can begin.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
function serialListener() { var receivedData = ""; serialPort = new SerialPort(portName, { baudrate: 9600, // defaults for Arduino serial communication dataBits: 8, parity: 'none', stopBits: 1, flowControl: false }); serialPort.on("open", function () { console.log('open serial communication'); // Listens to incoming data serialPort.on('data', function(data) { receivedData += data.toString(); if (receivedData .indexOf('E') >= 0 && receivedData .indexOf('B') >= 0) { // save the data between 'B' and 'E' sendData = receivedData .substring(receivedData .indexOf('B') + 1, receivedData .indexOf('E')); receivedData = ''; } // send the incoming data to browser with websockets. socketServer.emit('update', sendData); }); }); } |
When data is received from the web browser then Node.js sends it to the Arduino.
1 2 3 4 5 6 |
socket.on('buttonval', function(data) { serialPort.write(data + 'E'); }); socket.on('sliderval', function(data) { serialPort.write(data + 'P'); }); |
‘E’ and ‘P’ are stop characters, these values are used in the Arduino sketch to identify what to do with which LED.
Arduino
The components are set up as following. Notice the resistor between the reset and v5 pin? This is to prevent an autoreset from the Arduino when data is send to it. The value of the resistor has to be between 110Ohm and 124 Ohm (this depends on the type Arduino, see this page for more information) .
The Arduino sketch looks like this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
// LED vars const int ledPin = 13; const int pwmPin = 3; // LED read vars String inputString = ""; // a string to hold incoming data boolean toggleComplete = false; // whether the string is complete boolean pwmComplete = false; // Potmeter vars const int analogInPin = A0; int sensorValue = 0; // value read from the potmeter int prevValue = 0; // previous value from the potmeter void setup() { // initialize serial: Serial.begin(9600); // init LEDS pinMode(ledPin,OUTPUT); pinMode(pwmPin,OUTPUT); digitalWrite(ledPin,0); analogWrite(pwmPin,0); } void loop() { // Recieve data from Node and write it to a String while (Serial.available() && toggleComplete == false && pwmComplete == false) { char inChar = (char)Serial.read(); if(inChar == 'E'){ // end character for toggle LED toggleComplete = true; } if(inChar == 'P'){// end character for dim LED pwmComplete = true; } else{ inputString += inChar; } } // Toggle LED 13 if(!Serial.available() && toggleComplete == true) { // convert String to int. int recievedVal = stringToInt(); if(recievedVal == 0) { digitalWrite(ledPin,recievedVal); } else if(recievedVal == 1) { digitalWrite(ledPin,recievedVal); } toggleComplete = false; } // Dim LED 3 if(!Serial.available() && pwmComplete == true) { // convert String to int int recievedVal = stringToInt(); analogWrite(pwmPin,recievedVal); pwmComplete = false; } // Potmeter sensorValue = analogRead(analogInPin); // read the analog in value: if(prevValue != sensorValue){ Serial.print("B"); // begin character Serial.print(sensorValue); Serial.print("E"); // end character prevValue = sensorValue; } delay(50); // give the Arduino some breathing room. } int stringToInt() { char charHolder[inputString.length()+1]; inputString.toCharArray(charHolder,inputString.length()+1); inputString = ""; int _recievedVal = atoi(charHolder); return _recievedVal; } |
Conclusion
Communication between Arduino and Node.js works pretty well. Although there were some problems with the speed of the communication; if the browser sends every value when the slider sliders, the Arduino can’t handle the incoming data. I need to delve deeper into all of this to find a possible solution (or some sort of workaround).

35 Comments
Same issue as Ray has, also tested on FF33.1, en IE11. Help welcome!
Clear tutorial Barry. Go on!
Grtz Jan
Great article! I am trying to use some of these ideas to monitor a sump pump and with sensors connected to an arduino and be able to monitor water levels and pump activity on a web page and have got the sensor parts working separately. I tried your JS code and noticed that my browser does not auto update the yellow bar graph continually (as seen in the youtube demo). I have correct values coming in between the E and P markers (later I intend to change that part to JSON to distinguish between different types of data). The yellow bar displays the new values only when I refresh the browser. Could you give me some pointers as to where I need to look to figure out why the auto update isn’t working. I am using chrome on a debian laptop. I’ll test this behavior from a windows browser later tonight.
Thanks in advance.
Ok-by putting debug prints I found out a few bugs (maybe the link to the source zip file that you gave might not be the latest). In the interface.html file, function initSocketIO the line iosocket.on(‘update’, function(recievedData) should be changed to iosocket.on(‘updateData’,function(recievdData) as there is no ‘update’ being sent from Arduino, I can see updateData being sent from the Arduino. Also I did not understand how pollOneH is used. If I change the following line pollOneH = recievedData.pollOneValue/2; to be just pollOneH = recievedData; then it works. Trying to console.log (recievedData.poolOneValue) (for debugging) give a NaN. But now that I have the basic dataflow working from my sensor via Arduberry to a Pi to a browser running I can tailor stuff to my needs. Thanks for your tutorial.
My guess is that the Node.js modules are updated and that my example isn’t compatible with the newer version of socket.io. Check Matt Bighams comments for a possible solution.
When I’ve got time (and a decent internet connection) I will try to update my download.
Hello,
Your example is exactly what I have been looking for, except that the graph does not respond to the potentiometer. I am running node v0.10.28 and socket.io 2.0.0-alpha-5. I suspect that socket.io has changed since you wrote your example. I have tried your code on linux, mac and windows7 with the same results. I am new to node and have not been able to troubleshoot the problem.
thank you for your time.
Matt Bigham
Hi Matt,
I’m fairly busy at the moment, so I can’t guarantee that I can find the problem and/or update the application anytime soon. The only advice I can give you right now is to check what has changed in the Socket.io package and rewrite that part…
Good luck,
Barry
Hi Barry,
i got this one to work, i think it has something to do with namespace. i will play with it some more.
Matt
Hi Barry,
this one also works using eventEmitter, below are listed the changes to server.js
url = require(“url”),
// mpb; 20140904; added
EventEmitter = require(“events”).EventEmitter,
SerialPort = require(“serialport”).SerialPort;
// mpb; 20140904; added
var ee = new EventEmitter();
var socketServer;
// mpb; 20140904; added
//socketServer.on(‘update’, function(data) {
ee.on(‘update’, function(data) {
socket.emit(‘updateData’,{pollOneValue:data});
});
// mpb; 20140904; added
//socketServer.emit(‘update’, sendData);
ee.emit(‘update’, sendData);
if you would like i can send you the file.
thank you again for a great example to work with.
Matt
Hi barry,
This was a great tutorial! I hope you make more soon!
I was searching all around the web for something with nodejs + arduino. No luck so far, until I find your code that actually works! thank you so much for sharing.
Now i can build upon your work also post on my website in a few weeks.
Have a nice day,
Rui Santos
Thanks Rui!
Hello,
I have the following problem:
I would like to display the status of attached pins (HIGH / LOW) on the web server.
Your code (webserver -> arduino) I understand but I do not understand how it works (potentiometer -> Web server)?
I would ask for a simple example of what I have to put the code in files ArduinoNodeJS.ino, server.js and interface.html.
Switching pin can be presented using a simple text on the screen in a web server (pin ON / pin OFF).
First of all you have to send the data to the server when it is changed.
For example, if digitalpin 1 and 4 are changed from LOW to HIGH then you want to send the data to the server.
This can be done in the same way as with the potentiometer.
In Node.js you need to listen to the incoming data and make a substring of this data (See code-snippet SerialPort init and incoming data listener).
In the case of the changing of digitalPin1 the string ‘sendData’ will contain D11 (digitalPin1 with the value of 1 (HIGH)). You can send this data to the page where you can break the incoming data further down with substring or indexOf (D11 = Digital, Pin, PinStatus) and do something with this.
it´s possible to retrieving real time weight from a digital scale conected to a pc via serial port?
If you can find a way to connect the digital scale to your pc, then it’s probably possible. However I think you might need to do some hacking on the digital scale. For examples, help and inspiration I would recommend to take a look at the Arduino forum.
i have one digital scale, and a serial usb-cable that creates a virtual com port.
Barry, finally i have success retrieving data from a digital scale+usb-serial cable+nodejs+serial.io, but i can´t display the weight displayed in node console into a web, just display one value and nothing happend after that.
if u culd help me i really apreciatte it.
Claudio.
Claudio, if you want the web page to update with every change, you’ll need to use something like socket.io to “push” the value to some javascript waiting on the client side (browser side) to consume the update and update the display.
Cheers
Thank you for so much information in such a short tutorial. I am creating something that requires me to communicate my Raspberry Pi to my Arduino. There are many tutorials online for this but it did not make sense till I read this article. I was wondering how you would like me to mention you in the README file for github. I edited the server.js and interfaces.html mainly. But everything else is yours. Just let me know and it will happen. Thanks again.
https://github.com/clemmen2/Pi2Arduino
Any way I can get a look at your html file for that bar? I am in the last part of getting this to work.
Of course! You can download the demo files at the end of the blog post (or click here). The HTML file can be found at pages/interface.html. Look for the function animation() at line 57.
Could you please explain more further why we have to define E and P as the end variable on arduino?
The E and P characters are identifiers, in this case for the two different LEDs. If the toggle LED button on the website is clicked then the server will send 1E.
The Arduino will listen for serial data in the loop. If there is data then Arduino will write this character to String inputString. If the incoming character is ‘E’ then the Arduino will set the boolean toggleComplete to true. The Arduino can now run the if statement on line 40.
Hope it helps!
Good night, i am testing the example and my command takes too long (more than a minute) to get to the arduino. Sometimes does not work , and is not logging anything. Does it takes some kind of aditional config to work properly? thank you.
Did you set portName (server.js) to your Arduino port name? Also what type of Arduino do you have? How is your Arduino behaving when you receive data in the IDE’s serial monitor?
Could you please explain better how do you created that yellow bar?
Is that flash?
Thank you.
The yellow graph is created with HTML5 canvas. The size of the graph is in direct correlation with the value of the potentiometer. Check out this site for a introduction to the canvas. Also take a look over here to get an impression for what is possible with the canvas.
Great code ! Good initiative. Would you have any idea or advices on how to deploy it whit providers so that people could read or interact with these data ?
You could do a few things actually.
1. Set up a server and host it yourself (this requires a stable internet connection).
2. Set up a local server and let it communicate with an hosted server (I made a quick sketch of this option). Maybe you can use a Raspberry PI for the local server to keep it low cost (or use the GPIO pins on the PI instead of an Arduino).
3. Use an Arduino with a Ethernet/Wireless shield and let it communicate with a hosted server.
If I were to use the 3rd option, how do I connect the Arduino to the server via web socket or node js? I notice that in the sketch, there’s no code connecting to a server or anything; just lines asking if serial is available. THANKS : )
I think the easiest way is to connect to the node.js server via a tcp or udp socket. You are right.. there is no code for this in the current sketch, this is a proof of concept and you can build your own preferences upon this sketch. However, in your case this is easily done with the ethernet shield libraries (If I remember correct. I don’t own a ethernet shield and it has been awhile since I’ve worked with one).
This is the only place where i could implement as mentioned. But, I want a small help. I have two ping sensors. I could see their output in my arduino serial port. Can u please help me with server.js(HHTP server) module specifically in function serialListener() – will read to variables and send them to HTML.
Thanks in advance
To send two signals you will first need to configure the Arduino sketch so that Node.js can parse the data.
Now go to server.js, serialListener() and dissect the data.
s needs to be a global variable. Use socketServer.emit(); to send the data to the browser.
Recent Posts
Sep 30, 2013
Jan 10, 2013
Dec 25, 2012
Dec 06, 2012
Recent Comments
Archives
Categories