Tap, Tap, Drop. ADXL345 Accelerometer + Arduino

Wednesday, March 16 th , 2011

You know [[accelerometers]] right? Yeah… the things that tell your phone how it is orientated. But, believe it or not accelerometers are best suited for something other than sensing orientation. Excuse my oversimplification here, but this is going to help those who don’t know what’s going on. [[Accelerometers]] for all intents and purposes sense movement, so because gravity is pulling on the object it senses that and we can then determine orientation. Well… many actions like walking, throwing or jumping have particular movements associated with them, and a profile can be designed to recognize these movements. This is how your wii-mote can tell if your are bowling and not throwing, and your high-end pedometer knows the difference between running and walking. But we mortals often lack the insane math skills needed to write these movement profiles, and so we often just use our accelerometers as orientation sensors. BUT!!! What if your accelerometer did the heavy lifting for you? Well the [[ADXL345]] does just that. It is able to sense taps, double taps, free-fall, activity and inactivity all by just configuring some parameters. Im using the ADXL345 breakout board from sparkfun.

Out of the box, the [[ADXL345]] is an [[I2C]] 3-[[axis]] accelerometer with user selectable sensitivity and 10-13 bit resolution (depending on sensitivity). And… It is pretty decent all around, but were not really going to spend much time talking about boring stuff today. Today, we are talking about getting the special features of the ADXL345 up and running. (tap, double tap, free fall, activity and inactivity)

These special detection features have the ability to trigger 2 interrupt pins, making the pin go HIGH the moment one of the events is sensed. You can select what events to watch for, and what interupt pin to trigger when it is sensed (I had issues with INT2, it would not reset). You can take these interrupt pins and connect them to your Arduino to trigger an interrupt. An interrupt, when sensed on the Arduino, pauses the system instantly, even if it is in the middle of something, and responds to that interrupt how ever you have it setup before returning to the normal code. Like a police officer coming down the street with its lights on… Even if you have a green light, you stop and let them go. But using interrupts is a little beyond the scope of this article, so we are going to just keep checking for these actions in code and respond to them when we see them.

Hooking it up

The ADXL345 supports both [[SPI]] and [[I2C]], but we are just going to talk I2C here. I2C is a 2-wire serial connection, so you just need to connect the SDA (Data) and SCL (Clock) lines to your Arduino for communication. On your Arduino (everything but the mega) SDA is on analog pin 4, and SCL is on analog pin 5. On an arduino mega, SDA is digital 20, and SCL is digital 21.

Make sure both [[VCC]] and the CS pins on the sensor are connected to 3.3v. We connect CS to 3.3V to tell the sensor we will be using it as an [[I2C]] device, and not an [[SPI]] device.

Code

Again, because this project is made up of many files, I am using bildr’s fancy bildrCode wrapper. All this example code will do for you now is output the name of the triggered action in the serial terminal. But I left the code in a state that should be pretty obvious how to extend it.

The special features require a lot of setup to get them working, but because this is bildr, we are going to start you off with working code, everything all setup, and spend a little bit explaining why certain things are how they are. To simplify everything in code, we will be using this Arduino library. But I have made a few small changes to it to make this a little easier to do, and to make it work a little better with other libraries, so the new library files are included in the code below.

To make this code work, before you load the code, or even open the Arduino program, we need to place the “adxl345” folder into your Arduino Library. If you don’t know where that is by default, Look to the right.

Once the ADXL345 folder is in there, you can just go ahead and open ADXL345_Example.pde in your Arduino software, and upload it.

The parameters that are set in the code should get you going, but you will most likely find that your project requires something different. Read through the setup code, there are a lot of things that can be changed, from the force needed to activate “activity”, the time before “inactivity” is triggered and the maximum length / minimum intensity of a tap. You can also completely turn off actions. I found that it was hard to trigger tap without triggering action, and double tap most often triggered tap as well. If you are up for it, the documentation on this chip is quite good, and explains a lot of the values in much greater detail (PDF).

Default Library Folder Location

On your Mac:: In (home directory)/Documents/Arduino/libraries
On your PC:: My Documents -> Arduino -> libraries
On your Linux box:: (home directory)/sketchbook/libraries

Download

If you click the download button to the right of “Arduino” you can download the whole thing as a zip, so you dont need to copy all the files.

