It is already installed but the basics of how to get it running are in the github readme.
So my plan is to eventually get all this running with the Modbus protocol and write my own Modbus class, however for now I just want to make sure I have the basics of node-serialport working.
So first of all this is my setup..
As I am planning on using Modbus for the communication I have used a 3.3V UART to RS485 converter chip wired to a cat 5 socket which then connects to various Modbus devices.
The chip used is a MAX 3483. This could easily have been a 3.3V UART to USB such as Any of these FTDI chips or simply a MAX232 chip to convert the logic up to RS232 levels. Anyway I have used the 3483 for this project.
The module makes a connection to the RX and TX pins on the GPIO header on the Raspberry Pi.
Which are located on GPIO 14 and GPIO 15 as can be seen from the image below.
For more info check out here..
All connected.. lets install!
First thing we are going to do is install express, this will take care of creating all the nice directory structure for us and starts up off with a webserver and our routes etc all written for us.
So create a directory on the Pi and make sure Node.js is installed (I might do a blog post on this in the future but at the minute you figure it out!). I am using Node 0.8.12 and NPM 1.1.63 find out your version by typing “node –v” and “npm –v” also I am using Raspbian Wheezy.
So go to the directory you made and type: “npm install express” –if the next step doesn’t work properly for you, maybe try typing “sudo npm install express –g” this will just install it globally on the computer.
Once installed type “express <your app name here>” so I typed “express serial” this will then generate all the relevant directories.
Once it has created them it will tell you to “cd <directory name” and then type npm install which will make npm install all the relevant modules etc and finalise the installation.
If you then just typed “node app.js” it would start the web server running, but for now were going to install a few more modules.
We are going to want to use node-serialport so in the working directory type “npm install serialport” this will add it to the project.
Finally I am going to want a way to get these serial messages to and from the browser window. For example I am going to want to maybe have a button send out a serial message and then have a textbox getting the value back.. or anything.. a graph? but to get messages to and from a browser is a bitch so the lovely people at socket.io have created this awesome library (which I will explain in another blog post) to get these messages in and out in a really easy way.
So as a final install type “npm install socket.io”
All Installed..lets code!
First of all open up the folder in a text editor (I use Sublime Text 2 because it is awesome!) and then open up “app.js” (this could be called server.js or something similar)At the top of the page there are all the require files for express, we want to add our own modules here so make sure to add this line to the end of the requires. (we are going to add socket.io in a different way later on)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
serialport = require("serialport").SerialPort; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Serial Port Setup. | |
*/ | |
var portName = '/dev/ttyAMA0'; //This is the standard Raspberry Pi Serial port | |
var readData = ''; //Array to hold the values read in from the port | |
var sp = new serialport(portName, { | |
baudRate: 9600, | |
dataBits: 8, | |
parity: 'none', | |
stopBits: 1, | |
flowControl: false | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Server Code | |
*/ | |
var server = http.createServer(app).listen(app.get('port'), function(){ | |
console.log("Express server listening on port " + app.get('port')); | |
}); | |
var io = require('socket.io').listen(server); |
The way socket.io works is that on both the server and the client (the website) there will be something called listeners and emitters. A listener will be listening to the socket connection for certain keywords, when it hears it’s keyword it will fire its code and when it’s done it could emit a keyword to start some other code on the client or it could just do nothing.
So the first thing you need to do before you can add any listeners or emitters is to finish setting up the socket server. This is done through listening for “connection”, once a connection is made you can start having fun with emitters etc.
So this is the code for the server, at the minute it is just listening for the connection, once it is connected it will emit “connected” and it will also send the number 123 to the client. – This bit is not needed it is just an example of how to emit and listen.
Server Code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
io.sockets.on('connection', function(socket){ | |
console.log("Socket connected"); | |
socket.emit('connected', 123); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* GET home page. | |
*/ | |
var fs = require('fs') | |
exports.index = function(req, res){ | |
res.writeHead(200, {'Content-Type': 'text/html'}); | |
var contents = fs.readFileSync("./public/index.html", "UTF-8"); | |
res.end(contents); | |
// res.render('index'); | |
} |
Client Code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var socket = io.connect('http://your ip address here..'); | |
socket.on('connected', function(data) { | |
console.log('Connected, this is what I received : ', data); | |
//you could then emit something here for the server to receive like socket.emit("blah", "helloworld") -hello world is a string of data you are passing the sever here.. | |
}); |
So add the following code to the server MAKE SURE IT IS ENCASED WITHIN THE IO.SOCKETS.CONNECTED BIT OF CODE.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
socket.on('sendSerial', function(data) { | |
console.log("Client sent us: " + data + "to send to serial"); | |
sp.write(mbBuffer, function (err, bytesWritten) { | |
console.log('bytes written:', bytesWritten); | |
}); |
So underneath the above code, add the following.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
sp.on('data', function (data) { | |
console.log(data); | |
data = data.toString(); | |
socket.emit('receiveSerial', data); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
sp.on('close', function (err) { | |
console.log('port closed'); | |
}); | |
sp.on('error', function (err) { | |
console.error("error", err); | |
}); | |
sp.on('open', function () { | |
console.log('port opened...'); | |
}); |
Okay so lets move over to our file “index.html”
This is hopefully all straight forward to any html developer, the file is using some basic jquery so please read up on that if you want to make sense of it.
Basically all that is happening is there is a send button and a textbox when the user clicks the send button it will take the data out of the text box and emit the “sendSerial” event. This will be picked up by the server and sent down the serial line.
There is also a read only textbox which just logs the values received by the serial port.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<script src="/socket.io/socket.io.js"></script> | |
<script src="http://code.jquery.com/jquery-latest.js"></script> | |
<script type="text/javascript"> | |
var socket = io.connect('http://YOUR IP HERE'); | |
socket.on('connected', function(data) { | |
console.log('Connected, this is what I received : ', data); | |
}); | |
// when you get a receiveSerial event, do this | |
socket.on('receiveSerial', function (data) { | |
// look for the textDisplay element in the HTML below: | |
var element = document.getElementById('modbusDisplay'); | |
console.log(data); //Check the console in chrome tools to see this | |
$("#serialDisplay").val(data); | |
// set the stuff inside the element's HTML tags to | |
// whatever the 'value' property of the received data is: | |
}); | |
</script> | |
<h2> SERIAL STRING SEND</h2> | |
<input id="send" type="submit" value="Send" /> | |
<input id="serialString" value="Enter your Serial string here..." /> | |
<h2> SERIAL STRING RECEIVED:</h2> | |
<input disabled="disabled" id="serialDisplay" value="Text will appear here.." /> | |
<script> | |
$("#send").click(function (event) { | |
event.preventDefault(); | |
var element = document.getElementById('serialString'); | |
socket.emit("sendSerial", element.value);<br /> }); | |
</script> | |
</head> | |
</html> |
That's it.. Finished files
So here are the final files which you need to make it work.
APP.JS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Module dependencies. | |
*/ | |
var express = require('express') | |
, routes = require('./routes') | |
, user = require('./routes/user') | |
, http = require('http') | |
, path = require('path') | |
, serialport = require("serialport").SerialPort; | |
/** | |
* Serial Port Setup. | |
*/ | |
var portName = '/dev/ttyAMA0'; //This is the standard Raspberry Pi Serial port | |
var readData = ''; //Array to hold the values read in from the port | |
var sp = new serialport(portName, { | |
baudRate: 9600, | |
dataBits: 8, | |
parity: 'none', | |
stopBits: 1, | |
flowControl: false | |
}); | |
/** | |
* Express Setup. | |
*/ | |
var app = express(); | |
app.configure(function(){ | |
app.set('port', process.env.PORT || 80); | |
app.set('views', __dirname + '/views'); | |
app.set('view engine', 'jade'); | |
app.use(express.favicon()); | |
app.use(express.logger('dev')); | |
app.use(express.bodyParser()); | |
app.use(express.methodOverride()); | |
app.use(app.router); | |
app.use(express.static(path.join(__dirname, 'public'))); | |
}); | |
app.configure('development', function(){ | |
app.use(express.errorHandler()); | |
}); | |
app.get('/', routes.index); | |
app.get('/users', user.list); | |
/** | |
* Actual Server Code | |
*/ | |
var server = http.createServer(app).listen(app.get('port'), function(){ | |
console.log("Express server listening on port " + app.get('port')); | |
}); | |
var io = require('socket.io').listen(server); | |
/** | |
* Server and socket started, below are all my listeners and emitters | |
*/ | |
io.sockets.on('connection', function(socket){ | |
console.log("Socket connected"); | |
socket.emit('connected', 123); | |
socket.on('sendSerial', function(data) { | |
console.log("Client sent us: " + data + "to send to serial"); | |
sp.write(mbBuffer, function (err, bytesWritten) { | |
console.log('bytes written:', bytesWritten); | |
}); | |
}); | |
sp.on('data', function (data) { | |
console.log(data); | |
var mbRec = new Buffer(data, 'utf') | |
console.log(mbRec); | |
mbRec = mbRec.toString('hex'); | |
console.log(mbRec); | |
socket.emit('serialEvent', mbRec); | |
}); | |
sp.on('close', function (err) { | |
console.log('port closed'); | |
}); | |
sp.on('error', function (err) { | |
console.error("error", err); | |
}); | |
sp.on('open', function () { | |
console.log('port opened...'); | |
}); | |
}); |
INDEX.HTML
This is shown above in full..INDEX.JS(ROUTER)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* GET home page. | |
*/ | |
var fs = require('fs') | |
exports.index = function(req, res){ | |
res.writeHead(200, {'Content-Type': 'text/html'}); | |
var contents = fs.readFileSync("./public/index.html", "UTF-8"); | |
res.end(contents); | |
// res.render('index'); | |
}; |
Hey sam, nice tutorial, really neat, one of the issues is trying to install node.js on Raspian Wheezy (2012-12-16), do you have any recommendations or site links on how to get that running. I am getting "illegal instruction" when i install serialport , "#npm install serialport"
ReplyDeleteHey man, I am going to do an installing node.js on a blank pi tutorial this week.. my new blog is over at www.badgersblog.co.uk so check it out there.. it will probs be on in next few days.. :) merry christmas!
DeleteWoo-Hoo! Awesome! Thanks Sam, Merry Christmas to you too !
DeleteJust letting you know, instructions are now up on the blog for node install :)
DeleteThanks Sam, :-)
DeleteSam, I would kill for (ok, maybe not) a tutorial / parts list of your breakout board with MAX 3483. I also want to communicate modbus (RS485) from my Raspberry Pi. Planning to go and buy a MAX 3483 tomorrow but I'll guess there's more parts needed than that? You have a diod for example.
ReplyDeleteI totally only just saw this, it didn't show up on my email.. how are you getting on? still need some help
DeleteHi Sam
ReplyDeleteDid you ever complete your node.js modbus RTU package?
please provide whole code in zip file.
ReplyDeleteHi Sam
ReplyDeleteI have found that this works pretty well
https://github.com/morkai/h5.modbus
I hope this helps someone
Any chance you can update the project to use express 4 instead of 3? I was getting a lot of errors with the code with express 4 so I installed express 3 but now the socket.io faults as well. Please help.
ReplyDeleteExcellent article. Very interesting to read. I really love to read such a nice article. Thanks! keep rocking. Best spanner set brand India
ReplyDelete