From 344d06a114bb556b84467bc57c94615b54cbc390 Mon Sep 17 00:00:00 2001 From: koalo <koalo@koalo.de> Date: Thu, 22 Aug 2019 01:21:42 +0200 Subject: [PATCH] feat(bhi160): Provide Gyroscope data --- epicardium/epicardium.h | 6 +- epicardium/modules/bhi.c | 39 +++++++++++- epicardium/modules/stream.h | 3 +- pycardium/modules/bhi160-sys.c | 8 +-- pycardium/modules/interrupt.c | 2 + pycardium/modules/py/bhi160.py | 112 ++++++++++++++++++++++----------- pycardium/modules/qstrdefs.h | 1 + 7 files changed, 126 insertions(+), 45 deletions(-) diff --git a/epicardium/epicardium.h b/epicardium/epicardium.h index 266a5a266..7af2a7989 100644 --- a/epicardium/epicardium.h +++ b/epicardium/epicardium.h @@ -157,9 +157,11 @@ API(API_INTERRUPT_DISABLE, int epic_interrupt_disable(api_int_id_t int_id)); /** TODO: BHI */ #define EPIC_INT_BHI160_ACCELEROMETER 4 API_ISR(EPIC_INT_BHI160_ACCELEROMETER, epic_isr_bhi160_accelerometer); +#define EPIC_INT_BHI160_GYROSCOPE 5 +API_ISR(EPIC_INT_BHI160_GYROSCOPE, epic_isr_bhi160_gyroscope); /* Number of defined interrupts. */ -#define EPIC_INT_NUM 5 +#define EPIC_INT_NUM 6 /* clang-format on */ /* @@ -923,7 +925,7 @@ enum bhi160_sensor_type { BHI160_MAGNETOMETER = 1, /** Orientation (**Unimplemented**) */ BHI160_ORIENTATION = 2, - /** Gyroscope (**Unimplemented**) */ + /** Gyroscope */ BHI160_GYROSCOPE = 3, /** Gravity (**Unimplemented**) */ BHI160_GRAVITY = 4, diff --git a/epicardium/modules/bhi.c b/epicardium/modules/bhi.c index 6aa5f3fba..04e2ec54c 100644 --- a/epicardium/modules/bhi.c +++ b/epicardium/modules/bhi.c @@ -73,6 +73,7 @@ static size_t bhi160_lookup_data_size(enum bhi160_sensor_type type) case BHI160_ACCELEROMETER: case BHI160_MAGNETOMETER: case BHI160_ORIENTATION: + case BHI160_GYROSCOPE: return sizeof(struct bhi160_data_vector); default: return 0; @@ -87,6 +88,8 @@ static bhy_virtual_sensor_t bhi160_lookup_vs_id(enum bhi160_sensor_type type) switch (type) { case BHI160_ACCELEROMETER: return VS_ID_ACCELEROMETER; + case BHI160_GYROSCOPE: + return VS_ID_GYROSCOPE; default: return -1; } @@ -100,6 +103,8 @@ static int bhi160_lookup_sd(enum bhi160_sensor_type type) switch (type) { case BHI160_ACCELEROMETER: return SD_BHI160_ACCELEROMETER; + case BHI160_GYROSCOPE: + return SD_BHI160_GYROSCOPE; default: return -1; } @@ -134,9 +139,14 @@ int epic_bhi160_enable_sensor( return -ENOMEM; } - stream_register(bhi160_lookup_sd(sensor_type), stream); + int streamret = stream_register(bhi160_lookup_sd(sensor_type), stream); + if (streamret < 0) { + xSemaphoreGive(bhi160_mutex); + hwlock_release(HWLOCK_I2C); + return streamret; + } - bhy_enable_virtual_sensor( + int bhyret = bhy_enable_virtual_sensor( vs_id, VS_WAKEUP, config->sample_rate, @@ -145,6 +155,11 @@ int epic_bhi160_enable_sensor( 0, config->dynamic_range /* dynamic range is sensor dependent */ ); + if (bhyret != BHY_SUCCESS) { + xSemaphoreGive(bhi160_mutex); + hwlock_release(HWLOCK_I2C); + return bhyret; + } xSemaphoreGive(bhi160_mutex); } else { hwlock_release(HWLOCK_I2C); @@ -152,7 +167,7 @@ int epic_bhi160_enable_sensor( } hwlock_release(HWLOCK_I2C); - return 0; + return bhi160_lookup_sd(sensor_type); } int epic_bhi160_disable_sensor(enum bhi160_sensor_type sensor_type) @@ -231,6 +246,24 @@ bhi160_handle_packet(bhy_data_type_t data_type, bhy_data_generic_t *sensor_data) api_interrupt_trigger(EPIC_INT_BHI160_ACCELEROMETER); } break; + case VS_ID_GYROSCOPE: + case VS_ID_GYROSCOPE_WAKEUP: + MXC_ASSERT(data_type == BHY_DATA_TYPE_VECTOR); + if (bhi160_streams[BHI160_GYROSCOPE].queue == NULL) { + break; + } + data_vector.x = sensor_data->data_vector.x; + data_vector.y = sensor_data->data_vector.y; + data_vector.z = sensor_data->data_vector.z; + xQueueSend( + bhi160_streams[BHI160_GYROSCOPE].queue, + &data_vector, + BHI160_MUTEX_WAIT_MS + ); + if (sensor_id == VS_ID_GYROSCOPE_WAKEUP) { + api_interrupt_trigger(EPIC_INT_BHI160_GYROSCOPE); + } + break; default: break; } diff --git a/epicardium/modules/stream.h b/epicardium/modules/stream.h index 8b121bfcb..668f78623 100644 --- a/epicardium/modules/stream.h +++ b/epicardium/modules/stream.h @@ -25,8 +25,9 @@ typedef unsigned int size_t; * Please keep IDs in sequential order. */ enum stream_descriptor { - /** BHI160 Accelerometer */ + /** BHI160 */ SD_BHI160_ACCELEROMETER, + SD_BHI160_GYROSCOPE, /** Highest descriptor must always be ``SD_MAX``. */ SD_MAX, }; diff --git a/pycardium/modules/bhi160-sys.c b/pycardium/modules/bhi160-sys.c index c5bde7147..439ac1d42 100644 --- a/pycardium/modules/bhi160-sys.c +++ b/pycardium/modules/bhi160-sys.c @@ -23,17 +23,17 @@ STATIC mp_obj_t mp_bhi160_enable_sensor(size_t n_args, const mp_obj_t *args) cfg.sample_rate = mp_obj_get_int(args[2]); cfg.dynamic_range = mp_obj_get_int(args[3]); - int sd = epic_bhi160_enable_sensor(sensor_type, &cfg); + int stream_id = epic_bhi160_enable_sensor(sensor_type, &cfg); - return MP_OBJ_NEW_SMALL_INT(sd); + return MP_OBJ_NEW_SMALL_INT(stream_id); } STATIC mp_obj_t mp_bhi160_read_sensor(mp_obj_t stream_id_in) { struct bhi160_data_vector buf[100]; - int sd = mp_obj_get_int(stream_id_in); + int stream_id = mp_obj_get_int(stream_id_in); - int n = epic_stream_read(sd, buf, sizeof(buf)); + int n = epic_stream_read(stream_id, buf, sizeof(buf)); mp_obj_list_t *list = mp_obj_new_list(0, NULL); for (int i = 0; i < n; i++) { diff --git a/pycardium/modules/interrupt.c b/pycardium/modules/interrupt.c index 90dd700a8..087facf7b 100644 --- a/pycardium/modules/interrupt.c +++ b/pycardium/modules/interrupt.c @@ -87,6 +87,8 @@ static const mp_rom_map_elem_t interrupt_module_globals_table[] = { MP_OBJ_NEW_SMALL_INT(EPIC_INT_RTC_ALARM) }, { MP_ROM_QSTR(MP_QSTR_BHI160_ACCELEROMETER), MP_OBJ_NEW_SMALL_INT(EPIC_INT_BHI160_ACCELEROMETER) }, + { MP_ROM_QSTR(MP_QSTR_BHI160_GYROSCOPE), + MP_OBJ_NEW_SMALL_INT(EPIC_INT_BHI160_GYROSCOPE) }, }; static MP_DEFINE_CONST_DICT( interrupt_module_globals, interrupt_module_globals_table diff --git a/pycardium/modules/py/bhi160.py b/pycardium/modules/py/bhi160.py index a4eb371e1..5b07cc483 100644 --- a/pycardium/modules/py/bhi160.py +++ b/pycardium/modules/py/bhi160.py @@ -2,20 +2,21 @@ import sys_bhi160 import interrupt -class BHI160Accelerometer: - def __init__( - self, sample_rate=4, dynamic_range=2, callback=None, sample_buffer_len=200 - ): - interrupt.disable_callback(interrupt.BHI160_ACCELEROMETER) - interrupt.set_callback( - interrupt.BHI160_ACCELEROMETER, self._accelerometer_interrupt - ) - self.acc_sd = sys_bhi160.enable_sensor( - 0, sample_buffer_len, sample_rate, dynamic_range +class BHI160: + def enable_sensor(self): + interrupt.disable_callback(self.interrupt_id) + interrupt.set_callback(self.interrupt_id, self._interrupt) + self.stream_id = sys_bhi160.enable_sensor( + self.sensor_id, self.sample_buffer_len, self.sample_rate, self.dynamic_range ) - self._callback = callback - if callback: - interrupt.enable_callback(interrupt.BHI160_ACCELEROMETER) + + if self.stream_id < 0: + raise ValueError("Enable sensor returned %i", self.stream_id) + + self.active = True + + if self._callback: + interrupt.enable_callback(self.interrupt_id) def __enter__(self): return self @@ -24,33 +25,74 @@ class BHI160Accelerometer: self.close() def close(self): - if self.acc_sd is not None: - self.acc_sd = None - self.acc_sd = sys_bhi160.disable_sensor(0) - interrupt.disable_callback(interrupt.BHI160_ACCELEROMETER) - interrupt.set_callback(interrupt.BHI160_ACCELEROMETER, None) - - def convert(self, value): - return 2 * value / 32768.0 + if self.active: + self.active = False + sys_bhi160.disable_sensor(self.sensor_id) + interrupt.disable_callback(self.interrupt_id) + interrupt.set_callback(self.interrupt_id, None) def read(self): result = [] - if self.acc_sd is not None: - for sample in sys_bhi160.read_sensor(self.acc_sd): - result.append( - dict( - { - "x": self.convert(sample.x()), - "y": self.convert(sample.y()), - "z": self.convert(sample.z()), - } - ) - ) + if self.active: + for sample in sys_bhi160.read_sensor(self.stream_id): + result.append(self.convert(sample)) return result - def _accelerometer_interrupt(self, _): - if self.acc_sd is not None: - data = sys_bhi160.read_sensor(self.acc_sd) + def _interrupt(self, _): + if self.active: + data = self.read() print(data) if self._callback: self._callback(data) + + +class BHI160Accelerometer(BHI160): + def __init__( + self, sample_rate=4, dynamic_range=2, callback=None, sample_buffer_len=200 + ): + self.sample_rate = sample_rate + self.dynamic_range = dynamic_range + self.callback = callback + self.sample_buffer_len = sample_buffer_len + self.sensor_id = 0 + self.interrupt_id = interrupt.BHI160_ACCELEROMETER + self._callback = callback + self.enable_sensor() + + def convert_single(self, value): + return 2 * value / 32768.0 + + def convert(self, sample): + return dict( + { + "x": self.convert_single(sample.x()), + "y": self.convert_single(sample.y()), + "z": self.convert_single(sample.z()), + } + ) + + +class BHI160Gyroscope(BHI160): + def __init__( + self, sample_rate=4, dynamic_range=2, callback=None, sample_buffer_len=200 + ): + self.sample_rate = sample_rate + self.dynamic_range = dynamic_range + self.callback = callback + self.sample_buffer_len = sample_buffer_len + self.sensor_id = 3 + self.interrupt_id = interrupt.BHI160_GYROSCOPE + self._callback = callback + self.enable_sensor() + + def convert_single(self, value): + return 360 * value / 32768.0 + + def convert(self, sample): + return dict( + { + "x": self.convert_single(sample.x()), + "y": self.convert_single(sample.y()), + "z": self.convert_single(sample.z()), + } + ) diff --git a/pycardium/modules/qstrdefs.h b/pycardium/modules/qstrdefs.h index 84bd55b9c..94ead401b 100644 --- a/pycardium/modules/qstrdefs.h +++ b/pycardium/modules/qstrdefs.h @@ -58,6 +58,7 @@ Q(set_callback) Q(enable_callback) Q(disable_callback) Q(BHI160_ACCELEROMETER) +Q(BHI160_GYROSCOPE) Q(RTC_ALARM) /* bhi160 */ -- GitLab