Skip to content

Commit 4bd085d

Browse files
Added scaled read, C++ wrapper and headers
The new files wrap the mpu6050_i2c.c functions in a cpp class. New read function includes scale. Also split separate accel, gyro, and temp scale functions. NOT tested.
1 parent daf21fd commit 4bd085d

File tree

4 files changed

+123
-13
lines changed

4 files changed

+123
-13
lines changed

i2c/mpu6050_i2c/mpu6050.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#include "mpu6050.hpp"
2+
#include "mpu6050_i2c.h"
3+
#include "pico/stdlib.h"
4+
#include "pico/binary_info.h"
5+
#include "hardware/i2c.h"
6+
7+
static MPU6050_Scale MPU6050::accel_scale;
8+
static MPU6050_Scale MPU6050::gyro_scale;
9+
10+
/*MPU6050::MPU6050() : //TODO: is there a good way to do this
11+
chip_temp(*temp) {
12+
accel = {0., 0., 0.};
13+
gyro = {0., 0., 0.};
14+
temp = {};
15+
MPU6050(accel, gyro, temp);
16+
} */
17+
18+
MPU6050::MPU6050(float *accel_out, float *gyro_out) :
19+
accel(accel_out), gyro(gyro_out), chip_temp(temp) {
20+
accel_scale = MPU_FS_0;
21+
gyro_scale = MPU_FS_0;
22+
//I2C init
23+
i2c_init(i2c_default, 400 * 1000); // Max bus speed 400 kHz
24+
gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
25+
gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
26+
gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
27+
gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);
28+
}
29+
30+
MPU6050::power(uint8_t CLKSEL, bool temp_disable, bool sleep, bool cycle) {
31+
mpu6050_power(CLKSEL, temp_disable, sleep, cycle);
32+
}
33+
34+
MPU6050::reset(void) {
35+
mpu6050_reset();
36+
}
37+
38+
MPU6050::setscale_accel(uint8_t scale_num) {
39+
accel_scale = (MPU6050_Scale)(scale_num & 3);
40+
mpu6050_setscale_accel(accel_scale);
41+
}
42+
43+
MPU6050::setscale_gyro(uint8_t scale_num) {
44+
gyro_scale = (MPU6050_Scale)(scale_num & 3);
45+
mpu6050_setscale_gyro(gyro_scale);
46+
}
47+
48+
MPU6050::read(void) {
49+
mpu6050_read(accel, gyro, &temp, accel_scale, gyro_scale);
50+
}
51+

i2c/mpu6050_i2c/mpu6050.hpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/* class for using an MPU6050 IMU sensor on pi pico.
2+
An abstraction of pico example C code. */
3+
4+
class MPU6050 {
5+
float *accel, *gyro, temp;
6+
public:
7+
const float &accel[3], &gyro[3], &chip_temp; // [m/s^2], [rad/s], [C]
8+
MPU6050(void);
9+
MPU6050(float *accel_out, float *gyro_out);
10+
void power(uint8_t CLKSEL, bool temp_disable, bool sleep, bool cycle);
11+
void reset(void);
12+
void setscale_accel(uint8_t scale_num); //scale 0-3 is 2g, 4g, 8g, or 16g
13+
void setscale_gyro(uint8_t scale_num); // scale 0-3 is 250, 500, 1000, or 2000 deg/s
14+
void read(void);
15+
}

i2c/mpu6050_i2c/mpu6050_i2c.c

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ const uint8_t REG_PWR_MGMT_1 = 0x6B, REG_ACCEL_OUT = 0x3B, REG_GYRO_OUT = 0x43,
3636
REG_SIGNAL_PATH_RESET = 0x68, REG_GYRO_CONFIG = 0x1B, REG_ACCEL_CONFIG = 0x1C;
3737
typedef enum MPU6050_Scale {MPU_FS_0, MPU_FS_1, MPU_FS_2, MPU_FS_3} MPU6050_Scale;
3838

