mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-03 15:58:53 +08:00
602 lines
15 KiB
C++
602 lines
15 KiB
C++
/****************************************************************************
|
|
*
|
|
* Copyright (c) 2018 PX4 Development Team. All rights reserved.
|
|
*
|
|
* 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 PX4 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 OWNER 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 "VL53L0X.hpp"
|
|
|
|
/* VL53L0X Registers addresses */
|
|
#define VHV_CONFIG_PAD_SCL_SDA_EXTSUP_HW_REG 0x89
|
|
#define MSRC_CONFIG_CONTROL_REG 0x60
|
|
#define FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT_REG 0x44
|
|
#define SYSTEM_SEQUENCE_CONFIG_REG 0x01
|
|
#define DYNAMIC_SPAD_REF_EN_START_OFFSET_REG 0x4F
|
|
#define DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD_REG 0x4E
|
|
#define GLOBAL_CONFIG_REF_EN_START_SELECT_REG 0xB6
|
|
#define GLOBAL_CONFIG_SPAD_ENABLES_REF_0_REG 0xB0
|
|
#define SYSTEM_INTERRUPT_CONFIG_GPIO_REG 0x0A
|
|
#define SYSTEM_SEQUENCE_CONFIG_REG 0x01
|
|
#define SYSRANGE_START_REG 0x00
|
|
#define RESULT_INTERRUPT_STATUS_REG 0x13
|
|
#define SYSTEM_INTERRUPT_CLEAR_REG 0x0B
|
|
#define GLOBAL_CONFIG_SPAD_ENABLES_REF_0_REG 0xB0
|
|
#define GPIO_HV_MUX_ACTIVE_HIGH_REG 0x84
|
|
#define SYSTEM_INTERRUPT_CLEAR_REG 0x0B
|
|
#define RESULT_RANGE_STATUS_REG 0x14
|
|
#define VL53L0X_RA_IDENTIFICATION_MODEL_ID 0xC0
|
|
#define VL53L0X_IDENTIFICATION_MODEL_ID 0xEEAA
|
|
|
|
#define VL53L0X_US 1000 // 1ms
|
|
#define VL53L0X_SAMPLE_RATE 50000 // 50ms
|
|
|
|
#define VL53L0X_BUS_CLOCK 400000 // 400kHz bus clock speed
|
|
|
|
VL53L0X::VL53L0X(I2CSPIBusOption bus_option, const int bus, const uint8_t rotation, int bus_frequency, int address) :
|
|
I2C(DRV_DIST_DEVTYPE_VL53L0X, MODULE_NAME, bus, address, bus_frequency),
|
|
I2CSPIDriver(MODULE_NAME, px4::device_bus_to_wq(get_device_id()), bus_option, bus),
|
|
_px4_rangefinder(0 /* device id not yet used */, ORB_PRIO_DEFAULT, rotation)
|
|
{
|
|
// VL53L0X typical range 0-2 meters with 25 degree field of view
|
|
_px4_rangefinder.set_min_distance(0.f);
|
|
_px4_rangefinder.set_max_distance(2.f);
|
|
_px4_rangefinder.set_fov(math::radians(25.f));
|
|
|
|
// Allow 3 retries as the device typically misses the first measure attempts.
|
|
I2C::_retries = 3;
|
|
}
|
|
|
|
VL53L0X::~VL53L0X()
|
|
{
|
|
// free perf counters
|
|
perf_free(_sample_perf);
|
|
perf_free(_comms_errors);
|
|
}
|
|
|
|
int VL53L0X::collect()
|
|
{
|
|
// Read from the sensor.
|
|
uint8_t val[2] {};
|
|
perf_begin(_sample_perf);
|
|
|
|
_collect_phase = false;
|
|
|
|
const hrt_abstime timestamp_sample = hrt_absolute_time();
|
|
|
|
if (transfer(nullptr, 0, &val[0], 2) != PX4_OK) {
|
|
perf_count(_comms_errors);
|
|
perf_end(_sample_perf);
|
|
return PX4_ERROR;
|
|
}
|
|
|
|
perf_end(_sample_perf);
|
|
|
|
uint16_t distance_mm = (val[0] << 8) | val[1];
|
|
float distance_m = distance_mm / 1000.f;
|
|
|
|
_px4_rangefinder.update(timestamp_sample, distance_m);
|
|
|
|
return PX4_OK;
|
|
}
|
|
|
|
int VL53L0X::measure()
|
|
{
|
|
uint8_t wait_for_measurement = 0;
|
|
uint8_t system_start = 0;
|
|
|
|
// Send the command to begin a measurement.
|
|
const uint8_t cmd = RESULT_RANGE_STATUS_REG + 10;
|
|
|
|
if (_new_measurement) {
|
|
|
|
_new_measurement = false;
|
|
|
|
writeRegister(0x80, 0x01);
|
|
writeRegister(0xFF, 0x01);
|
|
writeRegister(0x00, 0x00);
|
|
writeRegister(0x91, _stop_variable);
|
|
writeRegister(0x00, 0x01);
|
|
writeRegister(0xFF, 0x00);
|
|
writeRegister(0x80, 0x00);
|
|
|
|
writeRegister(SYSRANGE_START_REG, 0x01);
|
|
|
|
readRegister(SYSRANGE_START_REG, system_start);
|
|
|
|
if ((system_start & 0x01) == 1) {
|
|
ScheduleDelayed(VL53L0X_US);
|
|
return PX4_OK;
|
|
|
|
} else {
|
|
_measurement_started = true;
|
|
}
|
|
}
|
|
|
|
if (!_collect_phase && !_measurement_started) {
|
|
|
|
readRegister(SYSRANGE_START_REG, system_start);
|
|
|
|
if ((system_start & 0x01) == 1) {
|
|
ScheduleDelayed(VL53L0X_US);
|
|
return PX4_OK;
|
|
|
|
} else {
|
|
_measurement_started = true;
|
|
}
|
|
}
|
|
|
|
readRegister(RESULT_INTERRUPT_STATUS_REG, wait_for_measurement);
|
|
|
|
if ((wait_for_measurement & 0x07) == 0) {
|
|
ScheduleDelayed(VL53L0X_US); // reschedule every 1 ms until measurement is ready
|
|
return PX4_OK;
|
|
}
|
|
|
|
_collect_phase = true;
|
|
|
|
int ret = transfer(&cmd, sizeof(cmd), nullptr, 0);
|
|
|
|
if (ret != PX4_OK) {
|
|
perf_count(_comms_errors);
|
|
DEVICE_LOG("i2c::transfer returned %d", ret);
|
|
return ret;
|
|
}
|
|
|
|
return PX4_OK;
|
|
}
|
|
|
|
void VL53L0X::print_status()
|
|
{
|
|
I2CSPIDriverBase::print_status();
|
|
perf_print_counter(_comms_errors);
|
|
perf_print_counter(_sample_perf);
|
|
_px4_rangefinder.print_status();
|
|
}
|
|
|
|
int VL53L0X::probe()
|
|
{
|
|
if (sensorInit() == PX4_OK) {
|
|
return PX4_OK;
|
|
}
|
|
|
|
// Device not found on any address.
|
|
return -EIO;
|
|
}
|
|
|
|
int VL53L0X::readRegister(const uint8_t reg_address, uint8_t &value)
|
|
{
|
|
// Write register address to the sensor.
|
|
int ret = transfer(®_address, sizeof(reg_address), nullptr, 0);
|
|
|
|
if (ret != PX4_OK) {
|
|
perf_count(_comms_errors);
|
|
return ret;
|
|
}
|
|
|
|
// Read from the sensor.
|
|
ret = transfer(nullptr, 0, &value, 1);
|
|
|
|
if (ret != PX4_OK) {
|
|
perf_count(_comms_errors);
|
|
return ret;
|
|
}
|
|
|
|
return PX4_OK;
|
|
}
|
|
|
|
int VL53L0X::readRegisterMulti(const uint8_t reg_address, uint8_t *value, const uint8_t length)
|
|
{
|
|
// Write register address to the sensor.
|
|
int ret = transfer(®_address, 1, nullptr, 0);
|
|
|
|
if (ret != PX4_OK) {
|
|
perf_count(_comms_errors);
|
|
return ret;
|
|
}
|
|
|
|
// Read from the sensor.
|
|
ret = transfer(nullptr, 0, &value[0], length);
|
|
|
|
if (ret != PX4_OK) {
|
|
perf_count(_comms_errors);
|
|
return ret;
|
|
}
|
|
|
|
return PX4_OK;
|
|
}
|
|
|
|
void VL53L0X::RunImpl()
|
|
{
|
|
measure();
|
|
|
|
if (_collect_phase) {
|
|
|
|
_collect_phase = false;
|
|
_new_measurement = true;
|
|
|
|
collect();
|
|
|
|
ScheduleDelayed(VL53L0X_SAMPLE_RATE);
|
|
}
|
|
}
|
|
|
|
int VL53L0X::spadCalculations()
|
|
{
|
|
uint8_t val = 0;
|
|
uint8_t spad_count = 0;
|
|
uint8_t ref_spad_map[6] = {};
|
|
|
|
bool spad_type_is_aperture = false;
|
|
|
|
writeRegister(0x80, 0x01);
|
|
writeRegister(0xFF, 0x01);
|
|
writeRegister(0x00, 0x00);
|
|
writeRegister(0xFF, 0x06);
|
|
|
|
readRegister(0x83, val);
|
|
writeRegister(0x83, val | 0x04);
|
|
|
|
writeRegister(0xFF, 0x07);
|
|
writeRegister(0x81, 0x01);
|
|
writeRegister(0x80, 0x01);
|
|
writeRegister(0x94, 0x6b);
|
|
writeRegister(0x83, 0x00);
|
|
|
|
readRegister(0x83, val);
|
|
|
|
while (val == 0x00) {
|
|
readRegister(0x83, val);
|
|
}
|
|
|
|
writeRegister(0x83, 0x01);
|
|
readRegister(0x92, val);
|
|
|
|
spad_count = val & 0x7f;
|
|
spad_type_is_aperture = (val >> 7) & 0x01;
|
|
|
|
writeRegister(0x81, 0x00);
|
|
writeRegister(0xFF, 0x06);
|
|
|
|
readRegister(0x83, val);
|
|
writeRegister(0x83, val & ~0x04);
|
|
|
|
writeRegister(0xFF, 0x01);
|
|
writeRegister(0x00, 0x01);
|
|
writeRegister(0xFF, 0x00);
|
|
writeRegister(0x80, 0x00);
|
|
|
|
readRegisterMulti(GLOBAL_CONFIG_SPAD_ENABLES_REF_0_REG, &ref_spad_map[0], 6);
|
|
|
|
writeRegister(0xFF, 0x01);
|
|
writeRegister(DYNAMIC_SPAD_REF_EN_START_OFFSET_REG, 0x00);
|
|
writeRegister(DYNAMIC_SPAD_NUM_REQUESTED_REF_SPAD_REG, 0x2C);
|
|
writeRegister(0xFF, 0x00);
|
|
writeRegister(GLOBAL_CONFIG_REF_EN_START_SELECT_REG, 0xB4);
|
|
|
|
uint8_t first_spad_to_enable = spad_type_is_aperture ? 12 : 0;
|
|
uint8_t spads_enabled = 0;
|
|
|
|
for (uint8_t i = 0; i < 48; i++) {
|
|
if (i < first_spad_to_enable || spads_enabled == spad_count) {
|
|
ref_spad_map[i / 8] &= ~(1 << (i % 8));
|
|
|
|
} else if ((ref_spad_map[i / 8] >> (i % 8)) & 0x1) {
|
|
spads_enabled++;
|
|
}
|
|
}
|
|
|
|
writeRegisterMulti(GLOBAL_CONFIG_SPAD_ENABLES_REF_0_REG, &ref_spad_map[0], 6);
|
|
|
|
sensorTuning();
|
|
|
|
writeRegister(SYSTEM_INTERRUPT_CONFIG_GPIO_REG, 4); // 4: GPIO interrupt on new data.
|
|
readRegister(GPIO_HV_MUX_ACTIVE_HIGH_REG, val);
|
|
|
|
writeRegister(GPIO_HV_MUX_ACTIVE_HIGH_REG, val & ~0x10); // Active low.
|
|
writeRegister(SYSTEM_INTERRUPT_CLEAR_REG, 0x01);
|
|
writeRegister(SYSTEM_SEQUENCE_CONFIG_REG, 0xE8);
|
|
writeRegister(SYSTEM_SEQUENCE_CONFIG_REG, 0x01);
|
|
|
|
singleRefCalibration(0x40);
|
|
|
|
writeRegister(SYSTEM_SEQUENCE_CONFIG_REG, 0x02);
|
|
|
|
singleRefCalibration(0x00);
|
|
|
|
writeRegister(SYSTEM_SEQUENCE_CONFIG_REG, 0xE8); // Restore config.
|
|
|
|
return OK;
|
|
}
|
|
|
|
int VL53L0X::sensorInit()
|
|
{
|
|
uint8_t val = 0;
|
|
|
|
// I2C at 2.8V on sensor side of level shifter
|
|
int ret = PX4_OK;
|
|
ret |= readRegister(VHV_CONFIG_PAD_SCL_SDA_EXTSUP_HW_REG, val);
|
|
|
|
if (ret != PX4_OK) {
|
|
return PX4_ERROR;
|
|
}
|
|
|
|
ret |= writeRegister(VHV_CONFIG_PAD_SCL_SDA_EXTSUP_HW_REG, val | 0x01);
|
|
|
|
// set I2C to standard mode
|
|
ret |= writeRegister(0x88, 0x00);
|
|
ret |= writeRegister(0x80, 0x01);
|
|
ret |= writeRegister(0xFF, 0x01);
|
|
ret |= writeRegister(0x00, 0x00);
|
|
ret |= readRegister(0x91, val);
|
|
ret |= writeRegister(0x00, 0x01);
|
|
ret |= writeRegister(0xFF, 0x00);
|
|
ret |= writeRegister(0x80, 0x00);
|
|
|
|
if (ret != PX4_OK) {
|
|
return PX4_ERROR;
|
|
}
|
|
|
|
_stop_variable = val;
|
|
|
|
// Disable SIGNAL_RATE_MSRC (bit 1) and SIGNAL_RATE_PRE_RANGE (bit 4) limit checks
|
|
readRegister(MSRC_CONFIG_CONTROL_REG, val);
|
|
writeRegister(MSRC_CONFIG_CONTROL_REG, val | 0x12);
|
|
|
|
// Set signal rate limit to 0.1
|
|
float rate_limit = 0.1 * 65536;
|
|
uint8_t rate_limit_split[2] = {};
|
|
|
|
rate_limit_split[0] = (((uint16_t)rate_limit) >> 8);
|
|
rate_limit_split[1] = (uint16_t)rate_limit;
|
|
|
|
writeRegisterMulti(FINAL_RANGE_CONFIG_MIN_COUNT_RATE_RTN_LIMIT_REG, &rate_limit_split[0], 2);
|
|
writeRegister(SYSTEM_SEQUENCE_CONFIG_REG, 0xFF);
|
|
|
|
spadCalculations();
|
|
|
|
return PX4_OK;
|
|
}
|
|
|
|
int VL53L0X::sensorTuning()
|
|
{
|
|
// Magic register settings taken from the ST Micro API.
|
|
writeRegister(0xFF, 0x01);
|
|
writeRegister(0x00, 0x00);
|
|
writeRegister(0xFF, 0x00);
|
|
writeRegister(0x09, 0x00);
|
|
writeRegister(0x10, 0x00);
|
|
writeRegister(0x11, 0x00);
|
|
writeRegister(0x24, 0x01);
|
|
writeRegister(0x25, 0xFF);
|
|
writeRegister(0x75, 0x00);
|
|
writeRegister(0xFF, 0x01);
|
|
writeRegister(0x4E, 0x2C);
|
|
writeRegister(0x48, 0x00);
|
|
writeRegister(0x30, 0x20);
|
|
writeRegister(0xFF, 0x00);
|
|
writeRegister(0x30, 0x09);
|
|
writeRegister(0x54, 0x00);
|
|
writeRegister(0x31, 0x04);
|
|
writeRegister(0x32, 0x03);
|
|
writeRegister(0x40, 0x83);
|
|
writeRegister(0x46, 0x25);
|
|
writeRegister(0x60, 0x00);
|
|
writeRegister(0x27, 0x00);
|
|
writeRegister(0x50, 0x06);
|
|
writeRegister(0x51, 0x00);
|
|
writeRegister(0x52, 0x96);
|
|
writeRegister(0x56, 0x08);
|
|
writeRegister(0x57, 0x30);
|
|
writeRegister(0x61, 0x00);
|
|
writeRegister(0x62, 0x00);
|
|
writeRegister(0x64, 0x00);
|
|
writeRegister(0x65, 0x00);
|
|
writeRegister(0x66, 0xA0);
|
|
writeRegister(0xFF, 0x01);
|
|
writeRegister(0x22, 0x32);
|
|
writeRegister(0x47, 0x14);
|
|
writeRegister(0x49, 0xFF);
|
|
writeRegister(0x4A, 0x00);
|
|
writeRegister(0xFF, 0x00);
|
|
writeRegister(0x7A, 0x0A);
|
|
writeRegister(0x7B, 0x00);
|
|
writeRegister(0x78, 0x21);
|
|
writeRegister(0xFF, 0x01);
|
|
writeRegister(0x23, 0x34);
|
|
writeRegister(0x42, 0x00);
|
|
writeRegister(0x44, 0xFF);
|
|
writeRegister(0x45, 0x26);
|
|
writeRegister(0x46, 0x05);
|
|
writeRegister(0x40, 0x40);
|
|
writeRegister(0x0E, 0x06);
|
|
writeRegister(0x20, 0x1A);
|
|
writeRegister(0x43, 0x40);
|
|
writeRegister(0xFF, 0x00);
|
|
writeRegister(0x34, 0x03);
|
|
writeRegister(0x35, 0x44);
|
|
writeRegister(0xFF, 0x01);
|
|
writeRegister(0x31, 0x04);
|
|
writeRegister(0x4B, 0x09);
|
|
writeRegister(0x4C, 0x05);
|
|
writeRegister(0x4D, 0x04);
|
|
writeRegister(0xFF, 0x00);
|
|
writeRegister(0x44, 0x00);
|
|
writeRegister(0x45, 0x20);
|
|
writeRegister(0x47, 0x08);
|
|
writeRegister(0x48, 0x28);
|
|
writeRegister(0x67, 0x00);
|
|
writeRegister(0x70, 0x04);
|
|
writeRegister(0x71, 0x01);
|
|
writeRegister(0x72, 0xFE);
|
|
writeRegister(0x76, 0x00);
|
|
writeRegister(0x77, 0x00);
|
|
writeRegister(0xFF, 0x01);
|
|
writeRegister(0x0D, 0x01);
|
|
writeRegister(0xFF, 0x00);
|
|
writeRegister(0x80, 0x01);
|
|
writeRegister(0x01, 0xF8);
|
|
writeRegister(0xFF, 0x01);
|
|
writeRegister(0x8E, 0x01);
|
|
writeRegister(0x00, 0x01);
|
|
writeRegister(0xFF, 0x00);
|
|
writeRegister(0x80, 0x00);
|
|
|
|
return PX4_OK;
|
|
}
|
|
|
|
int VL53L0X::singleRefCalibration(const uint8_t byte)
|
|
{
|
|
uint8_t val = 0;
|
|
|
|
writeRegister(SYSRANGE_START_REG, byte | 0x01); // VL53L0X_REG_SYSRANGE_MODE_START_STOP
|
|
readRegister(RESULT_INTERRUPT_STATUS_REG, val);
|
|
|
|
while ((val & 0x07) == 0) {
|
|
readRegister(RESULT_INTERRUPT_STATUS_REG, val);
|
|
}
|
|
|
|
writeRegister(SYSTEM_INTERRUPT_CLEAR_REG, 0x01);
|
|
writeRegister(SYSRANGE_START_REG, 0x00);
|
|
|
|
return PX4_OK;
|
|
}
|
|
|
|
void VL53L0X::start()
|
|
{
|
|
// Schedule the first cycle.
|
|
ScheduleNow();
|
|
}
|
|
|
|
int VL53L0X::writeRegister(const uint8_t reg_address, const uint8_t value)
|
|
{
|
|
uint8_t cmd[2] {reg_address, value};
|
|
int ret = transfer(&cmd[0], 2, nullptr, 0);
|
|
|
|
if (ret != PX4_OK) {
|
|
perf_count(_comms_errors);
|
|
return ret;
|
|
}
|
|
|
|
return PX4_OK;
|
|
}
|
|
|
|
int VL53L0X::writeRegisterMulti(const uint8_t reg_address, const uint8_t *value, const uint8_t length)
|
|
{
|
|
if (length > 6 || length < 1) {
|
|
DEVICE_LOG("VL53L0X::writeRegisterMulti length out of range");
|
|
return PX4_ERROR;
|
|
}
|
|
|
|
/* be careful: for uint16_t to send first higher byte */
|
|
uint8_t cmd[7] {};
|
|
cmd[0] = reg_address;
|
|
|
|
memcpy(&cmd[1], &value[0], length);
|
|
|
|
int ret = transfer(&cmd[0], length + 1, nullptr, 0);
|
|
|
|
if (ret != PX4_OK) {
|
|
perf_count(_comms_errors);
|
|
return ret;
|
|
}
|
|
|
|
return PX4_OK;
|
|
}
|
|
|
|
void VL53L0X::print_usage()
|
|
{
|
|
PRINT_MODULE_USAGE_NAME("vl53l0x", "driver");
|
|
PRINT_MODULE_USAGE_SUBCATEGORY("distance_sensor");
|
|
PRINT_MODULE_USAGE_COMMAND("start");
|
|
PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, false);
|
|
PRINT_MODULE_USAGE_PARAM_INT('R', 25, 1, 25, "Sensor rotation - downward facing by default", true);
|
|
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
|
|
}
|
|
|
|
I2CSPIDriverBase *VL53L0X::instantiate(const BusCLIArguments &cli, const BusInstanceIterator &iterator,
|
|
int runtime_instance)
|
|
{
|
|
VL53L0X *instance = new VL53L0X(iterator.configuredBusOption(), iterator.bus(), cli.orientation, cli.bus_frequency);
|
|
|
|
if (instance == nullptr) {
|
|
PX4_ERR("alloc failed");
|
|
return nullptr;
|
|
}
|
|
|
|
if (instance->init() != PX4_OK) {
|
|
delete instance;
|
|
return nullptr;
|
|
}
|
|
|
|
instance->start();
|
|
return instance;
|
|
}
|
|
|
|
extern "C" __EXPORT int vl53l0x_main(int argc, char *argv[])
|
|
{
|
|
int ch;
|
|
using ThisDriver = VL53L0X;
|
|
BusCLIArguments cli{true, false};
|
|
cli.default_i2c_frequency = 400000;
|
|
cli.orientation = distance_sensor_s::ROTATION_DOWNWARD_FACING;
|
|
|
|
while ((ch = cli.getopt(argc, argv, "R:")) != EOF) {
|
|
switch (ch) {
|
|
case 'R':
|
|
cli.orientation = atoi(cli.optarg());
|
|
break;
|
|
}
|
|
}
|
|
|
|
const char *verb = cli.optarg();
|
|
|
|
if (!verb) {
|
|
ThisDriver::print_usage();
|
|
return -1;
|
|
}
|
|
|
|
BusInstanceIterator iterator(MODULE_NAME, cli, DRV_DIST_DEVTYPE_VL53L0X);
|
|
|
|
if (!strcmp(verb, "start")) {
|
|
return ThisDriver::module_start(cli, iterator);
|
|
}
|
|
|
|
if (!strcmp(verb, "stop")) {
|
|
return ThisDriver::module_stop(iterator);
|
|
}
|
|
|
|
if (!strcmp(verb, "status")) {
|
|
return ThisDriver::module_status(iterator);
|
|
}
|
|
|
|
ThisDriver::print_usage();
|
|
return -1;
|
|
}
|