Skip to content

Instantly share code, notes, and snippets.

@sahilshekhawat
Created May 5, 2014 09:49
Show Gist options
  • Save sahilshekhawat/67dff74f1fc6e6b96e9f to your computer and use it in GitHub Desktop.
Save sahilshekhawat/67dff74f1fc6e6b96e9f to your computer and use it in GitHub Desktop.
#include <Wire.h>
// The name of the sensor is "MPU-6050".
// For program code, I omit the '-',
// therefor I use the name "MPU6050....".
// Register names according to the datasheet.
// According to the InvenSense document
// "MPU-6000 and MPU-6050 Register Map
// and Descriptions Revision 3.2", there are no registers
// at 0x02 ... 0x18, but according other information
// the registers in that unknown area are for gain
// and offsets.
//
#define MPU6050_PWR_MGMT_1 0x6B // R/W
#define MPU6050_WHO_AM_I 0x75 // R
#define MPU6050_I2C_ADDRESS 0x68
// Defines for the bits, to be able to change
// between bit number and binary definition.
// By using the bit number, programming the sensor
// is like programming the AVR microcontroller.
// But instead of using "(1<<X)", or "_BV(X)",
// the Arduino "bit(X)" is used.
typedef union accel_t_gyro_union
{
struct
{
uint8_t x_accel_h;
uint8_t x_accel_l;
uint8_t y_accel_h;
uint8_t y_accel_l;
uint8_t z_accel_h;
uint8_t z_accel_l;
uint8_t t_h;
uint8_t t_l;
uint8_t x_gyro_h;
uint8_t x_gyro_l;
uint8_t y_gyro_h;
uint8_t y_gyro_l;
uint8_t z_gyro_h;
uint8_t z_gyro_l;
} reg;
struct
{
int16_t x_accel;
int16_t y_accel;
int16_t z_accel;
int16_t temperature;
int16_t x_gyro;
int16_t y_gyro;
int16_t z_gyro;
} value;
};
struct {
uint8_t buttons;
int8_t x;
int8_t y;
int8_t wheel; /* Not yet implemented */
} mouseReport;
uint8_t nullReport[4] = { 0, 0, 0, 0 };
float distx=0,disty=0,sumvelx=0,sumvely=0,sumaccx=0,sumaccy=0,avgvelx=0,avgvely=0,avgdistx=0,avgdisty=0,prevx=0,prevy=0;
int i=0,j=0;
int LDR = A3; //analog pin to which LDR is connected, here we set it to 0 so it means A0
int LDRValue = 0; //that’s a variable to store LDR values
int light_sensitivity = 100; //This is the approx value of light surrounding your LDR
void setup()
{
int error;
uint8_t c;
Serial.begin(9600);
//Serial.println(F("InvenSense MPU-6050"));
//Serial.println(F("June 2012"));
// Initialize the 'Wire' class for the I2C-bus.
Wire.begin();
// default at power-up:
// Gyro at 250 degrees second
// Acceleration at 2g
// Clock source at internal 8MHz
// The device is in sleep mode.
//
#define MPU6050_ACCEL_XOUT_H 0x3B // R
error = MPU6050_read (MPU6050_WHO_AM_I, &c, 1);
//Serial.print(F("WHO_AM_I : "));
//Serial.print(c,HEX);
//Serial.print(F(", error = "));
//Serial.println(error,DEC);
// According to the datasheet, the 'sleep' bit
// should read a '1'.
// That bit has to be cleared, since the sensor
// is in sleep mode at power-up.
error = MPU6050_read (MPU6050_PWR_MGMT_1, &c, 1);
//Serial.print(F("PWR_MGMT_1 : "));
//Serial.print(c,HEX);
//Serial.print(F(", error = "));
//Serial.println(error,DEC);
// Clear the 'sleep' bit to start the sensor.
MPU6050_write_reg (MPU6050_PWR_MGMT_1, 0);
//delay(200);
}
/* Move the mouse in a clockwise square every 5 seconds */
void loop()
{
int ind;
int error;
double dT;
accel_t_gyro_union accel_t_gyro;
//delay(100);
LDRValue = analogRead(LDR); //reads the ldr’s value through LDR which we have set to Analog input 0 “A0″
//Serial.println(LDRValue); //prints the LDR values to serial monitor
//delay(50);
if (LDRValue < light_sensitivity)
{
mouseReport.buttons=1;
}
else
{
mouseReport.buttons=0;
}
//mouseReport.buttons = 0;
mouseReport.x = 0;
mouseReport.y = 0;
mouseReport.wheel = 0;
error = MPU6050_read (MPU6050_ACCEL_XOUT_H, (uint8_t *) &accel_t_gyro, sizeof(accel_t_gyro));
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);
if(i!=3)
{
sumaccx=sumaccx+accel_t_gyro.value.x_accel;
sumaccy=sumaccy+accel_t_gyro.value.y_accel;
i=i+1;
}
if(i==3)
{
avgvelx=sumaccx*(0.003);
avgvely=sumaccy*(0.003);
sumvelx=sumvelx+avgvelx;
sumvely=sumvely+avgvely;
j=j+1;
i=0;
sumaccx=0;
sumaccy=0;
}
if(j==3)
{prevx=avgdistx;
prevy=avgdisty;
avgdistx=sumvelx*(0.009);
avgdisty=sumvely*(0.009);
distx=avgdistx-prevx;
disty=avgdisty-prevy;
j=0;
sumvelx=0;
sumvely=0;
mouseReport.x = (-10)*avgdistx;
mouseReport.y = 10*avgdisty;
//Serial.print(avgdistx);
for (ind=0; ind<1; ind++) {
Serial.write((uint8_t *)&mouseReport, 4);
Serial.write((uint8_t *)&nullReport, 4);
}}
delay(10);
}
// --------------------------------------------------------
// 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);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment