Compare and contrast getting normalized accelerometer values, where the raw value is -13248.00. (A.k.a. Please, make it make sense.)

Library 1; jarzebski's Arduino-MPU6050 - https://github.com/jarzebski/Arduino-MPU6050/
Library 2; Adafruit's Adafruit_MPU6050 - https://github.com/adafruit/Adafruit_MPU6050
Library 3; i2cdevlib/ElectronicCats' mpu6050 - https://github.com/ElectronicCats/mpu6050


Library 1;


Expandcode )

Formula for normalized acceleration value at MPU6050_RANGE_2G;
raw * rangePerDigit * gravityConst
(raw * (1.0/16384)) * gravityConst
== (raw / 16384) * gravityConst
(-13248.00 * .000061) * 9.80665 = -7.92502845
== (-13248.00 / 16384) * 9.80665 = -7.92959589


Library 2;


Expandcode )

Formula for normalized acceleration value at MPU6050_RANGE_2_G;
(raw / accel_scale) * gravityConst
(-13248.00 / 16384) * 9.80665 = -7.92959589


Library 3;


Expandcode )

No normalized functions in MPU6050.cpp. Can use MotionApps files, but they go through Quaternions.
Expandcode )

Formula for normalized acceleration value at MPU6050_ACCEL_FS_2;
// jarzebski way;
raw * accelerationResolution * gravityConst
-13248.00 * 0.000122 * 9.80665 = -15.850057

// adafruit way;
// (raw * (1.0/16384)) * gravityConst
// (raw * (2.0/16384)) * gravityConst
(-13248.00 / (2.0*16384)) * 9.80665 = -15.85919
((-13248.00*2.0) / 16384) * 9.80665 = -15.85919

Result is twice that of the others. accelerationResolution itself seems to be twice the others, so half it? Not sure if this is a mistake, or I'm missing something about MPU6050_ACCEL_FS_2 vs MPU6050_RANGE_2_G.
raw * (accelerationResolution/2) * gravityConst
-13248.00 * (accelerationResolution/2) * 9.80665 = -7.9250

