Let's Make Robots!

Outboard Accelerometer as Bump Sensor and now position tracker! (Yes, OddBot has improved it again!)

Detects impacts using accelerometer
MMA7361BumpDetector.ino_.zip1.21 KB
MMA7361BumpDetector2.zip1.95 KB
MMA7361BumpDetectorWSerial.zip1.26 KB
MMA7361BumpDetector_with_Magnitude_and_Angle.zip1.91 KB

Note: it's getting harder and harder for me to take much credit for this-OddBot has done all the work since I first posted it and he's taken it from a built-in feature of a product that his company sells to being a highly-functional DIY open-source project.  He deserves full credit (and big props) for this.

It's hard to beat the Dagu MicroMagician for an Arduino Bot Brain with all its built-in goodness.  OddBot and Chris The Carpenter have made the code available/linked to it from their websites on GoogleCode. However if you're like me and you have half a dozen various 'dweenies scattered around the lab but no MM yet, you can still take advantage of some of the Brilliant work that OddBot did in making the accelerometer into a bump sensor by using an outboard accelerometer.  To make things simple, I used a breakout that employs the same chip that the MicroMagician does:the MMA7361, but the prinicpal can be applied to just about any accelerometer-Polulu and Sparkfun use about the same thing, for example.

To experiment with these ideas, set up the circuit as shown in the main image:

  • Arduino Digital 13 to an LED with an appropriate resistor to Ground
  • Arduino Digital 12 to MMA7361 Breakout Sleep Pin
  • Arduino Analog 0, 1 and 2 to MMA7361 Breakout X, Y and Z respectively
  • Arduino 3.3v and Gnd to MA7361 Breakout 3v3 and Gnd

Download the attached .zip file, expand it and import the sketch to your Arduino IDE, then load the sketch into your board.  You should be able to move the breakout board around smoothly without lighting the LED, but if you give it a good thump it ought to light right up. 

Simple code explanation:

