Skip to content

Commit af67a2a

Browse files
committed
bricks/cplushub: add experimental IMU class
This gets us talking to the IMU. All calls are currently blocking so could have adverse affects, although reading 6 bytes at ~400kHz should not be too bad. from experimental import IMU imu = IMU() while True: print(imu.accel()) print(imu.gyro()) wait(500)
1 parent 11f6e7a commit af67a2a

File tree

6 files changed

+224
-0
lines changed

6 files changed

+224
-0
lines changed

bricks/cplushub/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ PB_CMSIS_MCU = STM32L431xx
77
PB_FIRMWARE_MAX_SIZE = 225280
88
PB_USE_HAL = 1
99
PB_LIB_BLE5STACK = 1
10+
PB_USE_LSM6DS3TR_C = 1
1011

1112
include ../stm32/stm32.mk

bricks/cplushub/mpconfigport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define PYBRICKS_HUB_CPLUSHUB (1)
1212

1313
// Pybricks modules
14+
#define PYBRICKS_PY_EXPERIMENTAL (1)
1415
#define PYBRICKS_PY_IODEVICES (1)
1516
#define PYBRICKS_PY_PARAMETERS (1)
1617
#define PYBRICKS_PY_PUPDEVICES (1)

bricks/stm32/configport.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ extern const struct _mp_obj_module_t pb_module_hubs;
109109
#define _PYBRICKS_MODULE_HUBS \
110110
{ MP_OBJ_NEW_QSTR(MP_QSTR_hubs), (mp_obj_t)&pb_module_hubs},
111111

112+
#if PYBRICKS_PY_EXPERIMENTAL
113+
extern const struct _mp_obj_module_t pb_module_experimental;
114+
#define _PYBRICKS_MODULE_EXPERIMENTAL \
115+
{ MP_OBJ_NEW_QSTR(MP_QSTR_experimental), (mp_obj_t)&pb_module_experimental },
116+
#else
117+
#define _PYBRICKS_MODULE_EXPERIMENTAL
118+
#endif
112119
#if PYBRICKS_PY_IODEVICES
113120
extern const struct _mp_obj_module_t pb_module_iodevices;
114121
#define _PYBRICKS_MODULE_IODEVICES \
@@ -153,6 +160,7 @@ extern const struct _mp_obj_module_t pb_module_uos;
153160
#endif
154161

155162
#define MICROPY_PORT_BUILTIN_MODULES \
163+
_PYBRICKS_MODULE_EXPERIMENTAL \
156164
_PYBRICKS_MODULE_HUBS \
157165
_PYBRICKS_MODULE_IODEVICES \
158166
_PYBRICKS_MODULE_PARAMETERS \