Video

Extending this

Im sure you could come up with 101 ways to expand on this, but incase you need some help, here we go: What about a tap dance sensitive floor that caused lights to change with the rhythm of the dance? Shoes that shock you if you haven’t walked in 5 min. Something as simple as a ball that you throw up and only lights up on its way down… Anything you could think of that needs or could incorporate (in)activity, free-fall, or taps, you could find a way to use this to make it happen.

We need your help

bildr is in need of people interested in helping write any sort of blog post for bildr. If you think you would like to help bildr by writing something, supplying code or schematic, or just have an idea for an article you think should be written, please contact us at blog@bildr.org or let us know in the forum.

Stable Orientation – Digital IMU 6DOF + Arduino

Wednesday, March 14 th , 2012

A while back we wrote an article on sensing orientation with the adxl335 accelerometer. In that article I mentioned all the drawbacks of trying to do this with just an accelerometer, and said that if you needed something stable, what you really needed was an IMU. Well… We are back with an article covering just that, the Digital IMU 6DOF (6 degrees of freedom) breakout board from sparkfun.

An IMU (Inertial Measurement Unit) is a system comprised of an accelerometer and a gyroscope working in tandem to compensate for the pitfalls of each other. This particular board is comprised of the ADXL345 accelerometer (bildr article) and the ITG-3200 gyroscope. Correctly setup, the gyro is able to kick in where an accelerometer leaves off, and vise versa. A gyro is great at measuring rotation, but has no understanding of orientation. And an accelerometer is good at determining orientation, but has no ability to keep track during movement and rotation. But just sticking these together wont give you a clean orientation, we need some hardcore math that will be able to take both the readings, along with previous readings, and make a really good estimate of what is going on. The math for this is known as filtering.

You may have heard of something called a kalman filter. I have searched for years and have never seen a working version for 3axis that could run on the arduino. Sadly, the arduino just dosnt have the power to make it work. Thankfully Kalman isnt the only name in town, and the fusion filter does an excellent job, and is very light mathematically and runs really well on the arduino. The awesome thing about this is that the guys over at varesano did all the hard work in their library for the 9DOF( has 3 axis magnetometer )

Hooking it up

The both components of the Digital IMU 6DOF are [[I2C]] devices on a single bus. I2C is a 2-wire serial connection, so we just need to connect the SDA (Data) and SCL (Clock) lines to your Arduino for communication. On your Arduino (everything but the [[Arduino_Mega |mega]]) SDA is on analog pin 4, and SCL is on analog pin 5. On an arduino mega, SDA is digital 20, and SCL is digital 21. (The Arduino Leonardo will also be different). Other than these 2 lines, we just need to connect power(3.3v), ground and we are all set.

Note: I noticed that this device is particularly sensitive to so-so wiring, so make sure your connections are solid, or you will see this guy freezing left and right.

Code

Using this part isnt simple from a code point, so we have a library for you, and a big one at that. As I said before the guys over at varesano did all the hard work in their library for the 9DOF( has 3 axis magnetometer ) I just modified for use specifically for this board and made it into a single library so it wouldn’t cause any conflicts. Because this is based off of the FreeIMU code, we are keeping their GPL license on it.

To make this code work, before you load the code, or even open the Arduino program, we need to place the “FreeSixIMU” folder into your Arduino Library. If you don’t know where that is by default, Look to the right.

If you click the download button to the right of “Arduino” you can download the whole thing as a zip, so you dont need to copy all the files.

Default Library Folder Location

On your Mac:: In (home directory)/Documents/Arduino/libraries
On your PC:: My Documents -> Arduino -> libraries
On your Linux box:: (home directory)/sketchbook/libraries

Visualizing the orientation with a processing sketch

Sometimes it is hard to see if the output is correct… So we can verify it with a processing sketch (check out the video below). We have included a processing example “freeSixCube” and it has 2 parts. A specialized arduino firmware that must be loaded first, and a processing sketch. You need to configure the sketch to use the correct serial port.

If you are having issues with processing sketch missing a font, let me know, I did my best to not require any font files.

When you launch the processing sketch, (make sure to hold it very still for the first 2 seconds) it should draw up a cube, and after a second it will move to mimic your movement of the 6DOF board. You can hit “h” to reset the orientation to level so you can get it to what you consider level, hit “h” and it should look just like how you hold it from there on out.