The X, Y and Z axis sensors on the MMA7361 put out an analog signal based on what are essentially tiny pendulums etched into the SMD chip.  On the breakout (as opposed to the MicroMagician) you have to set the sleep pin high or else it will go off line and not give you any decent information.  OddBot's code essentially records the values for each vector and compares it to the last iteration of each vector with an adjustment for sensitivity and for the vibration that an impact would cause.  For demonstration purposes I took the code out of a library function and made it the entire loop such that the LED lights up when an impact is detected.  OddBot's code is very well commented (not to mention elegant as anything I've ever seen) so you can tell line by line what is happening in the program.


I intend to use this in my current project, K-9, which is a stylized version of Dr. Who's robot companion from the 80's when he was running around Spacetime with Richard Dawkins' wife.  The plan is to do this project in Marks, which is the hardware version of v.x language.  Mark 1 is spec'ed to use an Arduino Mega 2560, Mk2 will use a BeagleBoard (I couldn't resist-what else would you use for a robot dog's brains?)  The upgrade path made the use of an outboard breakout obvious.  Even more to the point, the BeagleBoard's GPIO doesn't have any ADCs on it, but luckily you can use a serial connection to transmit the translated analog information from the accelerometer via Arduino or, as I'll be doing it, via an ATTiny.  OddBot's code doesn't use any special TCCR or OCR commands so it translates to ATTiny with Arduino as ISP flawlessly.  Theoretically you could use a 45/85 to do this, but I have an IR Proximity sensor in the project as well, so it will be making use of the ATTiny too.  Add to that a digital output pin to trigger the processors' interrupts and you need a few more pins than the 45/85s provide, so I got a tube of 44s.  Chances are this will be enough for me to justify doing my own PCBs for the project, or rather having JAX's friends at DorkbotPDX do them for me.  In any case, as you can tell, I'm pretty taken with OddBot's code, and thankful to him for putting it out there for all to see.


OddBot graciously took a look over the code and made some improvements to it.  The file attachment has been updated and is far more useful for you (and me!) to turn into a function for robotics because now it doesn't rely on the delay command, meaning any other processes running on the micro won't be interrupted!  I should note that the MicroMagician uses an interrupt on TCCR2 as I understand it, which I assume you can emulate by applying an attachInterrupt to pins 2 or 3 of most Arduinos.  Also this code is instructive for the use of millis as a method of timing instead of delay for other uses too.  Anywhere you want to keep track of timing and keep running other processes, this is your method.

Big ass SERIOUS update!

Let's imagine you want your robot to act a little smarter than just backing up and picking a random direction to go in after it takes a whackin'. Most likely, he/she (I think most of us get a little sexist in referring to our creations) suffered an impact off-center. What's great is that the accelerometer knows this! What's even greatere is that OddBot's code is set up to easily tell you how to use this information. In the latest iteration of the code attachments (I thought I got rid of the first one but apparently I didn't, so we'll see if the delete works this time) MMA7361BumpDetectorWSerial does just what it says:adds a serial window which displays the DeltX and DeltY variables. (DeltZ could also be displayed but with less utility-chances are that, unless you've done something strange like mount your sensor perpendicular to the surface of the earth as the chasis rides, if a DeltZ event occurs it's too late for your robot to do anything about it.)

Here's the sticky part-you're going to have to do some work on your own to figure out where the impact took place. That's because I don't know where or how you'll mount your accelerometer. I can tell you how to figure it out with this program though.

Unzip/load/upload the new sketch and then open a serial window. (If you're unfamiliar with Arduino, you have to keep the USB cable attached to the Arduino for this part.) Then beat your robot senseless, but a little at a time, waiting for the LED to cycle off between each whipping and paying attention to where on the little friend you're applying the abuse. Try to apply thumps to it at say, every 60° around the perimeter, starting at dead center in the "Front" (defined here as the greatest protrusion from the center in the most frequent direction of travel.) Pay attention also to which serial window line corresponds to which whackin'. You should get a data set that looks kind of like this:


What do you notice?  Chances are that, relative to your sensor, the abuse delivered to one side shows up in negative integers and the abuse delivered to the other in positive.  Same for the front and back.

So once you know this, it's a simple matter to program for the results.  For example, let's say that impacts on the right and front are negative and the left and back are positive and that the X axis is paralell to the "axels."  Your condition would look something like this:

if (deltax>1 && deltay<1){



else if (deltax>1 && deltay>1){



etc...where the doBackUp* functions are defined by you.  You could also nest your if statements but with four directions of travel I don't think a switch case is going to make for any more "elegance."  (I'm guessing I missed something obvious that OddBot will catch right away and simplify or expand if I'm lucky enough to catch his attention with this update!)

Sorry this approach requires so much dirty work, but there's really no way around it without me dictating the build.  I wouldn't be much interested in sharing that way though.  

And another update!  With PICTURES!

I got another email from OddBot a few nights ago with the fourth file attachment here, MMA7361BumpDetector_with_Magnitude_and_Angle.zip, in it.  He's gone and made it even better.  This update translates the magnitude of the impact using the Atan function so that you and your robot are speaking the same language when it comes to the angle of impact.  He included this picture as an example:

With the following note:


Note: there is an optinal line of code to let you choose the angle range between ±180° or 0° to 360°
Which direction your robot calls 0° will depend how the sensor is mounted.


One thing you'll notice when you run the sketch is that it's hard to find exactly where 0°, 180°, 90° etc. are on your board/bot, but the sensor as mentioned is just a set of tiny silicon pendulums so the accuracy is amazing as far as I'm concerned.  I didn't have to do any adjusments to get useful data.

The most useful part of this is that you can calculate your robot's likely orientation to the walls of a regular rooom.  Most of the obstacles in a room will be walls or regular objects with edges paralell and perpendicular to the walls (that is until feng shui got popular...)  If you wanted to, you could use the collision angle to program your machine to right itself to the flow of most environments.  You would have to time the actuators or use encoders (or another method that we'll discuss in a minute) to manipulate the machine an amount that equalled the complement/supplement of the angle of impact, but this could have functionality for Roomba/Scooba type machines if for instance you wanted to regulate it to right turns or get fairly regular patterns of movement.

Now the bonus I mentioned. When I first ran the sketch, it seemed to be detecting every movement, not just impacts, which I realized immediately could be useful too.  For example, you could not only replace your robot's "bump" switch but you could also use it to forgo the wheel encoders now!  I can't replicate the error that was causing this now, but all you have to do is remove the condition 


 if (magnitude>sensitivity){---}

from the code and continuosly track the variable angle, then compensate with direction adjustments, tracking from an initial zero degree orientation and trying to come back to it.  This of course isn't perfect, but neither is any method of tracking position.  Base systems (like Northstar) can be blocked, encoders don't know that one wheel has gone over a bump that the other wheel didn't, simple PWM matching schemes have that problem and are easily foiled by something as imperceptible as humidity.  This method is processor intensive, but if you swing towards programming more than hardware (note-that doesn't sound like something I'd do) then it's another weapon in the arsenal.  I haven't applied the method yet and I'm sure it would need a little fine tuning for each and every machine it went into (for example, you'd want to adjust the sample time (micros and millis in this code) according to your robot's wheel base, size, wheel diameter, etc.) but I'm pretty confident that the theory is sound.  At least I'm so excited about the idea now that I can't see any obvious flaws in it!

So here's Oddbot's take on it:


The problem with using an accelerometer for a straight line is that you are not constantly accelerating.
If you have it mounted in the correct place relative to the wheels then it might be sensitive enough to help correct speed differences in the motors when starting and stopping.
A sensitive gyro might be a better choice. In both cases, the noise from rough terrain would swamp the signal you want.


I'm can't argue with that.  The only hope I see for the system I propose is that most motors available to hobbyists aren't going to be consistent enough to produce a steady enough motion that the accelerometer wouldn't be constantly picking up on the minute changes in velocity (here, speed and direction.)  That may be enough to make the data useless gibberish. (I think the fact that I've never had a robot that I wanted to map its envrions, so the obvious challenges and call to do the work aren't there for me.)

Any way, once again, thanks to OddBot for giving us more power to drive evolution!


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Nice tips ! I'll use it on my robot as soon as I get my accelerometer !

Thanks for posting the results of your experiments. Accelerometers are cheap and extremely useful for robots. I am surprised more robots on LMR do not use them.

  • They can tell your robot to stop before it falls over because the robot is at a sharp angle.
  • If your robot falls over then they can help your robot get back on it's wheels (or feet,tracks,etc.).
  • Detect impact magnitude and direction.
  • Allow your robot to recognize smooth floors and rough terrain.
  • allow your robot to map rough terrain, recognize stair cases by their angle.
  • Detect when a robot falls (0G) so that motors/servos can quickly shut down to protect gears.

I like it when people learn something new and share it with everyone else.

I'm not sure how well this code will work as the library depended on testing the accelerometer outputs every 2mS using an interrupt on timer 2. Because you have the delay(500) in the code this will effectively make the devibrate value a minimum of 250 (250 code loops at 2mS per loop).

Now that you've posted the updated code that last part is irrelevant.


...are a very talented person...

Everything you said could not be more correct sir. The more I work with the MicroM board, the more I love it. Yes, a truly great board. However, I simply wrote a few example sketches specific to my little bots, Mr. Oddbot is responsible for the library in its entirety.

Actually, the library is where its at, man --and another reason the MicroM is so awesome. All the features of the board are taken care of by that wonderful library. All the sausage making is hidden and you are left with just the fun stuff.

Word to ya motha!


In my book.  I wasn't sure about the division of labor, so I added the "linked to it..." thing.  Still, I wouldn't have learned the method without Little Line and Ledge Bot mentioned here.  Thanks to you both!