diff options
author | Stanley Huang <stanleyhuangyc@gmail.com> | 2013-03-25 00:57:28 +0800 |
---|---|---|
committer | Stanley Huang <stanleyhuangyc@gmail.com> | 2013-03-25 00:57:28 +0800 |
commit | 8e57c683d3d16f1dee320f10c411602ea38ba651 (patch) | |
tree | 75df3040d13c3f1850d93e29eb93a3836cae133c /obdlogger/MPU6050.cpp | |
download | 2021-arduino-obd-8e57c683d3d16f1dee320f10c411602ea38ba651.tar.gz 2021-arduino-obd-8e57c683d3d16f1dee320f10c411602ea38ba651.tar.bz2 2021-arduino-obd-8e57c683d3d16f1dee320f10c411602ea38ba651.zip |
initial commit
Diffstat (limited to 'obdlogger/MPU6050.cpp')
-rw-r--r-- | obdlogger/MPU6050.cpp | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/obdlogger/MPU6050.cpp b/obdlogger/MPU6050.cpp new file mode 100644 index 0000000..302a0c4 --- /dev/null +++ b/obdlogger/MPU6050.cpp @@ -0,0 +1,194 @@ +// MPU-6050 Accelerometer + Gyro +// ----------------------------- +// +// By arduino.cc user "Krodal". +// June 2012 +// Open Source / Public Domain +// +// Using Arduino 1.0.1 +// It will not work with an older version, +// since Wire.endTransmission() uses a parameter +// to hold or release the I2C bus. +// +// Documentation: +// - The InvenSense documents: +// - "MPU-6000 and MPU-6050 Product Specification", +// PS-MPU-6000A.pdf +// - "MPU-6000 and MPU-6050 Register Map and Descriptions", +// RM-MPU-6000A.pdf or RS-MPU-6000A.pdf +// - "MPU-6000/MPU-6050 9-Axis Evaluation Board User Guide" +// AN-MPU-6000EVB.pdf +// +// The accuracy is 16-bits. +// +// Temperature sensor from -40 to +85 degrees Celsius +// 340 per degrees, -512 at 35 degrees. +// +// At power-up, all registers are zero, except these two: +// Register 0x6B (PWR_MGMT_2) = 0x40 (I read zero). +// Register 0x75 (WHO_AM_I) = 0x68. +// + +#include "MPU6050.h" + +// -------------------------------------------------------- +// MPU6050_read +// +// This is a common function to read multiple bytes +// from an I2C device. +// +// It uses the boolean parameter for Wire.endTransMission() +// to be able to hold or release the I2C-bus. +// This is implemented in Arduino 1.0.1. +// +// Only this function is used to read. +// There is no function for a single byte. +// +int MPU6050_read(int start, uint8_t *buffer, int size) +{ + int i, n, error; + + Wire.beginTransmission(MPU6050_I2C_ADDRESS); + n = Wire.write(start); + if (n != 1) + return (-10); + + n = Wire.endTransmission(false); // hold the I2C-bus + if (n != 0) + return (n); + + // Third parameter is true: relase I2C-bus after data is read. + Wire.requestFrom(MPU6050_I2C_ADDRESS, size, true); + i = 0; + while(Wire.available() && i<size) + { + buffer[i++]=Wire.read(); + } + if ( i != size) + return (-11); + + return (0); // return : no error +} + + +// -------------------------------------------------------- +// MPU6050_write +// +// This is a common function to write multiple bytes to an I2C device. +// +// If only a single register is written, +// use the function MPU_6050_write_reg(). +// +// Parameters: +// start : Start address, use a define for the register +// pData : A pointer to the data to write. +// size : The number of bytes to write. +// +// If only a single register is written, a pointer +// to the data has to be used, and the size is +// a single byte: +// int data = 0; // the data to write +// MPU6050_write (MPU6050_PWR_MGMT_1, &c, 1); +// +int MPU6050_write(int start, const uint8_t *pData, int size) +{ + int n, error; + + Wire.beginTransmission(MPU6050_I2C_ADDRESS); + n = Wire.write(start); // write the start address + if (n != 1) + return (-20); + + n = Wire.write(pData, size); // write data bytes + if (n != size) + return (-21); + + error = Wire.endTransmission(true); // release the I2C-bus + if (error != 0) + return (error); + + return (0); // return : no error +} + +// -------------------------------------------------------- +// MPU6050_write_reg +// +// An extra function to write a single register. +// It is just a wrapper around the MPU_6050_write() +// function, and it is only a convenient function +// to make it easier to write a single register. +// +int MPU6050_write_reg(int reg, uint8_t data) +{ + int error; + + error = MPU6050_write(reg, &data, 1); + + return (error); +} + +// -------------------------------------------------------- +// MPU6050_init +// +// Initialization +// +int MPU6050_init() +{ + // default at power-up: + // Gyro at 250 degrees second + // Acceleration at 2g + // Clock source at internal 8MHz + // The device is in sleep mode. + // + uint8_t c; + int error; + error = MPU6050_read (MPU6050_WHO_AM_I, &c, 1); + if (error) return error; + + // According to the datasheet, the 'sleep' bit + // should read a '1'. But I read a '0'. + // That bit has to be cleared, since the sensor + // is in sleep mode at power-up. Even if the + // bit reads '0'. + error = MPU6050_read (MPU6050_PWR_MGMT_2, &c, 1); + if (error) return error; + + // Clear the 'sleep' bit to start the sensor. + MPU6050_write_reg (MPU6050_PWR_MGMT_1, 0); + return 0; +} + +// -------------------------------------------------------- +// MPU6050_readout +// +// Perform an complete read-out +// + +int MPU6050_readout(accel_t_gyro_union* accel_t_gyro) +{ + int error; + + // Read the raw values. + // Read 14 bytes at once, + // containing acceleration, temperature and gyro. + // With the default settings of the MPU-6050, + // there is no filter enabled, and the values + // are not very stable. + error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *)accel_t_gyro, sizeof(accel_t_gyro_union)); + if (error) return error; + + // Swap all high and low bytes. + // After this, the registers values are swapped, + // so the structure name like x_accel_l does no + // longer contain the lower byte. + uint8_t swap; + #define SWAP(x,y) swap = x; x = y; y = swap + + SWAP (accel_t_gyro->reg.x_accel_h, accel_t_gyro->reg.x_accel_l); + SWAP (accel_t_gyro->reg.y_accel_h, accel_t_gyro->reg.y_accel_l); + SWAP (accel_t_gyro->reg.z_accel_h, accel_t_gyro->reg.z_accel_l); + SWAP (accel_t_gyro->reg.t_h, accel_t_gyro->reg.t_l); + SWAP (accel_t_gyro->reg.x_gyro_h, accel_t_gyro->reg.x_gyro_l); + SWAP (accel_t_gyro->reg.y_gyro_h, accel_t_gyro->reg.y_gyro_l); + SWAP (accel_t_gyro->reg.z_gyro_h, accel_t_gyro->reg.z_gyro_l); +} |