You will see it drifting (moving onscreen without you moving the sensor) quite a bit at first, but hold it still and it will smooth out. But even then, the yaw will still be drifting a bit. To understand why, read on.

Drifting Yaw

[[Yaw]] is name for rotation around an axis that is similar to spinning a top, or shaking your head “no.” Accelerometers can’t measure this type of motion, but gyros can. Unfortunately gyros have no sense of direction, and also drift. So your yaw measurements from this will be without a sense of direction, and will drift over time. How much? Maybe a few degrees a second, maybe less, it’s hard to say because this library does a good job if suppressing it, but it’s not perfect.

In the first second after the Arduino resets (due to code upload, serial connection, etc), the firmware will try to reduce the drift from the gyroscope. So Make sure to keep the IMU steady during that startup time for best results.

If you need direction, and no drift in your yaw you need to get your self an AHRS, that’s an IMU with a magnetometer on it. Like this guy here.

Video

Sensing Orientation With The ADXL335 + Arduino

Friday, April 22 nd , 2011

I know, I know, this one has such a simple name. Where’s the pun? Honestly, the description was just to long to include one. Maybe it could have been “What’s Up? Sensing Orientation With The [[3_axis_accelerometer_-_ADXL335|ADXL335]] + Arduino” – Ehhh… Probably not.

A few weeks ago we wrote a tutorial about using the ADXL345 to sense taps, and drops, but this week we are going to wind it back, go back to basics, and show you how to take an analog 3-axis [[accelerometer]] and use it to sense simple orientation with it, specifically the ADXL335, but this can be applied to any analog 3-axis accelerometer.

Before we really dive into it, we need a general understanding of how accelerometers work, so if you already know why each axis can only differentiate 180deg of movement, you can skip this. Wraning: Over-simplification ahead. In the last article I described an accelerometer as a device that sensed movement. Today, think of them as devices that sense gravity.

Basic Understanding Of Accelerometers

[[Accelerometers]] measure acceleration, often caused by motion. But when they are standing still, the only acceleration the accelerometer senses is due to gravity pulling down on it.

Imagine a box that has little springs sticking straight out from the sides of the box, and that the [[accelerometer]] measures how hard gravity is stretching out those springs. The springs on the side are all bending the same amount, the spring on the bottom is all stretched out, and the one at the top is not stretched at all (because the spring is pull back into itself), so the accelerometer sees it as feeling no gravity, or 0g (gravity). If you rotate the box 90º and follow the spring on the top. It is now on the side and is hanging down some and the sensor sees it now feels .5g. Rotate 90º again, and it is at the bottom, stretched out, and it feels 1g. Rotate again 90º and we are at the side again, with it feeling .5g, and 90º rotation again, we are back at the top and it feels 0g. So we made a full rotation and the accelerometer saw this: 0g-> .5g -> 1g -> .5g -> 0g.

If you look at this, it means that the accelerometer can really only sense differences in 180º of movement as the other 180deg is just a mirror image. So how can we sense 360 deg of movement?

The trick to this is that while one axis can only sense a 180deg difference, so can the another axis, but they sense it differently. If you look at the chart to the right, you can see the sensed values while rotating round the X Axis. (The x never changes because it is always facing the same direction) – So we can combine the y, and z values to find x using a trigonometry function called Atan2 who then gives us values back as -180º to 180º (but in radians, so it is -π to π and well have to convent it).

No Love For Yaw

[[Yaw]] is name for rotation around an axis that is similar to spinning a top, or shaking your head “no.” [[Accelerometers]] can’t measure this type of motion. Why? Well think about the box. If you turn the box in this manner, non of the sides change their orientation to the ground. If you need to measure yaw, you will need to incorporate a gyro or digital compass into your project, but it gets tricky, and is beyond the scope of this article.

Why So Shaky?

The accelerometer is really going to report a proper measurement when it is standing still. if it is shaken, moved, bumped, or in free fall, the acceleration the accelerometer measures is no longer purely gravity based, and you are going to see that in your readings.

But I Need A Cleaner Reading

