Merge branch 'main' into motor-and-encoder
This commit is contained in:
commit
305462d33c
|
@ -9,8 +9,8 @@ on:
|
|||
env:
|
||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||
MICROPYTHON_VERSION: v1.18
|
||||
BLINKA_VERSION: 6.20.1
|
||||
PLATFORMDETECT_VERSION: 3.19.3
|
||||
BLINKA_VERSION: 7.3.0
|
||||
PLATFORMDETECT_VERSION: 3.22.1
|
||||
BUILD_TYPE: Release
|
||||
BOARD_TYPE: PICO
|
||||
|
||||
|
@ -64,6 +64,7 @@ jobs:
|
|||
cp -r pimoroni-pico-${GITHUB_SHA}/micropython/modules_py/* micropython/ports/rp2/modules/
|
||||
mkdir -p micropython/ports/rp2/modules/adafruit_blinka/microcontroller/
|
||||
cp -r Adafruit_Blinka/src/adafruit_blinka/microcontroller/rp2040 micropython/ports/rp2/modules/adafruit_blinka/microcontroller/
|
||||
cp -r Adafruit_Blinka/src/adafruit_blinka/microcontroller/generic_micropython micropython/ports/rp2/modules/adafruit_blinka/microcontroller/
|
||||
mkdir -p micropython/ports/rp2/modules/adafruit_blinka/board/raspberrypi/
|
||||
cp Adafruit_Blinka/src/adafruit_blinka/microcontroller/__init__.py micropython/ports/rp2/modules/adafruit_blinka/microcontroller/
|
||||
cp Adafruit_Blinka/src/adafruit_blinka/board/__init__.py micropython/ports/rp2/modules/adafruit_blinka/board/
|
||||
|
|
|
@ -17,3 +17,7 @@
|
|||
[submodule "micropython/modules/qrcode"]
|
||||
path = micropython/modules/qrcode
|
||||
url = https://github.com/pimoroni/QR-Code-Generator
|
||||
[submodule "drivers/vl53l5cx/src"]
|
||||
path = drivers/vl53l5cx/src
|
||||
url = https://github.com/ST-mirror/VL53L5CX_ULD_driver
|
||||
branch = lite/en
|
||||
|
|
|
@ -32,3 +32,4 @@ add_subdirectory(pwm)
|
|||
add_subdirectory(servo)
|
||||
add_subdirectory(encoder)
|
||||
add_subdirectory(motor)
|
||||
add_subdirectory(vl53l5cx)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
include(${CMAKE_CURRENT_LIST_DIR}/vl53l5cx.cmake)
|
|
@ -0,0 +1,235 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2020, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* This file is part of the VL53L5CX Ultra Lite Driver and is dual licensed,
|
||||
* either 'STMicroelectronics Proprietary license'
|
||||
* or 'BSD 3-clause "New" or "Revised" License' , at your option.
|
||||
*
|
||||
********************************************************************************
|
||||
*
|
||||
* 'STMicroelectronics Proprietary license'
|
||||
*
|
||||
********************************************************************************
|
||||
*
|
||||
* License terms: STMicroelectronics Proprietary in accordance with licensing
|
||||
* terms at www.st.com/sla0081
|
||||
*
|
||||
* STMicroelectronics confidential
|
||||
* Reproduction and Communication of this document is strictly prohibited unless
|
||||
* specifically authorized in writing by STMicroelectronics.
|
||||
*
|
||||
*
|
||||
********************************************************************************
|
||||
*
|
||||
* Alternatively, the VL53L5CX Ultra Lite Driver may be distributed under the
|
||||
* terms of 'BSD 3-clause "New" or "Revised" License', in which case the
|
||||
* following provisions apply instead of the ones mentioned above :
|
||||
*
|
||||
********************************************************************************
|
||||
*
|
||||
* License terms: BSD 3-clause "New" or "Revised" License.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#include "platform.h"
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
uint8_t RdByte(
|
||||
VL53L5CX_Platform *p_platform,
|
||||
uint16_t RegisterAdress,
|
||||
uint8_t *p_value)
|
||||
{
|
||||
const uint8_t buf[2] = {
|
||||
RegisterAdress >> 8,
|
||||
RegisterAdress & 0xff
|
||||
};
|
||||
i2c_write_blocking(p_platform->i2c, p_platform->address, buf, sizeof(buf), true);
|
||||
if(i2c_read_blocking(p_platform->i2c, p_platform->address, p_value, 1, false) != PICO_ERROR_GENERIC){
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 255;
|
||||
}
|
||||
|
||||
uint8_t WrByte(
|
||||
VL53L5CX_Platform *p_platform,
|
||||
uint16_t RegisterAdress,
|
||||
uint8_t value)
|
||||
{
|
||||
const uint8_t buf[3] = {
|
||||
RegisterAdress >> 8,
|
||||
RegisterAdress & 0xff,
|
||||
value,
|
||||
};
|
||||
if(i2c_write_blocking(p_platform->i2c, p_platform->address, buf, sizeof(buf), false) != PICO_ERROR_GENERIC) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 255;
|
||||
}
|
||||
|
||||
uint8_t WrMulti(
|
||||
VL53L5CX_Platform *p_platform,
|
||||
uint16_t RegisterAdress,
|
||||
uint8_t *p_values,
|
||||
uint32_t size)
|
||||
{
|
||||
uint8_t buf[2];
|
||||
buf[0] = RegisterAdress >> 8;
|
||||
buf[1] = RegisterAdress & 0xff;
|
||||
|
||||
// Send the 16-bit address with no STOP condition
|
||||
int result = i2c_write_blocking(p_platform->i2c, p_platform->address, buf, sizeof(buf), true);
|
||||
|
||||
// Handle an error early... it gets dicey from here
|
||||
if(result == PICO_ERROR_GENERIC) return 255;
|
||||
|
||||
// The VL53L5CX does not support "Repeated Start" and the Pico's I2C API doesn't
|
||||
// let us send more bytes without sending another start condition.
|
||||
|
||||
// The horrow below lets us send out "p_values" followed by a STOP condition,
|
||||
// without having to copy everything into a temporary buffer.
|
||||
uint8_t *src = p_values;
|
||||
|
||||
// Send the rest of the data, followed by a STOP condition
|
||||
// This re-implements the relevant portion of i2c_write_blocking_internal which is NOT sent a timeout check function by i2c_write_blocking
|
||||
for (int byte_ctr = 0; byte_ctr < size; ++byte_ctr) {
|
||||
bool last = byte_ctr == size - 1;
|
||||
p_platform->i2c->hw->data_cmd =
|
||||
bool_to_bit(last) << I2C_IC_DATA_CMD_STOP_LSB | *src++;
|
||||
|
||||
// Wait until the transmission of the address/data from the internal
|
||||
// shift register has completed. For this to function correctly, the
|
||||
// TX_EMPTY_CTRL flag in IC_CON must be set. The TX_EMPTY_CTRL flag
|
||||
// was set in i2c_init.
|
||||
do {
|
||||
tight_loop_contents();
|
||||
} while (!(p_platform->i2c->hw->raw_intr_stat & I2C_IC_RAW_INTR_STAT_TX_EMPTY_BITS));
|
||||
|
||||
if (p_platform->i2c->hw->tx_abrt_source) {
|
||||
// Note clearing the abort flag also clears the reason, and
|
||||
// this instance of flag is clear-on-read! Note also the
|
||||
// IC_CLR_TX_ABRT register always reads as 0.
|
||||
p_platform->i2c->hw->clr_tx_abrt;
|
||||
|
||||
// An abort on the LAST byte means things are probably fine
|
||||
if(last) {
|
||||
// TODO Could there be an abort while waiting for the STOP
|
||||
// condition here? If so, additional code would be needed here
|
||||
// to take care of the abort.
|
||||
do {
|
||||
tight_loop_contents();
|
||||
} while (!(p_platform->i2c->hw->raw_intr_stat & I2C_IC_RAW_INTR_STAT_STOP_DET_BITS));
|
||||
} else {
|
||||
// Ooof, unhandled abort. Fail?
|
||||
return 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Not sure it matters where we clear this, but by default a "nostop" style write
|
||||
// will set this flag so the next transaction starts with a "Repeated Start."
|
||||
p_platform->i2c->restart_on_next = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t RdMulti(
|
||||
VL53L5CX_Platform *p_platform,
|
||||
uint16_t RegisterAdress,
|
||||
uint8_t *p_values,
|
||||
uint32_t size)
|
||||
{
|
||||
const uint8_t buf[2] = {
|
||||
RegisterAdress >> 8,
|
||||
RegisterAdress & 0xff
|
||||
};
|
||||
i2c_write_blocking(p_platform->i2c, p_platform->address, buf, sizeof(buf), true);
|
||||
if(i2c_read_blocking(p_platform->i2c, p_platform->address, p_values, size, false) != PICO_ERROR_GENERIC){
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 255;
|
||||
}
|
||||
|
||||
uint8_t Reset_Sensor(
|
||||
VL53L5CX_Platform *p_platform)
|
||||
{
|
||||
uint8_t status = 0;
|
||||
|
||||
/* (Optional) Need to be implemented by customer. This function returns 0 if OK */
|
||||
|
||||
/* Set pin LPN to LOW */
|
||||
/* Set pin AVDD to LOW */
|
||||
/* Set pin VDDIO to LOW */
|
||||
WaitMs(p_platform, 100);
|
||||
|
||||
/* Set pin LPN of to HIGH */
|
||||
/* Set pin AVDD of to HIGH */
|
||||
/* Set pin VDDIO of to HIGH */
|
||||
WaitMs(p_platform, 100);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void SwapBuffer(
|
||||
uint8_t *buffer,
|
||||
uint16_t size)
|
||||
{
|
||||
uint32_t i, tmp;
|
||||
|
||||
/*for(auto i = 0u; i < size / 4u; i++) {
|
||||
uint32_t *dword = &((uint32_t *)buffer)[i];
|
||||
*dword = __builtin_bswap32(*dword);
|
||||
}*/
|
||||
|
||||
/* Example of possible implementation using <string.h> */
|
||||
for(i = 0; i < size; i = i + 4)
|
||||
{
|
||||
tmp = (
|
||||
buffer[i]<<24)
|
||||
|(buffer[i+1]<<16)
|
||||
|(buffer[i+2]<<8)
|
||||
|(buffer[i+3]);
|
||||
|
||||
memcpy(&(buffer[i]), &tmp, 4);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t WaitMs(
|
||||
VL53L5CX_Platform *p_platform,
|
||||
uint32_t TimeMs)
|
||||
{
|
||||
sleep_ms(TimeMs);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,219 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2020, STMicroelectronics - All Rights Reserved
|
||||
*
|
||||
* This file is part of the VL53L5CX Ultra Lite Driver and is dual licensed,
|
||||
* either 'STMicroelectronics Proprietary license'
|
||||
* or 'BSD 3-clause "New" or "Revised" License' , at your option.
|
||||
*
|
||||
********************************************************************************
|
||||
*
|
||||
* 'STMicroelectronics Proprietary license'
|
||||
*
|
||||
********************************************************************************
|
||||
*
|
||||
* License terms: STMicroelectronics Proprietary in accordance with licensing
|
||||
* terms at www.st.com/sla0081
|
||||
*
|
||||
* STMicroelectronics confidential
|
||||
* Reproduction and Communication of this document is strictly prohibited unless
|
||||
* specifically authorized in writing by STMicroelectronics.
|
||||
*
|
||||
*
|
||||
********************************************************************************
|
||||
*
|
||||
* Alternatively, the VL53L5CX Ultra Lite Driver may be distributed under the
|
||||
* terms of 'BSD 3-clause "New" or "Revised" License', in which case the
|
||||
* following provisions apply instead of the ones mentioned above :
|
||||
*
|
||||
********************************************************************************
|
||||
*
|
||||
* License terms: BSD 3-clause "New" or "Revised" License.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _PLATFORM_H_
|
||||
#define _PLATFORM_H_
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hardware/i2c.h"
|
||||
|
||||
/**
|
||||
* @brief Structure VL53L5CX_Platform needs to be filled by the customer,
|
||||
* depending on his platform. At least, it contains the VL53L5CX I2C address.
|
||||
* Some additional fields can be added, as descriptors, or platform
|
||||
* dependencies. Anything added into this structure is visible into the platform
|
||||
* layer.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* To be filled with customer's platform. At least an I2C address/descriptor
|
||||
* needs to be added */
|
||||
/* Example for most standard platform : I2C address of sensor */
|
||||
uint16_t address;
|
||||
i2c_inst_t *i2c;
|
||||
|
||||
} VL53L5CX_Platform;
|
||||
|
||||
/*
|
||||
* @brief The macro below is used to define the number of target per zone sent
|
||||
* through I2C. This value can be changed by user, in order to tune I2C
|
||||
* transaction, and also the total memory size (a lower number of target per
|
||||
* zone means a lower RAM). The value must be between 1 and 4.
|
||||
*/
|
||||
|
||||
#define VL53L5CX_NB_TARGET_PER_ZONE 1U
|
||||
|
||||
/*
|
||||
* @brief The macro below can be used to avoid data conversion into the driver.
|
||||
* By default there is a conversion between firmware and user data. Using this macro
|
||||
* allows to use the firmware format instead of user format. The firmware format allows
|
||||
* an increased precision.
|
||||
*/
|
||||
|
||||
// #define VL53L5CX_USE_RAW_FORMAT
|
||||
|
||||
/*
|
||||
* @brief All macro below are used to configure the sensor output. User can
|
||||
* define some macros if he wants to disable selected output, in order to reduce
|
||||
* I2C access.
|
||||
*/
|
||||
|
||||
// #define VL53L5CX_DISABLE_AMBIENT_PER_SPAD
|
||||
// #define VL53L5CX_DISABLE_NB_SPADS_ENABLED
|
||||
// #define VL53L5CX_DISABLE_NB_TARGET_DETECTED
|
||||
// #define VL53L5CX_DISABLE_SIGNAL_PER_SPAD
|
||||
// #define VL53L5CX_DISABLE_RANGE_SIGMA_MM
|
||||
// #define VL53L5CX_DISABLE_DISTANCE_MM
|
||||
// #define VL53L5CX_DISABLE_REFLECTANCE_PERCENT
|
||||
// #define VL53L5CX_DISABLE_TARGET_STATUS
|
||||
// #define VL53L5CX_DISABLE_MOTION_INDICATOR
|
||||
|
||||
/**
|
||||
* @param (VL53L5CX_Platform*) p_platform : Pointer of VL53L5CX platform
|
||||
* structure.
|
||||
* @param (uint16_t) Address : I2C location of value to read.
|
||||
* @param (uint8_t) *p_values : Pointer of value to read.
|
||||
* @return (uint8_t) status : 0 if OK
|
||||
*/
|
||||
|
||||
uint8_t RdByte(
|
||||
VL53L5CX_Platform *p_platform,
|
||||
uint16_t RegisterAdress,
|
||||
uint8_t *p_value);
|
||||
|
||||
/**
|
||||
* @brief Mandatory function used to write one single byte.
|
||||
* @param (VL53L5CX_Platform*) p_platform : Pointer of VL53L5CX platform
|
||||
* structure.
|
||||
* @param (uint16_t) Address : I2C location of value to read.
|
||||
* @param (uint8_t) value : Pointer of value to write.
|
||||
* @return (uint8_t) status : 0 if OK
|
||||
*/
|
||||
|
||||
uint8_t WrByte(
|
||||
VL53L5CX_Platform *p_platform,
|
||||
uint16_t RegisterAdress,
|
||||
uint8_t value);
|
||||
|
||||
/**
|
||||
* @brief Mandatory function used to read multiples bytes.
|
||||
* @param (VL53L5CX_Platform*) p_platform : Pointer of VL53L5CX platform
|
||||
* structure.
|
||||
* @param (uint16_t) Address : I2C location of values to read.
|
||||
* @param (uint8_t) *p_values : Buffer of bytes to read.
|
||||
* @param (uint32_t) size : Size of *p_values buffer.
|
||||
* @return (uint8_t) status : 0 if OK
|
||||
*/
|
||||
|
||||
uint8_t RdMulti(
|
||||
VL53L5CX_Platform *p_platform,
|
||||
uint16_t RegisterAdress,
|
||||
uint8_t *p_values,
|
||||
uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief Mandatory function used to write multiples bytes.
|
||||
* @param (VL53L5CX_Platform*) p_platform : Pointer of VL53L5CX platform
|
||||
* structure.
|
||||
* @param (uint16_t) Address : I2C location of values to write.
|
||||
* @param (uint8_t) *p_values : Buffer of bytes to write.
|
||||
* @param (uint32_t) size : Size of *p_values buffer.
|
||||
* @return (uint8_t) status : 0 if OK
|
||||
*/
|
||||
|
||||
uint8_t WrMulti(
|
||||
VL53L5CX_Platform *p_platform,
|
||||
uint16_t RegisterAdress,
|
||||
uint8_t *p_values,
|
||||
uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief Optional function, only used to perform an hardware reset of the
|
||||
* sensor. This function is not used in the API, but it can be used by the host.
|
||||
* This function is not mandatory to fill if user don't want to reset the
|
||||
* sensor.
|
||||
* @param (VL53L5CX_Platform*) p_platform : Pointer of VL53L5CX platform
|
||||
* structure.
|
||||
* @return (uint8_t) status : 0 if OK
|
||||
*/
|
||||
|
||||
uint8_t Reset_Sensor(
|
||||
VL53L5CX_Platform *p_platform);
|
||||
|
||||
/**
|
||||
* @brief Mandatory function, used to swap a buffer. The buffer size is always a
|
||||
* multiple of 4 (4, 8, 12, 16, ...).
|
||||
* @param (uint8_t*) buffer : Buffer to swap, generally uint32_t
|
||||
* @param (uint16_t) size : Buffer size to swap
|
||||
*/
|
||||
|
||||
void SwapBuffer(
|
||||
uint8_t *buffer,
|
||||
uint16_t size);
|
||||
/**
|
||||
* @brief Mandatory function, used to wait during an amount of time. It must be
|
||||
* filled as it's used into the API.
|
||||
* @param (VL53L5CX_Platform*) p_platform : Pointer of VL53L5CX platform
|
||||
* structure.
|
||||
* @param (uint32_t) TimeMs : Time to wait in ms.
|
||||
* @return (uint8_t) status : 0 if wait is finished.
|
||||
*/
|
||||
|
||||
uint8_t WaitMs(
|
||||
VL53L5CX_Platform *p_platform,
|
||||
uint32_t TimeMs);
|
||||
|
||||
#endif // _PLATFORM_H_
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 834fa4e53119b987ae9357afc9dfacc6ef8261f8
|
|
@ -0,0 +1,16 @@
|
|||
add_library(vl53l5cx INTERFACE)
|
||||
|
||||
target_sources(vl53l5cx INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/vl53l5cx.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/platform.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/VL53L5CX_ULD_API/src/vl53l5cx_api.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/VL53L5CX_ULD_API/src/vl53l5cx_plugin_detection_thresholds.c
|
||||
)
|
||||
|
||||
target_include_directories(vl53l5cx INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/VL53L5CX_ULD_API/inc
|
||||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(vl53l5cx INTERFACE pico_stdlib hardware_i2c)
|
|
@ -0,0 +1,85 @@
|
|||
#include "vl53l5cx.hpp"
|
||||
|
||||
namespace pimoroni {
|
||||
bool VL53L5CX::init() {
|
||||
if(!is_alive()) {
|
||||
return false;
|
||||
}
|
||||
uint8_t status = vl53l5cx_init(configuration);
|
||||
return status == VL53L5CX_STATUS_OK;
|
||||
}
|
||||
bool VL53L5CX::is_alive() {
|
||||
uint8_t is_alive = 0;
|
||||
uint8_t status = vl53l5cx_is_alive(configuration, &is_alive);
|
||||
return is_alive == 1 && status == VL53L5CX_STATUS_OK;
|
||||
}
|
||||
bool VL53L5CX::start_ranging() {
|
||||
uint8_t status = vl53l5cx_start_ranging(configuration);
|
||||
return status == VL53L5CX_STATUS_OK;
|
||||
}
|
||||
bool VL53L5CX::stop_ranging() {
|
||||
uint8_t status = vl53l5cx_stop_ranging(configuration);
|
||||
return status == VL53L5CX_STATUS_OK;
|
||||
}
|
||||
bool VL53L5CX::enable_motion_indicator(Resolution resolution) {
|
||||
uint8_t status = vl53l5cx_motion_indicator_init(configuration, motion_configuration, resolution);
|
||||
return status == VL53L5CX_STATUS_OK;
|
||||
}
|
||||
bool VL53L5CX::set_motion_distance(uint16_t distance_min, uint16_t distance_max) {
|
||||
uint8_t status = vl53l5cx_motion_indicator_set_distance_motion(configuration, motion_configuration, distance_min, distance_max);
|
||||
return status == VL53L5CX_STATUS_OK;
|
||||
}
|
||||
bool VL53L5CX::set_i2c_address(uint8_t i2c_address) {
|
||||
/* Must be a 7-bit i2c address */
|
||||
uint8_t status = vl53l5cx_set_i2c_address(configuration, i2c_address);
|
||||
return status == VL53L5CX_STATUS_OK;
|
||||
}
|
||||
bool VL53L5CX::set_ranging_mode(RangingMode ranging_mode) {
|
||||
uint8_t status = vl53l5cx_set_ranging_mode(configuration, (uint8_t)ranging_mode);
|
||||
return status == VL53L5CX_STATUS_OK;
|
||||
}
|
||||
bool VL53L5CX::set_ranging_frequency_hz(uint8_t ranging_frequency_hz) {
|
||||
uint8_t status = vl53l5cx_set_ranging_frequency_hz(configuration, ranging_frequency_hz);
|
||||
return status == VL53L5CX_STATUS_OK;
|
||||
}
|
||||
bool VL53L5CX::set_resolution(Resolution resolution) {
|
||||
/* One of VL53L5CX_RESOLUTION_4X4 or VL53L5CX_RESOLUTION_8X8 */
|
||||
uint8_t status = vl53l5cx_set_resolution(configuration, (uint8_t)resolution);
|
||||
if(status == VL53L5CX_STATUS_OK) {
|
||||
this->resolution = resolution;
|
||||
}
|
||||
return status == VL53L5CX_STATUS_OK;
|
||||
}
|
||||
VL53L5CX::Resolution VL53L5CX::get_resolution() {
|
||||
//Resolution resolution = RESOLUTION_4X4;
|
||||
//vl53l5cx_get_resolution(configuration, (uint8_t *)&resolution);
|
||||
return this->resolution;
|
||||
}
|
||||
bool VL53L5CX::set_integration_time_ms(uint32_t integration_time_ms) {
|
||||
/* Integration time between 2ms and 1000ms */
|
||||
uint8_t status = vl53l5cx_set_integration_time_ms(configuration, integration_time_ms);
|
||||
return status == VL53L5CX_STATUS_OK;
|
||||
}
|
||||
bool VL53L5CX::set_sharpener_percent(uint8_t sharpener_percent) {
|
||||
/* Sharpener intensity from 0 to 99 */
|
||||
uint8_t status = vl53l5cx_set_sharpener_percent(configuration, sharpener_percent);
|
||||
return status == VL53L5CX_STATUS_OK;
|
||||
}
|
||||
bool VL53L5CX::set_target_order(TargetOrder target_order) {
|
||||
uint8_t status = vl53l5cx_set_target_order(configuration, (uint8_t)target_order);
|
||||
return status == VL53L5CX_STATUS_OK;
|
||||
}
|
||||
bool VL53L5CX::set_power_mode(PowerMode power_mode) {
|
||||
uint8_t status = vl53l5cx_set_power_mode(configuration, (uint8_t)power_mode);
|
||||
return status == VL53L5CX_STATUS_OK;
|
||||
}
|
||||
bool VL53L5CX::data_ready() {
|
||||
uint8_t is_ready;
|
||||
uint8_t status = vl53l5cx_check_data_ready(configuration, &is_ready);
|
||||
return status == VL53L5CX_STATUS_OK && is_ready;
|
||||
}
|
||||
bool VL53L5CX::get_data(ResultsData *results) {
|
||||
uint8_t status = vl53l5cx_get_ranging_data(configuration, results);
|
||||
return status == VL53L5CX_STATUS_OK;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
#pragma once
|
||||
|
||||
extern "C" {
|
||||
#include "drivers/vl53l5cx/src/VL53L5CX_ULD_API/inc/vl53l5cx_api.h"
|
||||
#include "drivers/vl53l5cx/src/VL53L5CX_ULD_API/inc/vl53l5cx_plugin_motion_indicator.h"
|
||||
}
|
||||
|
||||
#include "common/pimoroni_i2c.hpp"
|
||||
#include "src/VL53L5CX_ULD_API/inc/vl53l5cx_api.h"
|
||||
#include "src/VL53L5CX_ULD_API/inc/vl53l5cx_plugin_motion_indicator.h"
|
||||
|
||||
namespace pimoroni {
|
||||
class VL53L5CX {
|
||||
public:
|
||||
typedef VL53L5CX_ResultsData ResultsData;
|
||||
enum TargetOrder : uint8_t {
|
||||
TARGET_ORDER_CLOSEST = VL53L5CX_TARGET_ORDER_CLOSEST,
|
||||
TARGET_ORDER_STRONGEST = VL53L5CX_TARGET_ORDER_STRONGEST
|
||||
};
|
||||
enum Resolution : uint8_t {
|
||||
RESOLUTION_4X4 = VL53L5CX_RESOLUTION_4X4,
|
||||
RESOLUTION_8X8 = VL53L5CX_RESOLUTION_8X8
|
||||
};
|
||||
enum RangingMode : uint8_t {
|
||||
RANGING_MODE_CONTINUOUS = VL53L5CX_RANGING_MODE_CONTINUOUS,
|
||||
RANGING_MODE_AUTONOMOUS = VL53L5CX_RANGING_MODE_AUTONOMOUS
|
||||
};
|
||||
enum PowerMode : uint8_t {
|
||||
POWER_MODE_SLEEP = VL53L5CX_POWER_MODE_SLEEP,
|
||||
POWER_MODE_WAKEUP = VL53L5CX_POWER_MODE_WAKEUP
|
||||
};
|
||||
|
||||
// 7-bit version of the default address (0x52)
|
||||
static const uint8_t DEFAULT_ADDRESS = VL53L5CX_DEFAULT_I2C_ADDRESS >> 1;
|
||||
|
||||
VL53L5CX(I2C *i2c, uint8_t i2c_addr=DEFAULT_ADDRESS) {
|
||||
configuration = new VL53L5CX_Configuration{
|
||||
.platform = VL53L5CX_Platform{
|
||||
.address = i2c_addr,
|
||||
.i2c = i2c->get_i2c()
|
||||
},
|
||||
};
|
||||
motion_configuration = new VL53L5CX_Motion_Configuration{};
|
||||
}
|
||||
~VL53L5CX() {
|
||||
delete configuration;
|
||||
delete motion_configuration;
|
||||
}
|
||||
bool init();
|
||||
bool is_alive();
|
||||
bool start_ranging();
|
||||
bool stop_ranging();
|
||||
|
||||
bool enable_motion_indicator(Resolution resolution);
|
||||
bool set_motion_distance(uint16_t distance_min, uint16_t distance_max);
|
||||
|
||||
bool set_i2c_address(uint8_t i2c_address);
|
||||
bool set_ranging_mode(RangingMode ranging_mode);
|
||||
bool set_ranging_frequency_hz(uint8_t ranging_frequency_hz);
|
||||
|
||||
bool set_resolution(Resolution resolution);
|
||||
Resolution get_resolution();
|
||||
|
||||
bool set_integration_time_ms(uint32_t integration_time_ms);
|
||||
bool set_sharpener_percent(uint8_t sharpener_percent);
|
||||
bool set_target_order(TargetOrder target_order);
|
||||
bool set_power_mode(PowerMode power_mode);
|
||||
bool data_ready();
|
||||
bool get_data(ResultsData *results);
|
||||
|
||||
VL53L5CX_Configuration* get_configuration() {
|
||||
return configuration;
|
||||
}
|
||||
private:
|
||||
VL53L5CX_Configuration *configuration;
|
||||
VL53L5CX_Motion_Configuration *motion_configuration;
|
||||
Resolution resolution = RESOLUTION_8X8;
|
||||
};
|
||||
}
|
|
@ -21,6 +21,7 @@ add_subdirectory(breakout_as7262)
|
|||
add_subdirectory(breakout_bh1745)
|
||||
add_subdirectory(breakout_icp10125)
|
||||
add_subdirectory(breakout_scd41)
|
||||
add_subdirectory(breakout_vl53l5cx)
|
||||
|
||||
add_subdirectory(pico_display)
|
||||
add_subdirectory(pico_display_2)
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
set(OUTPUT_NAME vl53l5cx_demo)
|
||||
|
||||
add_executable(
|
||||
${OUTPUT_NAME}
|
||||
vl53l5cx_demo.cpp
|
||||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(${OUTPUT_NAME} pico_stdlib hardware_i2c vl53l5cx pimoroni_i2c)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(${OUTPUT_NAME})
|
|
@ -0,0 +1,35 @@
|
|||
#include <stdio.h>
|
||||
#include "pico/stdlib.h"
|
||||
#include "hardware/i2c.h"
|
||||
#include "drivers/vl53l5cx/vl53l5cx.hpp"
|
||||
|
||||
#include "common/pimoroni_i2c.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
I2C i2c(4, 5);
|
||||
VL53L5CX vl53l5cx(&i2c);
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
|
||||
bool result = vl53l5cx.init();
|
||||
if(!result) {
|
||||
printf("Error initializing...\n");
|
||||
}
|
||||
vl53l5cx.set_ranging_mode(VL53L5CX::RANGING_MODE_AUTONOMOUS);
|
||||
vl53l5cx.set_resolution(VL53L5CX::RESOLUTION_4X4);
|
||||
vl53l5cx.start_ranging();
|
||||
|
||||
while(true) {
|
||||
if(vl53l5cx.data_ready()) {
|
||||
VL53L5CX::ResultsData result;
|
||||
if(vl53l5cx.get_data(&result)) {
|
||||
printf("Distance: %dmm\n", result.distance_mm[0]);
|
||||
}
|
||||
}
|
||||
sleep_ms(20);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -14,6 +14,7 @@
|
|||
- [Image](#image)
|
||||
- [QR gen](#qr-gen)
|
||||
- [Launcher](#launcher)
|
||||
- [Conway](#conway)
|
||||
|
||||
|
||||
## Function Examples
|
||||
|
@ -56,10 +57,12 @@ python3 convert.py --binary --resize image_file_1.png image_file_2.png image_fil
|
|||
|
||||
A checklist application, letting you navigate through items and tick each of them off.
|
||||
|
||||
* `checklist.txt` - A text file containing the titles of items for the list.
|
||||
|
||||
### Clock
|
||||
[clock.py](clock.py)
|
||||
|
||||
A simple clock showing the time and date, that uses the E Ink's fast speed to update every second
|
||||
A simple clock showing the time and date, that uses the E Ink's fast speed to update every second.
|
||||
|
||||
### E-Book
|
||||
[ebook.py](ebook.py)
|
||||
|
@ -83,10 +86,17 @@ python3 convert.py --binary --resize image_file_1.png image_file_2.png image_fil
|
|||
### QR gen
|
||||
[qrgen.py](qrgen.py)
|
||||
|
||||
This application looks for a file on your MicroPython drive:
|
||||
- `qrcode.txt` - A text file containing 9 lines. The first line should be a URL which will be converted into and displayed as a QR code. Up to 8 more lines of information can be added, which will be shown as plain text to the right of the QR code.
|
||||
Displays and lets you cycle through multiple QR codes, with configuration stored in text files within the MicroPython device's `/qrcodes` directory.
|
||||
|
||||
- `/qrcodes/qrcode.txt` - A text file containing 9 lines. The first line should be a URL which will be converted into and displayed as a QR code. Up to 8 more lines of information can be added, which will be shown as plain text to the right of the QR code.
|
||||
- `/qrcodes/*.txt` - additional text files can be created using the same format. All text files can be cycled through.
|
||||
|
||||
### Launcher
|
||||
[launcher.py](launcher.py)
|
||||
|
||||
A launcher-style application, that provide a menu of other applications that can be loaded, as well as information such as battery level.
|
||||
A launcher-style application, providing a menu of other applications that can be loaded, as well as information such as battery level.
|
||||
|
||||
### Conway
|
||||
[conway.py](conway.py)
|
||||
|
||||
Conway's classic Game of Life, implemented on the Badger. Note: this application is *not* linked from the Launcher by default - it can be run directly using Thonny or your MicroPython editor of choice, or you can modify the Launcher to add it (you'll want to update `launchericons.png` as well)
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
from breakout_roundlcd import BreakoutRoundLCD
|
||||
|
||||
|
||||
width = BreakoutRoundLCD.WIDTH
|
||||
height = BreakoutRoundLCD.HEIGHT
|
||||
|
||||
display_buffer = bytearray(width * height * 2) # 2-bytes per pixel (RGB565)
|
||||
display = BreakoutRoundLCD(display_buffer)
|
||||
|
||||
display.set_backlight(1)
|
||||
|
||||
while True:
|
||||
display.set_pen(0, 0, 0)
|
||||
display.clear()
|
||||
|
||||
# circle
|
||||
display.set_pen(255, 0, 0)
|
||||
display.circle(
|
||||
width // 5, # center point x
|
||||
height // 3, # center point y
|
||||
16, # radius
|
||||
)
|
||||
|
||||
# rectangle
|
||||
display.set_pen(255, 255, 0)
|
||||
display.rectangle(
|
||||
int((width * 2 / 5) - 16), # starting point x
|
||||
int(height // 3) - 8, # starting point y
|
||||
32, # width
|
||||
16, # height
|
||||
)
|
||||
|
||||
# triangle
|
||||
display.set_pen(0, 255, 0)
|
||||
display.triangle(
|
||||
int(width * 3 / 5), int(height // 3) - 16, # point 1 x, y
|
||||
int(width * 3 / 5) - 16, int(height // 3) + 16, # point 2 x, y
|
||||
int(width * 3 / 5) + 16, int(height // 3) + 16, # point 3 x, y
|
||||
)
|
||||
|
||||
# character
|
||||
display.set_pen(0, 255, 255)
|
||||
display.character(
|
||||
64, # int character code
|
||||
int(width * 4 / 5 - 16), # box starting point x
|
||||
int(height // 3) - 16, # box starting point y
|
||||
4, # scale - not required, default is 2
|
||||
)
|
||||
|
||||
# pixel span
|
||||
display.set_pen(255, 255, 255)
|
||||
display.pixel_span(
|
||||
int(width * 1 / 5), # starting point x
|
||||
int(height * 2.5 / 5), # starting point y
|
||||
130, # length
|
||||
)
|
||||
|
||||
# text
|
||||
display.set_pen(0, 0, 255)
|
||||
display.text(
|
||||
'test text', # text
|
||||
int(width // 5), # box starting point x
|
||||
int(height * 3 / 5), # box starting point y
|
||||
True, # word wrap
|
||||
6, # scale - not required, default is 2
|
||||
)
|
||||
|
||||
# lines
|
||||
display.set_pen(255, 0, 255)
|
||||
display.line(
|
||||
0, # staring point x
|
||||
int(height / 2), # staring point y
|
||||
width, # end point x
|
||||
height, # end point y
|
||||
)
|
||||
display.line(
|
||||
width, # staring point x
|
||||
int(height / 2), # staring point y
|
||||
0, # end point x
|
||||
height, # end point y
|
||||
)
|
||||
|
||||
# set clip
|
||||
display.set_clip(
|
||||
int(width * 2 / 5),
|
||||
int(height * 2 / 5),
|
||||
int(width * 1 / 5),
|
||||
int(height * 1 / 5)
|
||||
)
|
||||
|
||||
# draw a clipped circle
|
||||
display.circle(
|
||||
int(width * 2 / 5),
|
||||
int(height * 2 / 5),
|
||||
32,
|
||||
)
|
||||
|
||||
# remove clip
|
||||
display.remove_clip()
|
||||
|
||||
display.update()
|
|
@ -0,0 +1,32 @@
|
|||
import pimoroni_i2c
|
||||
import breakout_vl53l5cx
|
||||
import time
|
||||
|
||||
PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5}
|
||||
PINS_PICO_EXPLORER = {"sda": 20, "scl": 21}
|
||||
|
||||
# Sensor startup time is proportional to i2c baudrate
|
||||
# HOWEVER many sensors may not run at > 400KHz (400000)
|
||||
i2c = pimoroni_i2c.PimoroniI2C(**PINS_BREAKOUT_GARDEN, baudrate=2_000_000)
|
||||
|
||||
print("Starting up sensor...")
|
||||
t_sta = time.ticks_ms()
|
||||
sensor = breakout_vl53l5cx.VL53L5CX(i2c)
|
||||
t_end = time.ticks_ms()
|
||||
print("Done in {}ms...".format(t_end - t_sta))
|
||||
|
||||
# Make sure to set resolution and other settings *before* you start ranging
|
||||
sensor.set_resolution(breakout_vl53l5cx.RESOLUTION_4X4)
|
||||
sensor.start_ranging()
|
||||
|
||||
while True:
|
||||
if sensor.data_ready():
|
||||
# "data" is a namedtuple (attrtuple technically)
|
||||
# it includes average readings as "distance_avg" and "reflectance_avg"
|
||||
# plus a full 4x4 or 8x8 set of readings (as a 1d tuple) for both values.
|
||||
data = sensor.get_data()
|
||||
print("{}mm {}% (avg: {}mm {}%)".format(
|
||||
data.distance[0],
|
||||
data.reflectance[0],
|
||||
data.distance_avg,
|
||||
data.reflectance_avg))
|
|
@ -0,0 +1,35 @@
|
|||
import pimoroni_i2c
|
||||
import breakout_vl53l5cx
|
||||
import time
|
||||
from ulab import numpy
|
||||
|
||||
PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5}
|
||||
PINS_PICO_EXPLORER = {"sda": 20, "scl": 21}
|
||||
|
||||
# Sensor startup time is proportional to i2c baudrate
|
||||
# HOWEVER many sensors may not run at > 400KHz (400000)
|
||||
i2c = pimoroni_i2c.PimoroniI2C(**PINS_BREAKOUT_GARDEN, baudrate=2_000_000)
|
||||
|
||||
print("Starting up sensor...")
|
||||
t_sta = time.ticks_ms()
|
||||
sensor = breakout_vl53l5cx.VL53L5CX(i2c)
|
||||
t_end = time.ticks_ms()
|
||||
print("Done in {}ms...".format(t_end - t_sta))
|
||||
|
||||
# Make sure to set resolution and other settings *before* you start ranging
|
||||
sensor.set_resolution(breakout_vl53l5cx.RESOLUTION_4X4)
|
||||
|
||||
sensor.enable_motion_indicator(breakout_vl53l5cx.RESOLUTION_4X4)
|
||||
sensor.set_motion_distance(400, 1400)
|
||||
|
||||
sensor.start_ranging()
|
||||
|
||||
while True:
|
||||
if sensor.data_ready():
|
||||
# "data" is a namedtuple (attrtuple technically)
|
||||
# it includes average readings as "distance_avg" and "reflectance_avg"
|
||||
# plus a full 4x4 or 8x8 set of readings (as a 1d tuple) for both values.
|
||||
# Motion data is available in "motion_detection.motion"
|
||||
data = sensor.get_data()
|
||||
motion = numpy.array(data.motion_indicator.motion[0:16], dtype=numpy.int16).reshape((4, 4))
|
||||
print(motion)
|
|
@ -0,0 +1,98 @@
|
|||
import pimoroni_i2c
|
||||
import breakout_vl53l5cx
|
||||
import time
|
||||
from ulab import numpy
|
||||
|
||||
# This example attempts to track a "bright" object (such as a white business card)
|
||||
# It uses reflectance to identify the target and compute the X/Y coordinates
|
||||
# of its "center of mass" in the sensors view.
|
||||
|
||||
# Motion indication only works at distances > 400mm so it's not
|
||||
# really useful as a method to reject data.
|
||||
|
||||
# Configure your distance and brightness thresholds to suit your object
|
||||
DISTANCE_THRESHOLD = 400 # Distance in mm
|
||||
REFLECTANCE_THRESHOLD = 60 # Estimated reflectance in %
|
||||
|
||||
|
||||
PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5}
|
||||
PINS_PICO_EXPLORER = {"sda": 20, "scl": 21}
|
||||
|
||||
# Sensor startup time is proportional to i2c baudrate
|
||||
# HOWEVER many sensors may not run at > 400KHz (400000)
|
||||
i2c = pimoroni_i2c.PimoroniI2C(**PINS_BREAKOUT_GARDEN, baudrate=2_000_000)
|
||||
|
||||
print("Starting up sensor...")
|
||||
t_sta = time.ticks_ms()
|
||||
sensor = breakout_vl53l5cx.VL53L5CX(i2c)
|
||||
t_end = time.ticks_ms()
|
||||
print("Done in {}ms...".format(t_end - t_sta))
|
||||
|
||||
# Make sure to set resolution and other settings *before* you start ranging
|
||||
sensor.set_resolution(breakout_vl53l5cx.RESOLUTION_8X8)
|
||||
sensor.set_ranging_frequency_hz(15)
|
||||
sensor.start_ranging()
|
||||
|
||||
|
||||
while True:
|
||||
time.sleep(1.0 / 60)
|
||||
if sensor.data_ready():
|
||||
# "data" is a namedtuple (attrtuple technically)
|
||||
# it includes average readings as "distance_avg" and "reflectance_avg"
|
||||
# plus a full 4x4 or 8x8 set of readings (as a 1d tuple) for both values.
|
||||
data = sensor.get_data()
|
||||
|
||||
reflectance = numpy.array(data.reflectance).reshape((8, 8))
|
||||
distance = numpy.array(data.distance).reshape((8, 8))
|
||||
|
||||
scalar = 0
|
||||
target_distance = 0
|
||||
n_distances = 0
|
||||
# Filter out unwanted reflectance values
|
||||
for ox in range(8):
|
||||
for oy in range(8):
|
||||
d = distance[ox][oy]
|
||||
r = reflectance[ox][oy]
|
||||
if d > DISTANCE_THRESHOLD or r < REFLECTANCE_THRESHOLD:
|
||||
reflectance[ox][oy] = 0
|
||||
else:
|
||||
scalar += r
|
||||
|
||||
# Get a total from all the distances within our accepted target
|
||||
for ox in range(8):
|
||||
for oy in range(8):
|
||||
d = distance[ox][oy]
|
||||
r = reflectance[ox][oy]
|
||||
if r > 0:
|
||||
target_distance += d
|
||||
n_distances += 1
|
||||
|
||||
# Average the target distance
|
||||
if n_distances > 0:
|
||||
target_distance /= n_distances
|
||||
else:
|
||||
target_distance = 0
|
||||
|
||||
# Flip reflectance now we've applied distance
|
||||
# both fields are upside-down!
|
||||
reflectance = numpy.flip(reflectance, axis=0)
|
||||
|
||||
# Calculate the center of mass along X and Y
|
||||
x = 0
|
||||
y = 0
|
||||
if scalar > 0:
|
||||
for ox in range(8):
|
||||
for oy in range(8):
|
||||
y += reflectance[ox][oy] * ox
|
||||
y /= scalar
|
||||
y /= 3.5
|
||||
y -= 1.0
|
||||
|
||||
for oy in range(8):
|
||||
for ox in range(8):
|
||||
x += reflectance[ox][oy] * oy
|
||||
x /= scalar
|
||||
x /= 3.5
|
||||
x -= 1.0
|
||||
|
||||
print(round(x, 2), round(y, 2), round(target_distance, 2))
|
|
@ -179,7 +179,7 @@ MICROPY_EVENT_POLL_HOOK
|
|||
}
|
||||
|
||||
absolute_time_t t_end = make_timeout_time_ms(self->badger2040->update_time());
|
||||
self->badger2040->partial_update(x, y, w, h);
|
||||
self->badger2040->partial_update(x, y, w, h, false);
|
||||
|
||||
// Ensure blocking for the minimum amount of time
|
||||
// in cases where "is_busy" is unreliable.
|
||||
|
|
|
@ -493,10 +493,10 @@ mp_obj_t BreakoutColourLCD160x80_triangle(size_t n_args, const mp_obj_t *pos_arg
|
|||
|
||||
int x1 = args[ARG_x1].u_int;
|
||||
int y1 = args[ARG_y1].u_int;
|
||||
int x2 = args[ARG_x1].u_int;
|
||||
int y2 = args[ARG_y1].u_int;
|
||||
int x3 = args[ARG_x1].u_int;
|
||||
int y3 = args[ARG_y1].u_int;
|
||||
int x2 = args[ARG_x2].u_int;
|
||||
int y2 = args[ARG_y2].u_int;
|
||||
int x3 = args[ARG_x3].u_int;
|
||||
int y3 = args[ARG_y3].u_int;
|
||||
|
||||
Point p1(x1, y1);
|
||||
Point p2(x2, y2);
|
||||
|
@ -523,8 +523,8 @@ mp_obj_t BreakoutColourLCD160x80_line(size_t n_args, const mp_obj_t *pos_args, m
|
|||
|
||||
int x1 = args[ARG_x1].u_int;
|
||||
int y1 = args[ARG_y1].u_int;
|
||||
int x2 = args[ARG_x1].u_int;
|
||||
int y2 = args[ARG_y1].u_int;
|
||||
int x2 = args[ARG_x2].u_int;
|
||||
int y2 = args[ARG_y2].u_int;
|
||||
|
||||
Point p1(x1, y1);
|
||||
Point p2(x2, y2);
|
||||
|
|
|
@ -493,10 +493,10 @@ mp_obj_t BreakoutColourLCD240x240_triangle(size_t n_args, const mp_obj_t *pos_ar
|
|||
|
||||
int x1 = args[ARG_x1].u_int;
|
||||
int y1 = args[ARG_y1].u_int;
|
||||
int x2 = args[ARG_x1].u_int;
|
||||
int y2 = args[ARG_y1].u_int;
|
||||
int x3 = args[ARG_x1].u_int;
|
||||
int y3 = args[ARG_y1].u_int;
|
||||
int x2 = args[ARG_x2].u_int;
|
||||
int y2 = args[ARG_y2].u_int;
|
||||
int x3 = args[ARG_x3].u_int;
|
||||
int y3 = args[ARG_y3].u_int;
|
||||
|
||||
Point p1(x1, y1);
|
||||
Point p2(x2, y2);
|
||||
|
@ -523,8 +523,8 @@ mp_obj_t BreakoutColourLCD240x240_line(size_t n_args, const mp_obj_t *pos_args,
|
|||
|
||||
int x1 = args[ARG_x1].u_int;
|
||||
int y1 = args[ARG_y1].u_int;
|
||||
int x2 = args[ARG_x1].u_int;
|
||||
int y2 = args[ARG_y1].u_int;
|
||||
int x2 = args[ARG_x2].u_int;
|
||||
int y2 = args[ARG_y2].u_int;
|
||||
|
||||
Point p1(x1, y1);
|
||||
Point p2(x2, y2);
|
||||
|
|
|
@ -474,10 +474,10 @@ mp_obj_t BreakoutRoundLCD_triangle(size_t n_args, const mp_obj_t *pos_args, mp_m
|
|||
|
||||
int x1 = args[ARG_x1].u_int;
|
||||
int y1 = args[ARG_y1].u_int;
|
||||
int x2 = args[ARG_x1].u_int;
|
||||
int y2 = args[ARG_y1].u_int;
|
||||
int x3 = args[ARG_x1].u_int;
|
||||
int y3 = args[ARG_y1].u_int;
|
||||
int x2 = args[ARG_x2].u_int;
|
||||
int y2 = args[ARG_y2].u_int;
|
||||
int x3 = args[ARG_x3].u_int;
|
||||
int y3 = args[ARG_y3].u_int;
|
||||
|
||||
Point p1(x1, y1);
|
||||
Point p2(x2, y2);
|
||||
|
@ -504,8 +504,8 @@ mp_obj_t BreakoutRoundLCD_line(size_t n_args, const mp_obj_t *pos_args, mp_map_t
|
|||
|
||||
int x1 = args[ARG_x1].u_int;
|
||||
int y1 = args[ARG_y1].u_int;
|
||||
int x2 = args[ARG_x1].u_int;
|
||||
int y2 = args[ARG_y1].u_int;
|
||||
int x2 = args[ARG_x2].u_int;
|
||||
int y2 = args[ARG_y2].u_int;
|
||||
|
||||
Point p1(x1, y1);
|
||||
Point p2(x2, y2);
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
add_library(usermod_vl53l5cx INTERFACE)
|
||||
|
||||
target_sources(usermod_vl53l5cx INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/vl53l5cx.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/vl53l5cx.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../../drivers/vl53l5cx/vl53l5cx.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../../drivers/vl53l5cx/platform.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../../drivers/vl53l5cx/src/VL53L5CX_ULD_API/src/vl53l5cx_api.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../../drivers/vl53l5cx/src/VL53L5CX_ULD_API/src/vl53l5cx_plugin_motion_indicator.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../../drivers/vl53l5cx/src/VL53L5CX_ULD_API/src/vl53l5cx_plugin_detection_thresholds.c
|
||||
)
|
||||
|
||||
target_include_directories(usermod_vl53l5cx INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../../drivers/vl53l5cx/
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../../drivers/vl53l5cx/src/VL53L5CX_ULD_API/inc
|
||||
)
|
||||
|
||||
target_compile_definitions(usermod_vl53l5cx INTERFACE
|
||||
MODULE_VL53L5CX_ENABLED=1
|
||||
)
|
||||
|
||||
target_link_libraries(usermod INTERFACE usermod_vl53l5cx)
|
||||
|
||||
set_source_files_properties(
|
||||
${CMAKE_CURRENT_LIST_DIR}/vl53l5cx.c
|
||||
PROPERTIES COMPILE_FLAGS
|
||||
"-Wno-discarded-qualifiers -Wno-implicit-int"
|
||||
)
|
|
@ -0,0 +1,84 @@
|
|||
#include "vl53l5cx.h"
|
||||
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(VL53L5CX___del___obj, VL53L5CX___del__);
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(VL53L5CX_start_ranging_obj, VL53L5CX_start_ranging);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(VL53L5CX_stop_ranging_obj, VL53L5CX_stop_ranging);
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(VL53L5CX_enable_motion_indicator_obj, VL53L5CX_enable_motion_indicator);
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(VL53L5CX_set_motion_distance_obj, VL53L5CX_set_motion_distance);
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(VL53L5CX_set_i2c_address_obj, VL53L5CX_set_i2c_address);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(VL53L5CX_set_ranging_mode_obj, VL53L5CX_set_ranging_mode);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(VL53L5CX_set_ranging_frequency_hz_obj, VL53L5CX_set_ranging_frequency_hz);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(VL53L5CX_set_resolution_obj, VL53L5CX_set_resolution);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(VL53L5CX_set_integration_time_ms_obj, VL53L5CX_set_integration_time_ms);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(VL53L5CX_set_sharpener_percent_obj, VL53L5CX_set_sharpener_percent);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(VL53L5CX_set_target_order_obj, VL53L5CX_set_target_order);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(VL53L5CX_set_power_mode_obj, VL53L5CX_set_power_mode);
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(VL53L5CX_data_ready_obj, VL53L5CX_data_ready);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(VL53L5CX_get_data_obj, VL53L5CX_get_data);
|
||||
|
||||
|
||||
/***** Binding of Methods *****/
|
||||
STATIC const mp_rom_map_elem_t VL53L5CX_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&VL53L5CX___del___obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_start_ranging), MP_ROM_PTR(&VL53L5CX_start_ranging_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_stop_ranging), MP_ROM_PTR(&VL53L5CX_stop_ranging_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_enable_motion_indicator), MP_ROM_PTR(&VL53L5CX_enable_motion_indicator_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_motion_distance), MP_ROM_PTR(&VL53L5CX_set_motion_distance_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_i2c_address), MP_ROM_PTR(&VL53L5CX_set_i2c_address_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_ranging_mode), MP_ROM_PTR(&VL53L5CX_set_ranging_mode_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_ranging_frequency_hz), MP_ROM_PTR(&VL53L5CX_set_ranging_frequency_hz_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_resolution), MP_ROM_PTR(&VL53L5CX_set_resolution_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_integration_time_ms), MP_ROM_PTR(&VL53L5CX_set_integration_time_ms_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_sharpener_percent), MP_ROM_PTR(&VL53L5CX_set_sharpener_percent_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_target_order), MP_ROM_PTR(&VL53L5CX_set_target_order_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_power_mode), MP_ROM_PTR(&VL53L5CX_set_power_mode_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_data_ready), MP_ROM_PTR(&VL53L5CX_data_ready_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get_data), MP_ROM_PTR(&VL53L5CX_get_data_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(VL53L5CX_locals_dict, VL53L5CX_locals_dict_table);
|
||||
|
||||
/***** Class Definition *****/
|
||||
const mp_obj_type_t VL53L5CX_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_breakout_vl53l5cx,
|
||||
.print = VL53L5CX_print,
|
||||
.make_new = VL53L5CX_make_new,
|
||||
.locals_dict = (mp_obj_dict_t*)&VL53L5CX_locals_dict,
|
||||
};
|
||||
|
||||
/***** Module Globals *****/
|
||||
STATIC const mp_map_elem_t vl53l5cx_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_breakout_vl53l5cx) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_VL53L5CX), (mp_obj_t)&VL53L5CX_type },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_TARGET_ORDER_CLOSEST), MP_ROM_INT(VL53L5CX_TARGET_ORDER_CLOSEST) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_TARGET_ORDER_STRONGEST), MP_ROM_INT(VL53L5CX_TARGET_ORDER_STRONGEST) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_RESOLUTION_4X4), MP_ROM_INT(VL53L5CX_RESOLUTION_4X4) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_RESOLUTION_8X8), MP_ROM_INT(VL53L5CX_RESOLUTION_8X8) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_RANGING_MODE_CONTINUOUS), MP_ROM_INT(VL53L5CX_RANGING_MODE_CONTINUOUS) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_RANGING_MODE_AUTONOMOUS), MP_ROM_INT(VL53L5CX_RANGING_MODE_AUTONOMOUS) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_POWER_MODE_SLEEP), MP_ROM_INT(VL53L5CX_POWER_MODE_SLEEP) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_POWER_MODE_WAKEUP), MP_ROM_INT(VL53L5CX_POWER_MODE_WAKEUP) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_vl53l5cx_globals, vl53l5cx_globals_table);
|
||||
|
||||
/***** Module Definition *****/
|
||||
const mp_obj_module_t vl53l5cx_user_cmodule = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&mp_module_vl53l5cx_globals,
|
||||
};
|
||||
|
||||
/***** Module Registration: as "breakout_vl53l5cx" *****/
|
||||
MP_REGISTER_MODULE(MP_QSTR_breakout_vl53l5cx, vl53l5cx_user_cmodule, MODULE_VL53L5CX_ENABLED);
|
|
@ -0,0 +1,269 @@
|
|||
#include <cstdio>
|
||||
#include "vl53l5cx.hpp"
|
||||
#include "pico/multicore.h"
|
||||
|
||||
#define MP_OBJ_TO_PTR2(o, t) ((t *)(uintptr_t)(o))
|
||||
|
||||
|
||||
extern "C" {
|
||||
#include "vl53l5cx.h"
|
||||
#include "pimoroni_i2c.h"
|
||||
|
||||
typedef struct _mp_obj_float_t {
|
||||
mp_obj_base_t base;
|
||||
mp_float_t value;
|
||||
} mp_obj_float_t;
|
||||
|
||||
const mp_obj_float_t const_float_1 = {{&mp_type_float}, 1.0f};
|
||||
|
||||
/***** I2C Struct *****/
|
||||
typedef struct _PimoroniI2C_obj_t {
|
||||
mp_obj_base_t base;
|
||||
pimoroni::I2C *i2c;
|
||||
} _PimoroniI2C_obj_t;
|
||||
|
||||
|
||||
/***** Variables Struct *****/
|
||||
typedef struct _VL53L5CX_obj_t {
|
||||
mp_obj_base_t base;
|
||||
_PimoroniI2C_obj_t *i2c;
|
||||
pimoroni::VL53L5CX* breakout;
|
||||
} _VL53L5CX_obj_t;
|
||||
|
||||
|
||||
/***** Print *****/
|
||||
void VL53L5CX_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
(void)kind; // Unused input parameter
|
||||
_VL53L5CX_obj_t *self = MP_OBJ_TO_PTR2(self_in, _VL53L5CX_obj_t);
|
||||
mp_print_str(print, "VL53L5CX( ");
|
||||
|
||||
|
||||
mp_print_str(print, "i2c = ");
|
||||
mp_obj_print_helper(print, mp_obj_new_int((self->breakout->get_configuration()->platform.i2c == i2c0) ? 0 : 1), PRINT_REPR);
|
||||
|
||||
mp_print_str(print, " addr = ");
|
||||
mp_obj_print_helper(print, mp_obj_new_int(self->breakout->get_configuration()->platform.address), PRINT_REPR);
|
||||
|
||||
mp_print_str(print, " )");
|
||||
}
|
||||
|
||||
/***** Destructor ******/
|
||||
mp_obj_t VL53L5CX___del__(mp_obj_t self_in) {
|
||||
_VL53L5CX_obj_t *self = MP_OBJ_TO_PTR2(self_in, _VL53L5CX_obj_t);
|
||||
//self->breakout->stop_ranging(); // i2c object might have been deleted already?
|
||||
delete self->breakout;
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
/***** Constructor *****/
|
||||
mp_obj_t VL53L5CX_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
_VL53L5CX_obj_t *self = nullptr;
|
||||
|
||||
enum {
|
||||
ARG_i2c,
|
||||
ARG_addr
|
||||
};
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_i2c, MP_ARG_OBJ, {.u_obj = nullptr} },
|
||||
{ MP_QSTR_addr, MP_ARG_INT, {.u_int = pimoroni::VL53L5CX::DEFAULT_ADDRESS} }
|
||||
};
|
||||
|
||||
// Parse args.
|
||||
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);
|
||||
|
||||
if(!MP_OBJ_IS_TYPE(args[ARG_i2c].u_obj, &PimoroniI2C_type)) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("VL53L5CX: Bad i2C object"));
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
_PimoroniI2C_obj_t *i2c = (_PimoroniI2C_obj_t *)MP_OBJ_TO_PTR(args[ARG_i2c].u_obj);
|
||||
int addr = args[ARG_addr].u_int;
|
||||
|
||||
self = m_new_obj_with_finaliser(_VL53L5CX_obj_t);
|
||||
self->base.type = &VL53L5CX_type;
|
||||
self->i2c = i2c;
|
||||
self->breakout = new pimoroni::VL53L5CX(i2c->i2c, addr);
|
||||
|
||||
if(!self->breakout->init()) {
|
||||
mp_raise_msg(&mp_type_RuntimeError, "VL53L5CX: error initialising");
|
||||
}
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
mp_obj_t VL53L5CX_start_ranging(mp_obj_t self_in) {
|
||||
_VL53L5CX_obj_t *self = MP_OBJ_TO_PTR2(self_in, _VL53L5CX_obj_t);
|
||||
bool status = self->breakout->start_ranging();
|
||||
if(!status) {
|
||||
mp_raise_msg(&mp_type_RuntimeError, "VL53L5CX: start_ranging error");
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t VL53L5CX_stop_ranging(mp_obj_t self_in) {
|
||||
_VL53L5CX_obj_t *self = MP_OBJ_TO_PTR2(self_in, _VL53L5CX_obj_t);
|
||||
bool status = self->breakout->stop_ranging();
|
||||
if(!status) {
|
||||
mp_raise_msg(&mp_type_RuntimeError, "VL53L5CX: stop_ranging error");
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t VL53L5CX_enable_motion_indicator(mp_obj_t self_in, mp_obj_t value) {
|
||||
_VL53L5CX_obj_t *self = MP_OBJ_TO_PTR2(self_in, _VL53L5CX_obj_t);
|
||||
bool status = self->breakout->enable_motion_indicator((pimoroni::VL53L5CX::Resolution)mp_obj_get_int(value));
|
||||
if(!status) {
|
||||
mp_raise_msg(&mp_type_RuntimeError, "VL53L5CX: enable_motion_indicator error");
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t VL53L5CX_set_motion_distance(mp_obj_t self_in, mp_obj_t distance_min, mp_obj_t distance_max) {
|
||||
_VL53L5CX_obj_t *self = MP_OBJ_TO_PTR2(self_in, _VL53L5CX_obj_t);
|
||||
bool status = self->breakout->set_motion_distance(mp_obj_get_int(distance_min), mp_obj_get_int(distance_max));
|
||||
if(!status) {
|
||||
mp_raise_msg(&mp_type_RuntimeError, "VL53L5CX: set_motion_distance error");
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t VL53L5CX_set_i2c_address(mp_obj_t self_in, mp_obj_t value) {
|
||||
_VL53L5CX_obj_t *self = MP_OBJ_TO_PTR2(self_in, _VL53L5CX_obj_t);
|
||||
bool status = self->breakout->set_i2c_address(mp_obj_get_int(value));
|
||||
if(!status) {
|
||||
mp_raise_msg(&mp_type_RuntimeError, "VL53L5CX: set_i2c_address error");
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t VL53L5CX_set_ranging_mode(mp_obj_t self_in, mp_obj_t value) {
|
||||
_VL53L5CX_obj_t *self = MP_OBJ_TO_PTR2(self_in, _VL53L5CX_obj_t);
|
||||
bool status = self->breakout->set_ranging_mode((pimoroni::VL53L5CX::RangingMode)mp_obj_get_int(value));
|
||||
if(!status) {
|
||||
mp_raise_msg(&mp_type_RuntimeError, "VL53L5CX: set_ranging_mode error");
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t VL53L5CX_set_ranging_frequency_hz(mp_obj_t self_in, mp_obj_t value) {
|
||||
_VL53L5CX_obj_t *self = MP_OBJ_TO_PTR2(self_in, _VL53L5CX_obj_t);
|
||||
bool status = self->breakout->set_ranging_frequency_hz(mp_obj_get_int(value));
|
||||
if(!status) {
|
||||
mp_raise_msg(&mp_type_RuntimeError, "VL53L5CX: set_ranging_frequency_hz error");
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t VL53L5CX_set_resolution(mp_obj_t self_in, mp_obj_t value) {
|
||||
_VL53L5CX_obj_t *self = MP_OBJ_TO_PTR2(self_in, _VL53L5CX_obj_t);
|
||||
bool status = self->breakout->set_resolution((pimoroni::VL53L5CX::Resolution)mp_obj_get_int(value));
|
||||
if(!status) {
|
||||
mp_raise_msg(&mp_type_RuntimeError, "VL53L5CX: set_resolution error");
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t VL53L5CX_set_integration_time_ms(mp_obj_t self_in, mp_obj_t value) {
|
||||
_VL53L5CX_obj_t *self = MP_OBJ_TO_PTR2(self_in, _VL53L5CX_obj_t);
|
||||
bool status = self->breakout->set_integration_time_ms(mp_obj_get_int(value));
|
||||
if(!status) {
|
||||
mp_raise_msg(&mp_type_RuntimeError, "VL53L5CX: set_integration_time_ms error");
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t VL53L5CX_set_sharpener_percent(mp_obj_t self_in, mp_obj_t value) {
|
||||
_VL53L5CX_obj_t *self = MP_OBJ_TO_PTR2(self_in, _VL53L5CX_obj_t);
|
||||
bool status = self->breakout->set_sharpener_percent(mp_obj_get_int(value));
|
||||
if(!status) {
|
||||
mp_raise_msg(&mp_type_RuntimeError, "VL53L5CX: set_sharpener_percent error");
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t VL53L5CX_set_target_order(mp_obj_t self_in, mp_obj_t value) {
|
||||
_VL53L5CX_obj_t *self = MP_OBJ_TO_PTR2(self_in, _VL53L5CX_obj_t);
|
||||
bool status = self->breakout->set_target_order((pimoroni::VL53L5CX::TargetOrder)mp_obj_get_int(value));
|
||||
if(!status) {
|
||||
mp_raise_msg(&mp_type_RuntimeError, "VL53L5CX: set_target_order error");
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t VL53L5CX_set_power_mode(mp_obj_t self_in, mp_obj_t value) {
|
||||
_VL53L5CX_obj_t *self = MP_OBJ_TO_PTR2(self_in, _VL53L5CX_obj_t);
|
||||
bool status = self->breakout->set_power_mode((pimoroni::VL53L5CX::PowerMode)mp_obj_get_int(value));
|
||||
if(!status) {
|
||||
mp_raise_msg(&mp_type_RuntimeError, "VL53L5CX: set_power_mode error");
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t VL53L5CX_data_ready(mp_obj_t self_in) {
|
||||
_VL53L5CX_obj_t *self = MP_OBJ_TO_PTR2(self_in, _VL53L5CX_obj_t);
|
||||
return self->breakout->data_ready() ? mp_const_true : mp_const_false;
|
||||
}
|
||||
|
||||
mp_obj_t VL53L5CX_get_data(mp_obj_t self_in) {
|
||||
_VL53L5CX_obj_t *self = MP_OBJ_TO_PTR2(self_in, _VL53L5CX_obj_t);
|
||||
pimoroni::VL53L5CX::ResultsData results;
|
||||
bool status = self->breakout->get_data(&results);
|
||||
if(!status) {
|
||||
mp_raise_msg(&mp_type_RuntimeError, "VL53L5CX: get_data error");
|
||||
}
|
||||
|
||||
// Get the current resolution so we only look at valid results.
|
||||
// This is so that our average distance works out and doesn't include bogus data.
|
||||
int scale = (uint8_t)self->breakout->get_resolution();
|
||||
int tuple_size = scale * VL53L5CX_NB_TARGET_PER_ZONE;
|
||||
|
||||
// TODO This doesn't really handle VL53L5CX_NB_TARGET_PER_ZONE > 1 gracefully
|
||||
// the zone data should be split into separate tuples
|
||||
|
||||
mp_obj_t tuple_distance_mm[tuple_size];
|
||||
mp_obj_t tuple_reflectance[tuple_size];
|
||||
|
||||
int32_t average_distance = 0;
|
||||
int32_t average_reflectance = 0;
|
||||
|
||||
// Build a tuple of motion data
|
||||
for(int i = 0u; i < tuple_size; i++) {
|
||||
tuple_distance_mm[i] = mp_obj_new_int(results.distance_mm[i]);
|
||||
tuple_reflectance[i] = mp_obj_new_int(results.reflectance[i]);
|
||||
average_distance += results.distance_mm[i];
|
||||
average_reflectance += results.reflectance[i];
|
||||
}
|
||||
|
||||
average_distance /= tuple_size;
|
||||
average_reflectance /= tuple_size;
|
||||
|
||||
mp_obj_t tuple_motion_data[32];
|
||||
|
||||
for(int i = 0u; i < 32; i++) {
|
||||
tuple_motion_data[i] = mp_obj_new_int(results.motion_indicator.motion[i]);
|
||||
}
|
||||
|
||||
STATIC const qstr tuple_motion_fields[] = {MP_QSTR_global_indicator_1, MP_QSTR_global_indicator_2, MP_QSTR_motion};
|
||||
|
||||
mp_obj_t tuple_motion[] = {
|
||||
mp_obj_new_int(results.motion_indicator.global_indicator_1),
|
||||
mp_obj_new_int(results.motion_indicator.global_indicator_2),
|
||||
mp_obj_new_tuple(sizeof(tuple_motion_data) / sizeof(mp_obj_t), tuple_motion_data)
|
||||
};
|
||||
|
||||
mp_obj_t tuple[] = {
|
||||
mp_obj_new_int(average_distance), // Average distance
|
||||
mp_obj_new_int(average_reflectance), // Average reflectance
|
||||
mp_obj_new_attrtuple(tuple_motion_fields, sizeof(tuple_motion) / sizeof(mp_obj_t), tuple_motion), // Motion data
|
||||
mp_obj_new_int(tuple_size), // Number of results
|
||||
mp_obj_new_tuple(tuple_size, tuple_distance_mm), // Full distance results
|
||||
mp_obj_new_tuple(tuple_size, tuple_reflectance) // Full reflectange results
|
||||
};
|
||||
|
||||
STATIC const qstr tuple_fields[] = {MP_QSTR_distance_avg, MP_QSTR_reflectance_avg, MP_QSTR_motion_indicator, MP_QSTR_results, MP_QSTR_distance, MP_QSTR_reflectance};
|
||||
|
||||
return mp_obj_new_attrtuple(tuple_fields, sizeof(tuple) / sizeof(mp_obj_t), tuple);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
#include "py/runtime.h"
|
||||
#include "drivers/vl53l5cx/src/VL53L5CX_ULD_API/inc/vl53l5cx_api.h"
|
||||
|
||||
extern const mp_obj_type_t VL53L5CX_type;
|
||||
|
||||
extern void VL53L5CX_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
|
||||
|
||||
extern mp_obj_t VL53L5CX___del__(mp_obj_t self_in);
|
||||
extern mp_obj_t VL53L5CX_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 VL53L5CX_start_ranging(mp_obj_t self_in);
|
||||
extern mp_obj_t VL53L5CX_stop_ranging(mp_obj_t self_in);
|
||||
|
||||
extern mp_obj_t VL53L5CX_enable_motion_indicator(mp_obj_t self_in, mp_obj_t value);
|
||||
extern mp_obj_t VL53L5CX_set_motion_distance(mp_obj_t self_in, mp_obj_t distance_min, mp_obj_t distance_max);
|
||||
|
||||
extern mp_obj_t VL53L5CX_set_i2c_address(mp_obj_t self_in, mp_obj_t value);
|
||||
extern mp_obj_t VL53L5CX_set_ranging_mode(mp_obj_t self_in, mp_obj_t value);
|
||||
extern mp_obj_t VL53L5CX_set_ranging_frequency_hz(mp_obj_t self_in, mp_obj_t value);
|
||||
extern mp_obj_t VL53L5CX_set_resolution(mp_obj_t self_in, mp_obj_t value);
|
||||
extern mp_obj_t VL53L5CX_set_integration_time_ms(mp_obj_t self_in, mp_obj_t value);
|
||||
extern mp_obj_t VL53L5CX_set_sharpener_percent(mp_obj_t self_in, mp_obj_t value);
|
||||
extern mp_obj_t VL53L5CX_set_target_order(mp_obj_t self_in, mp_obj_t value);
|
||||
extern mp_obj_t VL53L5CX_set_power_mode(mp_obj_t self_in, mp_obj_t value);
|
||||
|
||||
extern mp_obj_t VL53L5CX_data_ready(mp_obj_t self_in);
|
||||
extern mp_obj_t VL53L5CX_get_data(mp_obj_t self_in);
|
|
@ -29,6 +29,7 @@ include(breakout_bme280/micropython)
|
|||
include(breakout_bmp280/micropython)
|
||||
include(breakout_icp10125/micropython)
|
||||
include(breakout_scd41/micropython)
|
||||
include(breakout_vl53l5cx/micropython)
|
||||
|
||||
include(pico_scroll/micropython)
|
||||
include(pico_rgb_keypad/micropython)
|
||||
|
|
Loading…
Reference in New Issue