39-
float gyro_scale_deg[] = {250. / 0x7fff, 500. / 0x7fff, 1000. / 0x7fff, 2000. / 0x7fff};
40-
float gyro_scale_rad[] = {M_PI / 180. * 250. / 0x7fff, M_PI / 180. * 500. / 0x7fff,
39+
const float gyro_scale_deg[] = {250. / 0x7fff, 500. / 0x7fff, 1000. / 0x7fff, 2000. / 0x7fff};
40+
const float gyro_scale_rad[] = {M_PI / 180. * 250. / 0x7fff, M_PI / 180. * 500. / 0x7fff,
4141
M_PI / 180. * 1000. / 0x7fff, M_PI / 180. * 2000. / 0x7fff};
42-
float accel_scale[] = {2. / 0x7fff, 4. / 0x7fff, 8. / 0x7fff, 16. / 0x7fff};
42+
const float accel_scale[] = {2 * 9.81 / 0x7fff, 4 * 9.81 / 0x7fff, 8 * 9.81 / 0x7fff, 16 * 9.81 / 0x7fff};
4343

4444

4545
////////////////////////////////////////////////////lower level functions for i2c
@@ -102,31 +102,45 @@ void mpu6050_read_raw(int16_t accel[3], int16_t gyro[3], int16_t *temp) {
102102
mpu6050_readreg16(REG_TEMP_OUT, temp, 1);
103103
}
104104

105+
void mpu6050_read(float accel[3], float gyro_rad[3], float *temp, MPU6050_Scale accel_scale, MPU6050_Scale gyro_scale) {
106+
int16_t buffer[7];
107+
mpu6050_readreg16(REG_ACCEL_OUT, buffer, 7); //reads all at same time
108+
mpu6050_scale_accel(accel, buffer, accel_scale);
109+
if (temp) *temp = mpu6050_scale_temp(buffer[3]);
110+
mpu6050_scale_gyro_rad(gyro, buffer + 4, gyro_scale);
111+
}
112+
105113
// set and use sensitivity
106-
void mpu6050_setscale(MPU6050_Scale accel_scale, MPU6050_Scale gyro_scale) {
114+
void mpu6050_setscale_gyro(MPU6050_Scale gyro_scale) {
107115
mpu6050_writereg(REG_GYRO_CONFIG, (uint8_t)gyro_scale << 3);
116+
}
117+
void mpu6050_setscale_accel(MPU6050_Scale accel_scale) {
108118
mpu6050_writereg(REG_ACCEL_CONFIG, (uint8_t)accel_scale << 3);
109119
}
110-
void mpu6050_scale_accel(float *accel, int16_t *accel_raw, MPU6050_Scale scale) {
120+
void mpu6050_scale_accel(float accel[3], int16_t accel_raw[3], MPU6050_Scale scale) {
111121
for (int i = 0; i < 3; i++) {
112122
accel[i] = accel_raw[i] * accel_scale[scale];
113123
}
114124
}
115-
void mpu6050_scale_gyro_deg(float *gyro, int16_t *gyro_raw, MPU6050_Scale scale) {
125+
void mpu6050_scale_gyro_deg(float gyro[3], int16_t gyro_raw[3], MPU6050_Scale scale) {
116126
for (int i = 0; i < 3; i++) {
117127
gyro[i] = gyro_raw[i] * gyro_scale_deg[scale];
118128
}
119129
}
120-
void mpu6050_scale_gyro_rad(float *gyro, int16_t *gyro_raw, MPU6050_Scale scale) {
130+
void mpu6050_scale_gyro_rad(float gyro[3], int16_t gyro_raw[3], MPU6050_Scale scale) {
121131
for (int i = 0; i < 3; i++) {
122132
gyro[i] = gyro_raw[i] * gyro_scale_rad[scale];
123133
}
124134
}
135+
float mpu6050_scale_temp(float temp_raw) {
136+
return (temp_raw / 340.0) + 36.53;
137+
}
138+
125139
//TODO: set timing
126140
//TODO: set and read filter cutoff
127141
//TODO: read self test
128142

129-
143+
//TODO: functional mpu test
130144
int main() {
131145
stdio_init_all();
132146
#if !defined(i2c_default) || !defined(PICO_DEFAULT_I2C_SDA_PIN) || !defined(PICO_DEFAULT_I2C_SCL_PIN)
@@ -148,7 +162,8 @@ int main() {
148162
//setting CLKSEL = 1 gets better results than 0 if gyro is running and no sleep mode
149163
mpu6050_power(1, false, false, false);
150164
MPU6050_Scale testscale = MPU_FS_0;
151-
mpu6050_setscale(testscale, testscale);
165+
mpu6050_setscale_accel(testscale);
166+
mpu6050_setscale_gyro(testscale);
152167

153168
int16_t accel_raw[3], gyro_raw[3], temp_raw;
154169
float acceleration[3], gyro[3];
@@ -157,14 +172,12 @@ int main() {
157172
mpu6050_read_raw(accel_raw, gyro_raw, &temp_raw);
158173
//TODO time read function
159174

160-
// These are the raw numbers from the chip, so will need tweaking to be really useful.
161-
// See the datasheet for more information
175+
// These are the raw numbers from the chip
162176
printf("Raw Acc. X = %d, Y = %d, Z = %d\n", accel_raw[0], accel_raw[1], accel_raw[2]);
163177
printf("Raw Gyro. X = %d, Y = %d, Z = %d\n", gyro_raw[0], gyro_raw[1], gyro_raw[2]);
164178
// Temperature is simple so use the datasheet calculation to get deg C.
165179
// Note this is chip temperature.
166-
printf("Temp [C] = %f \t\t Scale = %d\n", (temp_raw / 340.0) + 36.53, testscale);
167-
//include the scaling
180+
printf("Temp [C] = %f \t\t Scale = %d\n", mpu6050_scale_temp(temp_raw), testscale);
168181
mpu6050_scale_accel(acceleration, accel_raw, testscale);
169182
mpu6050_scale_gyro_rad(gyro, gyro_raw, testscale);
170183
printf("Acc [m/s^2] X = %f, Y = %f, Z = %f\n", acceleration[0], acceleration[1], acceleration[2]);

i2c/mpu6050_i2c/mpu6050_i2c.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/* header for accessing mpu6050 functions in pico-examples
2+
3+
Niraj Patel March 2022 */
4+
5+
#include "pico/stdlib.h"
6+
#include "pico/binary_info.h"
7+
8+
typedef enum MPU6050_Scale {MPU_FS_0, MPU_FS_1, MPU_FS_2, MPU_FS_3} MPU6050_Scale;
9+
10+
// lower level functions for i2c
11+
void mpu6050_writereg(uint8_t reg, uint8_t value); //write one byte to a register
12+
void mpu6050_readreg(uint8_t reg, uint8_t *out, size_t length);
13+
void mpu6050_readreg16(uint8_t reg, uint16_t *out, size_t length);
14+
void mpu6050_setbusaddr(uint8_t addr); //set the i2c bus address for communication. MPU6050 must already have this value.
15+
16+
// higher level mpu6050 functions
17+
void mpu6050_power(uint8_t CLKSEL, bool temp_disable, bool sleep, bool cycle); /* Set the power and clock settings.
18+
CLKSEL is clock source, see docs. Recommended CLKSEL = 1 if gyro is enabled.
19+
temp_disable disables temperature, sleep enables sleep mode, cycle wakes up only when converting. */
20+
void mpu6050_reset(); // Reset power management and signal path registers. MPU6050 returns to default settings.
21+
//set and use scaling
22+
void mpu6050_setscale_accel(MPU6050_Scale accel_scale);
23+
void mpu6050_setscale_gyro(MPU6050_Scale gyro_scale);
24+
void mpu6050_scale_accel(float accel[3], int16_t accel_raw[3], MPU6050_Scale scale); //sets accel[3] in m/s^2 from accel_raw[3]
25+
void mpu6050_scale_gyro_deg(float gyro[3], int16_t gyro_raw[3], MPU6050_Scale scale); //sets gyro[3] in degrees from gyro_raw[3]
26+
void mpu6050_scale_gyro_rad(float gyro[3], int16_t gyro_raw[3], MPU6050_Scale scale); //sets gyro[3] in radians from gyro_raw[3]
27+
float mpu6050_scale_temp(float temp_raw);
28+
29+
void mpu6050_read_raw(int16_t accel[3], int16_t gyro[3], int16_t *temp); //read raw data values. Could read different timesteps.
30+
void mpu6050_read(float accel[3], float gyro[3], float *temp,
31+
MPU6050_Scale accel_scale, MPU6050_Scale gyro_scale); //reads all at same timestep, converts. temp can be NULL.

0 commit comments

Comments
 (0)