bricks/stm32/stm32.mk

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ endif
7878
ifeq ($(PB_LIB_BLE5STACK),1)
7979
INC += -I$(PBTOP)/lib/ble5stack/central
8080
endif
81+
ifeq ($(PB_USE_LSM6DS3TR_C),1)
82+
INC += -I$(PBTOP)/lib/lsm6ds3tr_c_STdC/driver
83+
endif
8184
INC += -I$(PBTOP)/extmod
8285
INC += -I$(PBTOP)/py
8386
INC += -I$(BUILD)
@@ -160,6 +163,7 @@ PYBRICKS_EXTMOD_SRC_C = $(addprefix extmod/,\
160163
modbuiltins.c \
161164
modbuttons.c \
162165
moddebug.c \
166+
modexperimental.c \
163167
modhubs.c \
164168
modiodevices.c \
165169
modlogger.c \
@@ -221,6 +225,7 @@ HAL_SRC_C = $(addprefix micropython/lib/stm32lib/STM32$(PB_MCU_SERIES)xx_HAL_Dri
221225
stm32$(PB_MCU_SERIES_LCASE)xx_hal_cortex.c \
222226
stm32$(PB_MCU_SERIES_LCASE)xx_hal_dma.c \
223227
stm32$(PB_MCU_SERIES_LCASE)xx_hal_gpio.c \
228+
stm32$(PB_MCU_SERIES_LCASE)xx_hal_i2c.c \
224229
stm32$(PB_MCU_SERIES_LCASE)xx_hal_pwr_ex.c \
225230
stm32$(PB_MCU_SERIES_LCASE)xx_hal_rcc.c \
226231
stm32$(PB_MCU_SERIES_LCASE)xx_hal_spi.c \
@@ -293,6 +298,10 @@ PBIO_SRC_C = $(addprefix lib/pbio/,\
293298
src/uartdev.c \
294299
)
295300

301+
# STM32 IMU Library
302+
303+
LSM6DS3TR_C_SRC_C = lib/lsm6ds3tr_c_STdC/driver/lsm6ds3tr_c_reg.c
304+
296305
# MicroPython math library
297306

298307
SRC_LIBM = $(addprefix micropython/lib/libm/,\
@@ -336,6 +345,9 @@ endif
336345
ifeq ($(PB_USE_HAL),1)
337346
OBJ += $(addprefix $(BUILD)/, $(HAL_SRC_C:.c=.o))
338347
endif
348+
ifeq ($(PB_USE_LSM6DS3TR_C),1)
349+
OBJ += $(addprefix $(BUILD)/, $(LSM6DS3TR_C_SRC_C:.c=.o))
350+
endif
339351
OBJ += $(addprefix $(BUILD)/, $(CONTIKI_SRC_C:.c=.o))
340352
OBJ += $(addprefix $(BUILD)/, $(LIBFIXMATH_SRC_C:.c=.o))
341353
OBJ += $(addprefix $(BUILD)/, $(PBIO_SRC_C:.c=.o))

extmod/modexperimental.c

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,177 @@
1111
#include "py/obj.h"
1212
#include "py/runtime.h"
1313

14+
#if PYBRICKS_HUB_CPLUSHUB
15+
16+
#include <lsm6ds3tr_c_reg.h>
17+
#include <stm32l4xx_hal.h>
18+
#include <stm32l4xx_ll_i2c.h>
19+
20+
typedef struct {
21+
mp_obj_base_t base;
22+
stmdev_ctx_t ctx;
23+
} mod_experimental_IMU_obj_t;
24+
25+
STATIC I2C_HandleTypeDef hi2c;
26+
27+
void mod_experimental_IMU_handle_i2c_er_irq() {
28+
HAL_I2C_ER_IRQHandler(&hi2c);
29+
}
30+
31+
void mod_experimental_IMU_handle_i2c_ev_irq() {
32+
HAL_I2C_EV_IRQHandler(&hi2c);
33+
}
34+
35+
STATIC int32_t mod_experimental_IMU_write_reg(void *handle, uint8_t reg, uint8_t *data, uint16_t len) {
36+
HAL_StatusTypeDef ret;
37+
38+
ret = HAL_I2C_Mem_Write(&hi2c, LSM6DS3TR_C_I2C_ADD_L, reg, I2C_MEMADD_SIZE_8BIT, data, len, 500);
39+
40+
return ret;
41+
}
42+
43+
STATIC int32_t mod_experimental_IMU_read_reg(void *handle, uint8_t reg, uint8_t *data, uint16_t len) {
44+
HAL_StatusTypeDef ret;
45+
46+
ret = HAL_I2C_Mem_Read(&hi2c, LSM6DS3TR_C_I2C_ADD_L, reg, I2C_MEMADD_SIZE_8BIT, data, len, 500);
47+
48+
return ret;
49+
}
50+
51+
STATIC mp_obj_t mod_experimental_IMU_make_new(const mp_obj_type_t *otype, size_t n_args, size_t n_kw, const mp_obj_t *args) {
52+
mod_experimental_IMU_obj_t *self = m_new_obj(mod_experimental_IMU_obj_t);
53+
54+
self->base.type = (mp_obj_type_t *)otype;
55+
self->ctx.write_reg = mod_experimental_IMU_write_reg;
56+
self->ctx.read_reg = mod_experimental_IMU_read_reg;
57+
58+
if (hi2c.Instance == NULL) {
59+
hi2c.Instance = I2C1;
60+
// Clock is 5MHz, so these timing come out to 1 usec. When combined with
61+
// internal delays, this is slightly slower than 400kHz
62+
hi2c.Init.Timing = __LL_I2C_CONVERT_TIMINGS(0, 0, 0, 4, 4);
63+
hi2c.Init.OwnAddress1 = 0;
64+
hi2c.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
65+
hi2c.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
66+
hi2c.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
67+
hi2c.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
68+
HAL_StatusTypeDef ret = HAL_I2C_Init(&hi2c);
69+
if (ret != HAL_OK) {
70+
hi2c.Instance = NULL;
71+
mp_raise_msg(&mp_type_RuntimeError, "failed to init I2C");
72+
}
73+
}
74+
75+
HAL_StatusTypeDef ret = HAL_I2C_IsDeviceReady(&hi2c, LSM6DS3TR_C_I2C_ADD_L, 10, 200);
76+
if (ret != HAL_OK) {
77+
mp_raise_msg(&mp_type_RuntimeError, "device is not ready");
78+
}
79+
80+
uint8_t id;
81+
if (lsm6ds3tr_c_device_id_get(&self->ctx, &id) != 0) {
82+
mp_raise_msg(&mp_type_RuntimeError, "failed to get device id");
83+
}
84+
85+
if (id != LSM6DS3TR_C_ID) {
86+
mp_raise_msg(&mp_type_RuntimeError, "incorrect device id");
87+
}
88+
89+
// Init based on data polling example
90+
91+
/*
92+
* Restore default configuration
93+
*/
94+
uint8_t rst;
95+
lsm6ds3tr_c_reset_set(&self->ctx, PROPERTY_ENABLE);
96+
do {
97+
lsm6ds3tr_c_reset_get(&self->ctx, &rst);
98+
} while (rst);
99+
/*
100+
* Enable Block Data Update
101+
*/
102+
lsm6ds3tr_c_block_data_update_set(&self->ctx, PROPERTY_ENABLE);
103+
/*
104+
* Set Output Data Rate
105+
*/
106+
lsm6ds3tr_c_xl_data_rate_set(&self->ctx, LSM6DS3TR_C_XL_ODR_12Hz5);
107+
lsm6ds3tr_c_gy_data_rate_set(&self->ctx, LSM6DS3TR_C_GY_ODR_12Hz5);
108+
/*
109+
* Set full scale
110+
*/
111+
lsm6ds3tr_c_xl_full_scale_set(&self->ctx, LSM6DS3TR_C_2g);
112+
lsm6ds3tr_c_gy_full_scale_set(&self->ctx, LSM6DS3TR_C_2000dps);
113+
114+
/*
115+
* Configure filtering chain(No aux interface)
116+
*/
117+
/* Accelerometer - analog filter */
118+
lsm6ds3tr_c_xl_filter_analog_set(&self->ctx, LSM6DS3TR_C_XL_ANA_BW_400Hz);
119+
120+
/* Accelerometer - LPF1 path ( LPF2 not used )*/
121+
// lsm6ds3tr_c_xl_lp1_bandwidth_set(&self->ctx, LSM6DS3TR_C_XL_LP1_ODR_DIV_4);
122+
123+
/* Accelerometer - LPF1 + LPF2 path */
124+
lsm6ds3tr_c_xl_lp2_bandwidth_set(&self->ctx, LSM6DS3TR_C_XL_LOW_NOISE_LP_ODR_DIV_100);
125+
126+
/* Accelerometer - High Pass / Slope path */
127+
// lsm6ds3tr_c_xl_reference_mode_set(&self->ctx, PROPERTY_DISABLE);
128+
// lsm6ds3tr_c_xl_hp_bandwidth_set(&self->ctx, LSM6DS3TR_C_XL_HP_ODR_DIV_100);
129+
130+
/* Gyroscope - filtering chain */
131+
lsm6ds3tr_c_gy_band_pass_set(&self->ctx, LSM6DS3TR_C_HP_260mHz_LP1_STRONG);
132+
133+
return MP_OBJ_FROM_PTR(self);
134+
}
135+
136+
STATIC mp_obj_t mod_experimental_IMU_accel(mp_obj_t self_in) {
137+
mod_experimental_IMU_obj_t *self = MP_OBJ_TO_PTR(self_in);
138+
int16_t data[3];
139+
140+
if (lsm6ds3tr_c_acceleration_raw_get(&self->ctx, (uint8_t *)data) != 0) {
141+
mp_raise_msg(&mp_type_RuntimeError, "failed to read data");
142+
}
143+
144+
mp_obj_t values[3];
145+
values[0] = mp_obj_new_float_from_f(lsm6ds3tr_c_from_fs2g_to_mg(data[0]) / 1000.0f);
146+
values[1] = mp_obj_new_float_from_f(lsm6ds3tr_c_from_fs2g_to_mg(data[1]) / 1000.0f);
147+
values[2] = mp_obj_new_float_from_f(lsm6ds3tr_c_from_fs2g_to_mg(data[2]) / 1000.0f);
148+
149+
return mp_obj_new_tuple(3, values);
150+
}
151+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_experimental_IMU_accel_obj, mod_experimental_IMU_accel);
152+
153+
STATIC mp_obj_t mod_experimental_IMU_gyro(mp_obj_t self_in) {
154+
mod_experimental_IMU_obj_t *self = MP_OBJ_TO_PTR(self_in);
155+
int16_t data[3];
156+
157+
if (lsm6ds3tr_c_angular_rate_raw_get(&self->ctx, (uint8_t *)data) != 0) {
158+
mp_raise_msg(&mp_type_RuntimeError, "failed to read data");
159+
}
160+
161+
mp_obj_t values[3];
162+
values[0] = mp_obj_new_float_from_f(lsm6ds3tr_c_from_fs2000dps_to_mdps(data[0]) / 1000.0f);
163+
values[1] = mp_obj_new_float_from_f(lsm6ds3tr_c_from_fs2000dps_to_mdps(data[1]) / 1000.0f);
164+
values[2] = mp_obj_new_float_from_f(lsm6ds3tr_c_from_fs2000dps_to_mdps(data[2]) / 1000.0f);
165+
166+
return mp_obj_new_tuple(3, values);
167+
}
168+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_experimental_IMU_gyro_obj, mod_experimental_IMU_gyro);
169+
170+
STATIC const mp_rom_map_elem_t mod_experimental_IMU_locals_dict_table[] = {
171+
{ MP_ROM_QSTR(MP_QSTR_accel), MP_ROM_PTR(&mod_experimental_IMU_accel_obj) },
172+
{ MP_ROM_QSTR(MP_QSTR_gyro), MP_ROM_PTR(&mod_experimental_IMU_gyro_obj) },
173+
};
174+
STATIC MP_DEFINE_CONST_DICT(mod_experimental_IMU_locals_dict, mod_experimental_IMU_locals_dict_table);
175+
176+
STATIC const mp_obj_type_t mod_experimental_IMU_type = {
177+
{ &mp_type_type },
178+
.name = MP_QSTR_IMU,
179+
.make_new = mod_experimental_IMU_make_new,
180+
.locals_dict = (mp_obj_dict_t *)&mod_experimental_IMU_locals_dict,
181+
};
182+
183+
#endif // PYBRICKS_HUB_CPLUSHUB
184+
14185
#if PYBRICKS_HUB_EV3
15186
#if !MICROPY_MODULE_BUILTIN_INIT
16187
#error "pybricks.experimental module requires that MICROPY_MODULE_BUILTIN_INIT is enabled"
@@ -47,6 +218,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_experimental_pthread_raise_obj, mod_experim
47218

48219
STATIC const mp_rom_map_elem_t mod_experimental_globals_table[] = {
49220
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_experimental_c) },
221+
#if PYBRICKS_HUB_CPLUSHUB
222+
{ MP_ROM_QSTR(MP_QSTR_IMU), MP_ROM_PTR(&mod_experimental_IMU_type) },
223+
#endif // PYBRICKS_HUB_CPLUSHUB
50224
#if PYBRICKS_HUB_EV3
51225
{ MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&mod_experimental___init___obj) },
52226
{ MP_ROM_QSTR(MP_QSTR_pthread_raise), MP_ROM_PTR(&mod_experimental_pthread_raise_obj) },

