Skip to content

MPU6050 i2c example expanded into library #504

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 32 additions & 5 deletions i2c/mpu6050_i2c/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,39 @@
add_executable(mpu6050_i2c
mpu6050_i2c.c
)

add_library(MPU6050_i2c_pico_lib mpu6050_i2c.c)
target_include_directories(MPU6050_i2c_pico_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
# pull in common dependencies and additional i2c hardware support
target_link_libraries(mpu6050_i2c pico_stdlib hardware_i2c)
target_link_libraries(MPU6050_i2c_pico_lib pico_stdlib hardware_i2c)

add_library(MPU6050_i2c_pico_cpp_lib mpu6050.cpp mpu6050_i2c.c)
target_include_directories(MPU6050_i2c_pico_cpp_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(MPU6050_i2c_pico_cpp_lib pico_stdlib hardware_i2c)


add_executable(mpu6050_i2c mpu6050_i2c_main.c)
target_link_libraries(mpu6050_i2c MPU6050_i2c_pico_lib)

# create map/bin/hex file etc.
pico_add_extra_outputs(mpu6050_i2c)
# enable usb and uart output
pico_enable_stdio_usb(mpu6050_i2c 1)
pico_enable_stdio_uart(mpu6050_i2c 1)

# add url via pico_set_program_url
example_auto_set_url(mpu6050_i2c)


add_executable(mpu6050_i2c_scale_test mpu6050_scale_test.cpp)
target_link_libraries(mpu6050_i2c_scale_test MPU6050_i2c_pico_cpp_lib)

# create map/bin/hex file etc.
pico_add_extra_outputs(mpu6050_i2c_scale_test)
pico_enable_stdio_usb(mpu6050_i2c_scale_test 1)
pico_enable_stdio_uart(mpu6050_i2c_scale_test 1)


add_executable(mpu6050_i2c_irq mpu6050_i2c_irq_main.cpp)
target_link_libraries(mpu6050_i2c_irq MPU6050_i2c_pico_cpp_lib)

# create map/bin/hex file etc.
pico_add_extra_outputs(mpu6050_i2c_irq)
pico_enable_stdio_usb(mpu6050_i2c_irq 1)
pico_enable_stdio_uart(mpu6050_i2c_irq 1)
99 changes: 99 additions & 0 deletions i2c/mpu6050_i2c/mpu6050.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#include "mpu6050.hpp"
#include "mpu6050_i2c.h"


MPU6050SensorTimingParams::MPU6050SensorTimingParams(int _bandwidth, float _delay, float _sample_rate)
: bandwidth(_bandwidth), delay(_delay), sample_rate(_sample_rate) {}

inline const MPU6050SensorTimingParams convert(mpu6050_timing_params_t *c_struct) { // unfortunate awkwardness of wrapping a C lib
return MPU6050SensorTimingParams(c_struct->bandwidth, c_struct->delay, c_struct->sample_rate);
}

MPU6050TimingParams::MPU6050TimingParams(uint8_t lowpass_filter_cfg, uint8_t sample_rate_div) {
mpu6050_timing_params_t accel_timing_c, gyro_timing_c;
mpu6050_calc_timing(lowpass_filter_cfg, sample_rate_div, &accel_timing_c, &gyro_timing_c);
accel_timing = convert(&accel_timing_c);
gyro_timing = convert(&gyro_timing_c);
}

MPU6050TimingParams::MPU6050TimingParams(const MPU6050SensorTimingParams &_accel_timing,
const MPU6050SensorTimingParams &_gyro_timing)
: accel_timing(_accel_timing), gyro_timing(_gyro_timing) {}


MPU6050::MPU6050(float *accel_out, float *gyro_out, uint8_t addr) :
chip_temp(temp), accel(accel_out), gyro(gyro_out), accel_scale(Scale_0), gyro_scale(Scale_0), bus_addr(addr) {
setup_MPU6050_i2c();
}

void MPU6050::power(uint8_t CLKSEL, bool temp_disable, bool sleep, bool cycle) {
mpu6050_setbusaddr(bus_addr);
mpu6050_power(CLKSEL, temp_disable, sleep, cycle);
}

void MPU6050::reset(void) {
mpu6050_setbusaddr(bus_addr);
mpu6050_reset();
}

void MPU6050::setscale_accel(MPU6050::Scale scale) {
mpu6050_setbusaddr(bus_addr);
mpu6050_setscale_accel((MPU6050_Scale)scale);
accel_scale = scale;
}

void MPU6050::setscale_gyro(MPU6050::Scale scale) {
mpu6050_setbusaddr(bus_addr);
mpu6050_setscale_gyro((MPU6050_Scale)scale);
gyro_scale = scale;
}

void MPU6050::read(void) {
mpu6050_setbusaddr(bus_addr);
mpu6050_read(accel, gyro, &temp, (MPU6050_Scale)accel_scale, (MPU6050_Scale)gyro_scale);
}

void MPU6050::read_accel(void) {
mpu6050_setbusaddr(bus_addr);
mpu6050_read_accel(accel, (MPU6050_Scale)accel_scale);
}

void MPU6050::read_gyro(void) {
mpu6050_setbusaddr(bus_addr);
mpu6050_read_gyro_rad(gyro, (MPU6050_Scale)gyro_scale);
}

bool MPU6050::is_connected() {
mpu6050_setbusaddr(bus_addr);
return mpu6050_is_connected();
}

void MPU6050::set_timing(uint8_t lowpass_filter_cfg, uint8_t sample_rate_div) {
mpu6050_setbusaddr(bus_addr);
mpu6050_set_timing(lowpass_filter_cfg, sample_rate_div);
}

MPU6050TimingParams MPU6050::read_timing(void) {
mpu6050_setbusaddr(bus_addr);
mpu6050_timing_params_t accel_timing_c, gyro_timing_c;
mpu6050_read_timing(&accel_timing_c, &gyro_timing_c);
return MPU6050TimingParams(convert(&accel_timing_c), convert(&gyro_timing_c));
}

void MPU6050::configure_interrupt(bool active_low, bool open_drain, bool latch_pin, bool read_clear, bool enable) {
mpu6050_setbusaddr(bus_addr);
mpu6050_configure_interrupt(active_low, open_drain, latch_pin, read_clear, enable);
}

uint8_t MPU6050::read_interrupt_status() {
mpu6050_setbusaddr(bus_addr);
return mpu6050_read_interrupt_status();
}


float MPU6050_max_accel(MPU6050::Scale scale) {
return accel_scale_vals[(int)scale];
}
float MPU6050_max_gyro_rad(MPU6050::Scale scale) {
return gyro_scale_rad[(int)scale];
}
51 changes: 51 additions & 0 deletions i2c/mpu6050_i2c/mpu6050.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/* class for using an MPU6050 IMU sensor on pi pico.
A C++ interface to the pico example C code.
*/
#include "stdint.h"

struct MPU6050SensorTimingParams {
MPU6050SensorTimingParams() = default;
MPU6050SensorTimingParams(int _bandwidth, float _delay, float _sample_rate);
int bandwidth; // lowpass filter bandwidth [Hz]
float delay; // lowpass filter delay [ms]
float sample_rate; // rate of new data loading in the register [Hz]
};
struct MPU6050TimingParams {
MPU6050TimingParams(uint8_t lowpass_filter_cfg, uint8_t sample_rate_div);
MPU6050TimingParams(const MPU6050SensorTimingParams &_accel_timing, const MPU6050SensorTimingParams &_gyro_timing);
MPU6050SensorTimingParams accel_timing, gyro_timing;
};

class MPU6050 {
public:
const float &chip_temp; // [C]

MPU6050(float *accel_out, float *gyro_out, uint8_t i2c_addr=0x68); // [m/s^2], [rad/s]

void power(uint8_t CLKSEL, bool temp_disable, bool sleep, bool cycle);
void reset(void);

enum Scale {Scale_0 = 0, Scale_1, Scale_2, Scale_3};
// Warning: The first call to read() after setscale() might not have the updated scaling.
void setscale_accel(Scale scale); //scale 0-3 is 2g, 4g, 8g, or 16g
void setscale_gyro(Scale scale); // scale 0-3 is 250, 500, 1000, or 2000 deg/s
void read(void);
void read_accel(void);
void read_gyro(void);
bool is_connected(void);
void set_timing(uint8_t lowpass_filter_cfg, uint8_t sample_rate_div);
MPU6050TimingParams read_timing(void);
void configure_interrupt(bool active_low, // Whether the INT pin is active low or active high
bool open_drain, // Whether the INT pin is push-pull or open-drain
bool latch_pin, // Whether the INT pin latches or pulses for 50us
bool read_clear, // Whether interrupt status bits are cleared by reading interrupt status (default) or on any read
bool enable); // Turn interrupts on or off
uint8_t read_interrupt_status(); // 0 = no interrupts set, 1 = data ready
private:
float *accel, *gyro, temp;
enum Scale accel_scale, gyro_scale;
uint8_t bus_addr;
};

float MPU6050_max_accel(MPU6050::Scale scale);
float MPU6050_max_gyro_rad(MPU6050::Scale scale);
Loading