For the bag movement alarm project, I got myself a cheap postage sized accelerometer. The breakout board I purchased online is labeled GY-521, which I found out afterwards is just one of the many boards for the MPU-6050 chip. The MPU-6050 is actually both an accelerometer as well as a gyro. Pretty cool for such a tiny little chip.
This was my first project using the i2c serial connection to communicate with a breakout board or chip. The Ardunio Wire library enables communication using the i2c protocol. It is a two line protocol, with the two SDA pins (Data) connected and the two SCL (Clock) pins connected. I found Nick Gammon’s info on i2c and on protocols in general to be quite useful.
The i2c pins on each board are different, and on the Arduino Uno the pins you need are:
- Analog port 4 (A4) = SDA (serial data)
- Analog port 5 (A5) = SCL (serial clock)
The board I had came without the header soldered on, so at first I tried to just set the board on top of the header inserted into a breadboard, and wired it up to the Ardunio. I then tried to use an i2c scanner to see if the board existed… and it did not work. So I soldered it on, and this time I got a result: device found at address 0x68.
The MPU-6050 can have address of 0x68 or 0x69, depending on if the AD0 pin is held high or low. Without anything connected, it was at 0x68 for me.
The next step was to read the accelerometer. I used the short example on the Arduino forum as the basis, first getting out the raw data of the accelerometer, gyro and temperature sensor. As I am not that interested in the raw data, I decided to see if I could get it to indicate only when it has moved slightly based on a sensitivity. The code for that:
// MPU-6050 test for movement
//
// mostly taken from:
// MPU-6050 Short Example Sketch
// By Arduino User JohnChi
// August 17, 2014
// Public Domain//circuit:
// Arduino Ground –> MPU VCC
// Arduino 5V –> MPU VCC
// Arduino A4 (SDA) –> MPU SDA
// Arduino A5(SCL) –> MPU SCL#include<Wire.h>
const int MPU=0x68; // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;int OldAcX,OldAcY,OldAcZ,OldTmp,OldGyX,OldGyY,OldGyZ;
int AcSensitivity = 500;
boolean moved = false;void setup(){
Wire.begin();
Wire.beginTransmission(MPU);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
Serial.begin(9600);}
void loop(){
Wire.beginTransmission(MPU);
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU,14,true); // request a total of 14 registers
AcX=Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
AcY=Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
AcZ=Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
Tmp=Wire.read()<<8|Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
GyX=Wire.read()<<8|Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
GyY=Wire.read()<<8|Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
GyZ=Wire.read()<<8|Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)if (abs(OldAcX – AcX) > AcSensitivity) {
moved = true;
}
if (abs(OldAcY – AcY) > AcSensitivity) {
moved = true;
}if (abs(OldAcY – AcY) > AcSensitivity) {
moved = true;
}if (moved == true) {
Serial.println(“MOVED”);
}OldAcX = AcX;
OldAcY = AcY;
OldAcZ = AcZ;
moved = false;delay(333);
}
It works! If you tilt the Accelerometer only a tiny bit, it prints “MOVED” to the serial monitor, but doesn’t otherwise or if it only moves slightly. Here it is wired up, with the Uno taking the raw data from the accelerometer in and printing to the serial it has been moved more than the sensitivity.