lib/pbio/platform/cplus_hub/platform.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,34 @@ void DMA1_Channel1_IRQHandler() {
291291
pbdrv_adc_stm32_hal_handle_irq();
292292
}
293293

294+
void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) {
295+
GPIO_InitTypeDef gpio_init = { 0 };
296+
297+
gpio_init.Mode = GPIO_MODE_AF_OD;
298+
gpio_init.Pull = GPIO_NOPULL;
299+
gpio_init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
300+
gpio_init.Alternate = GPIO_AF4_I2C1;
301+
302+
gpio_init.Pin = GPIO_PIN_8;
303+
HAL_GPIO_Init(GPIOB, &gpio_init);
304+
gpio_init.Pin = GPIO_PIN_9;
305+
HAL_GPIO_Init(GPIOB, &gpio_init);
306+
307+
HAL_NVIC_SetPriority(I2C1_ER_IRQn, 0, 1);
308+
HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
309+
HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 2);
310+
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
311+
}
312+
313+
void I2C1_ER_IRQHandler(void) {
314+
extern void mod_experimental_IMU_handle_i2c_er_irq();
315+
mod_experimental_IMU_handle_i2c_er_irq();
316+
}
317+
318+
void I2C1_EV_IRQHandler(void) {
319+
extern void mod_experimental_IMU_handle_i2c_ev_irq();
320+
mod_experimental_IMU_handle_i2c_ev_irq();
321+
}
294322

295323
// Early initialization
296324

0 commit comments

Comments
 (0)