I picked myself up a cheap-as-chips MMA7361 Accelerometer module fom DX.com for around $5.
This little guy runs on either 3.3v or 5v, has a low-power sleep mode, a zero-g interrupt, and it can run in two modes; either
+/- 1.5g, or
+/- 6g, on all 3 axis.
The three axis are given as analog voltage signals, with one pin per axis, so it's really easy to plug it into an Arduino or Teensy and read the values.
Brilliant, wonderful, love it. Cheap and easy to use.
This gist by Natalie Freed shows you just how easy it can be to interact with the MMA7361 board.
This board costs less than a beer, so the components have fairly wide tolerances as to what constitutes zero, and don't seem to be calibrated.
In effect, if you plug the module in, and in turn you observed the positive and negative values for each axis at 1g (stable), you'll observe that each gives a different reading. Indeed, each axis has a different bracket size between the positive and negative value, so there's no apparent uniformity.
Like any sensible person, I started out by looking for existing solutions. Jeroen Doggen's Arduino MMA7361 library was the most advanced candidate, and comes with a
calibrate() method to help zero the module.
This method of calibration requires you to place the module in a static position, with the Z-axis perpendicular to earths gravity, then run the calibrate function. Offsets for each axis are then calculated, which should ensure each axis values are aligned to one another.
Unfortunately in testing this with my board, I discovered this only correctly zeroed the Z positive value. Z negative, X and Y still provided very strange numbers, when perpendicular to earths gravity. When calculating the magnitude of the gravity vector, the magnitude also wandered towards 0.6g at some orientations. Something was obviously not right.
It also became apparent that each axis always provides the same values, so the hardware is reliable between power cycles, just not sufficiently calibrated.
Better calibration method
As the hardware provides the same values between power cycles, the calibration doesn't need to be performed on each run; it merely needs to be executed once and then we can re-use those values for that module.
With each axis providing different values for both positive and negative 1g, each axis would need to have its 1g values read separately, at both positive and negative. This requires rolling the MMA7361 carefully through every orientation, and reading the "extremes" for each.
This creates the "offset" for each orientation (
-, rather than
axis zero) at 1g.
The MMA7361 Accelerometer library ended up having two parts;
- The MMA7361 Calibration class, which allows you to read the calibration values for your module.
- The core MMA7361 accelerometer class, which allows you to read the force vector and the g-force magnitude, using the offset calibration values.
You can wire the module up to a Teensy 3.1, or any Arduino-compatible board, like so:
Yes, this wiring diagram is unnecessarily complicated.
While writing the calibrator I found it was very easy to knock the module, and induce >1g by accident.
To counter this, the calibrator now takes 200 readings over time, and the readings must all be within a defined
Effectively if the variance of these 200 readings is >10, the reading is considered to be invalid, and discarded.
This causes calibration to be a slower process, but knocks and jabs do not affect the calibration readings. As calibration only needs to happen once per module, it's an acceptable annoyance.