Earlier this year Texas Instruments released their eZ430-Chronos Wireless Watch Development kit, available for $49.99 at their website. Essentially it is a development kit built around a new chip created by TI with several embedded sensors interfaced with said chip, such as a 3-axis accelerometer, a temperature sensor, an altimeter and more. What makes this chip special is that it is meant to send and receive serial data wirelessly using the 433 MHz RF frequency (other frequencies are available for other countries where 433 is not allowed).
The kit ships with a USB dongle that also has a 433 MHz RF antenna on it. This USB dongle just converts data coming in via the wireless link into serial data, which is transmitted to the computer using a virtual COM port. Using basic serial commands one can both send and receive packets of data between your program and the watch, regardless of what platform you are using to develop in. The catch, though, is that TI hasn’t released much information about the device or wireless protocol other than a surprisingly unhelpful 670 page PDF user guide!
This means I could easily plug the USB dongle into my laptop and push a few buttons on my watch to get a wireless link going, but without any information about the protocol or packet structure for the wireless data transmission theres not much one can do out of the box just yet as far as custom applications. Though I will say, getting the data itself is not the hard part – the USB dongle handles everything and creates a virtual COM port on your computer through which you can access serial data just like you would any other serial device. The hard part is understanding this data and breaking down the packet structure to obtain something useful.
Talking to the eZ430 using Processing
The first thing I came across was a post at a blog called Chemical Oliver which demonstrated how to get a Processing program to connect to the eZ430, request accelerometer data and then plot the data into a graph.
The eZ430 needs to be in ACC mode – remember to hit the SYNC button when you start your Processing app. If things are working you should see a blinking radio signal icon on the watch and the USB dongle activity light should be blinking rapidly.
As for the software side of things, any program you write using any language you choose will have to do the following things:
- Start communicating with the watch using the correct serial port
- Send a packet to the watch telling it to start its on-board RF access point
- Send a packet to the watch requesting that accelerometer data be sent to you
- Process all the incoming packets and extract the accelerometer data
- Apply that accelerometer data however you want
The best way for you to understand how to do each of these steps is by picking apart examples, such as the source code you’ll find at the very end of this post, or at the post I linked to at Chemical Oliver’s blog.
But wait, there’s something wrong!
Once I got my Processing app up and running I began to notice a very annoying problem – go back to that blog post from Chemical Oliber and take a look at the X, Y and Z graphs. See how they see to jump pretty huge distances in very short amounts of time? At first I thought that meant the accelerometer was just really sensitive, but nope. Even after I tried sketching up a fix it was still skipping around and being weird. So I had to dig deeper. And what I found out, from asking questions on the TI Chronos Google Group and reading technical datasheets of the accelerometer used in the eZ430, is you cannot interpret the accelerometer data bytes as literal values (at least not in the way I was thinking). You have to use Two’s Complement!
What the fruit is Two’s Complement?
First of all, remember that one byte is made of 8 bits. Normally you would look at these 8 bits and be able to come up with an integer value from it ( 10011011 = 155). In Two’s Complement, the left-most bit (the most significant bit or MSB) is actually a sign indicator: 0 means positive, 1 means negative. That leaves 7 bits left that we can form an integer from.
Using that same binary string, 10011011, and applying Two’s Complement, we actually get a negative value: -27!
But doing this explicit calculation to every single byte that comes in gets real expensive, real fast – the watch functions at a baud rate of 115,200 bps! So what I learned is that you could, in practice, subtract 255 to every accelerometer data byte that comes in. Now you have a nice value in the range of [-127-127] (instead of [0-255]) that you can graph and apply to other stuff!
Rotating a 3D model using the accelerometer data as a gravity vector
Initially my goal with this project was to accurately rotate a 3D model using the movement and rotation of the eZ430 watch attached to your wrist. But I learned several things early on that made me re-think this idea:
- When you move your hand around in seemingly small and simple motions there’s actually a lot of interesting motion going on! Your wrist will naturally want to rotate as you move your hand around, and its actually rather difficult swipe your hand in a perfectly straight line because you’re usually pivoting on either your shoulder or your elbow, which causes your hand to move in an arc.
- Gravity is always acting on objects with a (more or less) constant force. Therefore, no matter how you rotate or move your hand, gravity is acting upon it in the same direction. The accelerometer data reflects this: if you move or rotate your hand and then stop, you’ll notice that the graphs will flatten out into straight lines, but at different values depending on how your hand is positioned. Therefore you can use this data to get a rough idea of how the accelerometer is rotated!
As a test, I decided to directly apply the X and Y components of the accelerometer data to the rotation of a 3D cube and check out what happened. To no one’s surprise, it wiggled a bit. However, I couldn’t get it to rotate beyond a certain point no matter what I did. So I did some tweaking and value manipulation (including using one of my favorite Processing functions, map()) and got a more interesting result after a while.
rotateX( radians(map(adj_acc.x,-127,127,0,360))*4 ); rotateY( PI - radians(map(adj_acc.y,-127,127,0,360))*4 );
The next thing I want to do is reduce the amount of ‘jitter’ that occurs in the accelerometer data that is just inherent to the device itself. I have tried to take the average of a number of samples (8), but that didn’t help me much: in fact, it caused some really noticeable spikes for some reason. I have heard a lot about something called a Kalman Filter that is commonly used to smooth out data in real-time, but the math looks pretty intense, so I left it alone for now. I might be revisiting this project again in the future to hook into a large spherical display to be displayed on the outside of a planetarium, so I’ll take another stab at it then.