diff --git a/conf/airframes/tudelft/splash3.xml b/conf/airframes/tudelft/splash3.xml index 6573915535..09c7e28500 100644 --- a/conf/airframes/tudelft/splash3.xml +++ b/conf/airframes/tudelft/splash3.xml @@ -59,6 +59,7 @@ + diff --git a/conf/modules/lidar_tfmini.xml b/conf/modules/lidar_tfmini.xml new file mode 100644 index 0000000000..0279febee3 --- /dev/null +++ b/conf/modules/lidar_tfmini.xml @@ -0,0 +1,49 @@ + + + + + + TFMini Lidar using a single UART for communication + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/conf/telemetry/default_rotorcraft.xml b/conf/telemetry/default_rotorcraft.xml index bb830f7ac7..4fea279964 100644 --- a/conf/telemetry/default_rotorcraft.xml +++ b/conf/telemetry/default_rotorcraft.xml @@ -33,6 +33,7 @@ + @@ -195,6 +196,7 @@ + diff --git a/conf/userconf/tudelft/conf.xml b/conf/userconf/tudelft/conf.xml index 11feef2f5b..bed86e05a6 100644 --- a/conf/userconf/tudelft/conf.xml +++ b/conf/userconf/tudelft/conf.xml @@ -371,7 +371,7 @@ telemetry="telemetry/default_rotorcraft.xml" flight_plan="flight_plans/rotorcraft_basic.xml" settings="settings/rotorcraft_basic.xml" - settings_modules="modules/air_data.xml modules/ahrs_float_cmpl_quat.xml modules/stabilization_rate.xml modules/stabilization_int_quat.xml modules/nav_basic_rotorcraft.xml modules/guidance_rotorcraft.xml modules/gps_ubx_ucenter.xml modules/gps.xml modules/imu_common.xml" + settings_modules="modules/air_data.xml modules/lidar_tfmini.xml modules/ahrs_float_cmpl_quat.xml modules/stabilization_rate.xml modules/stabilization_int_quat.xml modules/nav_basic_rotorcraft.xml modules/guidance_rotorcraft.xml modules/gps_ubx_ucenter.xml modules/gps.xml modules/imu_common.xml" gui_color="blue" /> + * + * This file is part of paparazzi. + * + * paparazzi is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * paparazzi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/** @file modules/lidar/tfmini.c + * @brief driver for the TFMini lidar + * + */ +#include "tfmini.h" +#include "mcu_periph/uart.h" +#include "subsystems/abi.h" + +// State interface for rotation compensation +#include "state.h" + +// Messages +#include "pprzlink/messages.h" +#include "subsystems/datalink/downlink.h" + +struct TFMini tfmini = { + .parse_status = TFMINI_INITIALIZE +}; + +static void tfmini_parse(uint8_t byte); + +#if PERIODIC_TELEMETRY +#include "subsystems/datalink/telemetry.h" + +/** + * Downlink message lidar + */ +static void tfmini_send_lidar(struct transport_tx *trans, struct link_device *dev) +{ + pprz_msg_send_LIDAR(trans, dev, AC_ID, + &tfmini.distance, + &tfmini.mode, + &tfmini.parse_status); +} + +#endif + +/** + * Initialization function + */ +void tfmini_init(void) +{ + tfmini.device = &((TFMINI_PORT).device); + + tfmini.update_agl = USE_TFMINI_AGL; + tfmini.compensate_rotation = TFMINI_COMPENSATE_ROTATION; + + tfmini.strength = 0; + tfmini.distance = 0; + tfmini.parse_status = TFMINI_PARSE_HEAD; + +#if PERIODIC_TELEMETRY + register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_LIDAR, tfmini_send_lidar); +#endif +} + +/** + * Lidar event function + * Receive bytes from the UART port and parse them + */ +void tfmini_event(void) +{ + while (tfmini.parse_status != TFMINI_INITIALIZE && tfmini.device->char_available(tfmini.device->periph)) { + tfmini_parse(tfmini.device->get_byte(tfmini.device->periph)); + } +} + +/** + * Parse the lidar bytes 1 by 1 + */ +static void tfmini_parse(uint8_t byte) +{ + switch (tfmini.parse_status) { + case TFMINI_INITIALIZE: + break; + case TFMINI_PARSE_HEAD: + if (byte == 0x59) { + tfmini.parse_crc = byte; + tfmini.parse_status++; + } + break; + case TFMINI_PARSE_HEAD2: + if (byte == 0x59) { + tfmini.parse_crc += byte; + tfmini.parse_status++; + } else { + tfmini.parse_status = TFMINI_PARSE_HEAD; + } + break; + + case TFMINI_PARSE_DIST_L: + tfmini.raw_dist = byte; + tfmini.parse_crc += byte; + tfmini.parse_status++; + break; + case TFMINI_PARSE_DIST_H: + tfmini.raw_dist |= (byte << 8); + tfmini.parse_crc += byte; + tfmini.parse_status++; + break; + + case TFMINI_PARSE_STRENGTH_L: + tfmini.raw_strength = byte; + tfmini.parse_crc += byte; + tfmini.parse_status++; + break; + case TFMINI_PARSE_STRENGTH_H: + tfmini.raw_strength |= (byte << 8); + tfmini.parse_crc += byte; + tfmini.parse_status++; + break; + + case TFMINI_PARSE_MODE: + tfmini.raw_mode = byte; + tfmini.parse_crc += byte; + tfmini.parse_status++; + break; + case TFMINI_PARSE_BYTE7: + tfmini.parse_crc += byte; + tfmini.parse_status++; + break; + + case TFMINI_PARSE_CHECKSUM: + // When the CRC matches + if (tfmini.parse_crc == byte) { + tfmini.distance = tfmini.raw_dist / 100.f; + tfmini.strength = tfmini.raw_strength; + tfmini.mode = tfmini.raw_mode; + + // When the distance is valid + if (tfmini.distance != 0xFFFF) { + // compensate AGL measurement for body rotation + if (tfmini.compensate_rotation) { + float phi = stateGetNedToBodyEulers_f()->phi; + float theta = stateGetNedToBodyEulers_f()->theta; + float gain = (float)fabs((double)(cosf(phi) * cosf(theta))); + tfmini.distance = tfmini.distance / gain; + } + + // send message (if requested) + if (tfmini.update_agl) { + AbiSendMsgAGL(AGL_LIDAR_TFMINI_ID, tfmini.distance); + } + } + } + + // Start reading again + tfmini.parse_status = TFMINI_PARSE_HEAD; + break; + } +} diff --git a/sw/airborne/modules/lidar/tfmini.h b/sw/airborne/modules/lidar/tfmini.h new file mode 100644 index 0000000000..ddc08461d8 --- /dev/null +++ b/sw/airborne/modules/lidar/tfmini.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2019 Freek van Tienen + * + * This file is part of paparazzi. + * + * paparazzi is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * paparazzi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/** @file modules/lidar/tfmini.h + * @brief driver for the TFMini lidar + * + */ +#ifndef LIDAR_TFMINI_H +#define LIDAR_TFMINI_H + +#include "std.h" +#include "mcu_periph/i2c.h" + +enum TFMiniParseStatus { + TFMINI_INITIALIZE, + TFMINI_PARSE_HEAD, + TFMINI_PARSE_HEAD2, + TFMINI_PARSE_DIST_L, + TFMINI_PARSE_DIST_H, + TFMINI_PARSE_STRENGTH_L, + TFMINI_PARSE_STRENGTH_H, + TFMINI_PARSE_MODE, + TFMINI_PARSE_BYTE7, + TFMINI_PARSE_CHECKSUM +}; + +struct TFMini { + struct link_device *device; + enum TFMiniParseStatus parse_status; + uint8_t parse_crc; + uint16_t raw_dist; + uint16_t raw_strength; + uint8_t raw_mode; + + uint16_t strength; + float distance; // [m] + uint8_t mode; + bool update_agl; + bool compensate_rotation; +}; + +extern struct TFMini tfmini; + +extern void tfmini_init(void); +extern void tfmini_event(void); +extern void tfmini_downlink(void); + +#endif /* LIDAR_TFMINI_H */ + diff --git a/sw/airborne/subsystems/abi_sender_ids.h b/sw/airborne/subsystems/abi_sender_ids.h index beef38c221..6f8c62db51 100644 --- a/sw/airborne/subsystems/abi_sender_ids.h +++ b/sw/airborne/subsystems/abi_sender_ids.h @@ -157,6 +157,10 @@ #define AGL_RAY_SENSOR_GAZEBO_ID 10 #endif +#ifndef AGL_LIDAR_TFMINI_ID +#define AGL_LIDAR_TFMINI_ID 11 +#endif + /* * IDs of magnetometer sensors (including IMUs with mag) */