Skip to content

Commit 765bba4

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 27fad17 commit 765bba4

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
@@ -38,10 +38,10 @@ const uint8_t REG_PWR_MGMT_1 = 0x6B, REG_ACCEL_OUT = 0x3B, REG_GYRO_OUT = 0x43,
3838
REG_SIGNAL_PATH_RESET = 0x68, REG_GYRO_CONFIG = 0x1B, REG_ACCEL_CONFIG = 0x1C;
3939
typedef enum MPU6050_Scale {MPU_FS_0, MPU_FS_1, MPU_FS_2, MPU_FS_3} MPU6050_Scale;
4040

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

4646

4747
////////////////////////////////////////////////////lower level functions for i2c
@@ -104,31 +104,45 @@ void mpu6050_read_raw(int16_t accel[3], int16_t gyro[3], int16_t *temp) {
104104
mpu6050_readreg16(REG_TEMP_OUT, temp, 1);
105105
}
106106

107+
void mpu6050_read(float accel[3], float gyro_rad[3], float *temp, MPU6050_Scale accel_scale, MPU6050_Scale gyro_scale) {
108+
int16_t buffer[7];
109+
mpu6050_readreg16(REG_ACCEL_OUT, buffer, 7); //reads all at same time
110+
mpu6050_scale_accel(accel, buffer, accel_scale);
111+
if (temp) *temp = mpu6050_scale_temp(buffer[3]);
112+
mpu6050_scale_gyro_rad(gyro, buffer + 4, gyro_scale);
113+
}
114+
107115
// set and use sensitivity
108-
void mpu6050_setscale(MPU6050_Scale accel_scale, MPU6050_Scale gyro_scale) {
116+
void mpu6050_setscale_gyro(MPU6050_Scale gyro_scale) {
109117
mpu6050_writereg(REG_GYRO_CONFIG, (uint8_t)gyro_scale << 3);
118+
}
119+
void mpu6050_setscale_accel(MPU6050_Scale accel_scale) {
110120
mpu6050_writereg(REG_ACCEL_CONFIG, (uint8_t)accel_scale << 3);
111121
}
112-
void mpu6050_scale_accel(float *accel, int16_t *accel_raw, MPU6050_Scale scale) {
122+
void mpu6050_scale_accel(float accel[3], int16_t accel_raw[3], MPU6050_Scale scale) {
113123
for (int i = 0; i < 3; i++) {
114124
accel[i] = accel_raw[i] * accel_scale[scale];
115125
}
116126
}
117-
void mpu6050_scale_gyro_deg(float *gyro, int16_t *gyro_raw, MPU6050_Scale scale) {
127+
void mpu6050_scale_gyro_deg(float gyro[3], int16_t gyro_raw[3], MPU6050_Scale scale) {
118128
for (int i = 0; i < 3; i++) {
119129
gyro[i] = gyro_raw[i] * gyro_scale_deg[scale];
120130
}
121131
}
122-
void mpu6050_scale_gyro_rad(float *gyro, int16_t *gyro_raw, MPU6050_Scale scale) {
132+
void mpu6050_scale_gyro_rad(float gyro[3], int16_t gyro_raw[3], MPU6050_Scale scale) {
123133
for (int i = 0; i < 3; i++) {
124134
gyro[i] = gyro_raw[i] * gyro_scale_rad[scale];
125135
}
126136
}
137+
float mpu6050_scale_temp(float temp_raw) {
138+
return (temp_raw / 340.0) + 36.53;
139+
}
140+
127141
//TODO: set timing
128142
//TODO: set and read filter cutoff
129143
//TODO: read self test
130144

131-
145+
//TODO: functional mpu test
132146
int main() {
133147
stdio_init_all();
134148
#if !defined(i2c_default) || !defined(PICO_DEFAULT_I2C_SDA_PIN) || !defined(PICO_DEFAULT_I2C_SCL_PIN)
@@ -151,7 +165,8 @@ int main() {
151165
//setting CLKSEL = 1 gets better results than 0 if gyro is running and no sleep mode
152166
mpu6050_power(1, false, false, false);
153167
MPU6050_Scale testscale = MPU_FS_0;
154-
mpu6050_setscale(testscale, testscale);
168+
mpu6050_setscale_accel(testscale);
169+
mpu6050_setscale_gyro(testscale);
155170

156171
int16_t accel_raw[3], gyro_raw[3], temp_raw;
157172
float acceleration[3], gyro[3];
@@ -160,14 +175,12 @@ int main() {
160175
mpu6050_read_raw(accel_raw, gyro_raw, &temp_raw);
161176
//TODO time read function
162177

163-
// These are the raw numbers from the chip, so will need tweaking to be really useful.
164-
// See the datasheet for more information
178+
// These are the raw numbers from the chip
165179
printf("Raw Acc. X = %d, Y = %d, Z = %d\n", accel_raw[0], accel_raw[1], accel_raw[2]);
166180
printf("Raw Gyro. X = %d, Y = %d, Z = %d\n", gyro_raw[0], gyro_raw[1], gyro_raw[2]);
167181
// Temperature is simple so use the datasheet calculation to get deg C.
168182
// Note this is chip temperature.
169-
printf("Temp [C] = %f \t\t Scale = %d\n", (temp_raw / 340.0) + 36.53, testscale);
170-
//include the scaling
183+
printf("Temp [C] = %f \t\t Scale = %d\n", mpu6050_scale_temp(temp_raw), testscale);
171184
mpu6050_scale_accel(acceleration, accel_raw, testscale);
172185
mpu6050_scale_gyro_rad(gyro, gyro_raw, testscale);
173186
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)