Notes on switching from xbee to RN-XV for low latency applications using Pure Data
Happy new year!! It’s been a crazy crazy month! I wont even go into all the mental intensities emmerging from digging deeper into the mathematical underpinnings of sound design (which resulted in a couple of weeks of burnout). although a reprap breakdown has slowed down the pace of printing perks for crowdfunding campaign fullfillment, I have been working on personal mixes for my beatjazz supporter pack contributors and managed to mail off another controller! One more to go!! it still amazes me how much nicer they are than my own, which is constantly being added to and tweaked. this particular contributor received his system with my own personal xbee wirelesss data system. the one I have been using since the beginning of this journey.
As crazy as it sounds, one of the things I have learned about myself that if I have a hard “future” thing to do but I have a comfortable “now” thing laying around, I will go for the “now” thing. especially when there is a deadline or it’s a bit too abstract to fiddle with. so what I do is get rid of the “now” thing and make the “future” thing the “now” thing. I have done this for years, like when switching from saxophone to wind midi controller, switching from playing cover tunes to playing originals, from hardware to laptop, from wind controller to beatjazz controller and, last summer, from commercial audio software to using pure data as my central means of expression.
the Digi made, extremely popular Xbee series 1 and series 1 pro’s (the pro’s are the same, but with 63mW broadcast output as compared to the regular series ones 1mW), are marketed as “a drop in xbee replacement” which excited me. the xbee’s werent my first dalliance with wirelessness. I had a kenton midistream wireless midi system when they first came out in 2004. I also used my iphone’s accelerometer as a gestural controller for most of 2010-the summer before I began working on the beatjazz controller. the Xbee was my first interaction with actual networking protocols, although it was an older, slower yet more reliable one called Serial protocol.
Serial was created a long time ago and its very slow in comparison to todays protocols, but its stable and is good for less bandwitdth hungry data transmission such as that coming from the low powered arduino platform. there are multiple ways of integrating xbees with arduinos using snap on “shields” and, in my case with the arduino fio, having an xbee “shoe” built directly onto the board. this has worked for almost 2 years with some caveats that are worth mentioning;
- if the computer loses the connection, the software must be restarted, which sucks in a show.
bidirectionally, the data coming from the arduino is mostly speedy enough for low latency performance, but data transmitted BACK to the arduino from the computer, using the aforementioned xbee pro’s was useless for anything time sensitive so I only used it to change the light colors infrequently.
if I am in the vicinity of a “hipster forcefield”, (a phenomena whereby the sheer number of smartphones, with their numerous wireless capabilities, drown out my xbees broadcast capacity and the system becomes unresponsive), I end up huddled over my laptop-situated xbee basestation, gasping for bandwidth.
the RN-XV’s, made by roving networks, use wifi and are designed for serial communication although not limited by it. I purchased them but didn’t really use them much until a recent robotics project (I will be writing about soon). I found them to be remarkably faster by Wide margin, out of the box, but had less success when using them with the beatjazz prosthetics. the data was very shakey and garbled and I had no idea where to even begin fixing it. I put them away, mentally, until just recently when I became interested refining the system, which seemed a bit labored recently. so I just said fuck it and mailed the xbees off with the controller and stranded myself in 802.11 land.
Along the way, I learned a lot of very valuable stuff but there was one thing In particular that I wanted to share; If you use firmata, as I do, you can use it, (mostly) unedited. you can use the rn_xv to create a wireless arduino network with no serial port virtualization!
- go pure wifi instead of serial for wireless communication
- give each “unit” (headset, left hand, right hand) its own ip address, directed at a small dedicated wireless router (d-link dir-300)
- speed up bidirectional communication significantly enough to make better narrative use of the lights and haptic feedback, and reduce processing overhead.
- the inlet is where settings bound for the arduino are input into the [pd command processing] abstraction which then sends it to comport object, which is PD’s serial interface. The comport inlet (at the top of the object) sends the serially formatted data thru a serial connection, to the arduino. in my system, the xbee’s were the virtual (wireless) serial cable.
the outlet at the bottom of the comport object is the data that comes “from” the arduino. this data is a firmata-formatted stream of numbers
224 17 0 (repeat) but in a stream
this stream is sent to the [pd make lists] abstraction and then from there to the outlet where it is routed to digital and analog route objects where you can assign them to things in pd.
I needed to get sensor data from the arduinos as fast as it could send it, then process it in pd and send control data back to the arduino, wirelessly. it also needed to be as blazingly fast as was possible. My first idea was to emulate a serial port using one of many virtual serial port programs on the internet like Serial/IP, socat, HW-VCP and about 6-7 others. in all cases, the data I was getting was garbled and would stop after a while (more on this later). so after a long time of beating my head against this wall I decided to try simply getting rid of the serial communications system and trying this with networking objects.
I tried all of the networking objects I could find in pd with most people telling me to try UDP, which is a connectionless format that, unlike serial and TCP, doesn’t need to “hand-shake” to allow data to pass back and forth. both ends of the link simply “scream” data at the other. in this way it is great for things like skype and video streaming but not so much for things that have a low tolerance for errors. so after another week of fiddling I was able to place the [udpsend] object underneath the command processing abstraction, where the comport was. [udpreceive] receives data from the arduino and sends it to the rest of the pd-system. [udpsend] accepts data at its inlet and also needs the ip address and port to send the data to the right arduino.
the [udpreceive] object recieves it data from a port on the router that I set on the RN-XV itself, negating the need for arduino libraries or rewriting the firmata firmware. at this point I will jump to the RN-XV setup. it will make sense when I come back to this abstraction.
The RN-XV is a powerful 802.11b/g tranciever marketed as a drop-in xbee replacement, meaning that the it shares the same small pin spacing that xbee is based on but is a bit more tedious to program. for the purposes of this tutorial we will stick to the features that will enable us to link this directly to pd.
what we need to give each RN-XV its own static ip address and port, first. this is where the sparkfun USB explorer or equivalent usb serial to xbee board, comes in handy. with it you can program using a terminal like Putty or, in my case on win7, Coolterm.
in coolterm, goto Connection->Options and make sure the serial port your explorer is on is selected and the initial baudrate is 9600 and click OK.
in the main window, click the “connect” button then in the terminal window type
$$$ (but DO NOT press enter afterward.)
this puts the RN-XV into command mode and the green light blinks more quickly.
if you type “get everything” (no quotes) you should see all of the settings for the tranciever. these are the ones I found most important:
- “set ip address”<ip address> –is the ip address of the of the rn-xv
”set ip local port”<port number> –this is the port that [udpsend]will send data thru to the arduino
”set ip host” <ip address of the computer>
”set ip remote” <port number> –this is the port that the [udpreceive] will use to receive sensor data and send it to the system.
”set ip protocol” <1> this sets the rn-xv to use UDP protocol instead of TCP.
”set wlan ssid” <ssid> –this is the name of the wireless network you are connecting to.
“set wlan channel”<ch.number> –set your channel number here. I set mine to 0 so it associates with the AP with whatever channel is there.
“set wlan join” <1> joins the access point saved in memory (the one we input above)
”set wlan linkmon” <0> I turned this off.
“set wlan rate” <15> I am playing with it at this rate which is the fastest as 54mb/sec. 1-2mb/sec would be fine(0 or 1). roving states that lower transmit rates increase the range, so play with this one as you need.
”set sys autoconn” <0> this turns off the autoconnect timer.
”set uart baudrate” <baudrate> this effectively sets the baudrate of the connection. I have mine set to 115200 kbps and will experiment with higher rates but this seems to be fast enough for right now. one line in the arduino firmata firmware will need to be changed to allow this to work properly. if you need to use Coolterm with this rn-xv in the future, it must be at this baudrate in the option settings.
”set uart flow” <0>
”set uart mode” <1>
- and the last and possibly most important two settings
- “set comm size” <1420> this is the “packet” size or the number of bytes sent over udp as a block or numbers
”set comm time <5> this is the number of milliseconds between flushes of data blasted out to the computer from the rn-xv. every 5 ms, it sends a packet of data that “should be” 1420 bytes. I say should be because it is udp and there is no guarantee of delivery.
- after inputting all of this into the terminal window, type “save” which saves it all to its own local memory (which is why the arduino WiFly librairies are unneccessary in this instance) then type “reboot” which puts it back into regular mode, ready to be placed back into the arduino fio.
Arduino firmata edit
next thing is to now use the arduino software to change the baudrate of the firmata firmware from 57600kbps to 115200kbps. goto File->Examples->Firmata->standard firmata. scroll to the end of the sketch and then scroll up until you see
and change it to
then upload it to the arduino. 8you can not have the rn-xv attached to the arduino while uploading a sketch. put it on after uploading)
Setting up the new network arduino object
ok, so back to our edited [arduino] object, which I have named [myarduino-udp]. we need to tell [udpsend] where to send its data, so we create a message with [connect xxx.xxx.xxx.xxx xxxx < which is the ip address we put into the rn-xv earlier, and its port number. when you connect it and click on it, it “should” work and output a 1 at its outlet, signifying that it works. if it does not, make sure that the router is working properly and that everything is connected. if there is a red light blinking on the rn-xv, then it is not associated with the router.
Next, in the [udpreceive], enter to port number that you entered as the remote port in the rn-xv settings. if this is working, it should show the received ip address and bytes from the second outlet. ( I took this from the help files).
once it works, the “bytes received” number box should show some activity if you have sensors attached so you should send some data at this point. for reference, I attached a print object to the output of [udpreceive] so I could see what was coming out (below). it is blocks of numbers starting with a 2xx number the a 0-x number and another 0 to about 17 or so. these are the right numbers in the wrong format. they must come as a stream like;
so I used a list object called [list drip] which outputs a list as a stream. this formated the data properly and everything worked! it was at this point I realized that either [comport] or the serial port was the previous bottleneck in my system. the system was now noticibly quicker than with the xbees. so I decided to try to eek out a bit more speed by toying around with the [list-drip] since now, it was the new bottleneck when I came across this thread with test abstractions that sped up the [list-drip] object, significantly! I ended up using an undocumented version called [list-drip-scheid] which itself is a faster variation of one called [list-drip-quick2]!!! (the thread is great read as well)
one last thing I did was to place a bang object on the inlet of the [loadbang] because it doesn’t send the data to the arduino on the first [loadbang] so I do it manually after the patch has loaded. and that should be it! I say “should be” because there is always something that falls over somewhere but this works for me and has been stable for about a week since I figured it out. my operating latency is about 4ms bidirectionally and now the system is fast enough to control the lights with gestures and breath pressure in real time while allowing much more expandability. as well, there are no weird comport, serial port, ftdi driver issues; everything will work on any operating system with minimal fuss. I now need only add ip based components to my system for my router to recognize and pd to utilize.
this is my first official tutorial so let me know what you think. if it is confusing or too long or whatever. I aint gonna change it but I will incorporate the feedback for future posts. l8r.
EDIT. here is a demo of the complete system, working.