Tuesday, January 17, 2017

Reading Serial Sensor Data With Node and Arduino

Getting data into your application is key to being successful for any experiment. Node has a nice implementation of a serial port library called Node serial-port. You can install it pretty easily with a npm install --save serialport.

Node's evented nature fits nicely with responding to data or messages from microcontrollers, serial sources, or anything that happens asynchronously. Serialport's readline and delimiter mechanisms allow parsing individual messages or creating your own protocol a breeze. For example if you selected the readline parser, the "data" event would be triggered every time some data followed by a new line character arrives on the port. You can also specify a sequence of custom characters so that you can construct your own communications protocol.

Let's look at a simple example. First, we need a serial input to feed our Node app. I'm going to use an Arduino, more specifically the Adafruit Feather 32u4 Bluefruit LE. The simple sketch below will just print the string "hello world!" followed by the return carriage (\r) and new line character (\n)  over and over again.

Just prints "hello world!" over and over and over

Now we need to set up the Node side to receive the data. Start yourself a Node project and install serialport. I'm on a MacBook pro so my Arduino shows up under /dev in the file structure. Try an ls /dev/tty to show everything in the dev directory that starts with a "tty". My Arduino showed up as /dev/tty.usbmodem1421.



If you get an error that the port couldn't be opened, try a sudo chmod 777 on the serial port in /dev. 777 is the nuclear option for permissions and you probably should't be giving to too many files, but that should give you access to the port... and everybody else. If you run the node application, you should see "hello world!" pop up every 500 ms. 

If you wanted to get the same bit of data, but have it arrive as bytes instead of a string, use "SerialPort.parsers.byteDelimiter([13,10])". Why 13 and 10? Those are the Decimal value of the ascii bytes for \r and \n. So, you can do the same with any bytes or characters, just use their byte value.

Creating Your Own Simple Protocol (Book Ends)

Sometimes when you're transferring information, its a good idea to construct the message in a way that its easier to process or to add some reliability. If you are trying to transmit data over some unreliable transport layer (maybe you're trying to send data through salt water or something weird) it may make sense to check that the data arrives properly or that you just didn't read in some garbage.

A simple and limited way to check your data's validity is to use start and stop byte sequences. A start and stop sequence will allow you to delimit or 'bookend' your data and simply check if data is where it should be. For example, lets say we were trying to send a 4 byte number over and over again to our node app. What we want to do is read in byte0, followed by byte1, and byte3, and then, at last byte4. If we accidentally start reading in the middle of the number, we'll end up with a few bytes from one number and bytes from another. This would give us the completely wrong number. How can we remedy this?

If we start and stop the transmission with a fairly unique byte sequence, we can check the first and last bytes we received to check they match up with what we expect. Let's make an example.

Writes out the start sequence, followed by our 4 byte payload, and the stop sequence. 



The Node side. We're waiting for a byte sequence that ends with '%^' and begins with '!&'

In the code above, we're getting data from the event, checking the start sequence, and logging the payload. At first, we just get rid of the last 2 bytes. Since we're using the byteDelimiter, its safe to assume the last bytes are the delimiter because we got the event. Now, we check the first two bytes to make sure they match and if they do we can assume we got a complete message.

Where Bookends Come Up Short

Bookends are a simple way to ensure some reliability in your messages, but it does not guarantee your payload is what you originally intended to send. While your bookends may arrive at the correct time and in place, there is nothing about this method that guarantees the validity and integrity of the payload.


TODO: Give you code instead of pictures.

No comments:

Post a Comment