If you need a clean reading during movement, you need something this article won’t provide, and that is a [[gyro]] and an [[accelerometer]] working in combination. Together they form something called an [[IMU]] – Inertial measurement unit. Correctly setup, and gyro is able to kick in where an accelerometer leave off, and vise versa. A gyro is great at measuring rotation, but has no understanding of orientation. And an accelerometer is good at determining orientation, but has no ability to keep track during rotation.

Hooking It Up

Connecting the ADXL335 to your Arduino is a snap. It powers off of the 3.3v, and the x,y,z connectors just connect to the 0,1,2 analog input pins. This accelerometer is a very simple and just outputs an [[analog]] [[voltage]] depending on the sensed value.

Code For The ADXL335 Or Other Analog Accelerometer

So here is some code: This code simply calculates 0-360º values for X,Y & Z and prints it to the serial terminal. This code is not specific to the ADXL335, and with almost no tweaking you can make this work with any analog 3-axis accelerometer.

Our Arduino’s analog input pins are comparing the analog voltage from the accelerometer’s analog outputs to 5v, and assigning number to that. If the Arduino senses 0V it reports 0, and 5V it reports 1023 ( you read more in the [[ADC|ADC Article in our wiki]]). The highest value I read from the sensor when it was standing still was 402, so that is 1g, and the lowest was 265, so that is 0g. If you get funny output from the code, you will need to change this depending on the highest and lowest values you get from your accelerometer. (Ask us the discussion forum for help if you need it.) Just changing these values will make the code work for any other analog 3 axis accelerometer, not just the ADXL335.

Because 265 (0g) was sensed at 0º, and 402 (1g) was sensed at 180º we are going to convert those values accordingly. But atan2, likes using -90 to 90 better, so we will do that instead. Lastly we convert the atan2 radian output to degrees, and voila, we have 360º measurements!

[code lang=”arduino”]
//////////////////////////////////////////////////////////////////
//©2011 bildr
//Released under the MIT License – Please reuse change and share
//Simple code for the ADXL335, prints calculated orientation via serial
//////////////////////////////////////////////////////////////////

//Analog read pins
const int xPin = 0;
const int yPin = 1;
const int zPin = 2;

//The minimum and maximum values that came from
//the accelerometer while standing still
//You very well may need to change these
int minVal = 265;
int maxVal = 402;

//to hold the caculated values
double x;
double y;
double z;

void setup(){
Serial.begin(9600);
}

void loop(){

//read the analog values from the accelerometer
int xRead = analogRead(xPin);
int yRead = analogRead(yPin);
int zRead = analogRead(zPin);

//convert read values to degrees -90 to 90 – Needed for atan2
int xAng = map(xRead, minVal, maxVal, -90, 90);
int yAng = map(yRead, minVal, maxVal, -90, 90);
int zAng = map(zRead, minVal, maxVal, -90, 90);

//Caculate 360deg values like so: atan2(-yAng, -zAng)
//atan2 outputs the value of -π to π (radians)
//We are then converting the radians to degrees
x = RAD_TO_DEG * (atan2(-yAng, -zAng) + PI);
y = RAD_TO_DEG * (atan2(-xAng, -zAng) + PI);
z = RAD_TO_DEG * (atan2(-yAng, -xAng) + PI);

//Output the caculations
Serial.print(“x: “);
Serial.print(x);
Serial.print(” | y: “);
Serial.print(y);
Serial.print(” | z: “);
Serial.println(z);

delay(100);//just here to slow down the serial output – Easier to read
}

[/code]

Extending This

Even with the limitations of the ADXL335, you can do some great things. This is one time that I think just hooking a RGB LED to your Arduino with this makes a great device. Just kinda fun to play with, mixing colors as you turn it, so if you must use LEDs with this, I’m ok with that.

This can really come in handy when you want to control anything based on orientation. So, get your tools ready, and build a reclining chair that knows when you reclined, and turns on the TV for you, OR… use it to master your posture as you balance a book on your head while recording the values.

Just a note: I had issues with connecting this with a servo. The servo was taking too much power from the Arduino, and the it was really throwing off the analog readings. So just note that. I did read that the servo needed a decoupling capacitor to work well, but I have not tried it.

We need your help

bildr is in need of people interested in helping write any sort of blog post for bildr, not just tutorials. If you think you would like to help bildr by writing something, supplying code or schematic, or just have an idea for an article or other post you think should be written, please contact us at blog@bildr.org or let us know in the forum.