Compare commits

..

1 Commits

Author SHA1 Message Date
Hamish Willee 461395b077 docs(update): RTL types 4-5 docs for PR26220 2026-03-18 10:15:12 +11:00
110 changed files with 2356 additions and 4371 deletions
@@ -34,7 +34,6 @@ param set-default PWM_MAIN_FUNC2 102
param set-default PWM_MAIN_FUNC3 103
param set-default PWM_MAIN_FUNC4 104
param set-default SENS_GPS0_DELAY 0
param set-default SENS_GPS1_DELAY 0
param set-default EKF2_GPS_DELAY 0
param set SIH_VEHICLE_TYPE 0
@@ -44,8 +44,7 @@ param set-default PWM_MAIN_FUNC2 202
param set-default PWM_MAIN_FUNC3 203
param set-default PWM_MAIN_FUNC4 101
param set-default SENS_GPS0_DELAY 0
param set-default SENS_GPS1_DELAY 0
param set-default EKF2_GPS_DELAY 0
# Rate controllers
param set-default FW_RR_P 0.0500
@@ -11,8 +11,7 @@
PX4_SIMULATOR=${PX4_SIMULATOR:=sihsim}
PX4_SIM_MODEL=${PX4_SIM_MODEL:=xvert}
param set-default SENS_GPS0_DELAY 0
param set-default SENS_GPS1_DELAY 0
param set-default EKF2_GPS_DELAY 0
param set-default EKF2_FUSE_BETA 0 # side slip fusion is currently not supported for tailsitters
param set-default SENS_EN_GPSSIM 1
@@ -27,8 +27,7 @@ param set-default SENS_EN_BAROSIM 1
param set-default SENS_EN_MAGSIM 1
param set-default SENS_EN_ARSPDSIM 1
param set-default SENS_GPS0_DELAY 0
param set-default SENS_GPS1_DELAY 0
param set-default EKF2_GPS_DELAY 0
param set-default VT_TYPE 2
param set-default MPC_MAN_Y_MAX 60
@@ -44,5 +44,4 @@ param set-default PWM_MAIN_FUNC4 104
param set-default PWM_MAIN_FUNC5 105
param set-default PWM_MAIN_FUNC6 106
param set-default SENS_GPS0_DELAY 0
param set-default SENS_GPS1_DELAY 0
param set-default EKF2_GPS_DELAY 0
@@ -20,8 +20,8 @@ param set-default COM_DISARM_LAND 0.5
# EKF2 parameters
param set-default EKF2_DRAG_CTRL 1
param set-default EKF2_IMU_POS_X 0.02
param set-default SENS_GPS0_OFFX 0.055
param set-default SENS_GPS0_OFFZ -0.15
param set-default EKF2_GPS_POS_X 0.055
param set-default EKF2_GPS_POS_Z -0.15
param set-default EKF2_MIN_RNG 0.03
param set-default EKF2_OF_CTRL 1
param set-default EKF2_OF_POS_X 0.055
@@ -2,8 +2,7 @@
# shellcheck disable=SC2154
# EKF2 specifics
param set-default SENS_GPS0_DELAY 10
param set-default SENS_GPS1_DELAY 10
param set-default EKF2_GPS_DELAY 10
param set-default EKF2_MULTI_IMU 3
param set-default SENS_IMU_MODE 0
@@ -19,8 +19,8 @@ param set-default COM_DISARM_LAND 0.5
# EKF2 parameters
param set-default EKF2_DRAG_CTRL 1
param set-default EKF2_IMU_POS_X 0.02
param set-default SENS_GPS0_OFFX 0.055
param set-default SENS_GPS0_OFFZ -0.15
param set-default EKF2_GPS_POS_X 0.055
param set-default EKF2_GPS_POS_Z -0.15
param set-default EKF2_MIN_RNG 0.03
param set-default EKF2_OF_CTRL 1
param set-default EKF2_OF_POS_X 0.055
@@ -19,8 +19,8 @@ param set-default COM_DISARM_LAND 0.5
# EKF2 parameters
param set-default EKF2_DRAG_CTRL 1
param set-default EKF2_IMU_POS_X 0.02
param set-default SENS_GPS0_OFFX 0.055
param set-default SENS_GPS0_OFFZ -0.15
param set-default EKF2_GPS_POS_X 0.055
param set-default EKF2_GPS_POS_Z -0.15
param set-default EKF2_MIN_RNG 0.03
param set-default EKF2_OF_CTRL 1
param set-default EKF2_OF_POS_X 0.055
@@ -47,9 +47,8 @@ param set-default EKF2_BCOEF_Y 25.5
param set-default EKF2_DRAG_CTRL 1
param set-default SENS_GPS0_DELAY 100
param set-default SENS_GPS1_DELAY 100
param set-default SENS_GPS0_OFFX 0.06
param set-default EKF2_GPS_DELAY 100
param set-default EKF2_GPS_POS_X 0.06
param set-default EKF2_GPS_V_NOISE 0.5
param set-default EKF2_IMU_POS_X 0.06
-1
View File
@@ -1 +0,0 @@
CONFIG_MAVLINK_DIALECT="development"
+3
View File
@@ -421,6 +421,9 @@
/* This board provides a DMA pool and APIs */
#define BOARD_DMA_ALLOC_POOL_SIZE 5120
/* This board has 4 DMA channels available for bidirectional dshot */
#define BOARD_DMA_NUM_DSHOT_CHANNELS 4
/* This board provides the board_on_reset interface */
#define BOARD_HAS_ON_RESET 1
-19
View File
@@ -1,19 +0,0 @@
4001_quad_x
4050_generic_250
6001_hexa_x
12001_octo_cox
13100_generic_vtol_tiltrotor
5001_quad_+
24001_dodeca_cox
2100_standard_plane
13000_generic_vtol_standard
4601_droneblocks_dexi_5
11001_hexa_cox
14001_generic_mc_with_tilt
16001_helicopter
9001_octo_+
7001_hexa_+
3000_generic_wing
2106_albatross
13200_generic_vtol_tailsitter
13030_generic_vtol_quad_tiltrotor
-1
View File
@@ -1 +0,0 @@
CONFIG_MAVLINK_DIALECT="development"
+3
View File
@@ -306,6 +306,9 @@
/* This board provides a DMA pool and APIs */
#define BOARD_DMA_ALLOC_POOL_SIZE 5120
/* This board has 3 DMA channels available for bidirectional dshot */
#define BOARD_DMA_NUM_DSHOT_CHANNELS 3
/* This board provides the board_on_reset interface */
#define BOARD_HAS_ON_RESET 1
-1
View File
@@ -1 +0,0 @@
CONFIG_MAVLINK_DIALECT="development"
+3
View File
@@ -311,6 +311,9 @@
/* This board provides a DMA pool and APIs */
#define BOARD_DMA_ALLOC_POOL_SIZE 5120
/* This board has 4 DMA channels available for bidirectional dshot */
#define BOARD_DMA_NUM_DSHOT_CHANNELS 4
/* This board provides the board_on_reset interface */
#define BOARD_HAS_ON_RESET 1
@@ -58,13 +58,11 @@
//#define DMAMAP_USART6_RX DMAMAP_DMA12_USART6RX_0 /* 5 DMA1:71 PX4IO */
//#define DMAMAP_USART6_TX DMAMAP_DMA12_USART6TX_0 /* 6 DMA1:72 PX4IO */
// Dynamically assigned in timer_config.cpp for DShot (allocated/freed per cycle):
// Timer 1 TIM1UP (burst) + TIM1CH1-4 (capture)
// Timer 2 TIM2UP (burst) + TIM2CH1-4 (capture)
// Timer 3 TIM3UP (burst) + TIM3CH1-4 (capture)
// Timer 4 TIM4UP (burst) + TIM4CH1-3 (capture, CH4 has no DMA)
// Timer 5 TIM5UP (burst) + TIM5CH1-4 (capture)
// Timer 15 - no TIM15UP DMA, cannot do DShot
// Assigned in timer_config.cpp
// TODO
// Timer 4 /* 7 DMA1:32 TIM4UP */
// Timer 5 /* 8 DMA1:50 TIM5UP */
// DMAMUX2 Using at most 8 Channels on DMA2 -------- Assigned
// V
@@ -38,20 +38,18 @@ constexpr io_timers_t io_timers[MAX_IO_TIMERS] = {
initIOTimer(Timer::Timer1, DMA{DMA::Index1}),
initIOTimer(Timer::Timer4, DMA{DMA::Index1}),
initIOTimer(Timer::Timer5, DMA{DMA::Index1}),
initIOTimer(Timer::Timer15), // Note: Timer15 has no TIM_UP DMA on STM32H7, cannot do DShot
initIOTimer(Timer::Timer3, DMA{DMA::Index1}),
initIOTimer(Timer::Timer2, DMA{DMA::Index1}),
initIOTimer(Timer::Timer15),
initIOTimer(Timer::Timer3),
initIOTimer(Timer::Timer2),
};
// Note: Timer4 Channel4 has no DMAMUX mapping on STM32H7, so BDShot telemetry capture
// is not available on that channel. DShot output still works (uses TIM_UP DMA for burst).
constexpr timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = {
initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel1}, {GPIO::PortA, GPIO::Pin8}),
initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel2}, {GPIO::PortE, GPIO::Pin11}),
initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel3}, {GPIO::PortE, GPIO::Pin13}),
initIOTimerChannel(io_timers, {Timer::Timer1, Timer::Channel4}, {GPIO::PortE, GPIO::Pin14}),
initIOTimerChannel(io_timers, {Timer::Timer4, Timer::Channel3}, {GPIO::PortD, GPIO::Pin14}),
initIOTimerChannel(io_timers, {Timer::Timer4, Timer::Channel4}, {GPIO::PortD, GPIO::Pin15}), // no BDShot telemetry readback
initIOTimerChannel(io_timers, {Timer::Timer4, Timer::Channel4}, {GPIO::PortD, GPIO::Pin15}),
initIOTimerChannel(io_timers, {Timer::Timer5, Timer::Channel1}, {GPIO::PortA, GPIO::Pin0}),
initIOTimerChannel(io_timers, {Timer::Timer5, Timer::Channel2}, {GPIO::PortA, GPIO::Pin1}),
initIOTimerChannel(io_timers, {Timer::Timer15, Timer::Channel1}, {GPIO::PortE, GPIO::Pin5}),
+1 -1
View File
@@ -129,5 +129,5 @@ See also:
The PPS signal provides much higher temporal precision than the transmitted time data, which has latency and jitter from serial communication.
::: warning
If the PPS driver does not sending any data for 5 seconds (despite having `PPS_CAP_ENABLE` set to 1), the `SENS_GPS0_DELAY` will be used instead for estimating the latency.
If the PPS driver does not sending any data for 5 seconds (despite having `PPS_CAP_ENABLE` set to 1), the `EKF2_GPS_DELAY` will be used instead for estimating the latency.
:::
+69 -314
View File
@@ -4202,9 +4202,6 @@ Custom PWM rates can be used by directly setting any value >0.
**Values:**
- `-8`: BDShot150
- `-7`: BDShot300
- `-6`: BDShot600
- `-5`: DShot150
- `-4`: DShot300
- `-3`: DShot600
@@ -19502,33 +19499,18 @@ When mixer outputs 1000 or value inside DSHOT 3D deadband, DShot 0 is sent.
| ------ | -------- | -------- | --------- | ------------ | ---- |
|   | | | | Disabled (0) | |
### DSHOT_BIDIR_EDT (`INT32`) {#DSHOT_BIDIR_EDT}
### DSHOT_BIDIR_EN (`INT32`) {#DSHOT_BIDIR_EN}
Enable Extended DShot Telemetry.
Enable bidirectional DShot.
This parameter enables Extended DShot Telemetry which allows transmission of
additional telemetry within the eRPM frame. The EDT data is interleaved with
the eRPM frames at a low rate.
This parameter enables bidirectional DShot which provides RPM feedback.
Note that this requires ESCs that support bidirectional DSHot, e.g. BlHeli32.
This is not the same as DShot telemetry which requires an additional serial connection.
| Reboot | minValue | maxValue | increment | default | unit |
| ------- | -------- | -------- | --------- | ------------ | ---- |
| ✓ | | | | Disabled (0) | |
### DSHOT_ESC_TYPE (`INT32`) {#DSHOT_ESC_TYPE}
ESC Type.
The ESC firmware type
**Values:**
- `0`: Unknown
- `1`: AM32
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | | | | 0 | |
### DSHOT_MIN (`FLOAT`) {#DSHOT_MIN}
Minimum DShot Motor Output.
@@ -19541,174 +19523,6 @@ armed.
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | 0 | 1 | 0.01 | 0.055 | norm |
### DSHOT_MOT_POL1 (`INT32`) {#DSHOT_MOT_POL1}
Number of magnetic poles of motor 1.
Number of magnetic poles for motor 1.
Required to compute RPM from the eRPM returned by ESC telemetry.
Either get the number from the motor spec sheet or count the magnets
on the bell of the motor (not the stator magnets).
Typical motors for 5 inch props have 14 poles.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | 2 | 400 | | 14 | |
### DSHOT_MOT_POL10 (`INT32`) {#DSHOT_MOT_POL10}
Number of magnetic poles of motor 10.
Number of magnetic poles for motor 10.
Required to compute RPM from the eRPM returned by ESC telemetry.
Either get the number from the motor spec sheet or count the magnets
on the bell of the motor (not the stator magnets).
Typical motors for 5 inch props have 14 poles.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | 2 | 400 | | 14 | |
### DSHOT_MOT_POL11 (`INT32`) {#DSHOT_MOT_POL11}
Number of magnetic poles of motor 11.
Number of magnetic poles for motor 11.
Required to compute RPM from the eRPM returned by ESC telemetry.
Either get the number from the motor spec sheet or count the magnets
on the bell of the motor (not the stator magnets).
Typical motors for 5 inch props have 14 poles.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | 2 | 400 | | 14 | |
### DSHOT_MOT_POL12 (`INT32`) {#DSHOT_MOT_POL12}
Number of magnetic poles of motor 12.
Number of magnetic poles for motor 12.
Required to compute RPM from the eRPM returned by ESC telemetry.
Either get the number from the motor spec sheet or count the magnets
on the bell of the motor (not the stator magnets).
Typical motors for 5 inch props have 14 poles.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | 2 | 400 | | 14 | |
### DSHOT_MOT_POL2 (`INT32`) {#DSHOT_MOT_POL2}
Number of magnetic poles of motor 2.
Number of magnetic poles for motor 2.
Required to compute RPM from the eRPM returned by ESC telemetry.
Either get the number from the motor spec sheet or count the magnets
on the bell of the motor (not the stator magnets).
Typical motors for 5 inch props have 14 poles.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | 2 | 400 | | 14 | |
### DSHOT_MOT_POL3 (`INT32`) {#DSHOT_MOT_POL3}
Number of magnetic poles of motor 3.
Number of magnetic poles for motor 3.
Required to compute RPM from the eRPM returned by ESC telemetry.
Either get the number from the motor spec sheet or count the magnets
on the bell of the motor (not the stator magnets).
Typical motors for 5 inch props have 14 poles.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | 2 | 400 | | 14 | |
### DSHOT_MOT_POL4 (`INT32`) {#DSHOT_MOT_POL4}
Number of magnetic poles of motor 4.
Number of magnetic poles for motor 4.
Required to compute RPM from the eRPM returned by ESC telemetry.
Either get the number from the motor spec sheet or count the magnets
on the bell of the motor (not the stator magnets).
Typical motors for 5 inch props have 14 poles.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | 2 | 400 | | 14 | |
### DSHOT_MOT_POL5 (`INT32`) {#DSHOT_MOT_POL5}
Number of magnetic poles of motor 5.
Number of magnetic poles for motor 5.
Required to compute RPM from the eRPM returned by ESC telemetry.
Either get the number from the motor spec sheet or count the magnets
on the bell of the motor (not the stator magnets).
Typical motors for 5 inch props have 14 poles.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | 2 | 400 | | 14 | |
### DSHOT_MOT_POL6 (`INT32`) {#DSHOT_MOT_POL6}
Number of magnetic poles of motor 6.
Number of magnetic poles for motor 6.
Required to compute RPM from the eRPM returned by ESC telemetry.
Either get the number from the motor spec sheet or count the magnets
on the bell of the motor (not the stator magnets).
Typical motors for 5 inch props have 14 poles.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | 2 | 400 | | 14 | |
### DSHOT_MOT_POL7 (`INT32`) {#DSHOT_MOT_POL7}
Number of magnetic poles of motor 7.
Number of magnetic poles for motor 7.
Required to compute RPM from the eRPM returned by ESC telemetry.
Either get the number from the motor spec sheet or count the magnets
on the bell of the motor (not the stator magnets).
Typical motors for 5 inch props have 14 poles.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | 2 | 400 | | 14 | |
### DSHOT_MOT_POL8 (`INT32`) {#DSHOT_MOT_POL8}
Number of magnetic poles of motor 8.
Number of magnetic poles for motor 8.
Required to compute RPM from the eRPM returned by ESC telemetry.
Either get the number from the motor spec sheet or count the magnets
on the bell of the motor (not the stator magnets).
Typical motors for 5 inch props have 14 poles.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | 2 | 400 | | 14 | |
### DSHOT_MOT_POL9 (`INT32`) {#DSHOT_MOT_POL9}
Number of magnetic poles of motor 9.
Number of magnetic poles for motor 9.
Required to compute RPM from the eRPM returned by ESC telemetry.
Either get the number from the motor spec sheet or count the magnets
on the bell of the motor (not the stator magnets).
Typical motors for 5 inch props have 14 poles.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | 2 | 400 | | 14 | |
### DSHOT_TEL_CFG (`INT32`) {#DSHOT_TEL_CFG}
Serial Configuration for DShot Driver.
@@ -19734,6 +19548,20 @@ Configure on which serial port to run DShot Driver.
| ------- | -------- | -------- | --------- | ------- | ---- |
| ✓ | | | | 0 | |
### MOT_POLE_COUNT (`INT32`) {#MOT_POLE_COUNT}
Number of magnetic poles of the motors.
Specify the number of magnetic poles of the motors.
It is required to compute the RPM value from the eRPM returned with the ESC telemetry.
Either get the number from the motor spec sheet or count the magnets on the bell of the motor (not the stator magnets).
Typical motors for 5 inch props have 14 poles.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | | | | 14 | |
## EKF2
### EKF2_ABIAS_INIT (`FLOAT`) {#EKF2_ABIAS_INIT}
@@ -20469,6 +20297,16 @@ Set bits in the following positions to enable: 0 : Longitude and latitude fusion
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | 0 | 15 | | 7 | |
### EKF2_GPS_DELAY (`FLOAT`) {#EKF2_GPS_DELAY}
GPS measurement delay relative to IMU measurement.
GPS measurement delay relative to IMU measurement if PPS time correction is not available/enabled (PPS_CAP_ENABLE).
| Reboot | minValue | maxValue | increment | default | unit |
| ------- | -------- | -------- | --------- | ------- | ---- |
| ✓ | 0 | 300 | | 110 | ms |
### EKF2_GPS_MODE (`INT32`) {#EKF2_GPS_MODE}
Fusion reset mode.
@@ -20484,6 +20322,36 @@ Automatic: reset on fusion timeout if no other source of position is available.
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | | | | 0 | |
### EKF2_GPS_POS_X (`FLOAT`) {#EKF2_GPS_POS_X}
X position of GPS antenna in body frame.
Forward (roll) axis with origin relative to vehicle centre of gravity
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | | | | 0.0 | m |
### EKF2_GPS_POS_Y (`FLOAT`) {#EKF2_GPS_POS_Y}
Y position of GPS antenna in body frame.
Right (pitch) axis with origin relative to vehicle centre of gravity
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | | | | 0.0 | m |
### EKF2_GPS_POS_Z (`FLOAT`) {#EKF2_GPS_POS_Z}
Z position of GPS antenna in body frame.
Down (yaw) axis with origin relative to vehicle centre of gravity
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | | | | 0.0 | m |
### EKF2_GPS_P_GATE (`FLOAT`) {#EKF2_GPS_P_GATE}
Gate size for GNSS position fusion.
@@ -37318,129 +37186,14 @@ Configure on which serial port to run FT Technologies Digital Wind Sensor (seria
| ------- | -------- | -------- | --------- | ------- | ---- |
| ✓ | | | | 0 | |
### SENS_GPS0_DELAY (`INT32`) {#SENS_GPS0_DELAY}
GPS 0 measurement delay.
GPS measurement delay relative to IMU measurements.
Matched to physical GPS receiver via SENS_GPS0_ID.
Only applied when the GPS driver does not provide its own
timestamp_sample correction.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | 0 | 300 | | 110 | ms |
### SENS_GPS0_ID (`INT32`) {#SENS_GPS0_ID}
GPS 0 device ID.
Device ID of the GPS receiver for antenna offset slot 0.
Set to 0 to disable this slot. When all slots are 0, offsets are
matched by uORB instance index (only reliable for serial GPS).
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | | | | 0 | |
### SENS_GPS0_OFFX (`FLOAT`) {#SENS_GPS0_OFFX}
GPS 0 antenna X position.
Forward axis relative to vehicle centre of gravity.
Matched to physical GPS receiver via SENS_GPS0_ID.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | | | | 0.0 | m |
### SENS_GPS0_OFFY (`FLOAT`) {#SENS_GPS0_OFFY}
GPS 0 antenna Y position.
Right axis relative to vehicle centre of gravity.
Matched to physical GPS receiver via SENS_GPS0_ID.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | | | | 0.0 | m |
### SENS_GPS0_OFFZ (`FLOAT`) {#SENS_GPS0_OFFZ}
GPS 0 antenna Z position.
Down axis relative to vehicle centre of gravity.
Matched to physical GPS receiver via SENS_GPS0_ID.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | | | | 0.0 | m |
### SENS_GPS1_DELAY (`INT32`) {#SENS_GPS1_DELAY}
GPS 1 measurement delay.
GPS measurement delay relative to IMU measurements.
Matched to physical GPS receiver via SENS_GPS1_ID.
Only applied when the GPS driver does not provide its own
timestamp_sample correction.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | 0 | 300 | | 110 | ms |
### SENS_GPS1_ID (`INT32`) {#SENS_GPS1_ID}
GPS 1 device ID.
Device ID of the GPS receiver for antenna offset slot 1.
Set to 0 to disable this slot. When all slots are 0, offsets are
matched by uORB instance index (only reliable for serial GPS).
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | | | | 0 | |
### SENS_GPS1_OFFX (`FLOAT`) {#SENS_GPS1_OFFX}
GPS 1 antenna X position.
Forward axis relative to vehicle centre of gravity.
Matched to physical GPS receiver via SENS_GPS1_ID.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | | | | 0.0 | m |
### SENS_GPS1_OFFY (`FLOAT`) {#SENS_GPS1_OFFY}
GPS 1 antenna Y position.
Right axis relative to vehicle centre of gravity.
Matched to physical GPS receiver via SENS_GPS1_ID.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | | | | 0.0 | m |
### SENS_GPS1_OFFZ (`FLOAT`) {#SENS_GPS1_OFFZ}
GPS 1 antenna Z position.
Down axis relative to vehicle centre of gravity.
Matched to physical GPS receiver via SENS_GPS1_ID.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
|   | | | | 0.0 | m |
### SENS_GPS_MASK (`INT32`) {#SENS_GPS_MASK}
Multi GPS Blending Control Mask.
Set bits in the following positions to set which GPS accuracy metrics will
be used to calculate the blending weight. Set to zero to disable and always
used first GPS instance.
Set bits in the following positions to set which GPS accuracy metrics will be used to calculate the blending weight. Set to zero to disable and always used first GPS instance.
0 : Set to true to use speed accuracy
1 : Set to true to use horizontal position accuracy
2 : Set to true to use vertical position accuracy
**Bitmask:**
@@ -37461,7 +37214,11 @@ The GPS selection logic waits until the primary receiver is available to
send data to the EKF even if a secondary instance is already available.
The secondary instance is then only used if the primary one times out.
To select a DroneCAN GPS, set this to the node ID.
Accepted values:
-1 : Auto (equal priority for all instances)
0 : Main serial GPS instance
1 : Secondary serial GPS instance
2-127 : UAVCAN module node ID
This parameter has no effect if blending is active.
@@ -37473,9 +37230,7 @@ This parameter has no effect if blending is active.
Multi GPS Blending Time Constant.
Sets the longest time constant that will be applied to the calculation of GPS
position and height offsets used to correct data from multiple GPS data for
steady state position differences.
Sets the longest time constant that will be applied to the calculation of GPS position and height offsets used to correct data from multiple GPS data for steady state position differences.
| Reboot | minValue | maxValue | increment | default | unit |
| ------ | -------- | -------- | --------- | ------- | ---- |
+1 -1
View File
@@ -20,7 +20,7 @@ For more information see [Setting the Compass Orientation](../config/flight_cont
## Position
In order to compensate for the relative motion between the receiver and the CoG, you should [configure](../advanced_config/parameters.md) the following parameters to set the offsets: [SENS_GPS0_OFFX](../advanced_config/parameter_reference.md#SENS_GPS0_OFFX), [SENS_GPS0_OFFY](../advanced_config/parameter_reference.md#SENS_GPS0_OFFY) and [SENS_GPS0_OFFZ](../advanced_config/parameter_reference.md#SENS_GPS0_OFFZ).
In order to compensate for the relative motion between the receiver and the CoG, you should [configure](../advanced_config/parameters.md) the following parameters to set the offsets: [EKF2_GPS_POS_X](../advanced_config/parameter_reference.md#EKF2_GPS_POS_X), [EKF2_GPS_POS_Y](../advanced_config/parameter_reference.md#EKF2_GPS_POS_Y) and [EKF2_GPS_POS_Z](../advanced_config/parameter_reference.md#EKF2_GPS_POS_Z).
This is important because the body frame estimated by the EKF will converge on the location of the GNSS module and assume it to be at the CoG. If the GNSS module is significantly offset from the CoG, then rotation around the COG will be interpreted as an altitude change, which in some flight modes (such as position mode) will result in unnecessary corrections.
+1 -1
View File
@@ -72,7 +72,7 @@ The ESC RPM feedback is used to track the rotor blade pass frequency and its har
ESC RPM feedback requires ESCs capable of providing RPM feedback such as [DShot](../peripherals/dshot.md) with telemetry connected, a bidirectional DShot set up ([work in progress](https://github.com/PX4/PX4-Autopilot/pull/23863)), or [UAVCAN/DroneCAN ESCs](../dronecan/escs.md).
Before enabling, make sure that the ESC RPM is correct.
You might have to adjust the per-motor pole count (`DSHOT_MOT_POL1``DSHOT_MOT_POL12`).
You might have to adjust the [pole count of the motors](../advanced_config/parameter_reference.md#MOT_POLE_COUNT).
The following parameters should be set to enable and configure dynamic notch filters:
+1 -1
View File
@@ -97,7 +97,7 @@ There is also CAN built-in bus termination via [CANNODE_TERM](../advanced_config
You need to set necessary [DroneCAN](index.md) parameters and define offsets if the sensor is not centred within the vehicle:
- Enable [UAVCAN_SUB_GPS](../advanced_config/parameter_reference.md#UAVCAN_SUB_GPS), [UAVCAN_SUB_MAG](../advanced_config/parameter_reference.md#UAVCAN_SUB_MAG), and [UAVCAN_SUB_BARO](../advanced_config/parameter_reference.md#UAVCAN_SUB_BARO).
- The parameters [SENS_GPS0_OFFX](../advanced_config/parameter_reference.md#SENS_GPS0_OFFX), [SENS_GPS0_OFFY](../advanced_config/parameter_reference.md#SENS_GPS0_OFFY) and [SENS_GPS0_OFFZ](../advanced_config/parameter_reference.md#SENS_GPS0_OFFZ) can be set to account for the offset of the ARK G5 RTK GPS from the vehicle's centre of gravity.
- The parameters [EKF2_GPS_POS_X](../advanced_config/parameter_reference.md#EKF2_GPS_POS_X), [EKF2_GPS_POS_Y](../advanced_config/parameter_reference.md#EKF2_GPS_POS_Y) and [EKF2_GPS_POS_Z](../advanced_config/parameter_reference.md#EKF2_GPS_POS_Z) can be set to account for the offset of the ARK G5 RTK GPS from the vehicle's centre of gravity.
## LED Meanings
+1 -1
View File
@@ -99,7 +99,7 @@ You need to set necessary [DroneCAN](index.md) parameters and define offsets if
- Enable GPS yaw fusion by setting bit 3 of [EKF2_GPS_CTRL](../advanced_config/parameter_reference.md#EKF2_GPS_CTRL) to true.
- Enable GPS blending to ensure the heading is always published by setting [SENS_GPS_MASK](../advanced_config/parameter_reference.md#SENS_GPS_MASK) to 7 (all three bits checked).
- Enable [UAVCAN_SUB_GPS](../advanced_config/parameter_reference.md#UAVCAN_SUB_GPS), [UAVCAN_SUB_MAG](../advanced_config/parameter_reference.md#UAVCAN_SUB_MAG), and [UAVCAN_SUB_BARO](../advanced_config/parameter_reference.md#UAVCAN_SUB_BARO).
- The parameters [SENS_GPS0_OFFX](../advanced_config/parameter_reference.md#SENS_GPS0_OFFX), [SENS_GPS0_OFFY](../advanced_config/parameter_reference.md#SENS_GPS0_OFFY) and [SENS_GPS0_OFFZ](../advanced_config/parameter_reference.md#SENS_GPS0_OFFZ) can be set to account for the offset of the ARK G5 RTK HEADING GPS from the vehicle's centre of gravity.
- The parameters [EKF2_GPS_POS_X](../advanced_config/parameter_reference.md#EKF2_GPS_POS_X), [EKF2_GPS_POS_Y](../advanced_config/parameter_reference.md#EKF2_GPS_POS_Y) and [EKF2_GPS_POS_Z](../advanced_config/parameter_reference.md#EKF2_GPS_POS_Z) can be set to account for the offset of the ARK G5 RTK HEADING GPS from the vehicle's centre of gravity.
### Parameter references
+1 -1
View File
@@ -91,7 +91,7 @@ If the sensor is not centred within the vehicle you will also need to define sen
- Enable GPS yaw fusion by setting bit 3 of [EKF2_GPS_CTRL](../advanced_config/parameter_reference.md#EKF2_GPS_CTRL) to true.
- Enable [UAVCAN_SUB_GPS](../advanced_config/parameter_reference.md#UAVCAN_SUB_GPS), [UAVCAN_SUB_MAG](../advanced_config/parameter_reference.md#UAVCAN_SUB_MAG), and [UAVCAN_SUB_BARO](../advanced_config/parameter_reference.md#UAVCAN_SUB_BARO).
- The parameters [SENS_GPS0_OFFX](../advanced_config/parameter_reference.md#SENS_GPS0_OFFX), [SENS_GPS0_OFFY](../advanced_config/parameter_reference.md#SENS_GPS0_OFFY) and [SENS_GPS0_OFFZ](../advanced_config/parameter_reference.md#SENS_GPS0_OFFZ) can be set to account for the offset of the ARK GPS from the vehicles centre of gravity.
- The parameters [EKF2_GPS_POS_X](../advanced_config/parameter_reference.md#EKF2_GPS_POS_X), [EKF2_GPS_POS_Y](../advanced_config/parameter_reference.md#EKF2_GPS_POS_Y) and [EKF2_GPS_POS_Z](../advanced_config/parameter_reference.md#EKF2_GPS_POS_Z) can be set to account for the offset of the ARK GPS from the vehicles centre of gravity.
### ARK GPS Configuration
+1 -1
View File
@@ -86,7 +86,7 @@ You need to set necessary [DroneCAN](index.md) parameters and define offsets if
- Enable GPS blending to ensure the heading is always published by setting [SENS_GPS_MASK](../advanced_config/parameter_reference.md#SENS_GPS_MASK) to 7 (all three bits checked).
- If using [Moving Baseline & GPS Heading](#setting-up-moving-baseline--gps-heading), set [SENS_GPS_PRIME](../advanced_config/parameter_reference.md#SENS_GPS_PRIME) to the CAN node ID of the _Moving Base_ module. The moving base is preferred because the rover receiver in a moving baseline configuration can experience degraded navigation rate and increased data latency when corrections are intermittent.
- Enable [UAVCAN_SUB_GPS](../advanced_config/parameter_reference.md#UAVCAN_SUB_GPS), [UAVCAN_SUB_MAG](../advanced_config/parameter_reference.md#UAVCAN_SUB_MAG), and [UAVCAN_SUB_BARO](../advanced_config/parameter_reference.md#UAVCAN_SUB_BARO).
- The parameters [SENS_GPS0_OFFX](../advanced_config/parameter_reference.md#SENS_GPS0_OFFX), [SENS_GPS0_OFFY](../advanced_config/parameter_reference.md#SENS_GPS0_OFFY) and [SENS_GPS0_OFFZ](../advanced_config/parameter_reference.md#SENS_GPS0_OFFZ) can be set to account for the offset of the ARK RTK GPS from the vehicles centre of gravity.
- The parameters [EKF2_GPS_POS_X](../advanced_config/parameter_reference.md#EKF2_GPS_POS_X), [EKF2_GPS_POS_Y](../advanced_config/parameter_reference.md#EKF2_GPS_POS_Y) and [EKF2_GPS_POS_Z](../advanced_config/parameter_reference.md#EKF2_GPS_POS_Z) can be set to account for the offset of the ARK RTK GPS from the vehicles centre of gravity.
### ARK RTK GPS Configuration
+1 -1
View File
@@ -85,7 +85,7 @@ You need to set necessary [DroneCAN](index.md) parameters and define offsets if
- Enable GPS yaw fusion by setting bit 3 of [EKF2_GPS_CTRL](../advanced_config/parameter_reference.md#EKF2_GPS_CTRL) to true.
- Enable GPS blending to ensure the heading is always published by setting [SENS_GPS_MASK](../advanced_config/parameter_reference.md#SENS_GPS_MASK) to 7 (all three bits checked).
- Enable [UAVCAN_SUB_GPS](../advanced_config/parameter_reference.md#UAVCAN_SUB_GPS), [UAVCAN_SUB_MAG](../advanced_config/parameter_reference.md#UAVCAN_SUB_MAG), and [UAVCAN_SUB_BARO](../advanced_config/parameter_reference.md#UAVCAN_SUB_BARO).
- The parameters [SENS_GPS0_OFFX](../advanced_config/parameter_reference.md#SENS_GPS0_OFFX), [SENS_GPS0_OFFY](../advanced_config/parameter_reference.md#SENS_GPS0_OFFY) and [SENS_GPS0_OFFZ](../advanced_config/parameter_reference.md#SENS_GPS0_OFFZ) can be set to account for the offset of the ARK RTK GPS L1 L5 from the vehicles centre of gravity.
- The parameters [EKF2_GPS_POS_X](../advanced_config/parameter_reference.md#EKF2_GPS_POS_X), [EKF2_GPS_POS_Y](../advanced_config/parameter_reference.md#EKF2_GPS_POS_Y) and [EKF2_GPS_POS_Z](../advanced_config/parameter_reference.md#EKF2_GPS_POS_Z) can be set to account for the offset of the ARK RTK GPS L1 L5 from the vehicles centre of gravity.
### ARK RTK GPS L1 L5 Configuration
+1 -1
View File
@@ -88,7 +88,7 @@ You need to set necessary [DroneCAN](index.md) parameters and define offsets if
- Enable GPS yaw fusion by setting bit 3 of [EKF2_GPS_CTRL](../advanced_config/parameter_reference.md#EKF2_GPS_CTRL) to true.
- Enable GPS blending to ensure the heading is always published by setting [SENS_GPS_MASK](../advanced_config/parameter_reference.md#SENS_GPS_MASK) to 7 (all three bits checked).
- Enable [UAVCAN_SUB_GPS](../advanced_config/parameter_reference.md#UAVCAN_SUB_GPS), [UAVCAN_SUB_MAG](../advanced_config/parameter_reference.md#UAVCAN_SUB_MAG), and [UAVCAN_SUB_BARO](../advanced_config/parameter_reference.md#UAVCAN_SUB_BARO).
- The parameters [SENS_GPS0_OFFX](../advanced_config/parameter_reference.md#SENS_GPS0_OFFX), [SENS_GPS0_OFFY](../advanced_config/parameter_reference.md#SENS_GPS0_OFFY) and [SENS_GPS0_OFFZ](../advanced_config/parameter_reference.md#SENS_GPS0_OFFZ) can be set to account for the offset of the ARK X20 RTK GPS from the vehicles centre of gravity.
- The parameters [EKF2_GPS_POS_X](../advanced_config/parameter_reference.md#EKF2_GPS_POS_X), [EKF2_GPS_POS_Y](../advanced_config/parameter_reference.md#EKF2_GPS_POS_Y) and [EKF2_GPS_POS_Z](../advanced_config/parameter_reference.md#EKF2_GPS_POS_Z) can be set to account for the offset of the ARK X20 RTK GPS from the vehicles centre of gravity.
### ARK X20 RTK GPS Configuration
+1 -1
View File
@@ -94,4 +94,4 @@ If the sensor is not centred within the vehicle you will also need to define sen
- Enable GPS yaw fusion by setting bit 3 of [EKF2_GPS_CTRL](../advanced_config/parameter_reference.md#EKF2_GPS_CTRL) to true.
- Enable [UAVCAN_SUB_GPS](../advanced_config/parameter_reference.md#UAVCAN_SUB_GPS), [UAVCAN_SUB_MAG](../advanced_config/parameter_reference.md#UAVCAN_SUB_MAG), and [UAVCAN_SUB_BARO](../advanced_config/parameter_reference.md#UAVCAN_SUB_BARO).
- Set [CANNODE_TERM](../advanced_config/parameter_reference.md#CANNODE_TERM) to `1` if this is that last node on the CAN bus.
- The parameters [SENS_GPS0_OFFX](../advanced_config/parameter_reference.md#SENS_GPS0_OFFX), [SENS_GPS0_OFFY](../advanced_config/parameter_reference.md#SENS_GPS0_OFFY) and [SENS_GPS0_OFFZ](../advanced_config/parameter_reference.md#SENS_GPS0_OFFZ) can be set to account for the offset of the ARK GPS from the vehicles centre of gravity.
- The parameters [EKF2_GPS_POS_X](../advanced_config/parameter_reference.md#EKF2_GPS_POS_X), [EKF2_GPS_POS_Y](../advanced_config/parameter_reference.md#EKF2_GPS_POS_Y) and [EKF2_GPS_POS_Z](../advanced_config/parameter_reference.md#EKF2_GPS_POS_Z) can be set to account for the offset of the ARK GPS from the vehicles centre of gravity.
+1 -1
View File
@@ -188,7 +188,7 @@ GPS CANNODE parameter ([set using QGC](#qgc-cannode-parameter-configuration)):
Other PX4 Parameters:
- If the GPS is not positioned at the vehicle centre of gravity you can account for the offset using [SENS_GPS0_OFFX](../advanced_config/parameter_reference.md#SENS_GPS0_OFFX), [SENS_GPS0_OFFY](../advanced_config/parameter_reference.md#SENS_GPS0_OFFY) and [SENS_GPS0_OFFZ](../advanced_config/parameter_reference.md#SENS_GPS0_OFFZ).
- If the GPS is not positioned at the vehicle centre of gravity you can account for the offset using [EKF2_GPS_POS_X](../advanced_config/parameter_reference.md#EKF2_GPS_POS_X), [EKF2_GPS_POS_Y](../advanced_config/parameter_reference.md#EKF2_GPS_POS_Y) and [EKF2_GPS_POS_Z](../advanced_config/parameter_reference.md#EKF2_GPS_POS_Z).
- If the GPS module provides yaw information, you can enable GPS yaw fusion by setting bit 3 of [EKF2_GPS_CTRL](../advanced_config/parameter_reference.md#EKF2_GPS_CTRL) to true.
#### RTK GPS
-12
View File
@@ -51,18 +51,6 @@ Other
- Open source AM32 firmware
- [DIU Blue Framework Listed](https://www.diu.mil/blue-uas/framework)
## PX4 Configuration
The ARK 4IN1 ESC supports DShot 300/600, Bidirectional DShot, and PWM input protocols.
- **Bidirectional DShot**: Select BDShot300 or BDShot600 in the [Actuator Configuration](../config/actuators.md) to enable eRPM telemetry.
- **[Extended DShot Telemetry (EDT)](https://github.com/bird-sanctuary/extended-dshot-telemetry)**: AM32 firmware supports EDT, which provides temperature, voltage, and current through the BDShot signal. Enable with `DSHOT_BIDIR_EDT=1`.
- **AM32 EEPROM Settings**: Set `DSHOT_ESC_TYPE=1` to enable reading and writing ESC firmware settings via a ground station.
See [DShot ESCs](../peripherals/dshot.md) for full setup details.
## See Also
- [ARK 4IN1 ESC CONS](https://docs.arkelectron.com/electronic-speed-controller/ark-4in1-esc) (ARK Docs)
- [DShot and Bidirectional DShot](https://brushlesswhoop.com/dshot-and-bidirectional-dshot/) (brushlesswhoop.com - General DShot reference)
- [Extended DShot Telemetry (EDT) Specification](https://github.com/bird-sanctuary/extended-dshot-telemetry) (bird-sanctuary)
+53 -23
View File
@@ -4,11 +4,11 @@
The _Return_ flight mode is used to _fly a vehicle to safety_ on an unobstructed path to a safe destination, where it should land.
The following topics should be read first if you're using these vehicle types:
Each vehicle has a **default** return mode behavior which is described in the linked topics (read those first if you plan on using the defaults):
- [Multicopter](../flight_modes_mc/return.md)
- [Fixed-wing (Plane)](../flight_modes_fw/return.md)
- [VTOL](../flight_modes_vtol/return.md)
- [Multicopter](../flight_modes_mc/return.md) — Home/rally point return
- [Fixed-wing (Plane)](../flight_modes_fw/return.md) — Mission landing/Rally point return
- [VTOL](../flight_modes_vtol/return.md) — Mission landing/Rally point return
::: info
@@ -40,11 +40,9 @@ This topic covers all the possible return types that any vehicle _might_ be conf
The following sections explain how to configure the [return type](#return_types), [minimum return altitude](#minimum-return-altitude) and [landing/arrival behaviour](#loiter-landing-at-destination).
<a id="return_types"></a>
## Return Types (RTL_TYPE) {#return_types}
## Return Types (RTL_TYPE)
PX4 provides four alternative approaches for finding an unobstructed path to a safe destination and/or landing, which are set using the [RTL_TYPE](#RTL_TYPE) parameter.
PX4 provides a number of alternative approaches for finding an unobstructed path to a safe destination and/or landing, which are set using the [RTL_TYPE](#RTL_TYPE) parameter.
At high level these are:
@@ -56,12 +54,16 @@ At high level these are:
If no _mission_ defined, return direct to home (rally points are ignored).
- [Closest safe destination return](#closest-safe-destination-return-type-rtl-type-3) (`RTL_TYPE=3`): Ascend to a safe altitude and return via direct path to closest destination: home, start of mission landing pattern, or rally point.
If the destination is a mission landing pattern, follow the pattern to land.
- [Reverse mission return or mission landing](#mission-landing-or-reverse-mission-return-type-rtl-type-4) (`RTL_TYPE=4`): Return to the planned mission landing, or to home via the reverse mission path, whichever is closer (counted by waypoints).
Do not consider rally points.
If no mission is defined, return direct to home.
- [Safe point return](#safe-point-return-type-rtl-type-5) (`RTL_TYPE=5`): Return directly to the closest rally (safe) point.
Do not consider the home position or mission landing.
If no rally point is defined, descend and loiter at the current position.
More detailed explanations for each of the types are provided in the following sections.
<a id="home_return"></a>
### Home/Rally Point Return Type (RTL_TYPE=0)
### Home/Rally Point Return Type (RTL_TYPE=0) {#home_return}
This is the default return type for a [multicopter](../flight_modes_mc/return.md) (see topic for more information).
@@ -147,6 +149,34 @@ In this return type the vehicle:
By default an MC or VTOL in MC mode will land, and a fixed-wing vehicle circles at the descent altitude.
A VTOL in FW mode aligns its heading to the destination point, transitions to MC mode, and then lands.
### Mission Landing or Reverse Mission Return Type (RTL_TYPE=4)
This return type uses the mission (if defined) to provide a safe return path (either forward or in reverse), and the [mission landing pattern](#mission-landing-pattern) (if defined) to provide landing behaviour:
- If a mission landing pattern exists and it is closer (by waypoint count) than home via the reverse mission, the vehicle flies forward to the mission landing.
- Otherwise it flies the mission in reverse to return home.
- If no valid mission is defined, the vehicle returns directly to home.
- Rally points are ignored.
Note that this is similar to [RTL_TYPE=2](#mission-path-return-type-rtl-type-2), but the choice between fast-forward and fast-reverse is based on which destination is _closer by waypoint count_ rather than which flight mode is active when return mode is activated.
### Safe Point Return Type (RTL_TYPE=5)
In this return type the vehicle returns directly to the closest rally point (only).
Home position and mission landings are not considered.
The vehicle:
- Ascends to a safe [minimum return altitude](#minimum-return-altitude) (above any expected obstacles).
- Flies via a direct path to the closest rally point.
- On [arrival](#loiter-landing-at-destination) descends to the descent altitude and [lands or waits](#loiter-landing-at-destination) (depending on landing parameters).
If no rally point is defined, the vehicle will descend and loiter at its current position (it will not return to home).
::: info
This type is useful when the home position is not a safe return point.
:::
## Minimum Return Altitude
For most [return types](#return_types) a vehicle will ascend to a _minimum safe altitude_ before returning (unless already above that altitude), in order to avoid any obstacles between it and the destination.
@@ -205,15 +235,15 @@ For this reason fixed-wing vehicles are configured to use [Mission landing/reall
The RTL parameters are listed in [Parameter Reference > Return Mode](../advanced_config/parameter_reference.md#return-mode) (and summarised below).
| Parameter | Description |
| ----------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <a id="RTL_TYPE"></a>[RTL_TYPE](../advanced_config/parameter_reference.md#RTL_TYPE) | Return mechanism (path and destination).<br>`0`: Return to a rally point or home (whichever is closest) via direct path.<br>`1`: Return to a rally point or the mission landing pattern start point (whichever is closest), via direct path. If neither mission landing or rally points are defined return home via a direct path. If the destination is a mission landing pattern, follow the pattern to land.<br>`2`: Use mission path fast-forward to landing if a landing pattern is defined, otherwise fast-reverse to home. Ignore rally points. Fly direct to home if no mission plan is defined.<br>`3`: Return via direct path to closest destination: home, start of mission landing pattern or safe point. If the destination is a mission landing pattern, follow the pattern to land. |
| <a id="RTL_RETURN_ALT"></a>[RTL_RETURN_ALT](../advanced_config/parameter_reference.md#RTL_RETURN_ALT) | Return altitude in meters (default: 60m) when [RTL_CONE_ANG](../advanced_config/parameter_reference.md#RTL_CONE_ANG) is 0. If already above this value the vehicle will return at its current altitude. |
| <a id="RTL_DESCEND_ALT"></a>[RTL_DESCEND_ALT](../advanced_config/parameter_reference.md#RTL_DESCEND_ALT) | Minimum return altitude and altitude at which the vehicle will slow or stop its initial descent from a higher return altitude (default: 30m) |
| <a id="RTL_LAND_DELAY"></a>[RTL_LAND_DELAY](../advanced_config/parameter_reference.md#RTL_LAND_DELAY) | Time to wait at `RTL_DESCEND_ALT` before landing (default: 0.5s) -by default this period is short so that the vehicle will simply slow and then land immediately. If set to -1 the system will loiter at `RTL_DESCEND_ALT` rather than landing. The delay is provided to allow you to configure time for landing gear to be deployed (triggered automatically). |
| <a id="RTL_MIN_DIST"></a>[RTL_MIN_DIST](../advanced_config/parameter_reference.md#RTL_MIN_DIST) | Minimum horizontal distance from home position to trigger ascent to the return altitude specified by the "cone". If the vehicle is horizontally closer than this distance to home, it will return at its current altitude or `RTL_DESCEND_ALT` (whichever is higher) instead of first ascending to RTL_RETURN_ALT. |
| <a id="RTL_CONE_ANG"></a>[RTL_CONE_ANG](../advanced_config/parameter_reference.md#RTL_CONE_ANG) | Half-angle of the cone that defines the vehicle RTL return altitude. Values (in degrees): 0, 25, 45, 65, 80, 90. Note that 0 is "no cone" (always return at `RTL_RETURN_ALT` or higher), while 90 indicates that the vehicle must return at the current altitude or `RTL_DESCEND_ALT` (whichever is higher). |
| <a id="COM_RC_OVERRIDE"></a>[COM_RC_OVERRIDE](../advanced_config/parameter_reference.md#COM_RC_OVERRIDE) | Controls whether stick movement on a multicopter (or VTOL in MC mode) causes a mode change to [Position mode](../flight_modes_mc/position.md) (except when vehicle is handling a critical battery failsafe). This can be separately enabled for auto modes and for offboard mode, and is enabled in auto modes by default. |
| <a id="COM_RC_STICK_OV"></a>[COM_RC_STICK_OV](../advanced_config/parameter_reference.md#COM_RC_STICK_OV) | The amount of stick movement that causes a transition to [Position mode](../flight_modes_mc/position.md) (if [COM_RC_OVERRIDE](#COM_RC_OVERRIDE) is enabled). |
| <a id="RTL_LOITER_RAD"></a>[RTL_LOITER_RAD](../advanced_config/parameter_reference.md#RTL_LOITER_RAD) | [Fixed-wing Only] The radius of the loiter circle (at [RTL_LAND_DELAY](#RTL_LAND_DELAY)). |
| <a id="MIS_TKO_LAND_REQ"></a>[MIS_TKO_LAND_REQ](../advanced_config/parameter_reference.md#MIS_TKO_LAND_REQ) | Specify whether a mission landing or takeoff pattern is _required_. Generally fixed-wing vehicles set this to require a landing pattern but VTOL do not. |
| Parameter | Description |
| ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| <a id="RTL_TYPE"></a>[RTL_TYPE](../advanced_config/parameter_reference.md#RTL_TYPE) | Return mechanism (path and destination).<br>`0`: Return to a rally point or home (whichever is closest) via direct path.<br>`1`: Return to a rally point or the mission landing pattern start point (whichever is closest), via direct path. If neither mission landing or rally points are defined return home via a direct path. If the destination is a mission landing pattern, follow the pattern to land.<br>`2`: Use mission path fast-forward to landing if a landing pattern is defined, otherwise fast-reverse to home. Ignore rally points. Fly direct to home if no mission plan is defined.<br>`3`: Return via direct path to closest destination: home, start of mission landing pattern or safe point. If the destination is a mission landing pattern, follow the pattern to land.<br>`4`: Return home via the reverse mission path or to the planned mission landing, whichever is closer by waypoint count. Ignore rally points. Fly direct to home if no mission is defined.<br>`5`: Return directly to the closest rally point (safe point). Ignore home and mission landing. If no rally point is defined, descend at current position. |
| <a id="RTL_RETURN_ALT"></a>[RTL_RETURN_ALT](../advanced_config/parameter_reference.md#RTL_RETURN_ALT) | Return altitude in meters (default: 60m) when [RTL_CONE_ANG](../advanced_config/parameter_reference.md#RTL_CONE_ANG) is 0. If already above this value the vehicle will return at its current altitude. |
| <a id="RTL_DESCEND_ALT"></a>[RTL_DESCEND_ALT](../advanced_config/parameter_reference.md#RTL_DESCEND_ALT) | Minimum return altitude and altitude at which the vehicle will slow or stop its initial descent from a higher return altitude (default: 30m) |
| <a id="RTL_LAND_DELAY"></a>[RTL_LAND_DELAY](../advanced_config/parameter_reference.md#RTL_LAND_DELAY) | Time to wait at `RTL_DESCEND_ALT` before landing (default: 0.5s) -by default this period is short so that the vehicle will simply slow and then land immediately. If set to -1 the system will loiter at `RTL_DESCEND_ALT` rather than landing. The delay is provided to allow you to configure time for landing gear to be deployed (triggered automatically). |
| <a id="RTL_MIN_DIST"></a>[RTL_MIN_DIST](../advanced_config/parameter_reference.md#RTL_MIN_DIST) | Minimum horizontal distance from home position to trigger ascent to the return altitude specified by the "cone". If the vehicle is horizontally closer than this distance to home, it will return at its current altitude or `RTL_DESCEND_ALT` (whichever is higher) instead of first ascending to RTL_RETURN_ALT. |
| <a id="RTL_CONE_ANG"></a>[RTL_CONE_ANG](../advanced_config/parameter_reference.md#RTL_CONE_ANG) | Half-angle of the cone that defines the vehicle RTL return altitude. Values (in degrees): 0, 25, 45, 65, 80, 90. Note that 0 is "no cone" (always return at `RTL_RETURN_ALT` or higher), while 90 indicates that the vehicle must return at the current altitude or `RTL_DESCEND_ALT` (whichever is higher). |
| <a id="COM_RC_OVERRIDE"></a>[COM_RC_OVERRIDE](../advanced_config/parameter_reference.md#COM_RC_OVERRIDE) | Controls whether stick movement on a multicopter (or VTOL in MC mode) causes a mode change to [Position mode](../flight_modes_mc/position.md) (except when vehicle is handling a critical battery failsafe). This can be separately enabled for auto modes and for offboard mode, and is enabled in auto modes by default. |
| <a id="COM_RC_STICK_OV"></a>[COM_RC_STICK_OV](../advanced_config/parameter_reference.md#COM_RC_STICK_OV) | The amount of stick movement that causes a transition to [Position mode](../flight_modes_mc/position.md) (if [COM_RC_OVERRIDE](#COM_RC_OVERRIDE) is enabled). |
| <a id="RTL_LOITER_RAD"></a>[RTL_LOITER_RAD](../advanced_config/parameter_reference.md#RTL_LOITER_RAD) | [Fixed-wing Only] The radius of the loiter circle (at [RTL_LAND_DELAY](#RTL_LAND_DELAY)). |
| <a id="MIS_TKO_LAND_REQ"></a>[MIS_TKO_LAND_REQ](../advanced_config/parameter_reference.md#MIS_TKO_LAND_REQ) | Specify whether a mission landing or takeoff pattern is _required_. Generally fixed-wing vehicles set this to require a landing pattern but VTOL do not. |
+5
View File
@@ -4,6 +4,11 @@
The _Return_ flight mode is used to _fly a vehicle to safety_ on an unobstructed path to a safe destination, where it can land.
This topic describes the [Mission Landing/Rally Point](../flight_modes/return.md#mission-landing-rally-point-return-type-rtl-type-1) return type that FW vehicles use by default.
See the [Return Mode (Generic Vehicle)](../flight_modes/return.md#return-types-rtl-type) for an overview of the other supported types.
## Overview
Fixed-wing vehicles use the [Mission Landing/Rally Point](../flight_modes/return.md#mission-landing-rally-point-return-type-rtl-type-1) return type by default, and are expected to always have a mission with a landing pattern.
With this configuration, return mode causes the vehicle to ascend to a minimum safe altitude above obstructions (if needed), fly to the start of the landing pattern defined in the mission plan, and then follow it to land.
+5
View File
@@ -4,6 +4,11 @@
The _Return_ flight mode is used to _fly a vehicle to safety_ on an unobstructed path to a safe destination, where it can land.
This topic describes the [home/rally point return type](../flight_modes/return.md#home-rally-point-return-type-rtl-type-0) return type that MC vehicles use by default.
See the [Return Mode (Generic Vehicle)](../flight_modes/return.md#return-types-rtl-type) for an overview of the other supported types.
## Overview
Multicopters use a [home/rally point return type](../flight_modes/return.md#home-rally-point-return-type-rtl-type-0) by default.
In this return type vehicles ascend to a safe altitude above obstructions if needed, fly directly to the closest safe landing point (a rally point or the home position), descend to the "descent altitude", wait briefly, and then land.
The return altitude, descent altitude, and landing delay are normally set to conservative "safe" values, but can be changed if needed.
+5
View File
@@ -4,6 +4,11 @@
The _Return_ flight mode is used to _fly a vehicle to safety_ on an unobstructed path to a safe destination, where it may either wait (hover or circle) or land.
This topic describes the [Mission Landing/Rally Point](../flight_modes/return.md#mission-landing-rally-point-return-type-rtl-type-1) return type that VTOL vehicles use by default.
See the [Return Mode (Generic Vehicle)](../flight_modes/return.md#return-types-rtl-type) for an overview of the other supported types.
## Overview
VTOL vehicles use the [Mission Landing/Rally Point](../flight_modes/return.md#mission-landing-rally-point-return-type-rtl-type-1) return type by default.
In this return type a vehicle ascends to a minimum safe altitude above obstructions (if needed), and then flies directly to a rally point or the start of a mission landing point (whichever is nearest), or the home position if neither rally points or mission landing pattern is defined.
If the destination is a mission landing pattern, the vehicle will then follow the pattern to land.
+1 -1
View File
@@ -230,7 +230,7 @@ If you search in the file you'll find groups of messages defined in a switch sta
- `MAVLINK_MODE_IRIDIUM`: Streamed to an iridium satellite phone
Normally you'll be testing on a GCS, so you could just add the message to the `MAVLINK_MODE_NORMAL` case using the `configure_stream_local()` method.
For example, to stream `BATTERY_STATUS_DEMO` at 5 Hz:
For example, to stream CA_TRAJECTORY at 5 Hz:
```cpp
case MAVLINK_MODE_CONFIG: // USB
+193 -195
View File
@@ -95,204 +95,202 @@ They are not build into the module, and hence are neither published or subscribe
::: details See messages
- [OpenDroneIdSystem](../msg_docs/OpenDroneIdSystem.md)
- [OpenDroneIdArmStatus](../msg_docs/OpenDroneIdArmStatus.md)
- [HoverThrustEstimate](../msg_docs/HoverThrustEstimate.md)
- [PositionSetpoint](../msg_docs/PositionSetpoint.md)
- [Rpm](../msg_docs/Rpm.md)
- [VehicleAirData](../msg_docs/VehicleAirData.md)
- [ParameterSetValueResponse](../msg_docs/ParameterSetValueResponse.md)
- [EstimatorAidSource2d](../msg_docs/EstimatorAidSource2d.md)
- [SensorGyroFft](../msg_docs/SensorGyroFft.md)
- [ButtonEvent](../msg_docs/ButtonEvent.md)
- [GimbalManagerSetAttitude](../msg_docs/GimbalManagerSetAttitude.md)
- [YawEstimatorStatus](../msg_docs/YawEstimatorStatus.md)
- [RateCtrlStatus](../msg_docs/RateCtrlStatus.md)
- [InternalCombustionEngineControl](../msg_docs/InternalCombustionEngineControl.md)
- [ConfigOverridesV0](../msg_docs/ConfigOverridesV0.md)
- [CameraStatus](../msg_docs/CameraStatus.md)
- [OrbitStatus](../msg_docs/OrbitStatus.md)
- [RtlTimeEstimate](../msg_docs/RtlTimeEstimate.md)
- [EstimatorInnovations](../msg_docs/EstimatorInnovations.md)
- [MissionResult](../msg_docs/MissionResult.md)
- [DifferentialPressure](../msg_docs/DifferentialPressure.md)
- [GpsInjectData](../msg_docs/GpsInjectData.md)
- [GpsDump](../msg_docs/GpsDump.md)
- [QshellReq](../msg_docs/QshellReq.md)
- [EstimatorGpsStatus](../msg_docs/EstimatorGpsStatus.md)
- [TuneControl](../msg_docs/TuneControl.md)
- [LandingTargetPose](../msg_docs/LandingTargetPose.md)
- [EstimatorAidSource3d](../msg_docs/EstimatorAidSource3d.md)
- [PwmInput](../msg_docs/PwmInput.md)
- [FollowTargetEstimator](../msg_docs/FollowTargetEstimator.md)
- [RtlStatus](../msg_docs/RtlStatus.md)
- [ActuatorTest](../msg_docs/ActuatorTest.md)
- [VehicleImu](../msg_docs/VehicleImu.md)
- [Event](../msg_docs/Event.md)
- [FollowTarget](../msg_docs/FollowTarget.md)
- [BatteryInfo](../msg_docs/BatteryInfo.md)
- [GimbalDeviceInformation](../msg_docs/GimbalDeviceInformation.md)
- [OrbTestLarge](../msg_docs/OrbTestLarge.md)
- [QshellRetval](../msg_docs/QshellRetval.md)
- [UavcanParameterValue](../msg_docs/UavcanParameterValue.md)
- [VehicleConstraints](../msg_docs/VehicleConstraints.md)
- [GimbalControls](../msg_docs/GimbalControls.md)
- [LogMessage](../msg_docs/LogMessage.md)
- [RegisterExtComponentRequestV0](../msg_docs/RegisterExtComponentRequestV0.md)
- [RoverRateStatus](../msg_docs/RoverRateStatus.md)
- [LaunchDetectionStatus](../msg_docs/LaunchDetectionStatus.md)
- [FixedWingLateralStatus](../msg_docs/FixedWingLateralStatus.md)
- [VehicleAngularVelocity](../msg_docs/VehicleAngularVelocity.md)
- [TiltrotorExtraControls](../msg_docs/TiltrotorExtraControls.md)
- [EscStatus](../msg_docs/EscStatus.md)
- [GimbalManagerSetManualControl](../msg_docs/GimbalManagerSetManualControl.md)
- [GeofenceStatus](../msg_docs/GeofenceStatus.md)
- [DebugValue](../msg_docs/DebugValue.md)
- [PurePursuitStatus](../msg_docs/PurePursuitStatus.md)
- [GeneratorStatus](../msg_docs/GeneratorStatus.md)
- [Ping](../msg_docs/Ping.md)
- [EstimatorStatus](../msg_docs/EstimatorStatus.md)
- [PositionControllerStatus](../msg_docs/PositionControllerStatus.md)
- [DatamanRequest](../msg_docs/DatamanRequest.md)
- [VehicleImuStatus](../msg_docs/VehicleImuStatus.md)
- [VehicleOpticalFlowVel](../msg_docs/VehicleOpticalFlowVel.md)
- [ArmingCheckReplyV0](../msg_docs/ArmingCheckReplyV0.md)
- [AirspeedWind](../msg_docs/AirspeedWind.md)
- [ParameterResetRequest](../msg_docs/ParameterResetRequest.md)
- [InputRc](../msg_docs/InputRc.md)
- [EventV0](../msg_docs/EventV0.md)
- [VehicleAngularAccelerationSetpoint](../msg_docs/VehicleAngularAccelerationSetpoint.md)
- [FigureEightStatus](../msg_docs/FigureEightStatus.md)
- [UlogStreamAck](../msg_docs/UlogStreamAck.md)
- [GimbalDeviceSetAttitude](../msg_docs/GimbalDeviceSetAttitude.md)
- [ParameterSetUsedRequest](../msg_docs/ParameterSetUsedRequest.md)
- [SensorGyro](../msg_docs/SensorGyro.md)
- [TakeoffStatus](../msg_docs/TakeoffStatus.md)
- [AirspeedValidatedV0](../msg_docs/AirspeedValidatedV0.md)
- [IridiumsbdStatus](../msg_docs/IridiumsbdStatus.md)
- [DebugArray](../msg_docs/DebugArray.md)
- [FuelTankStatus](../msg_docs/FuelTankStatus.md)
- [MagWorkerData](../msg_docs/MagWorkerData.md)
- [SensorCorrection](../msg_docs/SensorCorrection.md)
- [ActuatorServosTrim](../msg_docs/ActuatorServosTrim.md)
- [VehicleAttitudeSetpointV0](../msg_docs/VehicleAttitudeSetpointV0.md)
- [DronecanNodeStatus](../msg_docs/DronecanNodeStatus.md)
- [FailureDetectorStatus](../msg_docs/FailureDetectorStatus.md)
- [PowerMonitor](../msg_docs/PowerMonitor.md)
- [FlightPhaseEstimation](../msg_docs/FlightPhaseEstimation.md)
- [Airspeed](../msg_docs/Airspeed.md)
- [EscEepromRead](../msg_docs/EscEepromRead.md)
- [VehicleAcceleration](../msg_docs/VehicleAcceleration.md)
- [SensorAccel](../msg_docs/SensorAccel.md)
- [ParameterUpdate](../msg_docs/ParameterUpdate.md)
- [AdcReport](../msg_docs/AdcReport.md)
- [UavcanParameterRequest](../msg_docs/UavcanParameterRequest.md)
- [CanInterfaceStatus](../msg_docs/CanInterfaceStatus.md)
- [RadioStatus](../msg_docs/RadioStatus.md)
- [SensorTemp](../msg_docs/SensorTemp.md)
- [GimbalManagerStatus](../msg_docs/GimbalManagerStatus.md)
- [VehicleStatusV0](../msg_docs/VehicleStatusV0.md)
- [RcParameterMap](../msg_docs/RcParameterMap.md)
- [VehicleGlobalPositionV0](../msg_docs/VehicleGlobalPositionV0.md)
- [PositionControllerLandingStatus](../msg_docs/PositionControllerLandingStatus.md)
- [TrajectorySetpoint6dof](../msg_docs/TrajectorySetpoint6dof.md)
- [VehicleOpticalFlow](../msg_docs/VehicleOpticalFlow.md)
- [ActionRequest](../msg_docs/ActionRequest.md)
- [EstimatorAidSource1d](../msg_docs/EstimatorAidSource1d.md)
- [RaptorStatus](../msg_docs/RaptorStatus.md)
- [MountOrientation](../msg_docs/MountOrientation.md)
- [Vtx](../msg_docs/Vtx.md)
- [TaskStackInfo](../msg_docs/TaskStackInfo.md)
- [SensorMag](../msg_docs/SensorMag.md)
- [DistanceSensorModeChangeRequest](../msg_docs/DistanceSensorModeChangeRequest.md)
- [RoverAttitudeStatus](../msg_docs/RoverAttitudeStatus.md)
- [RcChannels](../msg_docs/RcChannels.md)
- [GimbalManagerInformation](../msg_docs/GimbalManagerInformation.md)
- [EstimatorSensorBias](../msg_docs/EstimatorSensorBias.md)
- [MagnetometerBiasEstimate](../msg_docs/MagnetometerBiasEstimate.md)
- [LoggerStatus](../msg_docs/LoggerStatus.md)
- [RaptorInput](../msg_docs/RaptorInput.md)
- [GpioIn](../msg_docs/GpioIn.md)
- [EstimatorStates](../msg_docs/EstimatorStates.md)
- [SatelliteInfo](../msg_docs/SatelliteInfo.md)
- [NavigatorStatus](../msg_docs/NavigatorStatus.md)
- [SystemPower](../msg_docs/SystemPower.md)
- [OpenDroneIdSelfId](../msg_docs/OpenDroneIdSelfId.md)
- [SensorsStatus](../msg_docs/SensorsStatus.md)
- [WheelEncoders](../msg_docs/WheelEncoders.md)
- [SensorAirflow](../msg_docs/SensorAirflow.md)
- [DebugKeyValue](../msg_docs/DebugKeyValue.md)
- [SensorGnssRelative](../msg_docs/SensorGnssRelative.md)
- [SensorHygrometer](../msg_docs/SensorHygrometer.md)
- [SensorBaro](../msg_docs/SensorBaro.md)
- [SensorAccelFifo](../msg_docs/SensorAccelFifo.md)
- [CameraTrigger](../msg_docs/CameraTrigger.md)
- [VehicleRoi](../msg_docs/VehicleRoi.md)
- [Ekf2Timestamps](../msg_docs/Ekf2Timestamps.md)
- [PowerButtonState](../msg_docs/PowerButtonState.md)
- [BatteryStatusV0](../msg_docs/BatteryStatusV0.md)
- [MavlinkTunnel](../msg_docs/MavlinkTunnel.md)
- [NormalizedUnsignedSetpoint](../msg_docs/NormalizedUnsignedSetpoint.md)
- [DebugVect](../msg_docs/DebugVect.md)
- [ActuatorArmed](../msg_docs/ActuatorArmed.md)
- [ActuatorOutputs](../msg_docs/ActuatorOutputs.md)
- [EscReport](../msg_docs/EscReport.md)
- [SensorGnssStatus](../msg_docs/SensorGnssStatus.md)
- [EstimatorBias3d](../msg_docs/EstimatorBias3d.md)
- [FixedWingRunwayControl](../msg_docs/FixedWingRunwayControl.md)
- [GeofenceResult](../msg_docs/GeofenceResult.md)
- [EscEepromWrite](../msg_docs/EscEepromWrite.md)
- [NavigatorMissionItem](../msg_docs/NavigatorMissionItem.md)
- [SensorUwb](../msg_docs/SensorUwb.md)
- [RegisterExtComponentReplyV0](../msg_docs/RegisterExtComponentReplyV0.md)
- [Gripper](../msg_docs/Gripper.md)
- [LandingGearWheel](../msg_docs/LandingGearWheel.md)
- [GainCompression](../msg_docs/GainCompression.md)
- [OrbTestMedium](../msg_docs/OrbTestMedium.md)
- [UlogStream](../msg_docs/UlogStream.md)
- [VelocityLimits](../msg_docs/VelocityLimits.md)
- [EstimatorBias](../msg_docs/EstimatorBias.md)
- [AutotuneAttitudeControlStatus](../msg_docs/AutotuneAttitudeControlStatus.md)
- [NeuralControl](../msg_docs/NeuralControl.md)
- [VehicleStatusV1](../msg_docs/VehicleStatusV1.md)
- [GpioConfig](../msg_docs/GpioConfig.md)
- [Cpuload](../msg_docs/Cpuload.md)
- [ArmingCheckRequestV0](../msg_docs/ArmingCheckRequestV0.md)
- [ParameterSetValueRequest](../msg_docs/ParameterSetValueRequest.md)
- [DeviceInformation](../msg_docs/DeviceInformation.md)
- [EstimatorEventFlags](../msg_docs/EstimatorEventFlags.md)
- [HomePositionV0](../msg_docs/HomePositionV0.md)
- [SensorPreflightMag](../msg_docs/SensorPreflightMag.md)
- [VehicleLocalPositionSetpoint](../msg_docs/VehicleLocalPositionSetpoint.md)
- [PpsCapture](../msg_docs/PpsCapture.md)
- [CellularStatus](../msg_docs/CellularStatus.md)
- [SensorsStatusImu](../msg_docs/SensorsStatusImu.md)
- [ActuatorControlsStatus](../msg_docs/ActuatorControlsStatus.md)
- [FollowTargetStatus](../msg_docs/FollowTargetStatus.md)
- [OpenDroneIdOperatorId](../msg_docs/OpenDroneIdOperatorId.md)
- [OrbTest](../msg_docs/OrbTest.md)
- [SensorGyroFifo](../msg_docs/SensorGyroFifo.md)
- [RoverSpeedStatus](../msg_docs/RoverSpeedStatus.md)
- [Px4ioStatus](../msg_docs/Px4ioStatus.md)
- [ManualControlSwitches](../msg_docs/ManualControlSwitches.md)
- [MavlinkLog](../msg_docs/MavlinkLog.md)
- [Mission](../msg_docs/Mission.md)
- [ControlAllocatorStatus](../msg_docs/ControlAllocatorStatus.md)
- [HeaterStatus](../msg_docs/HeaterStatus.md)
- [VehicleLocalPositionV0](../msg_docs/VehicleLocalPositionV0.md)
- [VehicleMagnetometer](../msg_docs/VehicleMagnetometer.md)
- [GpioRequest](../msg_docs/GpioRequest.md)
- [InternalCombustionEngineStatus](../msg_docs/InternalCombustionEngineStatus.md)
- [TecsStatus](../msg_docs/TecsStatus.md)
- [HealthReport](../msg_docs/HealthReport.md)
- [GpioOut](../msg_docs/GpioOut.md)
- [CameraCapture](../msg_docs/CameraCapture.md)
- [LedControl](../msg_docs/LedControl.md)
- [SensorSelection](../msg_docs/SensorSelection.md)
- [TuneControl](../msg_docs/TuneControl.md)
- [ButtonEvent](../msg_docs/ButtonEvent.md)
- [MavlinkTunnel](../msg_docs/MavlinkTunnel.md)
- [VehicleStatusV1](../msg_docs/VehicleStatusV1.md)
- [GpsDump](../msg_docs/GpsDump.md)
- [LandingTargetInnovations](../msg_docs/LandingTargetInnovations.md)
- [IrlockReport](../msg_docs/IrlockReport.md)
- [DebugKeyValue](../msg_docs/DebugKeyValue.md)
- [SensorBaro](../msg_docs/SensorBaro.md)
- [HoverThrustEstimate](../msg_docs/HoverThrustEstimate.md)
- [TrajectorySetpoint6dof](../msg_docs/TrajectorySetpoint6dof.md)
- [WheelEncoders](../msg_docs/WheelEncoders.md)
- [Px4ioStatus](../msg_docs/Px4ioStatus.md)
- [DatamanRequest](../msg_docs/DatamanRequest.md)
- [SensorAccel](../msg_docs/SensorAccel.md)
- [PowerMonitor](../msg_docs/PowerMonitor.md)
- [EventV0](../msg_docs/EventV0.md)
- [ActionRequest](../msg_docs/ActionRequest.md)
- [DebugArray](../msg_docs/DebugArray.md)
- [PpsCapture](../msg_docs/PpsCapture.md)
- [Gripper](../msg_docs/Gripper.md)
- [EstimatorBias3d](../msg_docs/EstimatorBias3d.md)
- [GimbalManagerInformation](../msg_docs/GimbalManagerInformation.md)
- [PowerButtonState](../msg_docs/PowerButtonState.md)
- [PositionControllerStatus](../msg_docs/PositionControllerStatus.md)
- [EstimatorGpsStatus](../msg_docs/EstimatorGpsStatus.md)
- [ParameterSetValueResponse](../msg_docs/ParameterSetValueResponse.md)
- [SensorGyroFft](../msg_docs/SensorGyroFft.md)
- [RtlStatus](../msg_docs/RtlStatus.md)
- [VehicleGlobalPositionV0](../msg_docs/VehicleGlobalPositionV0.md)
- [FigureEightStatus](../msg_docs/FigureEightStatus.md)
- [VehicleOpticalFlow](../msg_docs/VehicleOpticalFlow.md)
- [AdcReport](../msg_docs/AdcReport.md)
- [VehicleImuStatus](../msg_docs/VehicleImuStatus.md)
- [ConfigOverridesV0](../msg_docs/ConfigOverridesV0.md)
- [GimbalDeviceInformation](../msg_docs/GimbalDeviceInformation.md)
- [GpioOut](../msg_docs/GpioOut.md)
- [GimbalControls](../msg_docs/GimbalControls.md)
- [ActuatorTest](../msg_docs/ActuatorTest.md)
- [ParameterResetRequest](../msg_docs/ParameterResetRequest.md)
- [MavlinkLog](../msg_docs/MavlinkLog.md)
- [VehicleAngularVelocity](../msg_docs/VehicleAngularVelocity.md)
- [CellularStatus](../msg_docs/CellularStatus.md)
- [LandingTargetPose](../msg_docs/LandingTargetPose.md)
- [HealthReport](../msg_docs/HealthReport.md)
- [Mission](../msg_docs/Mission.md)
- [GpsInjectData](../msg_docs/GpsInjectData.md)
- [OrbitStatus](../msg_docs/OrbitStatus.md)
- [FuelTankStatus](../msg_docs/FuelTankStatus.md)
- [PwmInput](../msg_docs/PwmInput.md)
- [SensorGyro](../msg_docs/SensorGyro.md)
- [RoverAttitudeStatus](../msg_docs/RoverAttitudeStatus.md)
- [CameraStatus](../msg_docs/CameraStatus.md)
- [GpioConfig](../msg_docs/GpioConfig.md)
- [RegisterExtComponentReplyV0](../msg_docs/RegisterExtComponentReplyV0.md)
- [DatamanResponse](../msg_docs/DatamanResponse.md)
- [FixedWingLateralGuidanceStatus](../msg_docs/FixedWingLateralGuidanceStatus.md)
- [VehicleImu](../msg_docs/VehicleImu.md)
- [GimbalManagerSetAttitude](../msg_docs/GimbalManagerSetAttitude.md)
- [EstimatorBias](../msg_docs/EstimatorBias.md)
- [Event](../msg_docs/Event.md)
- [EscReport](../msg_docs/EscReport.md)
- [Ping](../msg_docs/Ping.md)
- [EstimatorAidSource3d](../msg_docs/EstimatorAidSource3d.md)
- [VehicleLocalPositionSetpoint](../msg_docs/VehicleLocalPositionSetpoint.md)
- [FixedWingRunwayControl](../msg_docs/FixedWingRunwayControl.md)
- [EstimatorSelectorStatus](../msg_docs/EstimatorSelectorStatus.md)
- [GimbalManagerStatus](../msg_docs/GimbalManagerStatus.md)
- [GpioIn](../msg_docs/GpioIn.md)
- [InternalCombustionEngineControl](../msg_docs/InternalCombustionEngineControl.md)
- [EstimatorAidSource1d](../msg_docs/EstimatorAidSource1d.md)
- [EstimatorEventFlags](../msg_docs/EstimatorEventFlags.md)
- [AutotuneAttitudeControlStatus](../msg_docs/AutotuneAttitudeControlStatus.md)
- [UavcanParameterRequest](../msg_docs/UavcanParameterRequest.md)
- [UlogStreamAck](../msg_docs/UlogStreamAck.md)
- [VehicleLocalPositionV0](../msg_docs/VehicleLocalPositionV0.md)
- [EstimatorStatus](../msg_docs/EstimatorStatus.md)
- [PositionSetpoint](../msg_docs/PositionSetpoint.md)
- [SensorGyroFifo](../msg_docs/SensorGyroFifo.md)
- [FixedWingLateralGuidanceStatus](../msg_docs/FixedWingLateralGuidanceStatus.md)
- [VehicleCommandAckV0](../msg_docs/VehicleCommandAckV0.md)
- [FollowTarget](../msg_docs/FollowTarget.md)
- [VehicleOpticalFlowVel](../msg_docs/VehicleOpticalFlowVel.md)
- [OpenDroneIdSelfId](../msg_docs/OpenDroneIdSelfId.md)
- [Rpm](../msg_docs/Rpm.md)
- [GeofenceStatus](../msg_docs/GeofenceStatus.md)
- [OrbTest](../msg_docs/OrbTest.md)
- [FollowTargetEstimator](../msg_docs/FollowTargetEstimator.md)
- [PurePursuitStatus](../msg_docs/PurePursuitStatus.md)
- [BatteryStatusV0](../msg_docs/BatteryStatusV0.md)
- [ControlAllocatorStatus](../msg_docs/ControlAllocatorStatus.md)
- [RadioStatus](../msg_docs/RadioStatus.md)
- [MissionResult](../msg_docs/MissionResult.md)
- [HeaterStatus](../msg_docs/HeaterStatus.md)
- [GeneratorStatus](../msg_docs/GeneratorStatus.md)
- [AirspeedValidatedV0](../msg_docs/AirspeedValidatedV0.md)
- [VehicleMagnetometer](../msg_docs/VehicleMagnetometer.md)
- [LedControl](../msg_docs/LedControl.md)
- [ParameterSetUsedRequest](../msg_docs/ParameterSetUsedRequest.md)
- [ParameterUpdate](../msg_docs/ParameterUpdate.md)
- [CameraCapture](../msg_docs/CameraCapture.md)
- [EstimatorAidSource2d](../msg_docs/EstimatorAidSource2d.md)
- [GeofenceResult](../msg_docs/GeofenceResult.md)
- [OrbTestMedium](../msg_docs/OrbTestMedium.md)
- [VehicleRoi](../msg_docs/VehicleRoi.md)
- [VehicleAngularAccelerationSetpoint](../msg_docs/VehicleAngularAccelerationSetpoint.md)
- [RegisterExtComponentRequestV0](../msg_docs/RegisterExtComponentRequestV0.md)
- [SensorSelection](../msg_docs/SensorSelection.md)
- [RoverRateStatus](../msg_docs/RoverRateStatus.md)
- [ParameterSetValueRequest](../msg_docs/ParameterSetValueRequest.md)
- [Airspeed](../msg_docs/Airspeed.md)
- [SatelliteInfo](../msg_docs/SatelliteInfo.md)
- [MagnetometerBiasEstimate](../msg_docs/MagnetometerBiasEstimate.md)
- [VehicleAcceleration](../msg_docs/VehicleAcceleration.md)
- [SensorsStatus](../msg_docs/SensorsStatus.md)
- [SystemPower](../msg_docs/SystemPower.md)
- [SensorGnssStatus](../msg_docs/SensorGnssStatus.md)
- [Vtx](../msg_docs/Vtx.md)
- [LogMessage](../msg_docs/LogMessage.md)
- [MagWorkerData](../msg_docs/MagWorkerData.md)
- [RtlTimeEstimate](../msg_docs/RtlTimeEstimate.md)
- [LandingGearWheel](../msg_docs/LandingGearWheel.md)
- [Ekf2Timestamps](../msg_docs/Ekf2Timestamps.md)
- [NavigatorStatus](../msg_docs/NavigatorStatus.md)
- [EscStatus](../msg_docs/EscStatus.md)
- [DebugVect](../msg_docs/DebugVect.md)
- [RaptorStatus](../msg_docs/RaptorStatus.md)
- [DeviceInformation](../msg_docs/DeviceInformation.md)
- [UlogStream](../msg_docs/UlogStream.md)
- [FailureDetectorStatus](../msg_docs/FailureDetectorStatus.md)
- [VelocityLimits](../msg_docs/VelocityLimits.md)
- [LoggerStatus](../msg_docs/LoggerStatus.md)
- [SensorAirflow](../msg_docs/SensorAirflow.md)
- [VehicleConstraints](../msg_docs/VehicleConstraints.md)
- [SensorAccelFifo](../msg_docs/SensorAccelFifo.md)
- [FollowTargetStatus](../msg_docs/FollowTargetStatus.md)
- [OrbTestLarge](../msg_docs/OrbTestLarge.md)
- [DronecanNodeStatus](../msg_docs/DronecanNodeStatus.md)
- [EstimatorInnovations](../msg_docs/EstimatorInnovations.md)
- [ArmingCheckReplyV0](../msg_docs/ArmingCheckReplyV0.md)
- [IridiumsbdStatus](../msg_docs/IridiumsbdStatus.md)
- [QshellRetval](../msg_docs/QshellRetval.md)
- [GimbalDeviceSetAttitude](../msg_docs/GimbalDeviceSetAttitude.md)
- [ArmingCheckRequestV0](../msg_docs/ArmingCheckRequestV0.md)
- [CanInterfaceStatus](../msg_docs/CanInterfaceStatus.md)
- [UavcanParameterValue](../msg_docs/UavcanParameterValue.md)
- [RaptorInput](../msg_docs/RaptorInput.md)
- [SensorUwb](../msg_docs/SensorUwb.md)
- [TiltrotorExtraControls](../msg_docs/TiltrotorExtraControls.md)
- [VehicleAirData](../msg_docs/VehicleAirData.md)
- [SensorTemp](../msg_docs/SensorTemp.md)
- [VehicleStatusV0](../msg_docs/VehicleStatusV0.md)
- [AirspeedWind](../msg_docs/AirspeedWind.md)
- [BatteryInfo](../msg_docs/BatteryInfo.md)
- [Cpuload](../msg_docs/Cpuload.md)
- [OpenDroneIdArmStatus](../msg_docs/OpenDroneIdArmStatus.md)
- [DifferentialPressure](../msg_docs/DifferentialPressure.md)
- [YawEstimatorStatus](../msg_docs/YawEstimatorStatus.md)
- [CameraTrigger](../msg_docs/CameraTrigger.md)
- [GpioRequest](../msg_docs/GpioRequest.md)
- [SensorPreflightMag](../msg_docs/SensorPreflightMag.md)
- [LaunchDetectionStatus](../msg_docs/LaunchDetectionStatus.md)
- [VehicleAttitudeSetpointV0](../msg_docs/VehicleAttitudeSetpointV0.md)
- [PositionControllerLandingStatus](../msg_docs/PositionControllerLandingStatus.md)
- [RateCtrlStatus](../msg_docs/RateCtrlStatus.md)
- [SensorMag](../msg_docs/SensorMag.md)
- [SensorGnssRelative](../msg_docs/SensorGnssRelative.md)
- [ActuatorControlsStatus](../msg_docs/ActuatorControlsStatus.md)
- [NeuralControl](../msg_docs/NeuralControl.md)
- [TecsStatus](../msg_docs/TecsStatus.md)
- [NavigatorMissionItem](../msg_docs/NavigatorMissionItem.md)
- [RcChannels](../msg_docs/RcChannels.md)
- [NormalizedUnsignedSetpoint](../msg_docs/NormalizedUnsignedSetpoint.md)
- [ManualControlSwitches](../msg_docs/ManualControlSwitches.md)
- [ActuatorOutputs](../msg_docs/ActuatorOutputs.md)
- [SensorHygrometer](../msg_docs/SensorHygrometer.md)
- [FlightPhaseEstimation](../msg_docs/FlightPhaseEstimation.md)
- [EstimatorSensorBias](../msg_docs/EstimatorSensorBias.md)
- [RcParameterMap](../msg_docs/RcParameterMap.md)
- [MountOrientation](../msg_docs/MountOrientation.md)
- [OpenDroneIdSystem](../msg_docs/OpenDroneIdSystem.md)
- [FixedWingLateralStatus](../msg_docs/FixedWingLateralStatus.md)
- [OpenDroneIdOperatorId](../msg_docs/OpenDroneIdOperatorId.md)
- [TakeoffStatus](../msg_docs/TakeoffStatus.md)
- [SensorsStatusImu](../msg_docs/SensorsStatusImu.md)
- [DistanceSensorModeChangeRequest](../msg_docs/DistanceSensorModeChangeRequest.md)
- [DebugValue](../msg_docs/DebugValue.md)
- [GainCompression](../msg_docs/GainCompression.md)
- [GimbalManagerSetManualControl](../msg_docs/GimbalManagerSetManualControl.md)
- [SensorCorrection](../msg_docs/SensorCorrection.md)
- [TaskStackInfo](../msg_docs/TaskStackInfo.md)
- [EstimatorStates](../msg_docs/EstimatorStates.md)
- [InputRc](../msg_docs/InputRc.md)
- [QshellReq](../msg_docs/QshellReq.md)
- [ActuatorServosTrim](../msg_docs/ActuatorServosTrim.md)
- [HomePositionV0](../msg_docs/HomePositionV0.md)
- [ActuatorArmed](../msg_docs/ActuatorArmed.md)
- [IrlockReport](../msg_docs/IrlockReport.md)
- [RoverSpeedStatus](../msg_docs/RoverSpeedStatus.md)
:::
+46 -1
View File
@@ -191,13 +191,28 @@ Source: [drivers/dshot](https://github.com/PX4/PX4-Autopilot/tree/main/src/drive
### Description
This is the DShot output driver. It can be used as drop-in replacement
This is the DShot output driver. It is similar to the fmu driver, and can be used as drop-in replacement
to use DShot as ESC communication protocol instead of PWM.
On startup, the module tries to occupy all available pins for DShot output.
It skips all pins already in use (e.g. by a camera trigger module).
It supports:
- DShot150, DShot300, DShot600
- telemetry via separate UART and publishing as esc_status message
- sending DShot commands via CLI
### Examples
Permanently reverse motor 1:
```
dshot reverse -m 1
dshot save -m 1
```
After saving, the reversed direction will be regarded as the normal one. So to reverse again repeat the same commands.
### Usage {#dshot_usage}
@@ -211,6 +226,36 @@ dshot <command> [arguments...]
values: <device>
[-x] Swap RX/TX pins
reverse Reverse motor direction
[-m <val>] Motor index (1-based, default=all)
normal Normal motor direction
[-m <val>] Motor index (1-based, default=all)
save Save current settings
[-m <val>] Motor index (1-based, default=all)
3d_on Enable 3D mode
[-m <val>] Motor index (1-based, default=all)
3d_off Disable 3D mode
[-m <val>] Motor index (1-based, default=all)
beep1 Send Beep pattern 1
[-m <val>] Motor index (1-based, default=all)
beep2 Send Beep pattern 2
[-m <val>] Motor index (1-based, default=all)
beep3 Send Beep pattern 3
[-m <val>] Motor index (1-based, default=all)
beep4 Send Beep pattern 4
[-m <val>] Motor index (1-based, default=all)
beep5 Send Beep pattern 5
[-m <val>] Motor index (1-based, default=all)
stop
status print status info
-41
View File
@@ -1,41 +0,0 @@
---
pageClass: is-wide-page
---
# EscEepromRead (UORB message)
**TOPICS:** esc_eeprom_read
## Fields
| Name | Type | Unit [Frame] | Range/Enum | Description |
| --------- | ----------- | ------------ | ---------- | ---------------------------------------------------- |
| timestamp | `uint64` | us | | Time since system start |
| firmware | `uint8` | | | ESC firmware type (see ESC_FIRMWARE enum in MAVLink) |
| index | `uint8` | | | Index of the ESC (0 = ESC1, 1 = ESC2, etc.) |
| length | `uint16` | | | Length of valid data |
| data | `uint8[48]` | | | Raw ESC EEPROM data |
## Constants
| Name | Type | Value | Description |
| ----------------------------------------------- | ------- | ----- | -------------------------------- |
| <a id="#ORB_QUEUE_LENGTH"></a> ORB_QUEUE_LENGTH | `uint8` | 8 | To support 8 queued up responses |
## Source Message
[Source file (GitHub)](https://github.com/PX4/PX4-Autopilot/blob/main/msg/EscEepromRead.msg)
::: details Click here to see original file
```c
uint64 timestamp # [us] Time since system start
uint8 firmware # [-] ESC firmware type (see ESC_FIRMWARE enum in MAVLink)
uint8 index # [-] Index of the ESC (0 = ESC1, 1 = ESC2, etc.)
uint16 length # [-] Length of valid data
uint8[48] data # [-] Raw ESC EEPROM data
uint8 ORB_QUEUE_LENGTH = 8 # To support 8 queued up responses
```
:::
-43
View File
@@ -1,43 +0,0 @@
---
pageClass: is-wide-page
---
# EscEepromWrite (UORB message)
**TOPICS:** esc_eeprom_write
## Fields
| Name | Type | Unit [Frame] | Range/Enum | Description |
| ---------- | ----------- | ------------ | ---------- | ---------------------------------------------------------------------------------- |
| timestamp | `uint64` | us | | Time since system start |
| firmware | `uint8` | | | ESC firmware type (see ESC_FIRMWARE enum in MAVLink) |
| index | `uint8` | | | Index of the ESC (0 = ESC1, 1 = ESC2, etc, 255 = All) |
| length | `uint16` | | | Length of valid data |
| data | `uint8[48]` | | | Raw ESC EEPROM data |
| write_mask | `uint32[2]` | | | Bitmask indicating which bytes in the data array should be written (max 48 values) |
## Constants
| Name | Type | Value | Description |
| ----------------------------------------------- | ------- | ----- | ------------------------------- |
| <a id="#ORB_QUEUE_LENGTH"></a> ORB_QUEUE_LENGTH | `uint8` | 8 | To support 8 queued up requests |
## Source Message
[Source file (GitHub)](https://github.com/PX4/PX4-Autopilot/blob/main/msg/EscEepromWrite.msg)
::: details Click here to see original file
```c
uint64 timestamp # [us] Time since system start
uint8 firmware # [-] ESC firmware type (see ESC_FIRMWARE enum in MAVLink)
uint8 index # [-] Index of the ESC (0 = ESC1, 1 = ESC2, etc, 255 = All)
uint16 length # [-] Length of valid data
uint8[48] data # [-] Raw ESC EEPROM data
uint32[2] write_mask # [-] Bitmask indicating which bytes in the data array should be written (max 48 values)
uint8 ORB_QUEUE_LENGTH = 8 # To support 8 queued up requests
```
:::
+43 -50
View File
@@ -8,27 +8,28 @@ pageClass: is-wide-page
## Fields
| Name | Type | Unit [Frame] | Range/Enum | Description |
| ----------------- | --------- | ------------ | ------------------- | ------------------------------------------------------------------- |
| timestamp | `uint64` | us | | Time since system start |
| esc_errorcount | `uint32` | | | Number of reported errors by ESC - if supported |
| esc_rpm | `int32` | rpm | | Motor RPM, negative for reverse rotation - if supported |
| esc_voltage | `float32` | V | | Voltage measured from current ESC - if supported |
| esc_current | `float32` | A | | Current measured from current ESC - if supported |
| esc_temperature | `float32` | degC | | Temperature measured from current ESC - if supported |
| esc_address | `uint8` | | | Address of current ESC (in most cases 1-12 / must be set by driver) |
| motor_temperature | `int16` | degC | | Temperature measured from current motor - if supported |
| esc_state | `uint8` | | | State of ESC - depend on Vendor |
| actuator_function | `uint8` | | | Actuator output function (one of Motor1...MotorN) |
| failures | `uint16` | | [FAILURE](#FAILURE) | Bitmask to indicate the internal ESC faults |
| esc_power | `int8` | % | [0 : 100] | Applied power (negative values reserved) |
| Name | Type | Unit [Frame] | Range/Enum | Description |
| ----------------- | --------- | ------------ | ---------- | ------------------------------------------------------------------ |
| timestamp | `uint64` | | | time since system start (microseconds) |
| esc_errorcount | `uint32` | | | Number of reported errors by ESC - if supported |
| esc_rpm | `int32` | | | Motor RPM, negative for reverse rotation [RPM] - if supported |
| esc_voltage | `float32` | | | Voltage measured from current ESC [V] - if supported |
| esc_current | `float32` | | | Current measured from current ESC [A] - if supported |
| esc_temperature | `float32` | | | Temperature measured from current ESC [degC] - if supported |
| motor_temperature | `int16` | | | Temperature measured from current motor [degC] - if supported |
| esc_address | `uint8` | | | Address of current ESC (in most cases 1-8 / must be set by driver) |
| esc_cmdcount | `uint8` | | | Counter of number of commands |
| esc_state | `uint8` | | | State of ESC - depend on Vendor |
| actuator_function | `uint8` | | | actuator output function (one of Motor1...MotorN) |
| failures | `uint16` | | | Bitmask to indicate the internal ESC faults |
| esc_power | `int8` | | | Applied power 0-100 in % (negative values reserved) |
## Enums
### FAILURE {#FAILURE}
## Constants
| Name | Type | Value | Description |
| --------------------------------------------------------------------------- | ------- | ----- | ---------------------------------------------------------------------------- |
| <a id="#ACTUATOR_FUNCTION_MOTOR1"></a> ACTUATOR_FUNCTION_MOTOR1 | `uint8` | 101 |
| <a id="#ACTUATOR_FUNCTION_MOTOR_MAX"></a> ACTUATOR_FUNCTION_MOTOR_MAX | `uint8` | 112 | output_functions.yaml Motor.start + Motor.count - 1 |
| <a id="#FAILURE_OVER_CURRENT"></a> FAILURE_OVER_CURRENT | `uint8` | 0 | (1 << 0) |
| <a id="#FAILURE_OVER_VOLTAGE"></a> FAILURE_OVER_VOLTAGE | `uint8` | 1 | (1 << 1) |
| <a id="#FAILURE_MOTOR_OVER_TEMPERATURE"></a> FAILURE_MOTOR_OVER_TEMPERATURE | `uint8` | 2 | (1 << 2) |
@@ -39,14 +40,7 @@ pageClass: is-wide-page
| <a id="#FAILURE_MOTOR_WARN_TEMPERATURE"></a> FAILURE_MOTOR_WARN_TEMPERATURE | `uint8` | 7 | (1 << 7) |
| <a id="#FAILURE_WARN_ESC_TEMPERATURE"></a> FAILURE_WARN_ESC_TEMPERATURE | `uint8` | 8 | (1 << 8) |
| <a id="#FAILURE_OVER_ESC_TEMPERATURE"></a> FAILURE_OVER_ESC_TEMPERATURE | `uint8` | 9 | (1 << 9) |
## Constants
| Name | Type | Value | Description |
| --------------------------------------------------------------------- | ------- | ----- | --------------------------------------------------- |
| <a id="#ACTUATOR_FUNCTION_MOTOR1"></a> ACTUATOR_FUNCTION_MOTOR1 | `uint8` | 101 |
| <a id="#ACTUATOR_FUNCTION_MOTOR_MAX"></a> ACTUATOR_FUNCTION_MOTOR_MAX | `uint8` | 112 | output_functions.yaml Motor.start + Motor.count - 1 |
| <a id="#ESC_FAILURE_COUNT"></a> ESC_FAILURE_COUNT | `uint8` | 10 | Counter - keep it as last element! |
| <a id="#ESC_FAILURE_COUNT"></a> ESC_FAILURE_COUNT | `uint8` | 10 | Counter - keep it as last element! |
## Source Message
@@ -55,37 +49,36 @@ pageClass: is-wide-page
::: details Click here to see original file
```c
uint64 timestamp # [us] Time since system start
uint64 timestamp # time since system start (microseconds)
uint32 esc_errorcount # Number of reported errors by ESC - if supported
int32 esc_rpm # Motor RPM, negative for reverse rotation [RPM] - if supported
float32 esc_voltage # Voltage measured from current ESC [V] - if supported
float32 esc_current # Current measured from current ESC [A] - if supported
float32 esc_temperature # Temperature measured from current ESC [degC] - if supported
int16 motor_temperature # Temperature measured from current motor [degC] - if supported
uint8 esc_address # Address of current ESC (in most cases 1-8 / must be set by driver)
uint8 esc_cmdcount # Counter of number of commands
uint32 esc_errorcount # [-] Number of reported errors by ESC - if supported
int32 esc_rpm # [rpm] Motor RPM, negative for reverse rotation - if supported
float32 esc_voltage # [V] Voltage measured from current ESC - if supported
float32 esc_current # [A] Current measured from current ESC - if supported
float32 esc_temperature # [degC] Temperature measured from current ESC - if supported
uint8 esc_address # [-] Address of current ESC (in most cases 1-12 / must be set by driver)
int16 motor_temperature # [degC] Temperature measured from current motor - if supported
uint8 esc_state # [-] State of ESC - depend on Vendor
uint8 actuator_function # [-] Actuator output function (one of Motor1...MotorN)
uint8 esc_state # State of ESC - depend on Vendor
uint8 actuator_function # actuator output function (one of Motor1...MotorN)
uint8 ACTUATOR_FUNCTION_MOTOR1 = 101
uint8 ACTUATOR_FUNCTION_MOTOR_MAX = 112 # output_functions.yaml Motor.start + Motor.count - 1
uint16 failures # [@enum FAILURE] Bitmask to indicate the internal ESC faults
int8 esc_power # [%] [@range 0,100] Applied power (negative values reserved)
uint16 failures # Bitmask to indicate the internal ESC faults
int8 esc_power # Applied power 0-100 in % (negative values reserved)
uint8 FAILURE_OVER_CURRENT = 0 # (1 << 0)
uint8 FAILURE_OVER_VOLTAGE = 1 # (1 << 1)
uint8 FAILURE_MOTOR_OVER_TEMPERATURE = 2 # (1 << 2)
uint8 FAILURE_OVER_RPM = 3 # (1 << 3)
uint8 FAILURE_INCONSISTENT_CMD = 4 # (1 << 4) Set if ESC received an inconsistent command (i.e out of boundaries)
uint8 FAILURE_MOTOR_STUCK = 5 # (1 << 5)
uint8 FAILURE_GENERIC = 6 # (1 << 6)
uint8 FAILURE_MOTOR_WARN_TEMPERATURE = 7 # (1 << 7)
uint8 FAILURE_WARN_ESC_TEMPERATURE = 8 # (1 << 8)
uint8 FAILURE_OVER_ESC_TEMPERATURE = 9 # (1 << 9)
uint8 ESC_FAILURE_COUNT = 10 # Counter - keep it as last element!
uint8 FAILURE_OVER_CURRENT = 0 # (1 << 0)
uint8 FAILURE_OVER_VOLTAGE = 1 # (1 << 1)
uint8 FAILURE_MOTOR_OVER_TEMPERATURE = 2 # (1 << 2)
uint8 FAILURE_OVER_RPM = 3 # (1 << 3)
uint8 FAILURE_INCONSISTENT_CMD = 4 # (1 << 4) Set if ESC received an inconsistent command (i.e out of boundaries)
uint8 FAILURE_MOTOR_STUCK = 5 # (1 << 5)
uint8 FAILURE_GENERIC = 6 # (1 << 6)
uint8 FAILURE_MOTOR_WARN_TEMPERATURE = 7 # (1 << 7)
uint8 FAILURE_WARN_ESC_TEMPERATURE = 8 # (1 << 8)
uint8 FAILURE_OVER_ESC_TEMPERATURE = 9 # (1 << 9)
uint8 ESC_FAILURE_COUNT = 10 # Counter - keep it as last element!
```
:::
+40 -51
View File
@@ -8,34 +8,27 @@ pageClass: is-wide-page
## Fields
| Name | Type | Unit [Frame] | Range/Enum | Description |
| ------------------ | --------------- | ------------ | ------------------------------------------- | --------------------------------------------------------------- |
| timestamp | `uint64` | us | | Time since system start |
| counter | `uint16` | | | Incremented by the writing thread everytime new data is stored |
| esc_count | `uint8` | | | Number of connected ESCs |
| esc_connectiontype | `uint8` | | [ESC_CONNECTION_TYPE](#ESC_CONNECTION_TYPE) | How ESCs connected to the system |
| esc_online_flags | `uint16` | | | Bitmask indicating which ESC is online/offline (in motor order) |
| esc_armed_flags | `uint16` | | | Bitmask indicating which ESC is armed (in motor order) |
| esc | `EscReport[12]` | | |
## Enums
### ESC_CONNECTION_TYPE {#ESC_CONNECTION_TYPE}
| Name | Type | Value | Description |
| --------------------------------------------------------------------- | ------- | ----- | ------------------------ |
| <a id="#ESC_CONNECTION_TYPE_PPM"></a> ESC_CONNECTION_TYPE_PPM | `uint8` | 0 | Traditional PPM ESC |
| <a id="#ESC_CONNECTION_TYPE_SERIAL"></a> ESC_CONNECTION_TYPE_SERIAL | `uint8` | 1 | Serial Bus connected ESC |
| <a id="#ESC_CONNECTION_TYPE_ONESHOT"></a> ESC_CONNECTION_TYPE_ONESHOT | `uint8` | 2 | One Shot PPM |
| <a id="#ESC_CONNECTION_TYPE_I2C"></a> ESC_CONNECTION_TYPE_I2C | `uint8` | 3 | I2C |
| <a id="#ESC_CONNECTION_TYPE_CAN"></a> ESC_CONNECTION_TYPE_CAN | `uint8` | 4 | CAN-Bus |
| <a id="#ESC_CONNECTION_TYPE_DSHOT"></a> ESC_CONNECTION_TYPE_DSHOT | `uint8` | 5 | DShot |
| Name | Type | Unit [Frame] | Range/Enum | Description |
| ------------------ | -------------- | ------------ | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| timestamp | `uint64` | | | time since system start (microseconds) |
| counter | `uint16` | | | incremented by the writing thread everytime new data is stored |
| esc_count | `uint8` | | | number of connected ESCs |
| esc_connectiontype | `uint8` | | | how ESCs connected to the system |
| esc_online_flags | `uint8` | | | Bitmask indicating which ESC is online/offline |
| esc_armed_flags | `uint8` | | | Bitmask indicating which ESC is armed. For ESC's where the arming state is not known (returned by the ESC), the arming bits should always be set. |
| esc | `EscReport[8]` | | |
## Constants
| Name | Type | Value | Description |
| ------------------------------------------------- | ------- | ----- | --------------------------------------------- |
| <a id="#CONNECTED_ESC_MAX"></a> CONNECTED_ESC_MAX | `uint8` | 12 | The number of ESCs supported (Motor1-Motor12) |
| Name | Type | Value | Description |
| --------------------------------------------------------------------- | ------- | ----- | ----------------------------------------------------------------- |
| <a id="#CONNECTED_ESC_MAX"></a> CONNECTED_ESC_MAX | `uint8` | 8 | The number of ESCs supported. Current (Q2/2013) we support 8 ESCs |
| <a id="#ESC_CONNECTION_TYPE_PPM"></a> ESC_CONNECTION_TYPE_PPM | `uint8` | 0 | Traditional PPM ESC |
| <a id="#ESC_CONNECTION_TYPE_SERIAL"></a> ESC_CONNECTION_TYPE_SERIAL | `uint8` | 1 | Serial Bus connected ESC |
| <a id="#ESC_CONNECTION_TYPE_ONESHOT"></a> ESC_CONNECTION_TYPE_ONESHOT | `uint8` | 2 | One Shot PPM |
| <a id="#ESC_CONNECTION_TYPE_I2C"></a> ESC_CONNECTION_TYPE_I2C | `uint8` | 3 | I2C |
| <a id="#ESC_CONNECTION_TYPE_CAN"></a> ESC_CONNECTION_TYPE_CAN | `uint8` | 4 | CAN-Bus |
| <a id="#ESC_CONNECTION_TYPE_DSHOT"></a> ESC_CONNECTION_TYPE_DSHOT | `uint8` | 5 | DShot |
## Source Message
@@ -44,38 +37,34 @@ pageClass: is-wide-page
::: details Click here to see original file
```c
uint64 timestamp # [us] Time since system start
uint8 CONNECTED_ESC_MAX = 12 # The number of ESCs supported (Motor1-Motor12)
uint64 timestamp # time since system start (microseconds)
uint8 CONNECTED_ESC_MAX = 8 # The number of ESCs supported. Current (Q2/2013) we support 8 ESCs
uint8 ESC_CONNECTION_TYPE_PPM = 0 # Traditional PPM ESC
uint8 ESC_CONNECTION_TYPE_SERIAL = 1 # Serial Bus connected ESC
uint8 ESC_CONNECTION_TYPE_ONESHOT = 2 # One Shot PPM
uint8 ESC_CONNECTION_TYPE_I2C = 3 # I2C
uint8 ESC_CONNECTION_TYPE_CAN = 4 # CAN-Bus
uint8 ESC_CONNECTION_TYPE_DSHOT = 5 # DShot
uint8 ESC_CONNECTION_TYPE_PPM = 0 # Traditional PPM ESC
uint8 ESC_CONNECTION_TYPE_SERIAL = 1 # Serial Bus connected ESC
uint8 ESC_CONNECTION_TYPE_ONESHOT = 2 # One Shot PPM
uint8 ESC_CONNECTION_TYPE_I2C = 3 # I2C
uint8 ESC_CONNECTION_TYPE_CAN = 4 # CAN-Bus
uint8 ESC_CONNECTION_TYPE_DSHOT = 5 # DShot
uint16 counter # [-] Incremented by the writing thread everytime new data is stored
uint16 counter # incremented by the writing thread everytime new data is stored
uint8 esc_count # [-] Number of connected ESCs
uint8 esc_connectiontype # [@enum ESC_CONNECTION_TYPE] How ESCs connected to the system
uint8 esc_count # number of connected ESCs
uint8 esc_connectiontype # how ESCs connected to the system
uint16 esc_online_flags # Bitmask indicating which ESC is online/offline (in motor order)
# esc_online_flags bit 0 : Set to 1 if Motor1 is online
# esc_online_flags bit 1 : Set to 1 if Motor2 is online
# esc_online_flags bit 2 : Set to 1 if Motor3 is online
# esc_online_flags bit 3 : Set to 1 if Motor4 is online
# esc_online_flags bit 4 : Set to 1 if Motor5 is online
# esc_online_flags bit 5 : Set to 1 if Motor6 is online
# esc_online_flags bit 6 : Set to 1 if Motor7 is online
# esc_online_flags bit 7 : Set to 1 if Motor8 is online
# esc_online_flags bit 8 : Set to 1 if Motor9 is online
# esc_online_flags bit 9 : Set to 1 if Motor10 is online
# esc_online_flags bit 10: Set to 1 if Motor11 is online
# esc_online_flags bit 11: Set to 1 if Motor12 is online
uint8 esc_online_flags # Bitmask indicating which ESC is online/offline
# esc_online_flags bit 0 : Set to 1 if ESC0 is online
# esc_online_flags bit 1 : Set to 1 if ESC1 is online
# esc_online_flags bit 2 : Set to 1 if ESC2 is online
# esc_online_flags bit 3 : Set to 1 if ESC3 is online
# esc_online_flags bit 4 : Set to 1 if ESC4 is online
# esc_online_flags bit 5 : Set to 1 if ESC5 is online
# esc_online_flags bit 6 : Set to 1 if ESC6 is online
# esc_online_flags bit 7 : Set to 1 if ESC7 is online
uint16 esc_armed_flags # [-] Bitmask indicating which ESC is armed (in motor order)
uint8 esc_armed_flags # Bitmask indicating which ESC is armed. For ESC's where the arming state is not known (returned by the ESC), the arming bits should always be set.
EscReport[12] esc
EscReport[8] esc
```
:::
+39 -46
View File
@@ -10,48 +10,45 @@ GPS position in WGS84 coordinates. the field 'timestamp' is for the position & v
## Fields
| Name | Type | Unit [Frame] | Range/Enum | Description |
| ----------------------- | --------- | ------------------ | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| timestamp | `uint64` | | | time since system start (microseconds) |
| timestamp_sample | `uint64` | | |
| device_id | `uint32` | | | unique device ID for the sensor that does not change between power cycles |
| latitude_deg | `float64` | | | Latitude in degrees, allows centimeter level RTK precision |
| longitude_deg | `float64` | | | Longitude in degrees, allows centimeter level RTK precision |
| altitude_msl_m | `float64` | | | Altitude above MSL, meters |
| altitude_ellipsoid_m | `float64` | | | Altitude above Ellipsoid, meters |
| s_variance_m_s | `float32` | | | GPS speed accuracy estimate, (metres/sec) |
| c_variance_rad | `float32` | | | GPS course accuracy estimate, (radians) |
| fix_type | `uint8` | | | Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. |
| eph | `float32` | | | GPS horizontal position accuracy (metres) |
| epv | `float32` | | | GPS vertical position accuracy (metres) |
| hdop | `float32` | | | Horizontal dilution of precision |
| vdop | `float32` | | | Vertical dilution of precision |
| noise_per_ms | `int32` | | | GPS noise per millisecond |
| automatic_gain_control | `uint16` | | | Automatic gain control monitor |
| jamming_state | `uint8` | | | indicates whether jamming has been detected or suspected by the receivers. O: Unknown, 1: OK, 2: Mitigated, 3: Detected |
| jamming_indicator | `int32` | | | indicates jamming is occurring |
| spoofing_state | `uint8` | | | indicates whether spoofing has been detected or suspected by the receivers. O: Unknown, 1: OK, 2: Mitigated, 3: Detected |
| authentication_state | `uint8` | | | GPS signal authentication state |
| vel_m_s | `float32` | | | GPS ground speed, (metres/sec) |
| vel_n_m_s | `float32` | | | GPS North velocity, (metres/sec) |
| vel_e_m_s | `float32` | | | GPS East velocity, (metres/sec) |
| vel_d_m_s | `float32` | | | GPS Down velocity, (metres/sec) |
| cog_rad | `float32` | | | Course over ground (NOT heading, but direction of movement), -PI..PI, (radians) |
| vel_ned_valid | `bool` | | | True if NED velocity is valid |
| timestamp_time_relative | `int32` | | | timestamp + timestamp_time_relative = Time of the UTC timestamp since system start, (microseconds) |
| time_utc_usec | `uint64` | | | Timestamp (microseconds, UTC), this is the timestamp which comes from the gps module. It might be unavailable right after cold start, indicated by a value of 0 |
| satellites_used | `uint8` | | | Number of satellites used |
| system_error | `uint32` | | | General errors with the connected GPS receiver |
| heading | `float32` | | | heading angle of XYZ body frame rel to NED. Set to NaN if not available and updated (used for dual antenna GPS), (rad, [-PI, PI]) |
| heading_offset | `float32` | | | heading offset of dual antenna array in body frame. Set to NaN if not applicable. (rad, [-PI, PI]) |
| heading_accuracy | `float32` | | | heading accuracy (rad, [0, 2PI]) |
| rtcm_injection_rate | `float32` | | | RTCM message injection rate Hz |
| selected_rtcm_instance | `uint8` | | | uorb instance that is being used for RTCM corrections |
| rtcm_crc_failed | `bool` | | | RTCM message CRC failure detected |
| rtcm_msg_used | `uint8` | | | Indicates if the RTCM message was used successfully by the receiver |
| antenna_offset_x | `float32` | m [body frame FRD] | | X Position of GNSS antenna |
| antenna_offset_y | `float32` | m [body frame FRD] | | Y Position of GNSS antenna |
| antenna_offset_z | `float32` | m [body frame FRD] | | Z Position of GNSS antenna |
| Name | Type | Unit [Frame] | Range/Enum | Description |
| ----------------------- | --------- | ------------ | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| timestamp | `uint64` | | | time since system start (microseconds) |
| timestamp_sample | `uint64` | | |
| device_id | `uint32` | | | unique device ID for the sensor that does not change between power cycles |
| latitude_deg | `float64` | | | Latitude in degrees, allows centimeter level RTK precision |
| longitude_deg | `float64` | | | Longitude in degrees, allows centimeter level RTK precision |
| altitude_msl_m | `float64` | | | Altitude above MSL, meters |
| altitude_ellipsoid_m | `float64` | | | Altitude above Ellipsoid, meters |
| s_variance_m_s | `float32` | | | GPS speed accuracy estimate, (metres/sec) |
| c_variance_rad | `float32` | | | GPS course accuracy estimate, (radians) |
| fix_type | `uint8` | | | Some applications will not use the value of this field unless it is at least two, so always correctly fill in the fix. |
| eph | `float32` | | | GPS horizontal position accuracy (metres) |
| epv | `float32` | | | GPS vertical position accuracy (metres) |
| hdop | `float32` | | | Horizontal dilution of precision |
| vdop | `float32` | | | Vertical dilution of precision |
| noise_per_ms | `int32` | | | GPS noise per millisecond |
| automatic_gain_control | `uint16` | | | Automatic gain control monitor |
| jamming_state | `uint8` | | | indicates whether jamming has been detected or suspected by the receivers. O: Unknown, 1: OK, 2: Mitigated, 3: Detected |
| jamming_indicator | `int32` | | | indicates jamming is occurring |
| spoofing_state | `uint8` | | | indicates whether spoofing has been detected or suspected by the receivers. O: Unknown, 1: OK, 2: Mitigated, 3: Detected |
| authentication_state | `uint8` | | | GPS signal authentication state |
| vel_m_s | `float32` | | | GPS ground speed, (metres/sec) |
| vel_n_m_s | `float32` | | | GPS North velocity, (metres/sec) |
| vel_e_m_s | `float32` | | | GPS East velocity, (metres/sec) |
| vel_d_m_s | `float32` | | | GPS Down velocity, (metres/sec) |
| cog_rad | `float32` | | | Course over ground (NOT heading, but direction of movement), -PI..PI, (radians) |
| vel_ned_valid | `bool` | | | True if NED velocity is valid |
| timestamp_time_relative | `int32` | | | timestamp + timestamp_time_relative = Time of the UTC timestamp since system start, (microseconds) |
| time_utc_usec | `uint64` | | | Timestamp (microseconds, UTC), this is the timestamp which comes from the gps module. It might be unavailable right after cold start, indicated by a value of 0 |
| satellites_used | `uint8` | | | Number of satellites used |
| system_error | `uint32` | | | General errors with the connected GPS receiver |
| heading | `float32` | | | heading angle of XYZ body frame rel to NED. Set to NaN if not available and updated (used for dual antenna GPS), (rad, [-PI, PI]) |
| heading_offset | `float32` | | | heading offset of dual antenna array in body frame. Set to NaN if not applicable. (rad, [-PI, PI]) |
| heading_accuracy | `float32` | | | heading accuracy (rad, [0, 2PI]) |
| rtcm_injection_rate | `float32` | | | RTCM message injection rate Hz |
| selected_rtcm_instance | `uint8` | | | uorb instance that is being used for RTCM corrections |
| rtcm_crc_failed | `bool` | | | RTCM message CRC failure detected |
| rtcm_msg_used | `uint8` | | | Indicates if the RTCM message was used successfully by the receiver |
## Constants
@@ -185,10 +182,6 @@ uint8 RTCM_MSG_USED_NOT_USED = 1
uint8 RTCM_MSG_USED_USED = 2
uint8 rtcm_msg_used # Indicates if the RTCM message was used successfully by the receiver
float32 antenna_offset_x # [m] [@frame body frame FRD] X Position of GNSS antenna
float32 antenna_offset_y # [m] [@frame body frame FRD] Y Position of GNSS antenna
float32 antenna_offset_z # [m] [@frame body frame FRD] Z Position of GNSS antenna
# TOPICS sensor_gps vehicle_gps_position
```
+8 -36
View File
@@ -1052,20 +1052,6 @@ Actuator configuration command.
| 6 | | | ? |
| 7 | | | ? |
### VEHICLE_CMD_ESC_REQUEST_EEPROM (312)
Request EEPROM data from an ESC.
| Param | Units | Range/Enum | Description |
| ----- | ----- | ---------- | ------------- |
| 1 | | | ESC Index |
| 2 | | | Firmware Type |
| 3 | | | Unused |
| 4 | | | Unused |
| 5 | | | Unused |
| 6 | | | ? |
| 7 | | | ? |
### VEHICLE_CMD_COMPONENT_ARM_DISARM (400)
Arms / Disarms a component.
@@ -1540,22 +1526,16 @@ Change mode by specifying nav_state directly.
## Constants
| Name | Type | Value | Description |
| --------------------------------------------------------------------------------------------------------- | -------- | ----- | ----------------------------------------------------------------------------------------------------- |
| Name | Type | Value | Description |
| --------------------------------------------------------------------------------------------------------- | -------- | ----- | ------------------------------------------------------------------------------------------ |
| <a id="#MESSAGE_VERSION"></a> MESSAGE_VERSION | `uint32` | 0 |
| <a id="#PREFLIGHT_CALIBRATION_TEMPERATURE_CALIBRATION"></a> PREFLIGHT_CALIBRATION_TEMPERATURE_CALIBRATION | `uint16` | 3 | Param value for VEHICLE_CMD_PREFLIGHT_CALIBRATION to start temperature calibration. |
| <a id="#VEHICLE_MOUNT_MODE_RETRACT"></a> VEHICLE_MOUNT_MODE_RETRACT | `uint8` | 0 | Load and keep safe position (Roll,Pitch,Yaw) from permanent memory and stop stabilization. |
| <a id="#VEHICLE_MOUNT_MODE_NEUTRAL"></a> VEHICLE_MOUNT_MODE_NEUTRAL | `uint8` | 1 | Load and keep neutral position (Roll,Pitch,Yaw) from permanent memory. |
| <a id="#VEHICLE_MOUNT_MODE_MAVLINK_TARGETING"></a> VEHICLE_MOUNT_MODE_MAVLINK_TARGETING | `uint8` | 2 | Load neutral position and start MAVLink Roll,Pitch,Yaw control with stabilization. |
| <a id="#VEHICLE_MOUNT_MODE_RC_TARGETING"></a> VEHICLE_MOUNT_MODE_RC_TARGETING | `uint8` | 3 | Load neutral position and start RC Roll,Pitch,Yaw control with stabilization. |
| <a id="#VEHICLE_MOUNT_MODE_GPS_POINT"></a> VEHICLE_MOUNT_MODE_GPS_POINT | `uint8` | 4 | Load neutral position and start to point to Lat,Lon,Alt. |
| <a id="#PREFLIGHT_CALIBRATION_TEMPERATURE_CALIBRATION"></a> PREFLIGHT_CALIBRATION_TEMPERATURE_CALIBRATION | `uint16` | 3 | Param value for VEHICLE_CMD_PREFLIGHT_CALIBRATION to start temperature calibration. |
| <a id="#VEHICLE_MOUNT_MODE_RETRACT"></a> VEHICLE_MOUNT_MODE_RETRACT | `uint8` | 0 | Load and keep safe position (Roll,Pitch,Yaw) from permanent memory and stop stabilization. |
| <a id="#VEHICLE_MOUNT_MODE_NEUTRAL"></a> VEHICLE_MOUNT_MODE_NEUTRAL | `uint8` | 1 | Load and keep neutral position (Roll,Pitch,Yaw) from permanent memory. |
| <a id="#VEHICLE_MOUNT_MODE_MAVLINK_TARGETING"></a> VEHICLE_MOUNT_MODE_MAVLINK_TARGETING | `uint8` | 2 | Load neutral position and start MAVLink Roll,Pitch,Yaw control with stabilization. |
| <a id="#VEHICLE_MOUNT_MODE_RC_TARGETING"></a> VEHICLE_MOUNT_MODE_RC_TARGETING | `uint8` | 3 | Load neutral position and start RC Roll,Pitch,Yaw control with stabilization. |
| <a id="#VEHICLE_MOUNT_MODE_GPS_POINT"></a> VEHICLE_MOUNT_MODE_GPS_POINT | `uint8` | 4 | Load neutral position and start to point to Lat,Lon,Alt. |
| <a id="#VEHICLE_MOUNT_MODE_ENUM_END"></a> VEHICLE_MOUNT_MODE_ENUM_END | `uint8` | 5 |
| <a id="#ACTUATOR_CONFIGURATION_NONE"></a> ACTUATOR_CONFIGURATION_NONE | `uint8` | 0 | Do nothing. |
| <a id="#ACTUATOR_CONFIGURATION_BEEP"></a> ACTUATOR_CONFIGURATION_BEEP | `uint8` | 1 | Command the actuator to beep now. |
| <a id="#ACTUATOR_CONFIGURATION_3D_MODE_ON"></a> ACTUATOR_CONFIGURATION_3D_MODE_ON | `uint8` | 2 | Permanently set the actuator (ESC) to 3D mode (reversible thrust). |
| <a id="#ACTUATOR_CONFIGURATION_3D_MODE_OFF"></a> ACTUATOR_CONFIGURATION_3D_MODE_OFF | `uint8` | 3 | Permanently set the actuator (ESC) to non 3D mode (non-reversible thrust). |
| <a id="#ACTUATOR_CONFIGURATION_SPIN_DIRECTION1"></a> ACTUATOR_CONFIGURATION_SPIN_DIRECTION1 | `uint8` | 4 | Permanently set the actuator (ESC) to spin direction 1 (which can be clockwise or counter-clockwise). |
| <a id="#ACTUATOR_CONFIGURATION_SPIN_DIRECTION2"></a> ACTUATOR_CONFIGURATION_SPIN_DIRECTION2 | `uint8` | 5 | Permanently set the actuator (ESC) to spin direction 2 (opposite of direction 1). |
| <a id="#PARACHUTE_ACTION_DISABLE"></a> PARACHUTE_ACTION_DISABLE | `uint8` | 0 |
| <a id="#PARACHUTE_ACTION_ENABLE"></a> PARACHUTE_ACTION_ENABLE | `uint8` | 1 |
| <a id="#PARACHUTE_ACTION_RELEASE"></a> PARACHUTE_ACTION_RELEASE | `uint8` | 2 |
@@ -1680,7 +1660,6 @@ uint16 VEHICLE_CMD_GIMBAL_DEVICE_INFORMATION = 283 # Command to ask information
uint16 VEHICLE_CMD_MISSION_START = 300 # Start running a mission. |first_item: the first mission item to run|last_item: the last mission item to run (after this item is run, the mission ends)|
uint16 VEHICLE_CMD_ACTUATOR_TEST = 310 # Actuator testing command. |[@range -1,1] value|[s] timeout|Unused|Unused|output function|
uint16 VEHICLE_CMD_CONFIGURE_ACTUATOR = 311 # Actuator configuration command. |configuration|Unused|Unused|Unused|output function|
uint16 VEHICLE_CMD_ESC_REQUEST_EEPROM = 312 # Request EEPROM data from an ESC. |ESC Index|Firmware Type|Unused|Unused|Unused|
uint16 VEHICLE_CMD_COMPONENT_ARM_DISARM = 400 # Arms / Disarms a component. |1 to arm, 0 to disarm.
uint16 VEHICLE_CMD_RUN_PREARM_CHECKS = 401 # Instructs a target system to run pre-arm checks.
uint16 VEHICLE_CMD_INJECT_FAILURE = 420 # Inject artificial failure for testing purposes.
@@ -1730,13 +1709,6 @@ uint8 VEHICLE_ROI_LOCATION = 3 # Point toward fixed location.
uint8 VEHICLE_ROI_TARGET = 4 # Point toward target.
uint8 VEHICLE_ROI_ENUM_END = 5
uint8 ACTUATOR_CONFIGURATION_NONE = 0 # Do nothing.
uint8 ACTUATOR_CONFIGURATION_BEEP = 1 # Command the actuator to beep now.
uint8 ACTUATOR_CONFIGURATION_3D_MODE_ON = 2 # Permanently set the actuator (ESC) to 3D mode (reversible thrust).
uint8 ACTUATOR_CONFIGURATION_3D_MODE_OFF = 3 # Permanently set the actuator (ESC) to non 3D mode (non-reversible thrust).
uint8 ACTUATOR_CONFIGURATION_SPIN_DIRECTION1 = 4 # Permanently set the actuator (ESC) to spin direction 1 (which can be clockwise or counter-clockwise).
uint8 ACTUATOR_CONFIGURATION_SPIN_DIRECTION2 = 5 # Permanently set the actuator (ESC) to spin direction 2 (opposite of direction 1).
uint8 PARACHUTE_ACTION_DISABLE = 0
uint8 PARACHUTE_ACTION_ENABLE = 1
uint8 PARACHUTE_ACTION_RELEASE = 2
-2
View File
@@ -85,8 +85,6 @@ Graphs showing how these are used [can be found here](../middleware/uorb_graph.m
- [DistanceSensorModeChangeRequest](DistanceSensorModeChangeRequest.md)
- [DronecanNodeStatus](DronecanNodeStatus.md)
- [Ekf2Timestamps](Ekf2Timestamps.md) — this message contains the (relative) timestamps of the sensor inputs used by EKF2. It can be used for reproducible replay.
- [EscEepromRead](EscEepromRead.md)
- [EscEepromWrite](EscEepromWrite.md)
- [EscReport](EscReport.md)
- [EscStatus](EscStatus.md)
- [EstimatorAidSource1d](EstimatorAidSource1d.md)
+96 -53
View File
@@ -47,12 +47,71 @@ Then connect the battery and arm the vehicle.
The ESCs should initialize and the motors turn in the correct directions.
- If the motors do not spin in the correct direction (for the [selected airframe](../airframes/airframe_reference.md)) you can reverse them in the UI using the **Set Spin Direction** option (this option appears after you select DShot and assign motors).
You can also reverse motors by sending an [ESC Command](#commands).
## ESC Commands {#commands}
Commands can be sent to the ESC via the [MAVLink shell](../debug/mavlink_shell.md).
See [here](../modules/modules_driver.md#dshot) for a full reference of the supported commands.
The most important ones are:
- Make a motor connected to FMU output pin 1 beep (helps with identifying motors)
```sh
dshot beep1 -m 1
```
- Retrieve ESC information (requires telemetry, see below):
```sh
nsh> dshot esc_info -m 2
INFO [dshot] ESC Type: #TEKKO32_4in1#
INFO [dshot] MCU Serial Number: xxxxxx-xxxxxx-xxxxxx-xxxxxx
INFO [dshot] Firmware version: 32.60
INFO [dshot] Rotation Direction: normal
INFO [dshot] 3D Mode: off
INFO [dshot] Low voltage Limit: off
INFO [dshot] Current Limit: off
INFO [dshot] LED 0: unsupported
INFO [dshot] LED 1: unsupported
INFO [dshot] LED 2: unsupported
INFO [dshot] LED 3: unsupported
```
- Permanently set the spin direction of a motor connected to FMU output pin 1 (while motors are _not_ spinning):
- Set spin direction to `reversed`:
```sh
dshot reverse -m 1
dshot save -m 1
```
Retrieving ESC information will then show:
```sh
Rotation Direction: reversed
```
- Set spin direction to `normal`:
```sh
dshot normal -m 1
dshot save -m 1
```
Retrieving ESC information will then show:
```sh
Rotation Direction: normal
```
::: info
- The commands will have no effect if the motors are spinning, or if the ESC is already set to the corresponding direction.
- The ESC will revert to its last saved direction (normal or reversed) on reboot if `save` is not called after changing the direction.
:::
## ESC Telemetry
Some ESCs are capable of sending telemetry back to the flight controller through a UART RX port.
@@ -71,76 +130,60 @@ To enable this feature (on ESCs that support it):
1. Join all the telemetry wires from all the ESCs together, and then connect them to one of the RX pins on an unused flight controller serial port.
2. Enable telemetry on that serial port using [DSHOT_TEL_CFG](../advanced_config/parameter_reference.md#DSHOT_TEL_CFG).
:::tip
You may have to configure the per-motor pole count parameters ([`DSHOT_MOT_POL1``DSHOT_MOT_POL12`](../advanced_config/parameter_reference.md#DSHOT_MOT_POL1)) to get correct RPM values.
The default value for these is 14 poles, which is typical for 5-inch prop motors.
After a reboot you can check if telemetry is working (make sure the battery is connected) using:
```sh
dshot esc_info -m 1
```
::: tip
You may have to configure [MOT_POLE_COUNT](../advanced_config/parameter_reference.md#MOT_POLE_COUNT) to get the correct RPM values.
:::
:::tip
[Extended DShot Telemetry (EDT)](#extended-dshot-telemetry-edt) can provide temperature, voltage, and current through the BDShot signal — no serial telemetry wire needed.
::: tip
Not all DSHOT-capable ESCs support `[esc_info]`(e.g. APD 80F3x), even when telemetry is supported and enabled.
The resulting error is:
```sh
ERROR [dshot] No data received. If telemetry is setup correctly, try again.
```
Check manufacturer documentation for confirmation/details.
:::
## Bidirectional DShot (Telemetry)
<Badge type="tip" text="PX4 v1.16" />
Bidirectional DShot (BDShot) enables the ESC to send eRPM telemetry back to the flight controller on the same signal wire used for throttle commands — no additional telemetry wire is needed for RPM data.
High-rate eRPM data significantly improves the performance of [Dynamic Notch Filters](../config_mc/filter_tuning.md#dynamic-notch-filters) and enables more precise vehicle tuning.
Bidirectional DShot is a protocol that can provide telemetry including: high rate ESC RPM data, voltage, current, and temperature with a single wire.
With [Extended DShot Telemetry (EDT)](#extended-dshot-telemetry-edt) enabled, BDShot can also provide temperature, voltage, and current data.
### Hardware Support
BDShot requires a flight controller with DMA-capable timers.
Any FMU output on a supported timer can be used for BDShot — multiple timers are supported through sequential burst/capture.
Supported processors:
- **STM32H7**: All FMU outputs on DMA-capable timers
- **i.MXRT** (V6X-RT & Tropic): All FMU outputs
The PX4 implementation currently enables only ESC RPM (eRPM) data collection from each ESC at high frequencies.
This telemetry significantly improves the performance of [Dynamic Notch Filters](../config_mc/filter_tuning.md#dynamic-notch-filters) and enables more precise vehicle tuning.
::: info
The ESC must be connected to FMU outputs only.
These are labeled `MAIN` on controllers with a single PWM bus, and `AUX` on controllers with both `MAIN` and `AUX` ports (i.e. those with an IO board).
The [ESC Telemetry](#esc-telemetry) described above is currently still necessary if you want voltage, current, or temperature information.
It's setup and use is independent of bidirectional DShot.
:::
### PX4 Configuration {#bidirectional-dshot-configuration}
### Hardware Setup
BDShot is enabled **per-timer** in the [Actuator Configuration](../config/actuators.md) UI.
Select **BDShot150**, **BDShot300**, or **BDShot600** as the output protocol instead of the corresponding DShot speed.
There is no separate enable parameter — choosing a BDShot protocol activates bidirectional telemetry on that timer's outputs.
The ESC must be connected to FMU outputs only.
These will be labeled `MAIN` on flight controllers that only have one PWM bus, and `AUX` on controllers that have both `MAIN` and `AUX` ports (i.e. FCs that have an IO board).
The system calculates actual motor RPM from eRPM data using per-motor pole count parameters: `DSHOT_MOT_POL1` through `DSHOT_MOT_POL12` (one per motor output).
The default is 14 poles, which is typical for 5-inch prop motors.
If you are using AM32 ESCs, the motor pole count must also be set in the AM32 firmware configuration (e.g. via the AM32 configurator tool) to match.
::: warning **Limited hardware support**
This feature is only supported on flight controllers with the following processors:
### Extended DShot Telemetry (EDT)
- STM32H7: First four FMU outputs
- Must be connected to the first 4 FMU outputs, and these outputs must also be mapped to the same timer.
- [KakuteH7](../flight_controller/kakuteh7v2.md) is not supported because the outputs are not mapped to the same timer.
- [i.MXRT](../flight_controller/nxp_mr_vmu_rt1176.md) (V6X-RT & Tropic): 8 FMU outputs.
EDT extends BDShot by interleaving temperature, voltage, and current data into the eRPM telemetry frames.
This allows ESC health monitoring through the same signal wire, without requiring a separate serial telemetry connection.
No other boards are supported.
:::
To enable EDT:
### Configuration {#bidirectional-dshot-configuration}
1. Configure BDShot on the desired outputs (see above).
2. Set `DSHOT_BIDIR_EDT` to `1` and reboot.
To enable bidirectional DShot, set the [DSHOT_BIDIR_EN](../advanced_config/parameter_reference.md#DSHOT_BIDIR_EN) parameter.
The ESC firmware must support EDT (e.g. [AM32](https://github.com/am32-firmware/AM32)).
When both serial telemetry and BDShot/EDT are enabled, the driver merges data from both sources.
## AM32 ESC Settings (EEPROM)
PX4 can read and write AM32 ESC firmware settings (EEPROM) via a ground station, enabling remote ESC configuration without connecting directly to each ESC.
### Requirements
- ESCs running [AM32 firmware](https://github.com/am32-firmware/AM32) with serial telemetry connected ([DSHOT_TEL_CFG](../advanced_config/parameter_reference.md#DSHOT_TEL_CFG))
- `DSHOT_ESC_TYPE` set to `1` (AM32)
- Ground station with ESC EEPROM support (QGroundControl feature in development)
- MAVLink development dialect enabled on the flight controller
### How It Works
PX4 automatically reads the full EEPROM from each ESC on boot.
The ground station can then display individual settings and allow the user to modify them.
Changes are written back to the ESC one byte at a time using the DShot programming protocol.
The system calculates actual motor RPM from the received eRPM data using the [MOT_POLE_COUNT](../advanced_config/parameter_reference.md#MOT_POLE_COUNT) parameter.
This parameter must be set correctly for accurate RPM reporting.
+1 -1
View File
@@ -296,7 +296,7 @@ For all variants of SIH:
For SIH on SITL you will need to explicitly enable these sensors as shown below.
:::
- `param set-default SENS_GPS0_DELAY 0` to improve state estimator performance (the assumption of instant GPS measurements would normally be unrealistic, but is accurate for SIH).
- `param set-default EKF2_GPS_DELAY 0` to improve state estimator performance (the assumption of instant GPS measurements would normally be unrealistic, but is accurate for SIH).
For SIH on FC:
+1 -1
View File
@@ -7,7 +7,7 @@ Regression test for DSHOT working with PX4
## Preflight
- Ensure vehicle is using a DSHOT ESC
- Bidirectional DShot is configured (BDShot150/300/600 selected in [Actuator Configuration](../config/actuators.md))
- Parameter [DSHOT_BIDIR_EN](../advanced_config/parameter_reference.md#DSHOT_BIDIR_EN) is enabled
- Parameter [DSHOT_TEL_CFG](../advanced_config/parameter_reference.md#DSHOT_TEL_CFG) is configured (if ESC supports telemetry)
- Parameter [SDLOG_PROFILE](../advanced_config/parameter_reference.md#SDLOG_PROFILE) has Debug (`5`) checked
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
-2
View File
@@ -69,8 +69,6 @@ set(msg_files
DistanceSensorModeChangeRequest.msg
DronecanNodeStatus.msg
Ekf2Timestamps.msg
EscEepromRead.msg
EscEepromWrite.msg
EscReport.msg
EscStatus.msg
EstimatorAidSource1d.msg
-7
View File
@@ -1,7 +0,0 @@
uint64 timestamp # [us] Time since system start
uint8 firmware # [-] ESC firmware type (see ESC_FIRMWARE enum in MAVLink)
uint8 index # [-] Index of the ESC (0 = ESC1, 1 = ESC2, etc.)
uint16 length # [-] Length of valid data
uint8[48] data # [-] Raw ESC EEPROM data
uint8 ORB_QUEUE_LENGTH = 8 # To support 8 queued up responses
-8
View File
@@ -1,8 +0,0 @@
uint64 timestamp # [us] Time since system start
uint8 firmware # [-] ESC firmware type (see ESC_FIRMWARE enum in MAVLink)
uint8 index # [-] Index of the ESC (0 = ESC1, 1 = ESC2, etc, 255 = All)
uint16 length # [-] Length of valid data
uint8[48] data # [-] Raw ESC EEPROM data
uint32[2] write_mask # [-] Bitmask indicating which bytes in the data array should be written (max 48 values)
uint8 ORB_QUEUE_LENGTH = 8 # To support 8 queued up requests
+24 -25
View File
@@ -1,31 +1,30 @@
uint64 timestamp # [us] Time since system start
uint64 timestamp # time since system start (microseconds)
uint32 esc_errorcount # Number of reported errors by ESC - if supported
int32 esc_rpm # Motor RPM, negative for reverse rotation [RPM] - if supported
float32 esc_voltage # Voltage measured from current ESC [V] - if supported
float32 esc_current # Current measured from current ESC [A] - if supported
float32 esc_temperature # Temperature measured from current ESC [degC] - if supported
int16 motor_temperature # Temperature measured from current motor [degC] - if supported
uint8 esc_address # Address of current ESC (in most cases 1-8 / must be set by driver)
uint8 esc_cmdcount # Counter of number of commands
uint32 esc_errorcount # [-] Number of reported errors by ESC - if supported
int32 esc_rpm # [rpm] Motor RPM, negative for reverse rotation - if supported
float32 esc_voltage # [V] Voltage measured from current ESC - if supported
float32 esc_current # [A] Current measured from current ESC - if supported
float32 esc_temperature # [degC] Temperature measured from current ESC - if supported
uint8 esc_address # [-] Address of current ESC (in most cases 1-12 / must be set by driver)
int16 motor_temperature # [degC] Temperature measured from current motor - if supported
uint8 esc_state # [-] State of ESC - depend on Vendor
uint8 actuator_function # [-] Actuator output function (one of Motor1...MotorN)
uint8 esc_state # State of ESC - depend on Vendor
uint8 actuator_function # actuator output function (one of Motor1...MotorN)
uint8 ACTUATOR_FUNCTION_MOTOR1 = 101
uint8 ACTUATOR_FUNCTION_MOTOR_MAX = 112 # output_functions.yaml Motor.start + Motor.count - 1
uint16 failures # [@enum FAILURE] Bitmask to indicate the internal ESC faults
int8 esc_power # [%] [@range 0,100] Applied power (negative values reserved)
uint16 failures # Bitmask to indicate the internal ESC faults
int8 esc_power # Applied power 0-100 in % (negative values reserved)
uint8 FAILURE_OVER_CURRENT = 0 # (1 << 0)
uint8 FAILURE_OVER_VOLTAGE = 1 # (1 << 1)
uint8 FAILURE_MOTOR_OVER_TEMPERATURE = 2 # (1 << 2)
uint8 FAILURE_OVER_RPM = 3 # (1 << 3)
uint8 FAILURE_INCONSISTENT_CMD = 4 # (1 << 4) Set if ESC received an inconsistent command (i.e out of boundaries)
uint8 FAILURE_MOTOR_STUCK = 5 # (1 << 5)
uint8 FAILURE_GENERIC = 6 # (1 << 6)
uint8 FAILURE_MOTOR_WARN_TEMPERATURE = 7 # (1 << 7)
uint8 FAILURE_WARN_ESC_TEMPERATURE = 8 # (1 << 8)
uint8 FAILURE_OVER_ESC_TEMPERATURE = 9 # (1 << 9)
uint8 ESC_FAILURE_COUNT = 10 # Counter - keep it as last element!
uint8 FAILURE_OVER_CURRENT = 0 # (1 << 0)
uint8 FAILURE_OVER_VOLTAGE = 1 # (1 << 1)
uint8 FAILURE_MOTOR_OVER_TEMPERATURE = 2 # (1 << 2)
uint8 FAILURE_OVER_RPM = 3 # (1 << 3)
uint8 FAILURE_INCONSISTENT_CMD = 4 # (1 << 4) Set if ESC received an inconsistent command (i.e out of boundaries)
uint8 FAILURE_MOTOR_STUCK = 5 # (1 << 5)
uint8 FAILURE_GENERIC = 6 # (1 << 6)
uint8 FAILURE_MOTOR_WARN_TEMPERATURE = 7 # (1 << 7)
uint8 FAILURE_WARN_ESC_TEMPERATURE = 8 # (1 << 8)
uint8 FAILURE_OVER_ESC_TEMPERATURE = 9 # (1 << 9)
uint8 ESC_FAILURE_COUNT = 10 # Counter - keep it as last element!
+22 -26
View File
@@ -1,32 +1,28 @@
uint64 timestamp # [us] Time since system start
uint8 CONNECTED_ESC_MAX = 12 # The number of ESCs supported (Motor1-Motor12)
uint64 timestamp # time since system start (microseconds)
uint8 CONNECTED_ESC_MAX = 8 # The number of ESCs supported. Current (Q2/2013) we support 8 ESCs
uint8 ESC_CONNECTION_TYPE_PPM = 0 # Traditional PPM ESC
uint8 ESC_CONNECTION_TYPE_SERIAL = 1 # Serial Bus connected ESC
uint8 ESC_CONNECTION_TYPE_ONESHOT = 2 # One Shot PPM
uint8 ESC_CONNECTION_TYPE_I2C = 3 # I2C
uint8 ESC_CONNECTION_TYPE_CAN = 4 # CAN-Bus
uint8 ESC_CONNECTION_TYPE_DSHOT = 5 # DShot
uint8 ESC_CONNECTION_TYPE_PPM = 0 # Traditional PPM ESC
uint8 ESC_CONNECTION_TYPE_SERIAL = 1 # Serial Bus connected ESC
uint8 ESC_CONNECTION_TYPE_ONESHOT = 2 # One Shot PPM
uint8 ESC_CONNECTION_TYPE_I2C = 3 # I2C
uint8 ESC_CONNECTION_TYPE_CAN = 4 # CAN-Bus
uint8 ESC_CONNECTION_TYPE_DSHOT = 5 # DShot
uint16 counter # [-] Incremented by the writing thread everytime new data is stored
uint16 counter # incremented by the writing thread everytime new data is stored
uint8 esc_count # [-] Number of connected ESCs
uint8 esc_connectiontype # [@enum ESC_CONNECTION_TYPE] How ESCs connected to the system
uint8 esc_count # number of connected ESCs
uint8 esc_connectiontype # how ESCs connected to the system
uint16 esc_online_flags # Bitmask indicating which ESC is online/offline (in motor order)
# esc_online_flags bit 0 : Set to 1 if Motor1 is online
# esc_online_flags bit 1 : Set to 1 if Motor2 is online
# esc_online_flags bit 2 : Set to 1 if Motor3 is online
# esc_online_flags bit 3 : Set to 1 if Motor4 is online
# esc_online_flags bit 4 : Set to 1 if Motor5 is online
# esc_online_flags bit 5 : Set to 1 if Motor6 is online
# esc_online_flags bit 6 : Set to 1 if Motor7 is online
# esc_online_flags bit 7 : Set to 1 if Motor8 is online
# esc_online_flags bit 8 : Set to 1 if Motor9 is online
# esc_online_flags bit 9 : Set to 1 if Motor10 is online
# esc_online_flags bit 10: Set to 1 if Motor11 is online
# esc_online_flags bit 11: Set to 1 if Motor12 is online
uint8 esc_online_flags # Bitmask indicating which ESC is online/offline
# esc_online_flags bit 0 : Set to 1 if ESC0 is online
# esc_online_flags bit 1 : Set to 1 if ESC1 is online
# esc_online_flags bit 2 : Set to 1 if ESC2 is online
# esc_online_flags bit 3 : Set to 1 if ESC3 is online
# esc_online_flags bit 4 : Set to 1 if ESC4 is online
# esc_online_flags bit 5 : Set to 1 if ESC5 is online
# esc_online_flags bit 6 : Set to 1 if ESC6 is online
# esc_online_flags bit 7 : Set to 1 if ESC7 is online
uint16 esc_armed_flags # [-] Bitmask indicating which ESC is armed (in motor order)
uint8 esc_armed_flags # Bitmask indicating which ESC is armed. For ESC's where the arming state is not known (returned by the ESC), the arming bits should always be set.
EscReport[12] esc
EscReport[8] esc
-4
View File
@@ -87,8 +87,4 @@ uint8 RTCM_MSG_USED_NOT_USED = 1
uint8 RTCM_MSG_USED_USED = 2
uint8 rtcm_msg_used # Indicates if the RTCM message was used successfully by the receiver
float32 antenna_offset_x # [m] [@frame body frame FRD] X Position of GNSS antenna
float32 antenna_offset_y # [m] [@frame body frame FRD] Y Position of GNSS antenna
float32 antenna_offset_z # [m] [@frame body frame FRD] Z Position of GNSS antenna
# TOPICS sensor_gps vehicle_gps_position
-15
View File
@@ -80,7 +80,6 @@ uint16 VEHICLE_CMD_GIMBAL_DEVICE_INFORMATION = 283 # Command to ask information
uint16 VEHICLE_CMD_MISSION_START = 300 # Start running a mission. |first_item: the first mission item to run|last_item: the last mission item to run (after this item is run, the mission ends)|
uint16 VEHICLE_CMD_ACTUATOR_TEST = 310 # Actuator testing command. |[@range -1,1] value|[s] timeout|Unused|Unused|output function|
uint16 VEHICLE_CMD_CONFIGURE_ACTUATOR = 311 # Actuator configuration command. |configuration|Unused|Unused|Unused|output function|
uint16 VEHICLE_CMD_ESC_REQUEST_EEPROM = 312 # Request EEPROM data from an ESC. |ESC Index|Firmware Type|Unused|Unused|Unused|
uint16 VEHICLE_CMD_COMPONENT_ARM_DISARM = 400 # Arms / Disarms a component. |1 to arm, 0 to disarm.
uint16 VEHICLE_CMD_RUN_PREARM_CHECKS = 401 # Instructs a target system to run pre-arm checks.
uint16 VEHICLE_CMD_INJECT_FAILURE = 420 # Inject artificial failure for testing purposes.
@@ -130,13 +129,6 @@ uint8 VEHICLE_ROI_LOCATION = 3 # Point toward fixed location.
uint8 VEHICLE_ROI_TARGET = 4 # Point toward target.
uint8 VEHICLE_ROI_ENUM_END = 5
uint8 ACTUATOR_CONFIGURATION_NONE = 0 # Do nothing.
uint8 ACTUATOR_CONFIGURATION_BEEP = 1 # Command the actuator to beep now.
uint8 ACTUATOR_CONFIGURATION_3D_MODE_ON = 2 # Permanently set the actuator (ESC) to 3D mode (reversible thrust).
uint8 ACTUATOR_CONFIGURATION_3D_MODE_OFF = 3 # Permanently set the actuator (ESC) to non 3D mode (non-reversible thrust).
uint8 ACTUATOR_CONFIGURATION_SPIN_DIRECTION1 = 4 # Permanently set the actuator (ESC) to spin direction 1 (which can be clockwise or counter-clockwise).
uint8 ACTUATOR_CONFIGURATION_SPIN_DIRECTION2 = 5 # Permanently set the actuator (ESC) to spin direction 2 (opposite of direction 1).
uint8 PARACHUTE_ACTION_DISABLE = 0
uint8 PARACHUTE_ACTION_ENABLE = 1
uint8 PARACHUTE_ACTION_RELEASE = 2
@@ -180,13 +172,6 @@ uint8 ORBIT_YAW_BEHAVIOUR_HOLD_FRONT_TANGENT_TO_CIRCLE = 3
uint8 ORBIT_YAW_BEHAVIOUR_RC_CONTROLLED = 4
uint8 ORBIT_YAW_BEHAVIOUR_UNCHANGED = 5
# Used as param1&2 in CMD_START_RX_PAIR.
uint8 RC_TYPE_SPEKTRUM = 0
uint8 RC_TYPE_CRSF = 1
uint8 RC_SUB_TYPE_SPEKTRUM_DSM2 = 0
uint8 RC_SUB_TYPE_SPEKTRUM_DSMX = 1
uint8 RC_SUB_TYPE_SPEKTRUM_DSMX8 = 2
# Used as param1 in ARM_DISARM command.
int8 ARMING_ACTION_DISARM = 0
int8 ARMING_ACTION_ARM = 1
+19 -36
View File
@@ -63,6 +63,8 @@ static const uint32_t gcr_decode[32] = {
0x0, 0x0, 0x8, 0x1, 0x0, 0x4, 0xC, 0x0
};
uint32_t erpms[DSHOT_TIMERS];
typedef enum {
DSHOT_START = 0,
DSHOT_12BIT_FIFO,
@@ -319,10 +321,8 @@ static int flexio_irq_handler(int irq, void *context, void *arg)
}
int up_dshot_init(uint32_t channel_mask, uint32_t bdshot_channel_mask, unsigned dshot_pwm_freq, bool edt_enable)
int up_dshot_init(uint32_t channel_mask, unsigned dshot_pwm_freq, bool enable_bidirectional_dshot)
{
(void)edt_enable; // Not implemented
/* Calculate dshot timings based on dshot_pwm_freq */
dshot_tcmp = 0x2F00 | (((BOARD_FLEXIO_PREQ / (dshot_pwm_freq * 3) / 2) - 1) & 0xFF);
dshot_speed = dshot_pwm_freq;
@@ -360,7 +360,7 @@ int up_dshot_init(uint32_t channel_mask, uint32_t bdshot_channel_mask, unsigned
imxrt_config_gpio(timer_io_channels[channel].dshot.pinmux | IOMUX_PULL_UP);
if (bdshot_channel_mask & (1 << channel)) {
if (enable_bidirectional_dshot) {
dshot_inst[channel].bdshot = true;
dshot_inst[channel].bdshot_training_mask = 0;
dshot_inst[channel].bdshot_tcmp_offset = BDSHOT_TCMP_MIN_OFFSET;
@@ -383,7 +383,7 @@ int up_dshot_init(uint32_t channel_mask, uint32_t bdshot_channel_mask, unsigned
flexio_modifyreg32(IMXRT_FLEXIO_CTRL_OFFSET, 0,
FLEXIO_CTRL_FLEXEN_MASK);
return dshot_mask;
return channel_mask;
}
void up_bdshot_training(uint32_t channel, uint32_t value)
@@ -497,26 +497,24 @@ void up_bdshot_erpm(void)
}
uint16_t up_bdshot_get_ready_mask(void)
int up_bdshot_num_erpm_ready(void)
{
return (uint16_t)bdshot_parsed_recv_mask;
}
int num_ready = 0;
int up_bdshot_num_errors(uint8_t channel)
{
if (channel >= DSHOT_TIMERS) {
return 0;
for (unsigned i = 0; i < DSHOT_TIMERS; ++i) {
// We only check that data has been received, rather than if it's valid.
// This ensures data is published even if one channel has bit errors.
if (bdshot_parsed_recv_mask & (1 << i)) {
++num_ready;
}
}
return dshot_inst[channel].crc_error_cnt + dshot_inst[channel].frame_error_cnt + dshot_inst[channel].no_response_cnt;
return num_ready;
}
int up_bdshot_get_erpm(uint8_t channel, int *erpm)
{
if (channel >= DSHOT_TIMERS) {
return -1;
}
if (bdshot_parsed_recv_mask & (1 << channel)) {
*erpm = (int)dshot_inst[channel].erpm;
return 0;
@@ -525,28 +523,13 @@ int up_bdshot_get_erpm(uint8_t channel, int *erpm)
return -1;
}
int up_bdshot_get_extended_telemetry(uint8_t channel, int type, uint8_t *value)
{
// NOT IMPLEMENTED
return -1;
}
int up_bdshot_channel_capture_supported(uint8_t channel)
{
if (channel >= DSHOT_TIMERS) {
return 0;
}
return dshot_inst[channel].init && dshot_inst[channel].bdshot;
}
int up_bdshot_channel_online(uint8_t channel)
int up_bdshot_channel_status(uint8_t channel)
{
if (channel < DSHOT_TIMERS) {
return ((dshot_inst[channel].no_response_cnt - dshot_inst[channel].last_no_response_cnt) < BDSHOT_OFFLINE_COUNT);
}
return 0;
return -1;
}
void up_bdshot_status(void)
@@ -555,7 +538,7 @@ void up_bdshot_status(void)
for (uint8_t channel = 0; (channel < DSHOT_TIMERS); channel++) {
if (dshot_inst[channel].init) {
PX4_INFO("Channel %i %s Last erpm %i value", channel, up_bdshot_channel_online(channel) ? "online" : "offline",
PX4_INFO("Channel %i %s Last erpm %i value", channel, up_bdshot_channel_status(channel) ? "online" : "offline",
dshot_inst[channel].erpm);
PX4_INFO("BDSHOT Training done: %s TCMP offset: %d", dshot_inst[channel].bdshot_training_done ? "YES" : "NO",
dshot_inst[channel].bdshot_tcmp_offset);
@@ -618,7 +601,7 @@ uint64_t dshot_expand_data(uint16_t packet)
* bit 12 - dshot telemetry enable/disable
* bits 13-16 - XOR checksum
**/
void dshot_motor_data_set(uint8_t channel, uint16_t throttle, bool telemetry)
void dshot_motor_data_set(unsigned channel, uint16_t throttle, bool telemetry)
{
if (channel < DSHOT_TIMERS && dshot_inst[channel].init) {
uint16_t csum_data;
File diff suppressed because it is too large Load Diff
@@ -83,6 +83,7 @@ void VertiqTelemetryManager::StartPublishing(uORB::Publication<esc_status_s> *es
_esc_status.esc[i].esc_address = 0;
_esc_status.esc[i].esc_rpm = 0;
_esc_status.esc[i].esc_state = 0;
_esc_status.esc[i].esc_cmdcount = 0;
_esc_status.esc[i].esc_voltage = 0;
_esc_status.esc[i].esc_current = 0;
_esc_status.esc[i].esc_temperature = 0;
@@ -123,6 +124,7 @@ uint16_t VertiqTelemetryManager::UpdateTelemetry()
_esc_status.esc[_current_module_id_target_index].esc_temperature = telem_response.mcu_temp *
0.01; //"If you ask other escs for their temp, they're giving you the micro temp, so go with that"
_esc_status.esc[_current_module_id_target_index].esc_state = 0; //not implemented
_esc_status.esc[_current_module_id_target_index].esc_cmdcount = 0; //not implemented
_esc_status.esc[_current_module_id_target_index].failures = 0; //not implemented
//Update the overall _esc_status timestamp and our counter
+4 -2
View File
@@ -66,6 +66,7 @@ VoxlEsc::VoxlEsc() :
_esc_status.esc[i].esc_address = 0;
_esc_status.esc[i].esc_rpm = 0;
_esc_status.esc[i].esc_state = 0;
_esc_status.esc[i].esc_cmdcount = 0;
_esc_status.esc[i].esc_voltage = 0;
_esc_status.esc[i].esc_current = 0;
_esc_status.esc[i].esc_temperature = 0;
@@ -525,6 +526,7 @@ int VoxlEsc::parse_response(uint8_t *buf, uint8_t len, bool print_feedback)
_esc_status.esc[id].esc_rpm = fb.rpm;
_esc_status.esc[id].esc_power = fb.power;
_esc_status.esc[id].esc_state = fb.id_state & 0x0F;
_esc_status.esc[id].esc_cmdcount = fb.cmd_counter;
_esc_status.esc[id].esc_voltage = _esc_chans[id].voltage;
_esc_status.esc[id].esc_current = _esc_chans[id].current;
_esc_status.esc[id].failures = 0; //not implemented
@@ -561,11 +563,11 @@ int VoxlEsc::parse_response(uint8_t *buf, uint8_t len, bool print_feedback)
//print ESC status just for debugging
/*
PX4_INFO("[%lld] ID=%d, ADDR %d, STATE=%d, RPM=%5d, PWR=%3d%%, V=%.2fdV, I=%.2fA, T=%+3dC, FAIL %d",
PX4_INFO("[%lld] ID=%d, ADDR %d, STATE=%d, RPM=%5d, PWR=%3d%%, V=%.2fdV, I=%.2fA, T=%+3dC, CNT %d, FAIL %d",
_esc_status.esc[id].timestamp, id, _esc_status.esc[id].esc_address,
_esc_status.esc[id].esc_state, _esc_status.esc[id].esc_rpm, _esc_status.esc[id].esc_power,
(double)_esc_status.esc[id].esc_voltage, (double)_esc_status.esc[id].esc_current, _esc_status.esc[id].esc_temperature,
_esc_status.esc[id].failures);
_esc_status.esc[id].esc_cmdcount, _esc_status.esc[id].failures);
*/
}
}
+51 -62
View File
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (c) 2025 PX4 Development Team. All rights reserved.
* Copyright (c) 2024 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
@@ -31,6 +31,11 @@
*
****************************************************************************/
/**
* @file drv_dshot.h
*
*/
#pragma once
#include <px4_platform_common/defines.h>
@@ -43,40 +48,39 @@
__BEGIN_DECLS
// https://brushlesswhoop.com/dshot-and-bidirectional-dshot/#special-commands
enum {
DSHOT_CMD_MOTOR_STOP = 0,
DSHOT_CMD_BEEP1 = 1,
DSHOT_CMD_ESC_INFO = 6,
DSHOT_CMD_SPIN_DIRECTION_1 = 7,
DSHOT_CMD_SPIN_DIRECTION_2 = 8,
DSHOT_CMD_3D_MODE_OFF = 9,
DSHOT_CMD_3D_MODE_ON = 10,
DSHOT_CMD_SAVE_SETTINGS = 12,
DSHOT_EXTENDED_TELEMETRY_ENABLE = 13,
DSHOT_CMD_ENTER_PROGRAMMING_MODE = 36,
DSHOT_CMD_EXIT_PROGRAMMING_MODE = 37,
DSHOT_CMD_MAX = 47, // >47 are throttle values
DSHOT_CMD_MIN_THROTTLE = 48,
DSHOT_CMD_MAX_THROTTLE = 2047
};
typedef enum {
DShot_cmd_motor_stop = 0,
DShot_cmd_beacon1,
DShot_cmd_beacon2,
DShot_cmd_beacon3,
DShot_cmd_beacon4,
DShot_cmd_beacon5,
DShot_cmd_esc_info, // V2 includes settings
DShot_cmd_spin_direction_1,
DShot_cmd_spin_direction_2,
DShot_cmd_3d_mode_off,
DShot_cmd_3d_mode_on,
DShot_cmd_settings_request, // Currently not implemented
DShot_cmd_save_settings,
DShot_cmd_spin_direction_normal = 20,
DShot_cmd_spin_direction_reversed = 21,
DShot_cmd_led0_on, // BLHeli32 only
DShot_cmd_led1_on, // BLHeli32 only
DShot_cmd_led2_on, // BLHeli32 only
DShot_cmd_led3_on, // BLHeli32 only
DShot_cmd_led0_off, // BLHeli32 only
DShot_cmd_led1_off, // BLHeli32 only
DShot_cmd_led2_off, // BLHeli32 only
DShot_cmd_led4_off, // BLHeli32 only
DShot_cmd_audio_stream_mode_on_off = 30, // KISS audio Stream mode on/off
DShot_cmd_silent_mode_on_off = 31, // KISS silent Mode on/off
DShot_cmd_signal_line_telemetry_disable = 32,
DShot_cmd_signal_line_continuous_erpm_telemetry = 33,
DShot_cmd_MAX = 47, // >47 are throttle values
DShot_cmd_MIN_throttle = 48,
DShot_cmd_MAX_throttle = 2047
} dshot_command_t;
// Extended DShot Telemetry
enum {
DSHOT_EDT_ERPM = 0x00,
DSHOT_EDT_TEMPERATURE = 0x02, // C
DSHOT_EDT_VOLTAGE = 0x04, // 0.25V per step
DSHOT_EDT_CURRENT = 0x06, // A
DSHOT_EDT_DEBUG1 = 0x08,
DSHOT_EDT_DEBUG2 = 0x0A,
DSHOT_EDT_DEBUG3 = 0x0C,
DSHOT_EDT_STATE_EVENT = 0x0E,
};
struct BDShotTelemetry {
int type;
int32_t value;
};
/**
* Intialise the Dshot outputs using the specified configuration.
@@ -87,12 +91,12 @@ struct BDShotTelemetry {
* @param dshot_pwm_freq Frequency of DSHOT signal. Usually DSHOT150, DSHOT300, or DSHOT600
* @return <0 on error, the initialized channels mask.
*/
__EXPORT extern int up_dshot_init(uint32_t channel_mask, uint32_t bdshot_channel_mask, unsigned dshot_pwm_freq, bool edt_enable);
__EXPORT extern int up_dshot_init(uint32_t channel_mask, unsigned dshot_pwm_freq, bool enable_bidirectional_dshot);
/**
* Set Dshot motor data, used by up_dshot_motor_data_set() and up_dshot_motor_command() (internal method)
*/
__EXPORT extern void dshot_motor_data_set(uint8_t channel, uint16_t throttle, bool telemetry);
__EXPORT extern void dshot_motor_data_set(unsigned channel, uint16_t throttle, bool telemetry);
/**
* Set the current dshot throttle value for a channel (motor).
@@ -101,9 +105,9 @@ __EXPORT extern void dshot_motor_data_set(uint8_t channel, uint16_t throttle, bo
* @param throttle The output dshot throttle value in [0 = DSHOT_DISARM_VALUE, 1 = DSHOT_MIN_THROTTLE, 1999 = DSHOT_MAX_THROTTLE].
* @param telemetry If true, request telemetry from that motor
*/
static inline void up_dshot_motor_data_set(uint8_t channel, uint16_t throttle, bool telemetry)
static inline void up_dshot_motor_data_set(unsigned channel, uint16_t throttle, bool telemetry)
{
dshot_motor_data_set(channel, throttle + DSHOT_CMD_MIN_THROTTLE, telemetry);
dshot_motor_data_set(channel, throttle + DShot_cmd_MIN_throttle, telemetry);
}
/**
@@ -138,18 +142,17 @@ __EXPORT extern int up_dshot_arm(bool armed);
*/
__EXPORT extern void up_bdshot_status(void);
/**
* Get bitmask of channels that have processed BDShot data ready to read.
* Each bit corresponds to an output channel index.
*/
__EXPORT extern uint16_t up_bdshot_get_ready_mask(void);
/**
* Get the total number of errors for a channel
* @param channel Dshot channel
* @return The total number of recorded errors
* Get how many bidirectional erpm channels are ready
*
* When we get the erpm round-robin style, we need to get
* and publish the erpms less often.
*
* @return <0 on error, OK on succes
*/
__EXPORT extern int up_bdshot_num_errors(uint8_t channel);
__EXPORT extern int up_bdshot_num_erpm_ready(void);
/**
* Get bidrectional dshot erpm for a channel
@@ -159,14 +162,6 @@ __EXPORT extern int up_bdshot_num_errors(uint8_t channel);
*/
__EXPORT extern int up_bdshot_get_erpm(uint8_t channel, int *erpm);
/**
* Get bidrectional dshot extended telemetry for a channel
* @param channel Dshot channel
* @param type The type of telemetry value to get
* @param value pointer to write the telemetry value
* @return <0 on error, OK on succes
*/
__EXPORT extern int up_bdshot_get_extended_telemetry(uint8_t channel, int type, uint8_t *value);
/**
* Get bidrectional dshot status for a channel
@@ -174,13 +169,7 @@ __EXPORT extern int up_bdshot_get_extended_telemetry(uint8_t channel, int type,
* @param erpm pointer to write the erpm value
* @return <0 on error / not supported, 0 on offline, 1 on online
*/
__EXPORT extern int up_bdshot_channel_online(uint8_t channel);
__EXPORT extern int up_bdshot_channel_status(uint8_t channel);
/**
* Check if bidrectional dshot capture is supported for a channel
* @param channel Dshot channel
* @return 0 if not supported (no DMA), 1 if supported
*/
__EXPORT extern int up_bdshot_channel_capture_supported(uint8_t channel);
__END_DECLS
+1 -3
View File
@@ -1,6 +1,6 @@
############################################################################
#
# Copyright (c) 2019-2026 PX4 Development Team. All rights reserved.
# Copyright (c) 2019-2021 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
@@ -42,11 +42,9 @@ px4_add_module(
MAIN dshot
COMPILE_FLAGS
-DPARAM_PREFIX="${PARAM_PREFIX}"
# -DDEBUG_BUILD
SRCS
DShot.cpp
DShotTelemetry.cpp
esc/AM32Settings.cpp
DEPENDS
arch_io_pins
arch_dshot
+566 -1053
View File
File diff suppressed because it is too large Load Diff
+86 -163
View File
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (c) 2026 PX4 Development Team. All rights reserved.
* Copyright (c) 2019-2022 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
@@ -39,33 +39,23 @@
#include <uORB/topics/esc_status.h>
#include <uORB/topics/vehicle_command.h>
#include <uORB/topics/vehicle_command_ack.h>
#include <uORB/topics/esc_eeprom_write.h>
#include "DShotCommon.h"
#include "DShotTelemetry.h"
using namespace time_literals;
static_assert(DSHOT_MAXIMUM_CHANNELS <= 16, "DShot driver uses uint16_t bitmasks");
#if !defined(DIRECT_PWM_OUTPUT_CHANNELS)
# error "board_config.h needs to define DIRECT_PWM_OUTPUT_CHANNELS"
#endif
static constexpr hrt_abstime ESC_INIT_TELEM_DELAY = 5_s;
/** Dshot PWM frequency, Hz */
static constexpr unsigned int DSHOT150 = 150000u;
static constexpr unsigned int DSHOT300 = 300000u;
static constexpr unsigned int DSHOT600 = 600000u;
/// Dshot PWM frequency (Hz)
static constexpr uint32_t DSHOT150 = 150000u;
static constexpr uint32_t DSHOT300 = 300000u;
static constexpr uint32_t DSHOT600 = 600000u;
/// Timer config values from PWM_TIM param (matches pwm_out/module.yaml enum)
static constexpr int32_t TIM_CONFIG_DSHOT150 = -5;
static constexpr int32_t TIM_CONFIG_DSHOT300 = -4;
static constexpr int32_t TIM_CONFIG_DSHOT600 = -3;
static constexpr int32_t TIM_CONFIG_BDSHOT150 = -8;
static constexpr int32_t TIM_CONFIG_BDSHOT300 = -7;
static constexpr int32_t TIM_CONFIG_BDSHOT600 = -6;
static constexpr uint16_t DSHOT_DISARM_VALUE = 0;
static constexpr uint16_t DSHOT_MIN_THROTTLE = 1;
static constexpr uint16_t DSHOT_MAX_THROTTLE = 1999;
static constexpr int DSHOT_DISARM_VALUE = 0;
static constexpr int DSHOT_MIN_THROTTLE = 1;
static constexpr int DSHOT_MAX_THROTTLE = 1999;
class DShot final : public ModuleBase, public OutputModuleInterface
{
@@ -75,188 +65,121 @@ public:
DShot();
~DShot() override;
// @see ModuleBase
/** @see ModuleBase */
static int custom_command(int argc, char *argv[]);
// @see ModuleBase
int print_status() override;
// @see ModuleBase
static int print_usage(const char *reason = nullptr);
// @see ModuleBase
static int task_spawn(int argc, char *argv[]);
int init();
void mixerChanged() override;
bool updateOutputs(float *outputs, unsigned num_outputs, unsigned num_control_groups_updated) override;
/** @see ModuleBase::print_status() */
int print_status() override;
/** @see ModuleBase */
static int print_usage(const char *reason = nullptr);
/**
* Send a dshot command to one or all motors
* This is expected to be called from another thread.
* @param num_repetitions number of times to repeat, set at least to 1
* @param motor_index index or -1 for all
* @return 0 on success, <0 error otherwise
*/
int send_command_thread_safe(const dshot_command_t command, const int num_repetitions, const int motor_index);
/** @see ModuleBase */
static int task_spawn(int argc, char *argv[]);
bool telemetry_enabled() const { return _telemetry != nullptr; }
bool updateOutputs(float outputs[MAX_ACTUATORS], unsigned num_outputs, unsigned num_control_groups_updated) override;
private:
// Disallow copy construction and move assignment
/** Disallow copy construction and move assignment. */
DShot(const DShot &) = delete;
DShot operator=(const DShot &) = delete;
bool initialize_dshot();
enum class DShotConfig {
Disabled = 0,
DShot150 = 150,
DShot300 = 300,
DShot600 = 600,
};
struct Command {
dshot_command_t command{};
int num_repetitions{0};
uint8_t motor_mask{0xff};
bool save{false};
bool valid() const { return num_repetitions > 0; }
void clear() { num_repetitions = 0; }
};
int _last_telemetry_index{-1};
uint8_t _actuator_functions[esc_status_s::CONNECTED_ESC_MAX] {};
void enable_dshot_outputs(const bool enabled);
void init_telemetry(const char *device, bool swap_rxtx);
// Map output channel to motor index [0..DSHOT_MAX_MOTORS-1], or -1 if not a motor
int motor_index_from_output(int output_channel) const
{
if (!_mixing_output.isMotor(output_channel)) { return -1; }
int handle_new_telemetry_data(const int telemetry_index, const DShotTelemetry::EscData &data, bool ignore_rpm);
int idx = (int)_mixing_output.outputFunction(output_channel) - (int)OutputFunction::Motor1;
return (idx >= 0 && idx < DSHOT_MAX_MOTORS) ? idx : -1;
}
void publish_esc_status(void);
uint16_t esc_armed_mask(uint16_t *outputs, uint8_t num_outputs);
void update_motor_outputs(uint16_t *outputs, int num_outputs);
void update_motor_commands(int num_outputs);
void select_next_command();
bool set_next_telemetry_index(); // Returns true when the telemetry index has wrapped, indicating all configured motors have been sampled.
bool process_serial_telemetry();
bool process_bdshot_telemetry();
void consume_esc_data(const EscData &data);
uint16_t calculate_output_value(uint16_t raw, int index);
uint16_t convert_output_to_3d_scaling(uint16_t output);
int handle_new_bdshot_erpm(void);
void Run() override;
void update_params();
// Mavlink command handlers
void update_num_motors();
void handle_vehicle_commands();
void handle_configure_actuator(const vehicle_command_s &command);
void handle_esc_request_eeprom(const vehicle_command_s &command);
// Mixer
MixingOutput _mixing_output{PARAM_PREFIX, DSHOT_MAXIMUM_CHANNELS, *this, MixingOutput::SchedulingPolicy::Auto, false, false};
uint16_t convert_output_to_3d_scaling(uint16_t output);
// Actuator-order masks (indexed by output channel)
uint32_t _output_mask{0};
uint32_t _bdshot_output_mask{0};
MixingOutput _mixing_output{PARAM_PREFIX, DIRECT_PWM_OUTPUT_CHANNELS, *this, MixingOutput::SchedulingPolicy::Auto, false, false};
uint32_t _reversible_outputs{};
// Motor-order masks (indexed by motor number: Motor1=0, Motor2=1, etc.)
uint32_t _motor_mask{0};
uint32_t _bdshot_motor_mask{0};
uint8_t _motor_count{0};
DShotTelemetry *_telemetry{nullptr};
// uORB
uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s};
uORB::Subscription _vehicle_command_sub{ORB_ID(vehicle_command)};
uORB::Subscription _esc_eeprom_write_sub{ORB_ID(esc_eeprom_write)};
uORB::PublicationMultiData<esc_status_s> esc_status_pub{ORB_ID(esc_status)};
uORB::PublicationMultiData<esc_status_s> _esc_status_pub{ORB_ID(esc_status)};
uORB::Publication<vehicle_command_ack_s> _command_ack_pub{ORB_ID(vehicle_command_ack)};
esc_status_s _esc_status{};
// Status information
uint32_t _bdshot_telem_online_mask = 0; // Mask indicating telem receive status for bidirectional dshot telem
uint32_t _serial_telem_online_mask = 0; // Mask indicating telem receive status for serial telem
uint32_t _serial_telem_errors[DSHOT_MAX_MOTORS] = {};
uint32_t _bdshot_telem_errors[DSHOT_MAX_MOTORS] = {};
uint16_t _bdshot_edt_requested_mask = 0;
uint16_t _settings_requested_mask = 0;
// Array of timestamps indicating when the telemetry came online
hrt_abstime _serial_telem_online_timestamps[DSHOT_MAX_MOTORS] = {};
hrt_abstime _bdshot_telem_online_timestamps[DSHOT_MAX_MOTORS] = {};
// Serial telemetry adaptive skip: stop polling motors that never respond
static constexpr int SERIAL_TELEM_SKIP_THRESHOLD = 10; // consecutive timeouts before skipping
uint16_t _serial_telem_skip_mask = 0; // motors to skip in round-robin
uint8_t _serial_telem_consecutive_timeouts[DSHOT_MAX_MOTORS] = {};
// Serial Telemetry
DShotTelemetry _telemetry;
static char _serial_port_path[20];
static char _telemetry_device[20];
static bool _telemetry_swap_rxtx;
static px4::atomic_bool _request_telemetry_init;
int _telemetry_motor_index = -1;
uint32_t _telemetry_requested_mask = 0;
hrt_abstime _serial_telem_delay_until = ESC_INIT_TELEM_DELAY;
// Parameters we must load only at init
bool _serial_telemetry_enabled = false;
bool _bdshot_edt_enabled = false;
px4::atomic<Command *> _new_command{nullptr};
// Cached parameters (updated in update_params())
bool _3d_enabled = false;
int _3d_dead_l = 0;
int _3d_dead_h = 0;
float _dshot_min = 0.f;
int _esc_type = 0;
// Hardware initialization state
bool _hardware_initialized = false;
uint32_t _dshot_frequency = 0;
uint32_t _bdshot_timer_channels = 0;
bool _outputs_initialized{false};
bool _outputs_on{false};
bool _bidirectional_dshot_enabled{false};
static constexpr unsigned _num_outputs{DIRECT_PWM_OUTPUT_CHANNELS};
uint32_t _output_mask{0};
int _num_motors{0};
// Perf counters
perf_counter_t _cycle_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": cycle")};
perf_counter_t _bdshot_recv_perf{perf_alloc(PC_COUNT, MODULE_NAME": bdshot recv")};
perf_counter_t _bdshot_error_perf{perf_alloc(PC_COUNT, MODULE_NAME": bdshot error")};
perf_counter_t _serial_telem_success_perf{perf_alloc(PC_COUNT, MODULE_NAME": serial telem success")};
perf_counter_t _serial_telem_error_perf{perf_alloc(PC_COUNT, MODULE_NAME": serial telem error")};
perf_counter_t _serial_telem_timeout_perf{perf_alloc(PC_COUNT, MODULE_NAME": serial telem timeout")};
perf_counter_t _serial_telem_allsampled_perf{perf_alloc(PC_COUNT, MODULE_NAME": serial telem all sampled")};
perf_counter_t _bdshot_rpm_perf{perf_alloc(PC_COUNT, MODULE_NAME": bdshot rpm")};
perf_counter_t _dshot_telem_perf{perf_alloc(PC_COUNT, MODULE_NAME": dshot telem")};
// Commands
struct DShotCommand {
uint16_t command{};
int num_repetitions{0};
uint16_t motor_mask{(1u << DSHOT_MAXIMUM_CHANNELS) - 1};
bool save{false};
bool expect_response{false};
Command _current_command{};
bool finished() const { return num_repetitions == 0; }
void clear()
{
command = 0;
num_repetitions = 0;
motor_mask = 0;
save = false;
expect_response = false;
}
};
uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s};
uORB::Subscription _vehicle_command_sub{ORB_ID(vehicle_command)};
uORB::Publication<vehicle_command_ack_s> _command_ack_pub{ORB_ID(vehicle_command_ack)};
uint16_t _esc_status_counter{0};
DShotCommand _current_command{};
// DShot Programming Mode
enum class ProgrammingState {
Idle,
EnterMode,
SendAddress,
SendValue,
ExitMode
};
esc_eeprom_write_s _esc_eeprom_write{};
bool _dshot_programming_active = {false};
uint32_t _settings_written_mask[2] = {};
ProgrammingState _programming_state{ProgrammingState::Idle};
uint16_t _programming_address{};
uint16_t _programming_value{};
param_t _param_pole_count_handles[DSHOT_MAX_MOTORS] {};
int32_t _pole_count_params[DSHOT_MAX_MOTORS] {};
int get_pole_count(int motor_index) const;
// Parameters
DEFINE_PARAMETERS(
(ParamInt<px4::params::DSHOT_ESC_TYPE>) _param_dshot_esc_type,
(ParamFloat<px4::params::DSHOT_MIN>) _param_dshot_min,
(ParamBool<px4::params::DSHOT_3D_ENABLE>) _param_dshot_3d_enable,
(ParamInt<px4::params::DSHOT_3D_DEAD_H>) _param_dshot_3d_dead_h,
(ParamInt<px4::params::DSHOT_3D_DEAD_L>) _param_dshot_3d_dead_l,
(ParamBool<px4::params::DSHOT_BIDIR_EDT>) _param_dshot_bidir_edt
(ParamInt<px4::params::MOT_POLE_COUNT>) _param_mot_pole_count,
(ParamBool<px4::params::DSHOT_BIDIR_EN>) _param_bidirectional_enable
)
};
-93
View File
@@ -1,93 +0,0 @@
/****************************************************************************
*
* Copyright (c) 2026 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.
*
****************************************************************************/
#pragma once
#include <drivers/drv_hrt.h>
#include <board_config.h>
#include <uORB/topics/esc_status.h>
#if !defined(DIRECT_PWM_OUTPUT_CHANNELS)
# error "board_config.h needs to define DIRECT_PWM_OUTPUT_CHANNELS"
#endif
static constexpr int DSHOT_MAXIMUM_CHANNELS = DIRECT_PWM_OUTPUT_CHANNELS;
// Motor-indexed arrays use this — bounded by both hardware channels and protocol limit
static constexpr int DSHOT_MAX_MOTORS = DSHOT_MAXIMUM_CHANNELS < esc_status_s::CONNECTED_ESC_MAX
? DSHOT_MAXIMUM_CHANNELS : esc_status_s::CONNECTED_ESC_MAX;
enum class TelemetrySource {
Serial = 0,
BDShot = 1,
};
struct EscData {
int motor_index; // Motor index 0..(CONNECTED_ESC_MAX-1)
hrt_abstime timestamp; // Sample time
TelemetrySource source;
float temperature; // [C]
float voltage; // [V]
float current; // [A]
int32_t erpm; // [eRPM]
};
enum class TelemetryStatus {
NotStarted = 0,
NotReady = 1,
Ready = 2,
Timeout = 3,
ParseError = 4,
};
inline uint8_t crc8(const uint8_t *buf, unsigned len)
{
auto update_crc8 = [](uint8_t crc, uint8_t crc_seed) {
uint8_t crc_u = crc ^ crc_seed;
for (unsigned i = 0; i < 8; ++i) {
crc_u = (crc_u & 0x80) ? 0x7 ^ (crc_u << 1) : (crc_u << 1);
}
return crc_u;
};
uint8_t crc = 0;
for (unsigned i = 0; i < len; ++i) {
crc = update_crc8(buf[i], crc);
}
return crc;
}
+278 -207
View File
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (c) 2026 PX4 Development Team. All rights reserved.
* Copyright (c) 2019 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
@@ -34,7 +34,6 @@
#include "DShotTelemetry.h"
#include <px4_platform_common/log.h>
#include <drivers/drv_dshot.h>
#include <unistd.h>
#include <fcntl.h>
@@ -48,14 +47,6 @@ using namespace time_literals;
DShotTelemetry::~DShotTelemetry()
{
_uart.close();
// Clean up settings handlers
for (int i = 0; i < DSHOT_MAX_MOTORS; i++) {
if (_settings_handlers[i]) {
delete _settings_handlers[i];
_settings_handlers[i] = nullptr;
}
}
}
int DShotTelemetry::init(const char *port, bool swap_rxtx)
@@ -85,224 +76,304 @@ int DShotTelemetry::init(const char *port, bool swap_rxtx)
return PX4_OK;
}
void DShotTelemetry::initSettingsHandlers(ESCType esc_type, uint16_t output_mask)
int DShotTelemetry::update(int num_motors)
{
if (_settings_initialized) {
return;
if (_current_motor_index_request == -1) {
// nothing in progress, start a request
_current_motor_index_request = 0;
_current_request_start = 0;
_frame_position = 0;
return -1;
}
_esc_type = esc_type;
// read from the uart. This must be non-blocking, so check first if there is data available
int bytes_available = _uart.bytesAvailable();
for (uint8_t i = 0; i < DSHOT_MAX_MOTORS; i++) {
if (bytes_available <= 0) {
// no data available. Check for a timeout
const hrt_abstime now = hrt_absolute_time();
bool output_enabled = (1 << i) & output_mask;
if (!output_enabled) {
continue;
}
ESCSettingsInterface *interface = nullptr;
switch (esc_type) {
case ESCType::AM32:
interface = new AM32Settings(i);
break;
case ESCType::Unknown:
break;
default:
PX4_WARN("Unsupported ESC type for settings: %d", (int)esc_type);
break;
}
if (interface) {
_settings_handlers[i] = interface;
}
}
_settings_initialized = true;
}
void DShotTelemetry::resetCommandResponse()
{
_command_response_motor_index = -1;
_command_response_start = 0;
_command_response_position = 0;
}
void DShotTelemetry::parseCommandResponse()
{
if (hrt_elapsed_time(&_command_response_start) > 1_s) {
PX4_WARN("Command response timed out: %d bytes received", _command_response_position);
PX4_WARN("At time %.2fs", (double)hrt_absolute_time() / 1000000.);
resetCommandResponse();
return;
}
uint8_t buf[COMMAND_RESPONSE_MAX_SIZE] = {};
int bytes = _uart.read(buf, sizeof(buf));
if (bytes <= 0) {
return;
}
// Handle potential overflow, fail out
if (_command_response_position + bytes > COMMAND_RESPONSE_MAX_SIZE) {
PX4_ERR("command response overflow");
resetCommandResponse();
return;
}
// Add bytes to buffer
memcpy(&_command_response_buffer[_command_response_position], buf, bytes);
_command_response_position += bytes;
switch (_command_response_command) {
case DSHOT_CMD_ESC_INFO: {
if (_command_response_motor_index < 0 || _command_response_motor_index >= DSHOT_MAX_MOTORS) {
resetCommandResponse();
return;
}
auto handler = _settings_handlers[_command_response_motor_index];
if (!handler) {
resetCommandResponse();
break;
}
if (_command_response_position == handler->getExpectedResponseSize()) {
// TODO: handle command failures
handler->decodeInfoResponse(_command_response_buffer, _command_response_position);
resetCommandResponse();
}
break;
}
default:
break;
}
}
TelemetryStatus DShotTelemetry::parseTelemetryPacket(EscData *esc_data)
{
if (telemetryResponseFinished()) {
return TelemetryStatus::NotStarted;
}
hrt_abstime elapsed = hrt_elapsed_time(&_telemetry_request_start);
// At 115200 baud the 10-byte response takes ~868us. Skip polling until data could have arrived.
if (elapsed < 800) {
return TelemetryStatus::NotReady;
}
uint8_t buf[TELEMETRY_FRAME_SIZE];
int bytes = _uart.read(buf, sizeof(buf));
if (bytes <= 0) {
if (elapsed > 5_ms) {
++_num_timeouts;
// Mark telemetry request as finished
_telemetry_request_start = 0;
_frame_position = 0;
return TelemetryStatus::Timeout;
}
return TelemetryStatus::NotReady;
}
return decodeTelemetryResponse(buf, bytes, esc_data);
}
TelemetryStatus DShotTelemetry::decodeTelemetryResponse(uint8_t *buffer, int length, EscData *esc_data)
{
auto status = TelemetryStatus::NotReady;
for (int i = 0; i < length; i++) {
_frame_buffer[_frame_position++] = buffer[i];
/*
* ESC Telemetry Frame Structure (10 bytes total)
* =============================================
* Byte 0: Temperature (uint8_t) [deg C]
* Byte 1-2: Voltage (uint16_t, big-endian) [0.01V]
* Byte 3-4: Current (uint16_t, big-endian) [0.01A]
* Byte 5-6: Consumption (uint16_t, big-endian) [mAh]
* Byte 7-8: eRPM (uint16_t, big-endian) [100ERPM]
* Byte 9: CRC8 Checksum
*/
if (_frame_position == TELEMETRY_FRAME_SIZE) {
uint8_t checksum = crc8(_frame_buffer, TELEMETRY_FRAME_SIZE - 1);
uint8_t checksum_data = _frame_buffer[TELEMETRY_FRAME_SIZE - 1];
if (checksum == checksum_data) {
uint8_t temperature = _frame_buffer[0];
uint16_t voltage = (_frame_buffer[1] << 8) | _frame_buffer[2];
uint16_t current = (_frame_buffer[3] << 8) | _frame_buffer[4];
// int16_t consumption = (_frame_buffer[5]) << 8 | _frame_buffer[6];
uint16_t erpm = (_frame_buffer[7] << 8) | _frame_buffer[8];
esc_data->timestamp = hrt_absolute_time();
esc_data->temperature = (float)temperature;
esc_data->voltage = (float)voltage * 0.01f;
esc_data->current = (float)current * 0.01f;
esc_data->erpm = erpm * 100;
++_num_successful_responses;
status = TelemetryStatus::Ready;
if (_current_request_start > 0 && now - _current_request_start > 30_ms) {
if (_redirect_output) {
// clear and go back to internal buffer
_redirect_output = nullptr;
_current_motor_index_request = -1;
} else {
++_num_checksum_errors;
status = TelemetryStatus::ParseError;
PX4_DEBUG("ESC telemetry timeout for motor %i (frame pos=%i)", _current_motor_index_request, _frame_position);
++_num_timeouts;
}
// Mark telemetry request as finished
_telemetry_request_start = 0;
_frame_position = 0;
requestNextMotor(num_motors);
return -2;
}
return -1;
}
uint8_t buf[ESC_FRAME_SIZE];
int bytes = _uart.read(buf, sizeof(buf));
int ret = -1;
for (int i = 0; i < bytes && ret == -1; ++i) {
if (_redirect_output) {
_redirect_output->buffer[_redirect_output->buf_pos++] = buf[i];
if (_redirect_output->buf_pos == sizeof(_redirect_output->buffer)) {
// buffer full: return & go back to internal buffer
_redirect_output = nullptr;
ret = _current_motor_index_request;
_current_motor_index_request = -1;
requestNextMotor(num_motors);
}
} else {
bool successful_decoding;
if (decodeByte(buf[i], successful_decoding)) {
if (successful_decoding) {
ret = _current_motor_index_request;
}
requestNextMotor(num_motors);
}
}
}
return status;
return ret;
}
void DShotTelemetry::setExpectCommandResponse(int motor_index, uint16_t command)
bool DShotTelemetry::decodeByte(uint8_t byte, bool &successful_decoding)
{
_command_response_motor_index = motor_index;
_command_response_command = command;
_command_response_start = hrt_absolute_time();
_command_response_position = 0;
}
_frame_buffer[_frame_position++] = byte;
successful_decoding = false;
bool DShotTelemetry::commandResponseFinished()
{
return _command_response_motor_index < 0;
}
if (_frame_position == ESC_FRAME_SIZE) {
PX4_DEBUG("got ESC frame for motor %i", _current_motor_index_request);
uint8_t checksum = crc8(_frame_buffer, ESC_FRAME_SIZE - 1);
uint8_t checksum_data = _frame_buffer[ESC_FRAME_SIZE - 1];
bool DShotTelemetry::commandResponseStarted()
{
return _command_response_start > 0;
}
if (checksum == checksum_data) {
_latest_data.time = hrt_absolute_time();
_latest_data.temperature = _frame_buffer[0];
_latest_data.voltage = (_frame_buffer[1] << 8) | _frame_buffer[2];
_latest_data.current = (_frame_buffer[3] << 8) | _frame_buffer[4];
_latest_data.consumption = (_frame_buffer[5]) << 8 | _frame_buffer[6];
_latest_data.erpm = (_frame_buffer[7] << 8) | _frame_buffer[8];
PX4_DEBUG("Motor %i: temp=%i, V=%i, cur=%i, consumpt=%i, rpm=%i", _current_motor_index_request,
_latest_data.temperature, _latest_data.voltage, _latest_data.current, _latest_data.consumption,
_latest_data.erpm);
++_num_successful_responses;
successful_decoding = true;
void DShotTelemetry::startTelemetryRequest()
{
_frame_position = 0;
_telemetry_request_start = hrt_absolute_time();
}
} else {
++_num_checksum_errors;
}
bool DShotTelemetry::telemetryResponseFinished()
{
return _telemetry_request_start == 0;
return true;
}
return false;
}
void DShotTelemetry::printStatus() const
{
PX4_INFO("Successful ESC frames: %i", _num_successful_responses);
PX4_INFO("Timeouts: %i", _num_timeouts);
PX4_INFO("CRC errors: %i", _num_checksum_errors);
PX4_INFO("Number of successful ESC frames: %i", _num_successful_responses);
PX4_INFO("Number of timeouts: %i", _num_timeouts);
PX4_INFO("Number of CRC errors: %i", _num_checksum_errors);
}
uint8_t DShotTelemetry::crc8(const uint8_t *buf, uint8_t len)
{
auto update_crc8 = [](uint8_t crc, uint8_t crc_seed) {
uint8_t crc_u = crc ^ crc_seed;
for (int i = 0; i < 8; ++i) {
crc_u = (crc_u & 0x80) ? 0x7 ^ (crc_u << 1) : (crc_u << 1);
}
return crc_u;
};
uint8_t crc = 0;
for (int i = 0; i < len; ++i) {
crc = update_crc8(buf[i], crc);
}
return crc;
}
void DShotTelemetry::requestNextMotor(int num_motors)
{
_current_motor_index_request = (_current_motor_index_request + 1) % num_motors;
_current_request_start = 0;
_frame_position = 0;
}
int DShotTelemetry::getRequestMotorIndex()
{
if (_current_request_start != 0) {
// already in progress, do not send another request
return -1;
}
_current_request_start = hrt_absolute_time();
return _current_motor_index_request;
}
void DShotTelemetry::decodeAndPrintEscInfoPacket(const OutputBuffer &buffer)
{
static constexpr int version_position = 12;
const uint8_t *data = buffer.buffer;
if (buffer.buf_pos < version_position) {
PX4_ERR("Not enough data received");
return;
}
enum class ESCVersionInfo {
BLHELI32,
KissV1,
KissV2,
};
ESCVersionInfo version;
int packet_length;
if (data[version_position] == 254) {
version = ESCVersionInfo::BLHELI32;
packet_length = esc_info_size_blheli32;
} else if (data[version_position] == 255) {
version = ESCVersionInfo::KissV2;
packet_length = esc_info_size_kiss_v2;
} else {
version = ESCVersionInfo::KissV1;
packet_length = esc_info_size_kiss_v1;
}
if (buffer.buf_pos != packet_length) {
PX4_ERR("Packet length mismatch (%i != %i)", buffer.buf_pos, packet_length);
return;
}
if (DShotTelemetry::crc8(data, packet_length - 1) != data[packet_length - 1]) {
PX4_ERR("Checksum mismatch");
return;
}
uint8_t esc_firmware_version = 0;
uint8_t esc_firmware_subversion = 0;
uint8_t esc_type = 0;
switch (version) {
case ESCVersionInfo::KissV1:
esc_firmware_version = data[12];
esc_firmware_subversion = (data[13] & 0x1f) + 97;
esc_type = (data[13] & 0xe0) >> 5;
break;
case ESCVersionInfo::KissV2:
case ESCVersionInfo::BLHELI32:
esc_firmware_version = data[13];
esc_firmware_subversion = data[14];
esc_type = data[15];
break;
}
const char *esc_type_str = "";
switch (version) {
case ESCVersionInfo::KissV1:
case ESCVersionInfo::KissV2:
switch (esc_type) {
case 1: esc_type_str = "KISS8A";
break;
case 2: esc_type_str = "KISS16A";
break;
case 3: esc_type_str = "KISS24A";
break;
case 5: esc_type_str = "KISS Ultralite";
break;
default: esc_type_str = "KISS (unknown)";
break;
}
break;
case ESCVersionInfo::BLHELI32: {
char *esc_type_mutable = (char *)(data + 31);
esc_type_mutable[32] = 0;
esc_type_str = esc_type_mutable;
}
break;
}
PX4_INFO("ESC Type: %s", esc_type_str);
PX4_INFO("MCU Serial Number: %02x%02x%02x-%02x%02x%02x-%02x%02x%02x-%02x%02x%02x",
data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8],
data[9], data[10], data[11]);
switch (version) {
case ESCVersionInfo::KissV1:
case ESCVersionInfo::KissV2:
PX4_INFO("Firmware version: %d.%d%c", esc_firmware_version / 100, esc_firmware_version % 100,
(char)esc_firmware_subversion);
break;
case ESCVersionInfo::BLHELI32:
PX4_INFO("Firmware version: %d.%d", esc_firmware_version, esc_firmware_subversion);
break;
}
if (version == ESCVersionInfo::KissV2 || version == ESCVersionInfo::BLHELI32) {
PX4_INFO("Rotation Direction: %s", data[16] ? "reversed" : "normal");
PX4_INFO("3D Mode: %s", data[17] ? "on" : "off");
}
if (version == ESCVersionInfo::BLHELI32) {
uint8_t setting = data[18];
switch (setting) {
case 0:
PX4_INFO("Low voltage Limit: off");
break;
case 255:
PX4_INFO("Low voltage Limit: unsupported");
break;
default:
PX4_INFO("Low voltage Limit: %d.%01d V", setting / 10, setting % 10);
break;
}
setting = data[19];
switch (setting) {
case 0:
PX4_INFO("Current Limit: off");
break;
case 255:
PX4_INFO("Current Limit: unsupported");
break;
default:
PX4_INFO("Current Limit: %d A", setting);
break;
}
for (int i = 0; i < 4; ++i) {
setting = data[i + 20];
PX4_INFO("LED %d: %s", i, setting ? (setting == 255 ? "unsupported" : "on") : "off");
}
}
}
+66 -35
View File
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (c) 2026 PX4 Development Team. All rights reserved.
* Copyright (c) 2019 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
@@ -34,59 +34,90 @@
#pragma once
#include <px4_platform_common/Serial.hpp>
#include <uORB/Publication.hpp>
#include "DShotCommon.h"
#include "esc/AM32Settings.h"
#include <drivers/drv_hrt.h>
class DShotTelemetry
{
public:
struct EscData {
hrt_abstime time;
int8_t temperature; ///< [deg C]
int16_t voltage; ///< [0.01V]
int16_t current; ///< [0.01A]
int16_t consumption; ///< [mAh]
int16_t erpm; ///< [100ERPM]
};
static constexpr int esc_info_size_blheli32 = 64;
static constexpr int esc_info_size_kiss_v1 = 15;
static constexpr int esc_info_size_kiss_v2 = 21;
static constexpr int max_esc_info_size = esc_info_size_blheli32;
struct OutputBuffer {
uint8_t buffer[max_esc_info_size];
int buf_pos{0};
int motor_index;
};
~DShotTelemetry();
int init(const char *uart_device, bool swap_rxtx);
/**
* Read telemetry from the UART (non-blocking) and handle timeouts.
* @param num_motors How many DShot enabled motors
* @return -1 if no update, -2 timeout, >= 0 for the motor index. Use @latestESCData() to get the data.
*/
int update(int num_motors);
bool redirectActive() const { return _redirect_output != nullptr; }
/**
* Get the motor index for which telemetry should be requested.
* @return -1 if no request should be made, motor index otherwise
*/
int getRequestMotorIndex();
const EscData &latestESCData() const { return _latest_data; }
/**
* Check whether we are currently expecting to read new data from an ESC
*/
bool expectingData() const { return _current_request_start != 0; }
void printStatus() const;
void startTelemetryRequest();
bool telemetryResponseFinished();
TelemetryStatus parseTelemetryPacket(EscData *esc_data);
// Attempt to parse a command response. Returns the index of the ESC or -1 on failure.
void parseCommandResponse();
bool commandResponseFinished();
bool commandResponseStarted();
void setExpectCommandResponse(int motor_index, uint16_t command);
void resetCommandResponse();
void initSettingsHandlers(ESCType esc_type, uint16_t output_mask);
static void decodeAndPrintEscInfoPacket(const OutputBuffer &buffer);
private:
static constexpr int COMMAND_RESPONSE_MAX_SIZE = 49;
static constexpr int TELEMETRY_FRAME_SIZE = 10;
TelemetryStatus decodeTelemetryResponse(uint8_t *buffer, int length, EscData *esc_data);
static constexpr int ESC_FRAME_SIZE = 10;
device::Serial _uart{};
void requestNextMotor(int num_motors);
// Command response
int _command_response_motor_index{-1};
uint16_t _command_response_command{0};
uint8_t _command_response_buffer[COMMAND_RESPONSE_MAX_SIZE];
int _command_response_position{0};
hrt_abstime _command_response_start{0};
/**
* Decode a single byte from an ESC feedback frame
* @param byte
* @param successful_decoding set to true if checksum matches
* @return true if received the expected amount of bytes and the next motor can be requested
*/
bool decodeByte(uint8_t byte, bool &successful_decoding);
// Telemetry packet
uint8_t _frame_buffer[TELEMETRY_FRAME_SIZE];
static uint8_t crc8(const uint8_t *buf, uint8_t len);
device::Serial _uart {};
uint8_t _frame_buffer[ESC_FRAME_SIZE];
int _frame_position{0};
hrt_abstime _telemetry_request_start{0};
EscData _latest_data;
int _current_motor_index_request{-1};
hrt_abstime _current_request_start{0};
OutputBuffer *_redirect_output{nullptr}; ///< if set, all read bytes are stored here instead of the internal buffer
// statistics
int _num_timeouts{0};
int _num_successful_responses{0};
int _num_checksum_errors{0};
// Settings
ESCSettingsInterface *_settings_handlers[DSHOT_MAX_MOTORS] = {nullptr};
ESCType _esc_type{ESCType::Unknown};
bool _settings_initialized{false};
};
-85
View File
@@ -1,85 +0,0 @@
/****************************************************************************
*
* Copyright (c) 2026 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 "AM32Settings.h"
#include "../DShotCommon.h"
#include <px4_platform_common/log.h>
static constexpr int RESPONSE_SIZE = EEPROM_SIZE + 1; // 48B data + 1B CRC
uORB::Publication<esc_eeprom_read_s> AM32Settings::_esc_eeprom_read_pub{ORB_ID(esc_eeprom_read)};
AM32Settings::AM32Settings(int index)
: _esc_index(index)
{}
int AM32Settings::getExpectedResponseSize()
{
return RESPONSE_SIZE;
}
void AM32Settings::publish_latest()
{
esc_eeprom_read_s data = {};
data.timestamp = hrt_absolute_time();
data.firmware = 1; // ESC_FIRMWARE_AM32
data.index = _esc_index;
memcpy(data.data, &_eeprom_data, sizeof(_eeprom_data));
data.length = sizeof(_eeprom_data);
_esc_eeprom_read_pub.publish(data);
}
bool AM32Settings::decodeInfoResponse(const uint8_t *buf, int size)
{
if (size != RESPONSE_SIZE) {
return false;
}
uint8_t checksum = crc8(buf, EEPROM_SIZE);
uint8_t checksum_data = buf[EEPROM_SIZE];
if (checksum != checksum_data) {
PX4_WARN("Command Response checksum failed!");
return false;
}
PX4_DEBUG("Successfully received AM32 settings from ESC%d", _esc_index + 1);
// Store data for retrieval later if requested
memcpy(&_eeprom_data, buf, EEPROM_SIZE);
// Publish data immediately
publish_latest();
return true;
}
@@ -1,54 +0,0 @@
/****************************************************************************
*
* Copyright (c) 2026 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.
*
****************************************************************************/
#pragma once
#include <cstdint>
enum class ESCType : uint8_t {
Unknown = 0,
AM32 = 1,
};
class ESCSettingsInterface
{
public:
virtual ~ESCSettingsInterface() = default;
virtual bool decodeInfoResponse(const uint8_t *buf, int size) = 0;
virtual int getExpectedResponseSize() = 0;
virtual void publish_latest() { /* no-op */};
// TODO: function to read data
// TODO: function to write data
};
+11 -24
View File
@@ -8,15 +8,6 @@ serial_config:
parameters:
- group: DShot
definitions:
DSHOT_ESC_TYPE:
description:
short: ESC Type
long: The ESC firmware type
type: enum
values:
0: Unknown
1: AM32
default: 0
DSHOT_MIN:
description:
short: Minimum DShot Motor Output
@@ -42,13 +33,13 @@ parameters:
When mixer outputs 1000 or value inside DSHOT 3D deadband, DShot 0 is sent.
type: boolean
default: 0
DSHOT_BIDIR_EDT:
DSHOT_BIDIR_EN:
description:
short: Enable Extended DShot Telemetry
short: Enable bidirectional DShot
long: |
This parameter enables Extended DShot Telemetry which allows transmission of
additional telemetry within the eRPM frame. The EDT data is interleaved with
the eRPM frames at a low rate.
This parameter enables bidirectional DShot which provides RPM feedback.
Note that this requires ESCs that support bidirectional DSHot, e.g. BlHeli32.
This is not the same as DShot telemetry which requires an additional serial connection.
type: boolean
default: 0
reboot_required: true
@@ -72,18 +63,14 @@ parameters:
min: 0
max: 1000
default: 1000
DSHOT_MOT_POL${i}:
MOT_POLE_COUNT: # only used by dshot so far, so keep it under the dshot group
description:
short: Number of magnetic poles of motor ${i}
short: Number of magnetic poles of the motors
long: |
Number of magnetic poles for motor ${i}.
Required to compute RPM from the eRPM returned by ESC telemetry.
Either get the number from the motor spec sheet or count the magnets
on the bell of the motor (not the stator magnets).
Specify the number of magnetic poles of the motors.
It is required to compute the RPM value from the eRPM returned with the ESC telemetry.
Either get the number from the motor spec sheet or count the magnets on the bell of the motor (not the stator magnets).
Typical motors for 5 inch props have 14 poles.
type: int32
default: 14
min: 2
max: 400
num_instances: 12
instance_start: 1
-3
View File
@@ -21,9 +21,6 @@ actuator_output:
type: enum
default: 400
values:
-8: BDShot150
-7: BDShot300
-6: BDShot600
-5: DShot150
-4: DShot300
-3: DShot600
+5 -65
View File
@@ -37,6 +37,11 @@
#include <fcntl.h>
#include <uORB/topics/battery_status.h>
#include <uORB/topics/vehicle_attitude.h>
#include <uORB/topics/sensor_gps.h>
#include <uORB/topics/vehicle_status.h>
using namespace time_literals;
ModuleBase::Descriptor CrsfRc::desc{task_spawn, custom_command, print_usage};
@@ -187,43 +192,6 @@ void CrsfRc::Run()
const hrt_abstime time_now_us = hrt_absolute_time();
perf_count_interval(_cycle_interval_perf, time_now_us);
if (_vehicle_status_sub.updated()) {
vehicle_status_s vehicle_status;
if (_vehicle_status_sub.copy(&vehicle_status)) {
_armed = (vehicle_status.arming_state == vehicle_status_s::ARMING_STATE_ARMED);
}
}
vehicle_command_s vcmd{};
if (_vehicle_cmd_sub.update(&vcmd)) {
if (vcmd.command == vehicle_command_s::VEHICLE_CMD_START_RX_PAIR) {
uint8_t cmd_ret = vehicle_command_ack_s::VEHICLE_CMD_RESULT_UNSUPPORTED;
if (!_is_singlewire && !_armed) {
if ((int)vcmd.param1 == vehicle_command_s::RC_TYPE_CRSF) {
if (BindCRSF()) {
cmd_ret = vehicle_command_ack_s::VEHICLE_CMD_RESULT_ACCEPTED;
}
}
} else {
cmd_ret = vehicle_command_ack_s::VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED;
}
// publish acknowledgement
vehicle_command_ack_s command_ack{};
command_ack.command = vcmd.command;
command_ack.result = cmd_ret;
command_ack.target_system = vcmd.source_system;
command_ack.target_component = vcmd.source_component;
command_ack.timestamp = hrt_absolute_time();
uORB::Publication<vehicle_command_ack_s> vehicle_command_ack_pub{ORB_ID(vehicle_command_ack)};
vehicle_command_ack_pub.publish(command_ack);
}
}
// Read all available data from the serial RC input UART
int new_bytes = _uart->readAtLeast(&_rcs_buf[0], RC_MAX_BUFFER_SIZE, 1, 100);
@@ -550,23 +518,6 @@ bool CrsfRc::SendTelemetryFlightMode(const char *flight_mode)
return _uart->write((void *) buf, (size_t) offset);
}
bool CrsfRc::BindCRSF()
{
uint8_t bind_frame[] = {
0xC8, // sync
0x07, // frame length
(uint8_t)crsf_frame_type_t::command,
(uint8_t)crsf_address_t::crsf_receiver,
(uint8_t)crsf_address_t::flight_controller,
(uint8_t)crsf_sub_command_t::subcmd_rx,
(uint8_t)crsf_sub_command_t::subcmd_rx_bind,
0x9E, // command CRC8
0xE8, // packet CRC8
};
return _uart->write((void *)bind_frame, sizeof(bind_frame)) == sizeof(bind_frame);
}
int CrsfRc::print_status()
{
if (_device[0] != '\0') {
@@ -596,16 +547,6 @@ int CrsfRc::print_status()
int CrsfRc::custom_command(int argc, char *argv[])
{
if (!strcmp(argv[0], "bind")) {
uORB::Publication<vehicle_command_s> vehicle_command_pub{ORB_ID(vehicle_command)};
vehicle_command_s vcmd{};
vcmd.command = vehicle_command_s::VEHICLE_CMD_START_RX_PAIR;
vcmd.param1 = vehicle_command_s::RC_TYPE_CRSF;
vcmd.timestamp = hrt_absolute_time();
vehicle_command_pub.publish(vcmd);
return 0;
}
#ifdef CONFIG_RC_CRSF_INJECT
if (!strcmp(argv[0], "start")) {
@@ -663,7 +604,6 @@ This module parses the CRSF RC uplink protocol and generates CRSF downlink telem
PRINT_MODULE_USAGE_SUBCATEGORY("radio_control");
PRINT_MODULE_USAGE_COMMAND("start");
PRINT_MODULE_USAGE_PARAM_STRING('d', "/dev/ttyS3", "<file:dev>", "RC device", true);
PRINT_MODULE_USAGE_COMMAND_DESCR("bind", "Send a CRSF bind command (not available on singlewire)");
#ifdef CONFIG_RC_CRSF_INJECT
PRINT_MODULE_USAGE_COMMAND_DESCR("inject", "Inject frame data bytes (for testing)");
#endif
-17
View File
@@ -53,8 +53,6 @@
#include <uORB/topics/vehicle_attitude.h>
#include <uORB/topics/sensor_gps.h>
#include <uORB/topics/vehicle_status.h>
#include <uORB/topics/vehicle_command.h>
#include <uORB/topics/vehicle_command_ack.h>
using namespace device;
@@ -94,13 +92,10 @@ private:
bool SendTelemetryFlightMode(const char *flight_mode);
bool BindCRSF();
Serial *_uart = nullptr; ///< UART interface to RC
char _device[20] {}; ///< device / serial port path
bool _is_singlewire{false};
bool _armed{false};
static constexpr size_t RC_MAX_BUFFER_SIZE{64};
uint8_t _rcs_buf[RC_MAX_BUFFER_SIZE] {};
@@ -119,7 +114,6 @@ private:
uORB::Subscription _vehicle_attitude_sub{ORB_ID(vehicle_attitude)};
uORB::Subscription _vehicle_gps_position_sub{ORB_ID(vehicle_gps_position)};
uORB::Subscription _vehicle_status_sub{ORB_ID(vehicle_status)};
uORB::Subscription _vehicle_cmd_sub{ORB_ID(vehicle_command)};
enum class crsf_frame_type_t : uint8_t {
gps = 0x02,
@@ -146,17 +140,6 @@ private:
attitude = 6,
};
enum class crsf_address_t : uint8_t {
flight_controller = 0xC8,
crsf_receiver = 0xEC,
crsf_transmitter = 0xEE
};
enum class crsf_sub_command_t : uint8_t {
subcmd_rx = 0x10,
subcmd_rx_bind = 0x01,
};
void WriteFrameHeader(uint8_t *buf, int &offset, const crsf_frame_type_t type, const uint8_t payload_size);
void WriteFrameCrc(uint8_t *buf, int &offset, const int buf_size);
+7 -11
View File
@@ -166,29 +166,25 @@ void DsmRc::Run()
#if defined(SPEKTRUM_POWER)
if (!_rc_scan_locked && !_armed) {
if ((int)vcmd.param1 == vehicle_command_s::RC_TYPE_SPEKTRUM) {
if ((int)vcmd.param1 == 0) {
// DSM binding command
int dsm_bind_mode = (int)vcmd.param2;
int dsm_bind_pulses = 0;
if (dsm_bind_mode == vehicle_command_s::RC_SUB_TYPE_SPEKTRUM_DSM2) {
if (dsm_bind_mode == 0) {
dsm_bind_pulses = DSM2_BIND_PULSES;
} else if (dsm_bind_mode == vehicle_command_s::RC_SUB_TYPE_SPEKTRUM_DSMX) {
} else if (dsm_bind_mode == 1) {
dsm_bind_pulses = DSMX_BIND_PULSES;
} else if (dsm_bind_mode == vehicle_command_s::RC_SUB_TYPE_SPEKTRUM_DSMX8) {
dsm_bind_pulses = DSMX8_BIND_PULSES;
} else {
PX4_WARN("invalid Spektrum bind sub-type: %d", dsm_bind_mode);
cmd_ret = vehicle_command_ack_s::VEHICLE_CMD_RESULT_DENIED;
dsm_bind_pulses = DSMX8_BIND_PULSES;
}
if (dsm_bind_pulses > 0 && bind_spektrum(dsm_bind_pulses)) {
cmd_ret = vehicle_command_ack_s::VEHICLE_CMD_RESULT_ACCEPTED;
}
bind_spektrum(dsm_bind_pulses);
cmd_ret = vehicle_command_ack_s::VEHICLE_CMD_RESULT_ACCEPTED;
}
} else {
+7 -11
View File
@@ -388,29 +388,25 @@ void RCInput::Run()
#if defined(SPEKTRUM_POWER)
if (!_rc_scan_locked && !_armed) {
if ((int)vcmd.param1 == vehicle_command_s::RC_TYPE_SPEKTRUM) {
if ((int)vcmd.param1 == 0) {
// DSM binding command
int dsm_bind_mode = (int)vcmd.param2;
int dsm_bind_pulses = 0;
if (dsm_bind_mode == vehicle_command_s::RC_SUB_TYPE_SPEKTRUM_DSM2) {
if (dsm_bind_mode == 0) {
dsm_bind_pulses = DSM2_BIND_PULSES;
} else if (dsm_bind_mode == vehicle_command_s::RC_SUB_TYPE_SPEKTRUM_DSMX) {
} else if (dsm_bind_mode == 1) {
dsm_bind_pulses = DSMX_BIND_PULSES;
} else if (dsm_bind_mode == vehicle_command_s::RC_SUB_TYPE_SPEKTRUM_DSMX8) {
dsm_bind_pulses = DSMX8_BIND_PULSES;
} else {
PX4_WARN("invalid Spektrum bind sub-type: %d", dsm_bind_mode);
cmd_ret = vehicle_command_ack_s::VEHICLE_CMD_RESULT_DENIED;
dsm_bind_pulses = DSMX8_BIND_PULSES;
}
if (dsm_bind_pulses > 0 && bind_spektrum(dsm_bind_pulses)) {
cmd_ret = vehicle_command_ack_s::VEHICLE_CMD_RESULT_ACCEPTED;
}
bind_spektrum(dsm_bind_pulses);
cmd_ret = vehicle_command_ack_s::VEHICLE_CMD_RESULT_ACCEPTED;
}
} else {
+2 -2
View File
@@ -153,9 +153,9 @@ void UavcanEscController::esc_status_extended_sub_cb(const uavcan::ReceivedDataS
}
}
uint16_t UavcanEscController::check_escs_status()
uint8_t UavcanEscController::check_escs_status()
{
uint16_t esc_status_flags = 0;
int esc_status_flags = 0;
const hrt_abstime now = hrt_absolute_time();
for (int index = 0; index < esc_status_s::CONNECTED_ESC_MAX; index++) {
+1 -1
View File
@@ -99,7 +99,7 @@ private:
/**
* Checks all the ESCs freshness based on timestamp, if an ESC exceeds the timeout then is flagged offline.
*/
uint16_t check_escs_status();
uint8_t check_escs_status();
/**
* Gets failure flags for a specific ESC
-2
View File
@@ -140,8 +140,6 @@ public:
OutputFunction outputFunction(int index) const { return _function_assignment[index]; }
bool isMotor(int index) const { return isFunctionSet(index) && (_function_assignment[index] >= OutputFunction::Motor1) && (_function_assignment[index] <= OutputFunction::Motor12); }
/**
* Call this regularly from Run(). It will call interface.updateOutputs().
* @return true if outputs were updated
-46
View File
@@ -34,7 +34,6 @@
#include "param_translation.h"
#include <inttypes.h>
#include <px4_platform_common/log.h>
#include <lib/drivers/device/Device.hpp>
#include <drivers/drv_sensor.h>
@@ -178,50 +177,5 @@ param_modify_on_import_ret param_modify_on_import(bson_node_t node)
}
}
// 2026-03-11: translate EKF2_GPS_POS_X/Y/Z -> SENS_GPS0_OFFX/OFFY/OFFZ
{
if (strcmp("EKF2_GPS_POS_X", node->name) == 0) {
strcpy(node->name, "SENS_GPS0_OFFX");
PX4_INFO("migrating %s -> %s", "EKF2_GPS_POS_X", "SENS_GPS0_OFFX");
return param_modify_on_import_ret::PARAM_MODIFIED;
}
if (strcmp("EKF2_GPS_POS_Y", node->name) == 0) {
strcpy(node->name, "SENS_GPS0_OFFY");
PX4_INFO("migrating %s -> %s", "EKF2_GPS_POS_Y", "SENS_GPS0_OFFY");
return param_modify_on_import_ret::PARAM_MODIFIED;
}
if (strcmp("EKF2_GPS_POS_Z", node->name) == 0) {
strcpy(node->name, "SENS_GPS0_OFFZ");
PX4_INFO("migrating %s -> %s", "EKF2_GPS_POS_Z", "SENS_GPS0_OFFZ");
return param_modify_on_import_ret::PARAM_MODIFIED;
}
}
// 2026-03-11: translate EKF2_GPS_DELAY to SENS_GPS0_DELAY and SENS_GPS1_DELAY
{
if (strcmp("EKF2_GPS_DELAY", node->name) == 0) {
int32_t delay_ms = static_cast<int32_t>(node->d);
param_set(param_find("SENS_GPS0_DELAY"), &delay_ms);
param_set(param_find("SENS_GPS1_DELAY"), &delay_ms);
PX4_INFO("migrating %s -> %s, %s", "EKF2_GPS_DELAY", "SENS_GPS0_DELAY", "SENS_GPS1_DELAY");
}
}
// 2026-03-11: translate MOT_POLE_COUNT to per-motor DSHOT_MOT_POL1-12
{
if ((node->type == bson_type_t::BSON_INT32) && (strcmp("MOT_POLE_COUNT", node->name) == 0)) {
for (int i = 1; i <= 12; i++) {
char name[20];
snprintf(name, sizeof(name), "DSHOT_MOT_POL%d", i);
param_set(param_find(name), &node->i32);
}
PX4_INFO("migrating %s -> DSHOT_MOT_POL1-12 (value=%" PRId32 ")", "MOT_POLE_COUNT", node->i32);
return param_modify_on_import_ret::PARAM_SKIP_IMPORT;
}
}
return param_modify_on_import_ret::PARAM_NOT_MODIFIED;
}
-1
View File
@@ -1603,7 +1603,6 @@ Commander::handle_command(const vehicle_command_s &cmd)
case vehicle_command_s::VEHICLE_CMD_DO_GIMBAL_MANAGER_PITCHYAW:
case vehicle_command_s::VEHICLE_CMD_DO_GIMBAL_MANAGER_CONFIGURE:
case vehicle_command_s::VEHICLE_CMD_CONFIGURE_ACTUATOR:
case vehicle_command_s::VEHICLE_CMD_ESC_REQUEST_EEPROM:
case vehicle_command_s::VEHICLE_CMD_REQUEST_MESSAGE:
case vehicle_command_s::VEHICLE_CMD_DO_WINCH:
case vehicle_command_s::VEHICLE_CMD_DO_GRIPPER:
@@ -60,7 +60,7 @@ void Ekf::controlGnssHeightFusion(const gnssSample &gps_sample)
}
}
const Vector3f pos_offset_body = gps_sample.pos_body - _params.imu_pos_body;
const Vector3f pos_offset_body = _params.gps_pos_body - _params.imu_pos_body;
const Vector3f pos_offset_earth = _R_to_earth * pos_offset_body;
const float gnss_alt = gps_sample.alt + pos_offset_earth(2);
@@ -304,7 +304,7 @@ bool Ekf::isGnssPosResetAllowed() const
void Ekf::updateGnssVel(const imuSample &imu_sample, const gnssSample &gnss_sample, estimator_aid_source3d_s &aid_src)
{
// correct velocity for offset relative to IMU
const Vector3f pos_offset_body = gnss_sample.pos_body - _params.imu_pos_body;
const Vector3f pos_offset_body = _params.gps_pos_body - _params.imu_pos_body;
const Vector3f angular_velocity = imu_sample.delta_ang / imu_sample.delta_ang_dt - _state.gyro_bias;
const Vector3f vel_offset_body = angular_velocity % pos_offset_body;
@@ -342,7 +342,7 @@ void Ekf::updateGnssVel(const imuSample &imu_sample, const gnssSample &gnss_samp
void Ekf::updateGnssPos(const gnssSample &gnss_sample, estimator_aid_source2d_s &aid_src)
{
// correct position and height for offset relative to IMU
const Vector3f pos_offset_body = gnss_sample.pos_body - _params.imu_pos_body;
const Vector3f pos_offset_body = _params.gps_pos_body - _params.imu_pos_body;
const Vector3f pos_offset_earth = Vector3f(_R_to_earth * pos_offset_body);
const LatLonAlt measurement(gnss_sample.lat, gnss_sample.lon, gnss_sample.alt);
const LatLonAlt measurement_corrected = measurement + (-pos_offset_earth);
+4 -1
View File
@@ -203,7 +203,6 @@ struct gnssSample {
float yaw_offset{}; ///< Heading/Yaw offset for dual antenna GPS - refer to description for GPS_YAW_OFFSET
bool spoofed{}; ///< true if GNSS data is spoofed
bool jammed{}; ///< true if GNSS data is jammed
Vector3f pos_body{}; ///< position of GPS antenna in body frame (m)
};
struct magSample {
@@ -331,6 +330,10 @@ struct parameters {
#if defined(CONFIG_EKF2_GNSS)
int32_t ekf2_gps_ctrl {static_cast<int32_t>(GnssCtrl::HPOS) | static_cast<int32_t>(GnssCtrl::VEL)};
int32_t ekf2_gps_mode {static_cast<int32_t>(GnssMode::kAuto)};
float ekf2_gps_delay{110.0f}; ///< GPS measurement delay relative to the IMU (mSec)
Vector3f gps_pos_body{}; ///< xyz position of the GPS antenna in body frame (m)
// position and velocity fusion
float ekf2_gps_v_noise{0.5f}; ///< minimum allowed observation noise for gps velocity fusion (m/sec)
float ekf2_gps_p_noise{0.5f}; ///< minimum allowed observation noise for gps position fusion (m)
+4 -1
View File
@@ -159,7 +159,7 @@ void EstimatorInterface::setMagData(const magSample &mag_sample)
#endif // CONFIG_EKF2_MAGNETOMETER
#if defined(CONFIG_EKF2_GNSS)
void EstimatorInterface::setGpsData(const gnssSample &gnss_sample)
void EstimatorInterface::setGpsData(const gnssSample &gnss_sample, const bool pps_compensation)
{
if (!_initialised) {
return;
@@ -177,7 +177,10 @@ void EstimatorInterface::setGpsData(const gnssSample &gnss_sample)
}
}
const int64_t delay = pps_compensation ? 0 : static_cast<int64_t>(_params.ekf2_gps_delay * 1000);
const int64_t time_us = gnss_sample.time_us
- delay
- static_cast<int64_t>(_dt_ekf_avg * 5e5f); // seconds to microseconds divided by 2
if (time_us >= static_cast<int64_t>(_gps_buffer->get_newest().time_us + _min_obs_interval_us)) {
+1 -1
View File
@@ -89,7 +89,7 @@ public:
void setIMUData(const imuSample &imu_sample);
#if defined(CONFIG_EKF2_GNSS)
void setGpsData(const gnssSample &gnss_sample);
void setGpsData(const gnssSample &gnss_sample, const bool pps_compensation = false);
const gnssSample &get_gps_sample_delayed() const { return _gps_sample_delayed; }
+12 -17
View File
@@ -80,6 +80,10 @@ EKF2::EKF2(bool multi_mode, const px4::wq_config_t &config, bool replay_mode):
#if defined(CONFIG_EKF2_GNSS)
_param_ekf2_gps_ctrl(_params->ekf2_gps_ctrl),
_param_ekf2_gps_mode(_params->ekf2_gps_mode),
_param_ekf2_gps_delay(_params->ekf2_gps_delay),
_param_ekf2_gps_pos_x(_params->gps_pos_body(0)),
_param_ekf2_gps_pos_y(_params->gps_pos_body(1)),
_param_ekf2_gps_pos_z(_params->gps_pos_body(2)),
_param_ekf2_gps_v_noise(_params->ekf2_gps_v_noise),
_param_ekf2_gps_p_noise(_params->ekf2_gps_p_noise),
_param_ekf2_gps_p_gate(_params->ekf2_gps_p_gate),
@@ -927,17 +931,11 @@ void EKF2::VerifyParams()
#endif // CONFIG_EKF2_RANGE_FINDER
#if defined(CONFIG_EKF2_GNSS)
{
int32_t gps_delay_ms = 0;
if (param_get(param_find("SENS_GPS0_DELAY"), &gps_delay_ms) == PX4_OK) {
delay_max = math::max(delay_max, static_cast<float>(gps_delay_ms));
}
if (param_get(param_find("SENS_GPS1_DELAY"), &gps_delay_ms) == PX4_OK) {
delay_max = math::max(delay_max, static_cast<float>(gps_delay_ms));
}
if (_param_ekf2_gps_delay.get() > delay_max) {
delay_max = _param_ekf2_gps_delay.get();
}
#endif // CONFIG_EKF2_GNSS
#if defined(CONFIG_EKF2_OPTICAL_FLOW)
@@ -2438,12 +2436,12 @@ void EKF2::UpdateGpsSample(ekf2_timestamps_s &ekf2_timestamps)
const float altitude_amsl = static_cast<float>(vehicle_gps_position.altitude_msl_m);
const float altitude_ellipsoid = static_cast<float>(vehicle_gps_position.altitude_ellipsoid_m);
// timestamp_sample is corrected by the sensors module (per-receiver delay or PPS)
const bool timestamp_corrected = vehicle_gps_position.timestamp_sample > 0
&& vehicle_gps_position.timestamp_sample != vehicle_gps_position.timestamp;
// if pps_compensation is active but not valid, the timestamp_sample will be equal to timestamp
const bool pps_compensation = vehicle_gps_position.timestamp_sample > 0
&& vehicle_gps_position.timestamp_sample != vehicle_gps_position.timestamp;
gnssSample gnss_sample{
.time_us = timestamp_corrected ? vehicle_gps_position.timestamp_sample : vehicle_gps_position.timestamp,
.time_us = pps_compensation ? vehicle_gps_position.timestamp_sample : vehicle_gps_position.timestamp,
.lat = vehicle_gps_position.latitude_deg,
.lon = vehicle_gps_position.longitude_deg,
.alt = altitude_amsl,
@@ -2460,12 +2458,9 @@ void EKF2::UpdateGpsSample(ekf2_timestamps_s &ekf2_timestamps)
.yaw_offset = vehicle_gps_position.heading_offset,
.spoofed = vehicle_gps_position.spoofing_state == sensor_gps_s::SPOOFING_STATE_DETECTED,
.jammed = vehicle_gps_position.jamming_state == sensor_gps_s::JAMMING_STATE_DETECTED,
.pos_body = Vector3f(vehicle_gps_position.antenna_offset_x,
vehicle_gps_position.antenna_offset_y,
vehicle_gps_position.antenna_offset_z),
};
_ekf.setGpsData(gnss_sample);
_ekf.setGpsData(gnss_sample, pps_compensation);
const float geoid_height = altitude_ellipsoid - altitude_amsl;
+6
View File
@@ -514,6 +514,12 @@ private:
#if defined(CONFIG_EKF2_GNSS)
(ParamExtInt<px4::params::EKF2_GPS_CTRL>) _param_ekf2_gps_ctrl,
(ParamExtInt<px4::params::EKF2_GPS_MODE>) _param_ekf2_gps_mode,
(ParamExtFloat<px4::params::EKF2_GPS_DELAY>) _param_ekf2_gps_delay,
(ParamExtFloat<px4::params::EKF2_GPS_POS_X>) _param_ekf2_gps_pos_x,
(ParamExtFloat<px4::params::EKF2_GPS_POS_Y>) _param_ekf2_gps_pos_y,
(ParamExtFloat<px4::params::EKF2_GPS_POS_Z>) _param_ekf2_gps_pos_z,
(ParamExtFloat<px4::params::EKF2_GPS_V_NOISE>) _param_ekf2_gps_v_noise,
(ParamExtFloat<px4::params::EKF2_GPS_P_NOISE>) _param_ekf2_gps_p_noise,
+36
View File
@@ -27,6 +27,18 @@ parameters:
0: Automatic
1: Dead-reckoning
default: 0
EKF2_GPS_DELAY:
description:
short: GPS measurement delay relative to IMU measurement
long: GPS measurement delay relative to IMU measurement if PPS time correction
is not available/enabled (PPS_CAP_ENABLE).
type: float
default: 110
min: 0
max: 300
unit: ms
reboot_required: true
decimal: 1
EKF2_GPS_P_NOISE:
description:
short: Measurement noise for GNSS position
@@ -74,6 +86,30 @@ parameters:
max: 5.0
unit: m/s
decimal: 2
EKF2_GPS_POS_X:
description:
short: X position of GPS antenna in body frame
long: Forward (roll) axis with origin relative to vehicle centre of gravity
type: float
default: 0.0
unit: m
decimal: 3
EKF2_GPS_POS_Y:
description:
short: Y position of GPS antenna in body frame
long: Right (pitch) axis with origin relative to vehicle centre of gravity
type: float
default: 0.0
unit: m
decimal: 3
EKF2_GPS_POS_Z:
description:
short: Z position of GPS antenna in body frame
long: Down (yaw) axis with origin relative to vehicle centre of gravity
type: float
default: 0.0
unit: m
decimal: 3
EKF2_GPS_CHECK:
description:
short: Integer bitmask controlling GPS checks
@@ -15,9 +15,9 @@ Gps::~Gps()
void Gps::send(const uint64_t time)
{
const float dt = static_cast<float>(time - _gps_data.time_us - kGpsDelayUs) * 1e-6f;
const float dt = static_cast<float>(time - _gps_data.time_us) * 1e-6f;
_gps_data.time_us = time - kGpsDelayUs;
_gps_data.time_us = time;
if (fabsf(_gps_pos_rate(0)) > FLT_EPSILON || fabsf(_gps_pos_rate(1)) > FLT_EPSILON) {
stepHorizontalPositionByMeters(Vector2f(_gps_pos_rate) * dt);
@@ -71,8 +71,6 @@ public:
private:
void send(uint64_t time) override;
static constexpr uint64_t kGpsDelayUs{110000};
gnssSample _gps_data{};
Vector3f _gps_pos_rate{};
};
+1 -1
View File
@@ -64,7 +64,7 @@ void LoggedTopics::add_default_topics()
add_optional_topic("external_ins_attitude");
add_optional_topic("external_ins_global_position");
add_optional_topic("external_ins_local_position");
add_topic("esc_status", 100);
add_topic("esc_status");
add_topic("failure_detector_status", 100);
add_topic("failsafe_flags");
add_optional_topic("follow_target", 500);
-15
View File
@@ -1462,9 +1462,6 @@ Mavlink::configure_streams_to_default(const char *configure_single_stream)
configure_stream_local("EFI_STATUS", 2.0f);
configure_stream_local("ESC_INFO", 1.0f);
configure_stream_local("ESC_STATUS", 1.0f);
#if defined(MAVLINK_MSG_ID_ESC_EEPROM)
configure_stream_local("ESC_EEPROM", unlimited_rate);
#endif
configure_stream_local("ESTIMATOR_STATUS", 0.5f);
configure_stream_local("EXTENDED_SYS_STATE", 1.0f);
configure_stream_local("GIMBAL_DEVICE_ATTITUDE_STATUS", 5.0f);
@@ -1529,9 +1526,6 @@ Mavlink::configure_streams_to_default(const char *configure_single_stream)
configure_stream_local("DISTANCE_SENSOR", 10.0f);
configure_stream_local("ESC_INFO", 10.0f);
configure_stream_local("ESC_STATUS", 10.0f);
#if defined(MAVLINK_MSG_ID_ESC_EEPROM)
configure_stream_local("ESC_EEPROM", unlimited_rate);
#endif
configure_stream_local("MOUNT_ORIENTATION", 10.0f);
configure_stream_local("OBSTACLE_DISTANCE", 10.0f);
configure_stream_local("ODOMETRY", 30.0f);
@@ -1710,9 +1704,6 @@ Mavlink::configure_streams_to_default(const char *configure_single_stream)
configure_stream_local("EFI_STATUS", 10.0f);
configure_stream_local("ESC_INFO", 10.0f);
configure_stream_local("ESC_STATUS", 10.0f);
#if defined(MAVLINK_MSG_ID_ESC_EEPROM)
configure_stream_local("ESC_EEPROM", unlimited_rate);
#endif
configure_stream_local("ESTIMATOR_STATUS", 5.0f);
configure_stream_local("EXTENDED_SYS_STATE", 2.0f);
configure_stream_local("GLOBAL_POSITION_INT", 10.0f);
@@ -1808,9 +1799,6 @@ Mavlink::configure_streams_to_default(const char *configure_single_stream)
configure_stream_local("GIMBAL_DEVICE_SET_ATTITUDE", 5.0f);
configure_stream_local("ESC_INFO", 1.0f);
configure_stream_local("ESC_STATUS", 5.0f);
#if defined(MAVLINK_MSG_ID_ESC_EEPROM)
configure_stream_local("ESC_EEPROM", unlimited_rate);
#endif
configure_stream_local("ADSB_VEHICLE", 5.f);
configure_stream_local("ATTITUDE_TARGET", 2.0f);
@@ -1877,9 +1865,6 @@ Mavlink::configure_streams_to_default(const char *configure_single_stream)
configure_stream_local("GIMBAL_DEVICE_SET_ATTITUDE", 2.0f);
configure_stream_local("ESC_INFO", 1.0f);
configure_stream_local("ESC_STATUS", 2.0f);
#if defined(MAVLINK_MSG_ID_ESC_EEPROM)
configure_stream_local("ESC_EEPROM", unlimited_rate);
#endif
configure_stream_local("ADSB_VEHICLE", 1.0f);
configure_stream_local("ATTITUDE_TARGET", 0.5f);
configure_stream_local("AVAILABLE_MODES", 0.3f);
-7
View File
@@ -135,10 +135,6 @@
#include "streams/CURRENT_MODE.hpp"
#endif
#ifdef MAVLINK_MSG_ID_ESC_EEPROM // Only defined if development.xml is used
#include "streams/ESC_EEPROM.hpp"
#endif
#if !defined(CONSTRAINED_FLASH)
# include "streams/ADSB_VEHICLE.hpp"
# include "streams/AUTOPILOT_STATE_FOR_GIMBAL_DEVICE.hpp"
@@ -470,9 +466,6 @@ static const StreamListItem streams_list[] = {
#if defined(ESC_STATUS_HPP)
create_stream_list_item<MavlinkStreamESCStatus>(),
#endif // ESC_STATUS_HPP
#if defined(ESC_EEPROM_HPP)
create_stream_list_item<MavlinkStreamEscEeprom>(),
#endif // ESC_EEPROM_HPP
#if defined(AUTOPILOT_VERSION_HPP)
create_stream_list_item<MavlinkStreamAutopilotVersion>(),
#endif // AUTOPILOT_VERSION_HPP
+7 -67
View File
@@ -333,14 +333,6 @@ MavlinkReceiver::handle_message(mavlink_message_t *msg)
case MAVLINK_MSG_ID_SET_VELOCITY_LIMITS:
handle_message_set_velocity_limits(msg);
break;
#endif
#if defined(MAVLINK_MSG_ID_ESC_EEPROM) // For now only defined if development.xml is used
case MAVLINK_MSG_ID_ESC_EEPROM:
handle_message_esc_eeprom(msg);
break;
#endif
default:
@@ -606,24 +598,14 @@ void MavlinkReceiver::handle_message_command_both(mavlink_message_t *msg, const
uint16_t message_id = (uint16_t)roundf(vehicle_command.param1);
#if defined(MAVLINK_MSG_ID_ESC_EEPROM)
if (message_id == MAVLINK_MSG_ID_MESSAGE_INTERVAL) {
get_message_interval((int)(cmd_mavlink.param2 + 0.5f));
// Translate ESC_EEPROM request into the PX4 internal command so the DShot driver handles it
if (message_id == MAVLINK_MSG_ID_ESC_EEPROM) {
vehicle_command_s eeprom_cmd = vehicle_command;
eeprom_cmd.command = vehicle_command_s::VEHICLE_CMD_ESC_REQUEST_EEPROM;
_cmd_pub.publish(eeprom_cmd);
} else
#endif
if (message_id == MAVLINK_MSG_ID_MESSAGE_INTERVAL) {
get_message_interval((int)(cmd_mavlink.param2 + 0.5f));
} else {
result = handle_request_message_command(message_id,
vehicle_command.param2, vehicle_command.param3, vehicle_command.param4,
vehicle_command.param5, vehicle_command.param6, vehicle_command.param7);
}
} else {
result = handle_request_message_command(message_id,
vehicle_command.param2, vehicle_command.param3, vehicle_command.param4,
vehicle_command.param5, vehicle_command.param6, vehicle_command.param7);
}
} else if (cmd_mavlink.command == MAV_CMD_INJECT_FAILURE) {
if (_mavlink.failure_injection_enabled()) {
@@ -1326,48 +1308,6 @@ void MavlinkReceiver::handle_message_set_velocity_limits(mavlink_message_t *msg)
}
#endif // MAVLINK_MSG_ID_SET_VELOCITY_LIMITS
#if defined(MAVLINK_MSG_ID_ESC_EEPROM) // For now only defined if development.xml is used
void
MavlinkReceiver::handle_message_esc_eeprom(mavlink_message_t *msg)
{
mavlink_esc_eeprom_t message;
mavlink_msg_esc_eeprom_decode(msg, &message);
esc_eeprom_write_s eeprom{};
eeprom.timestamp = hrt_absolute_time();
eeprom.firmware = message.firmware;
eeprom.index = message.esc_index;
if (eeprom.index != 255 && eeprom.index >= esc_status_s::CONNECTED_ESC_MAX) {
PX4_ERR("ESC EEPROM: invalid esc_index %u", eeprom.index);
return;
}
uint8_t min_length = sizeof(eeprom.data);
int length = message.length;
if (length > min_length) {
length = min_length;
}
for (int i = 0; i < length && i < min_length; i++) {
int mask_index = i / 32; // Which uint32_t in the write_mask array
int bit_index = i % 32; // Which bit within that uint32_t
if (message.write_mask[mask_index] & (1U << bit_index)) {
eeprom.data[i] = message.data[i];
}
}
eeprom.length = length;
memcpy(eeprom.write_mask, message.write_mask, sizeof(eeprom.write_mask));
PX4_DEBUG("ESC EEPROM write request for ESC%d", eeprom.index + 1);
_esc_eeprom_write_pub.publish(eeprom);
}
#endif // MAVLINK_MSG_ID_ESC_EEPROM
void
MavlinkReceiver::handle_message_vision_position_estimate(mavlink_message_t *msg)
{
-12
View File
@@ -64,10 +64,6 @@
#include <uORB/topics/actuator_outputs.h>
#include <uORB/topics/airspeed.h>
#include <uORB/topics/autotune_attitude_control_status.h>
#if defined(MAVLINK_MSG_ID_ESC_EEPROM)
#include <uORB/topics/esc_eeprom_write.h>
#endif
#include <uORB/topics/esc_status.h>
#include <uORB/topics/battery_status.h>
#include <uORB/topics/camera_status.h>
#include <uORB/topics/cellular_status.h>
@@ -207,9 +203,6 @@ private:
void handle_message_utm_global_position(mavlink_message_t *msg);
#if defined(MAVLINK_MSG_ID_SET_VELOCITY_LIMITS) // For now only defined if development.xml is used
void handle_message_set_velocity_limits(mavlink_message_t *msg);
#endif
#if defined(MAVLINK_MSG_ID_ESC_EEPROM) // For now only defined if development.xml is used
void handle_message_esc_eeprom(mavlink_message_t *msg);
#endif
void handle_message_vision_position_estimate(mavlink_message_t *msg);
void handle_message_gimbal_manager_set_attitude(mavlink_message_t *msg);
@@ -337,11 +330,6 @@ private:
uORB::Publication<vehicle_odometry_s> _mocap_odometry_pub{ORB_ID(vehicle_mocap_odometry)};
uORB::Publication<vehicle_odometry_s> _visual_odometry_pub{ORB_ID(vehicle_visual_odometry)};
uORB::Publication<vehicle_rates_setpoint_s> _rates_sp_pub{ORB_ID(vehicle_rates_setpoint)};
#if defined(MAVLINK_MSG_ID_ESC_EEPROM)
uORB::Publication<esc_eeprom_write_s> _esc_eeprom_write_pub {ORB_ID(esc_eeprom_write)};
#endif
#if !defined(CONSTRAINED_FLASH)
uORB::Publication<debug_array_s> _debug_array_pub {ORB_ID(debug_array)};
uORB::Publication<debug_key_value_s> _debug_key_value_pub{ORB_ID(debug_key_value)};
@@ -1,89 +0,0 @@
/****************************************************************************
*
* Copyright (c) 2026 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.
*
****************************************************************************/
#ifndef ESC_EEPROM_HPP
#define ESC_EEPROM_HPP
#include <uORB/topics/esc_eeprom_read.h>
class MavlinkStreamEscEeprom : public MavlinkStream
{
public:
static MavlinkStream *new_instance(Mavlink *mavlink) { return new MavlinkStreamEscEeprom(mavlink); }
static constexpr const char *get_name_static() { return "ESC_EEPROM"; }
static constexpr uint16_t get_id_static() { return MAVLINK_MSG_ID_ESC_EEPROM; }
const char *get_name() const override { return get_name_static(); }
uint16_t get_id() override { return get_id_static(); }
unsigned get_size() override
{
return _esc_eeprom_read_sub.advertised() ? MAVLINK_MSG_ID_ESC_EEPROM_LEN + MAVLINK_NUM_NON_PAYLOAD_BYTES : 0;
}
private:
explicit MavlinkStreamEscEeprom(Mavlink *mavlink) : MavlinkStream(mavlink) {}
uORB::Subscription _esc_eeprom_read_sub{ORB_ID(esc_eeprom_read)};
bool emit_message(bool force)
{
esc_eeprom_read_s eeprom = {};
if (_esc_eeprom_read_sub.update(&eeprom) || force) {
mavlink_esc_eeprom_t msg = {};
msg.firmware = eeprom.firmware;
msg.esc_index = eeprom.index;
msg.msg_index = 0;
msg.msg_count = 1;
size_t copy_len = eeprom.length < sizeof(eeprom.data) ? eeprom.length : sizeof(eeprom.data);
memcpy(msg.data, eeprom.data, copy_len);
msg.length = copy_len;
mavlink_msg_esc_eeprom_send_struct(_mavlink->get_channel(), &msg);
return true;
}
return false;
}
bool send() override
{
return emit_message(false);
}
};
#endif // ESC_EEPROM_HPP
+46 -41
View File
@@ -52,7 +52,7 @@ public:
unsigned get_size() override
{
static constexpr unsigned message_size = MAVLINK_MSG_ID_ESC_INFO_LEN + MAVLINK_NUM_NON_PAYLOAD_BYTES;
return MAX_NUM_MSGS * message_size;
return _esc_status_subs.advertised_count() * message_size;
}
private:
@@ -66,101 +66,106 @@ private:
static constexpr hrt_abstime ESC_TIMEOUT = 100000;
struct EscOutputInterfaceInfo {
uint16_t counter;
uint8_t esc_count;
uint8_t esc_connectiontype;
uint8_t esc_online_flags;
};
struct EscInfo {
hrt_abstime timestamp;
uint16_t failure_flags;
uint32_t error_count;
int16_t temperature;
uint8_t connectiontype;
bool online;
};
uint16_t _total_counter = {};
uint8_t _total_esc_count = {};
int _total_esc_count = {};
EscOutputInterfaceInfo _interface[MAX_NUM_MSGS] = {};
EscInfo _escs[MAX_ESC_OUTPUTS] = {};
uint16_t _instance_counter[ORB_MULTI_MAX_INSTANCES] = {};
uint8_t _instance_esc_count[ORB_MULTI_MAX_INSTANCES] = {};
void update_data() override
{
for (int i = 0; i < _esc_status_subs.size(); i++) {
int subscriber_count = math::min(_esc_status_subs.size(), MAX_NUM_MSGS);
for (int i = 0; i < subscriber_count; i++) {
esc_status_s esc = {};
if (_esc_status_subs[i].update(&esc)) {
_instance_counter[i] = esc.counter;
_instance_esc_count[i] = esc.esc_count;
_interface[i].counter = esc.counter;
_interface[i].esc_count = esc.esc_count;
_interface[i].esc_connectiontype = esc.esc_connectiontype;
uint16_t online_flags = esc.esc_online_flags;
// Capture online_flags, we will map from index to motor number
uint8_t online_flags = esc.esc_online_flags;
_interface[i].esc_online_flags = 0;
for (int j = 0; j < esc_status_s::CONNECTED_ESC_MAX; j++) {
bool is_motor = math::isInRange(esc.esc[j].actuator_function,
esc_report_s::ACTUATOR_FUNCTION_MOTOR1, esc_report_s::ACTUATOR_FUNCTION_MOTOR_MAX);
if (is_motor) {
// Map OutputFunction number to index
int index = (int)esc.esc[j].actuator_function - esc_report_s::ACTUATOR_FUNCTION_MOTOR1;
if (index >= 0 && index < MAX_ESC_OUTPUTS) {
_escs[index].online = online_flags & (1 << j);
_escs[index].failure_flags = esc.esc[j].failures;
_escs[index].error_count = esc.esc[j].esc_errorcount;
_escs[index].timestamp = esc.esc[j].timestamp;
_escs[index].temperature = esc.esc[j].esc_temperature * 100.f;
_escs[index].connectiontype = esc.esc_connectiontype;
}
_escs[index].online = online_flags & (1 << j);
_escs[index].failure_flags = esc.esc[j].failures;
_escs[index].error_count = esc.esc[j].esc_errorcount;
_escs[index].timestamp = esc.esc[j].timestamp;
_escs[index].temperature = esc.esc[j].esc_temperature * 100.f;
}
}
}
}
_total_counter = 0;
_total_esc_count = 0;
int count = 0;
for (int i = 0; i < _esc_status_subs.size(); i++) {
_total_counter += _instance_counter[i];
_total_esc_count += _instance_esc_count[i];
for (int i = 0; i < MAX_NUM_MSGS; i++) {
count += _interface[i].esc_count;
}
_total_esc_count = count;
}
bool send() override
{
if (_total_esc_count == 0) {
return false;
}
bool updated = false;
const int num_msgs = math::min((_total_esc_count + ESCS_PER_MSG - 1) / ESCS_PER_MSG, (int)MAX_NUM_MSGS);
const hrt_abstime now = hrt_absolute_time();
for (int i = 0; i < MAX_NUM_MSGS; i++) {
for (int i = 0; i < num_msgs; i++) {
hrt_abstime now = hrt_absolute_time();
mavlink_esc_info_t msg = {};
msg.index = i * ESCS_PER_MSG;
msg.time_usec = now;
msg.counter = _total_counter;
msg.counter = _interface[i].counter;
msg.count = _total_esc_count;
msg.connection_type = 0;
msg.info = 0;
msg.connection_type = _interface[i].esc_connectiontype;
msg.info = _interface[i].esc_online_flags;
bool atleast_one_esc_updated = false;
for (int j = 0; j < ESCS_PER_MSG; j++) {
EscInfo &esc = _escs[i * ESCS_PER_MSG + j];
msg.info |= (esc.online << j);
if ((esc.timestamp != 0) && (esc.timestamp + ESC_TIMEOUT) > now) {
msg.info |= (esc.online << j);
msg.failure_flags[j] = esc.failure_flags;
msg.error_count[j] = esc.error_count;
msg.temperature[j] = esc.temperature;
if (msg.connection_type == 0) {
msg.connection_type = esc.connectiontype;
}
atleast_one_esc_updated = true;
}
}
mavlink_msg_esc_info_send_struct(_mavlink->get_channel(), &msg);
if (atleast_one_esc_updated) {
mavlink_msg_esc_info_send_struct(_mavlink->get_channel(), &msg);
updated = true;
}
}
return true;
return updated;
}
};

Some files were not shown because too many files have changed in this diff Show More