Below is the file 'mpu6050.c' from this revision. You can also download the file.
/* mpu6050.c */ #include "sensors.h" #include "mpu6050.h" #include "i2c.h" #include "uart.h" #include "dcm.h" #include "fisqrt.h" #include "stick.h" #include "watchdog.h" #include "status.h" #include "abs.h" #include "event.h" #include "timer.h" #include "panic.h" #include "log.h" #include "config.h" i2c_result mpu6050_result; unsigned int mpu6050_generation; signed int gyro_zero_roll; signed int gyro_zero_pitch; signed int gyro_zero_yaw; #define GYRO_ZERO_COUNT 1000 unsigned int mpu6050_gyro_zero_count; unsigned char mpu6050_sample_data[14]; /*unsigned char mpu6050_whoami_command[1] = {0x75}; */ unsigned char mpu6050_whoami_command[1] = {0x6B}; struct i2c_transaction mpu6050_whoami_transaction2; struct i2c_transaction mpu6050_whoami_transaction = { (0x68 << 1) + 0, /* write */ 1, mpu6050_whoami_command, &mpu6050_result, EVENT_MPU6050_I2C_COMPLETE, &mpu6050_whoami_transaction2 }; struct i2c_transaction mpu6050_whoami_transaction2 = { (0x68 << 1) + 1, /* read */ 1, mpu6050_sample_data, &mpu6050_result, EVENT_MPU6050_I2C_COMPLETE, NULL }; #define FS_SEL config.mpu6050.gyro_sensitivity #define AFS_SEL config.mpu6050.accel_sensitivity unsigned char mpu6050_init_command[] = {0x6B, 0x01}; unsigned char mpu6050_gyro_init_command[] = {0x1b, 0 /* (FS_SEL<<3) to be filled in at runtime */}; unsigned char mpu6050_accel_init_command[] = {0x1c, 0 /* (AFS_SEL<<3) to be filled in at runtime */}; unsigned char mpu6050_bypass_init_command[] = {0x37, 0x02}; struct i2c_transaction mpu6050_bypass_init_transaction = { (0x68 << 1) + 0, /* write */ 2, mpu6050_bypass_init_command, &mpu6050_result, EVENT_MPU6050_I2C_COMPLETE, NULL }; struct i2c_transaction mpu6050_accel_init_transaction = { (0x68 << 1) + 0, /* write */ 2, mpu6050_accel_init_command, &mpu6050_result, EVENT_MPU6050_I2C_COMPLETE, &mpu6050_bypass_init_transaction }; struct i2c_transaction mpu6050_gyro_init_transaction = { (0x68 << 1) + 0, /* write */ 2, mpu6050_gyro_init_command, &mpu6050_result, EVENT_MPU6050_I2C_COMPLETE, &mpu6050_accel_init_transaction }; struct i2c_transaction mpu6050_init_transaction = { (0x68 << 1) + 0, /* write */ 2, mpu6050_init_command, &mpu6050_result, EVENT_MPU6050_I2C_COMPLETE, &mpu6050_gyro_init_transaction }; unsigned char mpu6050_sample_command[] = {0x3B}; struct i2c_transaction mpu6050_sample_transaction2; struct i2c_transaction mpu6050_sample_transaction = { (0x68 << 1) + 0, /* write */ 1, mpu6050_sample_command, &mpu6050_result, EVENT_MPU6050_I2C_COMPLETE, &mpu6050_sample_transaction2 }; struct i2c_transaction mpu6050_sample_transaction2 = { (0x68 << 1) + 1, /* read */ 14, mpu6050_sample_data, &mpu6050_result, EVENT_MPU6050_I2C_COMPLETE, NULL }; void mpu6050_event_handler(void); bool mpu6050_init(void) { event_register(EVENT_MPU6050_I2C_COMPLETE, mpu6050_event_handler); /* Fill in sensitivity accordingly, as it's not known at compile time */ mpu6050_gyro_init_command[1] = FS_SEL << 3; mpu6050_accel_init_command[1] = AFS_SEL << 3; if (!i2c_start_transaction(&mpu6050_init_transaction)) return FALSE; while (i2c_busy()) ; return (mpu6050_result == I2C_SUCCESS); } /* LSB / g */ /* 1 for +- 2g */ /* 2 for +- 4g */ /* 4 for +- 8g */ /* 8 for +- 16g */ #define ACCEL_STEP (16384.0 / (float)(1<<AFS_SEL)) #define TWO_PI 6.28318531f #define DEG_TO_RAD (TWO_PI/360.0f) /* A step of 131 = 1 degree. */ /* Overall, this is LSB / rad/s */ #define GYRO_STEP (131.0 / DEG_TO_RAD / (float)(1<<FS_SEL)) /* LSB / degree C */ #define TEMP_STEP 340.0 #define TEMP_OFFSET 36.53 #define ACCEL_SCALE (1.0 / ACCEL_STEP) #define GYRO_SCALE (1.0 / GYRO_STEP) #define TEMP_SCALE (1.0 / TEMP_STEP) #if 0 bool mpu6050_sample(void) { unsigned int x, y, z; unsigned int temp; unsigned int roll, pitch, yaw; if (!i2c_start_transaction(&mpu6050_sample_transaction)) return FALSE; while (i2c_busy()); if (mpu6050_result != I2C_SUCCESS) return FALSE; mpu6050_result = I2C_IN_PROGRESS; x = (mpu6050_sample_data[0] << 8) + mpu6050_sample_data[1]; y = (mpu6050_sample_data[2] << 8) + mpu6050_sample_data[3]; z = (mpu6050_sample_data[4] << 8) + mpu6050_sample_data[5]; temp = (mpu6050_sample_data[6] << 8) + mpu6050_sample_data[7]; roll = (mpu6050_sample_data[ 8] << 8) + mpu6050_sample_data[ 9]; pitch = (mpu6050_sample_data[10] << 8) + mpu6050_sample_data[11]; yaw = (mpu6050_sample_data[12] << 8) + mpu6050_sample_data[13]; putstr("MPU6050 sample data:\r\n"); putstr("x: "); puthex(x); putstr(", y: "); puthex(y); putstr(", z: "); puthex(z); putstr("\r\ntemperature:"); puthex(temp); putstr("\r\nroll:"); puthex(roll); putstr(", pitch:"); puthex(pitch); putstr(", yaw:"); puthex(yaw); putstr("\r\n\r\n"); #if 0 sensors_write_gyro_data(roll, pitch, yaw); sensors_write_accel_data(x, y, z); #endif return TRUE; } #endif bool mpu6050_start_sample(void) { return i2c_start_transaction(&mpu6050_sample_transaction); } void mpu6050_start_zero(void) { mpu6050_gyro_zero_count = GYRO_ZERO_COUNT; gyro_zero_roll = 0; gyro_zero_pitch = 0; gyro_zero_yaw = 0; } void mpu6050_event_handler(void) { signed short int xi, yi, zi; signed short int tempi; signed short int rolli, pitchi, yawi; vec3f accel, gyro; float temp; CHECKPOINT(9); if (mpu6050_result != I2C_SUCCESS) return; mpu6050_result = I2C_IN_PROGRESS; sensors_sample_done(); xi = (mpu6050_sample_data[0] << 8) + mpu6050_sample_data[1]; yi = (mpu6050_sample_data[2] << 8) + mpu6050_sample_data[3]; zi = (mpu6050_sample_data[4] << 8) + mpu6050_sample_data[5]; tempi = (mpu6050_sample_data[6] << 8) + mpu6050_sample_data[7]; rolli = (mpu6050_sample_data[ 8] << 8)+mpu6050_sample_data[ 9]; pitchi = (mpu6050_sample_data[10] << 8)+mpu6050_sample_data[11]; yawi = (mpu6050_sample_data[12] << 8)+mpu6050_sample_data[13]; if (mpu6050_gyro_zero_count) { gyro_zero_roll += rolli; gyro_zero_pitch += pitchi; gyro_zero_yaw += yawi; if (--mpu6050_gyro_zero_count == 0) { gyro_zero_roll /= GYRO_ZERO_COUNT; gyro_zero_pitch /= GYRO_ZERO_COUNT; gyro_zero_yaw /= GYRO_ZERO_COUNT; } } else { rolli -= gyro_zero_roll; pitchi -= gyro_zero_pitch; yawi -= gyro_zero_yaw; } accel.x = ((float)xi) * ACCEL_SCALE; accel.y = ((float)yi) * ACCEL_SCALE; accel.z = ((float)zi) * ACCEL_SCALE; temp = ((float)tempi) * TEMP_SCALE + TEMP_OFFSET; gyro.x = ((float)rolli) * GYRO_SCALE; gyro.y = ((float)pitchi) * GYRO_SCALE; gyro.z = ((float)yawi) * GYRO_SCALE; sensors_write_gyro_data(gyro); sensors_write_accel_data(accel); sensors_write_temp_data(temp); log_put_array((char *)mpu6050_sample_data, 14); CHECKPOINT(10); }