accelerationResolution and get_acce_resolution() only exist in the ElectronicCats version, they're not accessible in the i2cdevlibs version. That version seems to really want you to use the Quaternion path. But you can always use the range values from the other versions yourself on the raw values.
The MPU-6050 is an accelerometer and gyroscope (with added thermometer), that contains a Digital Motion Processor (DMP) to handle a lot of the heavy maths lifting of turning the raw sensor values into useful motion values before they reach the microcontroller. It seems (caveat; I'm new to this area) that the original code is only available as a binary, or as some demo code. But some very determined people have pulled a library together.

/* Source is from the InvenSense MotionApps v2 demo code. Original source is
 * unavailable, unless you happen to be amazing as decompiling binary by
 * hand (in which case, please contact me, and I'm totally serious).
 *
 * Also, I'd like to offer many, many thanks to Noah Zerkin for all of the
 * DMP reverse-engineering he did to help make this bit of wizardry
 * possible.
 */


Well, actually, it seems quite a lot of people have pulled libraries together, to different levels of functionality, with very similar names. But the one most people seem to use is this one. Which includes the MotionApps files. This is important, not just for the right function calls, but because you need other libraries from this collection as well, particularly the I2Cdev one. These libraries, although for Arduino, are not findable inside the Arduino IDE's Library Manager. You need to side-load them, old school style. Which means downloading and extracting the .zip file. Then copying the specific libraries (being the folders that contain an 'Examples' folder as a first level child) for MPU6050 and I2Cdev into your Arduino > libraries folder. And restarting the IDE.

(I've also, after the fact, found what seems to be a copy of the MPU6050 library in an ElectronicCats repo, that is in the Library Manager, and seems to have rolled the I2Cdev code into itself. But the oldest change here seems to be 6 years ago. Whereas the i2cdevlib seems to be about 13 years ago. It does seem to have more recent updates than i2cdevlib though. So the choice is yours. I'm telling you, it's a nightmare finding what's what, especially when the code linking to it won't even compile with it.)

To help us get a feel for how the boards movements are interpreted, there's a nice demo we can try out. You can find the MPUTeapot Processing project inside the MPU6050 Arduino library; MPU6050 > examples > MPU6050_DMP6 > Processing > MPUTeapot.

First step is to install Processing. I'm using P4. Copy that MPUTeapot.pde file into a new sketch (or the whole folder to wherever you save your sketches). This sketch requires another stack of libraries, the Toxi/c libraries, which we need to side-load again. Download the newest release, extract the .zip file, and copy the libraries (being the folders that contain an 'examples' folder as a first level child) into your Processing > Libraries folder. Restart Processing.

Illustration of Arduino Mega board wired up to MPU6050 board as described below.

MPU6050 Circuit
Made with Fritzing



Wire up your MPU6050 to your Arduino (I'm using the Mega 2560). You need to connect the Interrupt pin to Digital pin 02 (on most Arduino boards). SDA -> SDA. SCL -> SCL. VCC -> 5V. GND -> GND.

Open the MPU6050 > MPU6050_DMP6 example, and load it onto your Arduino. By default it runs in readable yaw-pitch-roll mode. Open the Serial Monitor at 115200 baud. After finding and initialising your MPU6050 it will await char input. Send any char, and you'll get a lot of lines like;
DMP ready! Waiting for first interrupt...
ypr	0.01	-0.01	0.44
ypr	0.01	-0.01	0.44
ypr	0.01	-0.01	0.44
ypr	0.01	-0.01	0.43

Which are your yaw-pitch-roll Euler angles in degrees.

If you comment out the #define OUTPUT_READABLE_YAWPITCHROLL line, and uncomment the #define OUTPUT_TEAPOT line you'll prepare the code for use with the Processing demo. Instead of nice readable yaw-pitch-roll values the info is packed into a 42-byte FIFO packet buffer; [quat w][][quat x][][quat y][][quat z][][gyro x][][gyro y][][gyro z][][accl x][][accl y][][accl z][][]. Upload to your Arduino.

Moving over to Processing now, open the MPUTeapot demo. I find it nostalgic that this is running in OpenGL mode. If you want to increase the window size, go ahead and do that. Otherwise you just need to set the correct portName. For me that meant commenting out line 72, and uncommenting line 75, while updating line 75 to say "COM7". The demo is straight-forward, handling the drawing of the virtual plane, reading and unpacking the packets back to quaternion w,x,y,z values, and handing off the complications to the Toxi/c libraries. But when it works it's a lot of fun to manipulate the virtual plane by moving your MPU6050. And really helps you connect the board movement to what you want your project to detect/react to, in your mind.

Animation of a block plane (red board, green wings and tail fin, blue nose cone) rotating in 3D space.

MPUTeapot demo
Gif by [personal profile] chebe

The LilyPad Accelerometer (ADXL335). I've been trying to use this for over ten years. Turns out I've misunderstood what it measures for 10 years. I had partial success with just the x-axis using Leah Buechley's code, but it has since disappeared, so I can't even be sure what it did.

I was trying to do something else, and the numbers, very strangely kept coming out to an exact 100.0, which is very wrong. So I went back to make sure the accelerometer was giving me a full value range. Which it didn't seem to be, so I went researching and found this excellent tutorial.

Although the accelerometer gives you raw values between 0 and 1023 on an analog read, it actually measures gravity acting on it as it moves around in 3D space. Converting the raw to Gs is straight-forward;
long xAcceleration = map(xRawPinValue, 0, 1023, -3.0, 3.0);

To then turn this into a colour, simply, you could map the range onto -255 to +255 (the polarity demonstrating direction of change), and then reducing that to just value of change;
int xRed = map(xAcceleration, -3.0, 3.0, -255, 255);
int absoluteXRed = abs(xRed);


Do the same for the y and z. Write to RGB LED/pixel of your choice. (Warning; movement in video is quite sudden.)

ExpandShort video )

Sorry for the rough prototype version, I dismantled the version I made up for parts to make my tiara.

Other than light-up gloves, this could be used for rough gesture control, but doesn't give me the kind of information I needed for the thing I was trying to do as is.
Sorry it's been so quiet around here, things have been hectic in the analogue world. And to top it all off I'm running a series of four workshops on the LilyPad in TOG, starting Thursday. More hours in each day would come in handy right about now.

But, I haven't been idle. Remember way back when I made a simple accelerometer glove? Well, I'm working on a more elaborate matching pair now. PartFusion, a guy from the hackerspace, makes some really intense RGB daisy-chainable, sewable, LEDs. Armed with these, Adafruit's NeoPixel library, a couple of accelerometers, LilyPad Simple boards, and LiPo batteries, I had the fixings of something strong enough to help land planes.

I used some material from a free tshirt I acquired at some point, made a couple of armwarmers/gauntlets, with inside lining/pouch for the LilyPad Simple board itself. Some metal snaps and lots of conductive thread sewing later I've one strip done. It's still a work in progress, but I brought them along to one of the CoderDojo sessions, and people seemed to like them. I have a deadline for them, a concert I have tickets for, so hopefully they'll get finished soon.

ExpandFew photos )
My Lilypad is now aware! It actually does something in response to changes it detects! I can't take the glory, I simply used the code from the project that inspired mine: Leah Buechley's accelerometer shirt.

Interesting things about this code:
ExpandCode talk... )

The Result:
ExpandShort video... )

Also, there is a newer version of the Arduino IDE available, 17, that fixes the bug I mentioned in a previous post about how the Lilypad was using the wrong baud rate to communicate back to the computer. So now if you set it at 9600, it actually uses 9600. This makes me happy.

Next step? Using data from the 3-axes!

Getting there...

2009-Sep-16, Wednesday 10:33 pm
The physical construction of my Arduino Lilypad glove is almost complete. Just have to tighten the fit, finish a few edges. I was going to line, decorate, and all that jazz, but feel it's a bit unnecessary for this project. I am getting usable information in, and just have to decide what way I want to use that information, as in, how I want the lights to behave in relation to movement. Here's the glove:

ExpandSome text and pics )

Things I learned:

- Analog sensors give you a value between 0 and 1023, which represents the level of current flowing through it. Not anything useful like an absolute temperature, sound level, or angle. You have to work these things out yourself, with a thermometer or other measurement device in hand, and seeing what the values correspond to.

- Analog actuators take values between 0 and 255, which I assume represents a level of current?, but that doesn't really matter much. The easiest way to get from sensor data to usable actuator data is to simply divide by 4. This however, doesn't always give you the behaviour you desire.

- Accelerometers also require + and - lines. If you can't see the markings you need a magnifying glass. It will still seem to work without them hooked up, but you'll get somewhat random data that if plotted looks like a soft wave, sitting at 0 for a bit then increasing over a few values to 1023, where it will sit for a bit before descending over a few values to 0, and repeating.

- The language you use to program the Arduino is called Processing.

- Getting data from the Serial object is quite simple. For the regular Arduino if you specify the transfer rate Serial.begin(9600) it comes through on baud 9600. However, for some reason the Lilypad when set at 9600 comes in at 19200. If set at 4800 comes in at 9600. Don't know why. Yet.