From 39b18a4b9f23b6975a83b457cf20a30eb78867dc Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Tue, 23 Aug 2022 10:36:50 +0100 Subject: [PATCH] MLX90640: MicroPython module. --- drivers/mlx90640/mlx90640.hpp | 6 +- .../breakout_mlx90640/micropython.cmake | 21 ++++++ .../modules/breakout_mlx90640/mlx90640.c | 35 ++++++++++ .../modules/breakout_mlx90640/mlx90640.cpp | 65 +++++++++++++++++++ .../modules/breakout_mlx90640/mlx90640.h | 7 ++ micropython/modules/micropython-common.cmake | 1 + 6 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 micropython/modules/breakout_mlx90640/micropython.cmake create mode 100644 micropython/modules/breakout_mlx90640/mlx90640.c create mode 100644 micropython/modules/breakout_mlx90640/mlx90640.cpp create mode 100644 micropython/modules/breakout_mlx90640/mlx90640.h diff --git a/drivers/mlx90640/mlx90640.hpp b/drivers/mlx90640/mlx90640.hpp index 69a20b4c8..9133c3c21 100644 --- a/drivers/mlx90640/mlx90640.hpp +++ b/drivers/mlx90640/mlx90640.hpp @@ -1,3 +1,4 @@ +#include #include "src/headers/MLX90640_API.h" #include "common/pimoroni_i2c.hpp" @@ -8,13 +9,16 @@ void MLX90640_I2CConfigure(pimoroni::I2C *i2c_instance); namespace pimoroni { class MLX90640 { public: + static const int WIDTH = 32; + static const int HEIGHT = 24; + enum MLX90640_Error { OK = 0, INVALID_BAUDRATE = 1, INVALID_FPS = 2, }; - float mlx90640To[768] = {0.0f}; + float mlx90640To[WIDTH * HEIGHT] = {0.0f}; float emissivity = 1.0f; float reflected_temperature = 8.0f; diff --git a/micropython/modules/breakout_mlx90640/micropython.cmake b/micropython/modules/breakout_mlx90640/micropython.cmake new file mode 100644 index 000000000..0f2875b40 --- /dev/null +++ b/micropython/modules/breakout_mlx90640/micropython.cmake @@ -0,0 +1,21 @@ +add_library(usermod_mlx90640 INTERFACE) + +target_sources(usermod_mlx90640 INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/mlx90640.c + ${CMAKE_CURRENT_LIST_DIR}/mlx90640.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../../drivers/mlx90640/mlx90640.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../../drivers/mlx90640/src/functions/MLX90640_API.cpp + ${CMAKE_CURRENT_LIST_DIR}/../../../drivers/mlx90640/MLX90640_RP2040_I2C_Driver.cpp +) + +target_include_directories(usermod_mlx90640 INTERFACE + ${CMAKE_CURRENT_LIST_DIR} + ${CMAKE_CURRENT_LIST_DIR}/../../../drivers/mlx90640/ + ${CMAKE_CURRENT_LIST_DIR}/../../../drivers/mlx90640/src/headers/ +) + +target_compile_definitions(usermod_mlx90640 INTERFACE + MODULE_MLX90640_ENABLED=1 +) + +target_link_libraries(usermod INTERFACE usermod_mlx90640) \ No newline at end of file diff --git a/micropython/modules/breakout_mlx90640/mlx90640.c b/micropython/modules/breakout_mlx90640/mlx90640.c new file mode 100644 index 000000000..81593f529 --- /dev/null +++ b/micropython/modules/breakout_mlx90640/mlx90640.c @@ -0,0 +1,35 @@ +#include "mlx90640.h" + + +MP_DEFINE_CONST_FUN_OBJ_2(MLX90640_setup_obj, MLX90640_setup); +MP_DEFINE_CONST_FUN_OBJ_1(MLX90640_get_frame_obj, MLX90640_get_frame); + +STATIC const mp_rom_map_elem_t MLX90640_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_setup), MP_ROM_PTR(&MLX90640_setup_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_frame), MP_ROM_PTR(&MLX90640_get_frame_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(MLX90640_locals_dict, MLX90640_locals_dict_table); + +const mp_obj_type_t MLX90640_MLX90640_type = { + { &mp_type_type }, + .name = MP_QSTR_MLX90640, + .make_new = MLX90640_make_new, + .locals_dict = (mp_obj_dict_t*)&MLX90640_locals_dict, +}; + +STATIC const mp_map_elem_t MLX90640_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_msa301) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MLX90640), (mp_obj_t)&MLX90640_type }, +}; +STATIC MP_DEFINE_CONST_DICT(mp_module_MLX90640_globals, MLX90640_globals_table); + +const mp_obj_module_t MLX90640_user_cmodule = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mp_module_MLX90640_globals, +}; + +#if MICROPY_VERSION <= 70144 +MP_REGISTER_MODULE(MP_QSTR_MLX90640, MLX90640_user_cmodule, MODULE_MLX90640_ENABLED); +#else +MP_REGISTER_MODULE(MP_QSTR_MLX90640, MLX90640_user_cmodule); +#endif \ No newline at end of file diff --git a/micropython/modules/breakout_mlx90640/mlx90640.cpp b/micropython/modules/breakout_mlx90640/mlx90640.cpp new file mode 100644 index 000000000..369377024 --- /dev/null +++ b/micropython/modules/breakout_mlx90640/mlx90640.cpp @@ -0,0 +1,65 @@ +#include "drivers/mlx90640/mlx90640.hpp" + +#include "micropython/modules/util.hpp" + +using namespace pimoroni; + +extern "C" { +#include "mlx90640.h" +#include "pimoroni_i2c.h" + +typedef struct _ModMLX90640_obj_t { + mp_obj_base_t base; + MLX90640 *breakout; + _PimoroniI2C_obj_t *i2c; + int address; +} ModMLX90640_obj_t; + +mp_obj_t MLX90640_setup(mp_obj_t self_in, mp_obj_t fps) { + _ModMLX90640_obj_t *self = MP_OBJ_TO_PTR2(self_in, _ModMLX90640_obj_t); + + self->breakout->setup(mp_obj_get_int(fps)); + + return mp_const_none; +} + +mp_obj_t MLX90640_get_frame(mp_obj_t self_in) { + _ModMLX90640_obj_t *self = MP_OBJ_TO_PTR2(self_in, _ModMLX90640_obj_t); + + self->breakout->get_frame(); + + mp_obj_list_t *list = MP_OBJ_TO_PTR2(mp_obj_new_list(MLX90640::WIDTH * MLX90640::HEIGHT, NULL), mp_obj_list_t); + + for(auto y = 0u; y < MLX90640::HEIGHT; y++) { + for(auto x = 0u; x < MLX90640::WIDTH; x++) { + int offset = y * MLX90640::WIDTH + x; + float v = self->breakout->mlx90640To[offset]; + list->items[offset] = mp_obj_new_float(v); + } + } + + return list; +} + +mp_obj_t MLX90640_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_i2c, ARG_address }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_i2c, MP_ARG_OBJ, {.u_obj = nullptr} }, + { MP_QSTR_address, MP_ARG_INT, {.u_int = MLX90640_DEFAULT_I2C_ADDRESS}} + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + _ModMLX90640_obj_t *self = m_new_obj_with_finaliser(_ModMLX90640_obj_t); + self->base.type = &MLX90640_type; + + self->i2c = PimoroniI2C_from_machine_i2c_or_native(args[ARG_i2c].u_obj); + self->address = args[ARG_address].u_int; + + self->breakout = m_new_class(MLX90640, (pimoroni::I2C *)(self->i2c->i2c), self->address); + + return self; +} + +} \ No newline at end of file diff --git a/micropython/modules/breakout_mlx90640/mlx90640.h b/micropython/modules/breakout_mlx90640/mlx90640.h new file mode 100644 index 000000000..3bf4bc0f9 --- /dev/null +++ b/micropython/modules/breakout_mlx90640/mlx90640.h @@ -0,0 +1,7 @@ +#include "py/runtime.h" + +extern const mp_obj_type_t MLX90640_type; + +extern mp_obj_t MLX90640_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args); +extern mp_obj_t MLX90640_get_frame(mp_obj_t self_in); +extern mp_obj_t MLX90640_setup(mp_obj_t self_in, mp_obj_t fps_in); \ No newline at end of file diff --git a/micropython/modules/micropython-common.cmake b/micropython/modules/micropython-common.cmake index b1d0bb08c..dfad48404 100644 --- a/micropython/modules/micropython-common.cmake +++ b/micropython/modules/micropython-common.cmake @@ -22,6 +22,7 @@ include(breakout_bmp280/micropython) include(breakout_icp10125/micropython) include(breakout_scd41/micropython) include(breakout_vl53l5cx/micropython) +include(breakout_mlx90640/micropython) include(pico_scroll/micropython) include(pico_rgb_keypad/micropython)