mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-17 12:43:33 +08:00
VOXL2 specific drivers, modules, and miscellaneous support files (#22588)
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
menuconfig DRIVERS_ACTUATORS_MODAL_IO
|
||||
bool "modal_io"
|
||||
default n
|
||||
---help---
|
||||
Enable support for modal_io
|
||||
@@ -1,26 +0,0 @@
|
||||
module_name: MODAL IO Output
|
||||
actuator_output:
|
||||
show_subgroups_if: 'MODAL_IO_CONFIG>0'
|
||||
config_parameters:
|
||||
- param: 'MODAL_IO_CONFIG'
|
||||
label: 'Configure'
|
||||
function: 'enable'
|
||||
- param: 'MODAL_IO_BAUD'
|
||||
label: 'Bitrate'
|
||||
- param: 'MODAL_IO_RPM_MIN'
|
||||
label: 'RPM Min'
|
||||
- param: 'MODAL_IO_RPM_MAX'
|
||||
label: 'RPM Max'
|
||||
- param: 'MODAL_IO_SDIR1'
|
||||
label: 'ESC 1 Spin Direction'
|
||||
- param: 'MODAL_IO_SDIR2'
|
||||
label: 'ESC 2 Spin Direction'
|
||||
- param: 'MODAL_IO_SDIR3'
|
||||
label: 'ESC 3 Spin Direction'
|
||||
- param: 'MODAL_IO_SDIR4'
|
||||
label: 'ESC 4 Spin Direction'
|
||||
output_groups:
|
||||
- param_prefix: MODAL_IO
|
||||
group_label: 'ESCs'
|
||||
channel_label: 'ESC'
|
||||
num_channels: 4
|
||||
+7
-6
@@ -32,20 +32,21 @@
|
||||
############################################################################
|
||||
|
||||
px4_add_module(
|
||||
MODULE drivers__actuators__modal_io
|
||||
MAIN modal_io
|
||||
MODULE drivers__actuators__voxl_esc
|
||||
MAIN voxl_esc
|
||||
SRCS
|
||||
crc16.c
|
||||
crc16.h
|
||||
|
||||
modal_io_serial.cpp
|
||||
modal_io_serial.hpp
|
||||
modal_io.cpp
|
||||
modal_io.hpp
|
||||
voxl_esc_serial.cpp
|
||||
voxl_esc_serial.hpp
|
||||
voxl_esc.cpp
|
||||
voxl_esc.hpp
|
||||
qc_esc_packet_types.h
|
||||
qc_esc_packet.c
|
||||
qc_esc_packet.h
|
||||
DEPENDS
|
||||
battery
|
||||
px4_work_queue
|
||||
mixer_module
|
||||
MODULE_CONFIG
|
||||
@@ -0,0 +1,5 @@
|
||||
menuconfig DRIVERS_ACTUATORS_VOXL_ESC
|
||||
bool "voxl_esc"
|
||||
default n
|
||||
---help---
|
||||
Enable support for voxl_esc
|
||||
@@ -0,0 +1,41 @@
|
||||
module_name: VOXL ESC Output
|
||||
actuator_output:
|
||||
show_subgroups_if: 'VOXL_ESC_CONFIG>0'
|
||||
config_parameters:
|
||||
- param: 'VOXL_ESC_CONFIG'
|
||||
label: 'Configure'
|
||||
function: 'enable'
|
||||
- param: 'VOXL_ESC_BAUD'
|
||||
label: 'Bitrate'
|
||||
- param: 'VOXL_ESC_RPM_MIN'
|
||||
label: 'RPM Min'
|
||||
- param: 'VOXL_ESC_RPM_MAX'
|
||||
label: 'RPM Max'
|
||||
- param: 'VOXL_ESC_SDIR1'
|
||||
label: 'ESC 1 Spin Direction'
|
||||
- param: 'VOXL_ESC_SDIR2'
|
||||
label: 'ESC 2 Spin Direction'
|
||||
- param: 'VOXL_ESC_SDIR3'
|
||||
label: 'ESC 3 Spin Direction'
|
||||
- param: 'VOXL_ESC_SDIR4'
|
||||
label: 'ESC 4 Spin Direction'
|
||||
output_groups:
|
||||
- param_prefix: VOXL_ESC
|
||||
group_label: 'ESCs'
|
||||
channel_label: 'ESC'
|
||||
num_channels: 4
|
||||
|
||||
parameters:
|
||||
- group: ModalAI Custom Configuration
|
||||
definitions:
|
||||
MODALAI_CONFIG:
|
||||
description:
|
||||
short: Custom configuration for ModalAI drones
|
||||
long: |
|
||||
This can be set to indicate that drone behavior
|
||||
needs to be changed to match a custom setting
|
||||
type: int32
|
||||
reboot_required: true
|
||||
num_instances: 1
|
||||
instance_start: 1
|
||||
default: 0
|
||||
+40
-16
@@ -119,36 +119,60 @@ int32_t qc_esc_create_pwm_packet4_fb(int16_t pwm0, int16_t pwm1, int16_t pwm2, i
|
||||
}
|
||||
|
||||
|
||||
int32_t qc_esc_create_rpm_packet4(int16_t rpm0, int16_t rpm1, int16_t rpm2, int16_t rpm3,
|
||||
int32_t qc_esc_create_rpm_packet4(int32_t rpm0, int32_t rpm1, int32_t rpm2, int32_t rpm3,
|
||||
uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3,
|
||||
uint8_t *out, uint16_t out_size)
|
||||
uint8_t *out, uint16_t out_size, uint8_t ext_rpm)
|
||||
{
|
||||
return qc_esc_create_rpm_packet4_fb(rpm0, rpm1, rpm2, rpm3, led0, led1, led2, led3, -1, out, out_size);
|
||||
return qc_esc_create_rpm_packet4_fb(rpm0, rpm1, rpm2, rpm3, led0, led1, led2, led3, -1, out, out_size, ext_rpm);
|
||||
}
|
||||
|
||||
int32_t qc_esc_create_rpm_packet4_fb(int16_t rpm0, int16_t rpm1, int16_t rpm2, int16_t rpm3,
|
||||
int32_t qc_esc_create_rpm_packet4_fb(int32_t rpm0, int32_t rpm1, int32_t rpm2, int32_t rpm3,
|
||||
uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3,
|
||||
int32_t fb_id, uint8_t *out, uint16_t out_size)
|
||||
int32_t fb_id, uint8_t *out, uint16_t out_size, uint8_t ext_rpm)
|
||||
{
|
||||
uint16_t data[5];
|
||||
int16_t data[5];
|
||||
uint16_t leds = 0;
|
||||
uint8_t cmd = ESC_PACKET_TYPE_RPM_CMD;
|
||||
int32_t max = ext_rpm > 0 ? ESC_RPM_MAX_EXT : ESC_RPM_MAX;
|
||||
int32_t min = ext_rpm > 0 ? ESC_RPM_MIN_EXT : ESC_RPM_MIN;
|
||||
|
||||
// Limit RPMs to prevent overflow when converting to int16_t
|
||||
|
||||
if (rpm0 > max) { rpm0 = max; } if (rpm0 < min) { rpm0 = min; }
|
||||
|
||||
if (rpm1 > max) { rpm1 = max; } if (rpm1 < min) { rpm1 = min; }
|
||||
|
||||
if (rpm2 > max) { rpm2 = max; } if (rpm2 < min) { rpm2 = min; }
|
||||
|
||||
if (rpm3 > max) { rpm3 = max; } if (rpm3 < min) { rpm3 = min; }
|
||||
|
||||
if (fb_id != -1) { fb_id = fb_id % 4; }
|
||||
|
||||
//least significant bit is used for feedback request
|
||||
rpm0 &= ~(0x0001); rpm1 &= ~(0x0001); rpm2 &= ~(0x0001); rpm3 &= ~(0x0001);
|
||||
|
||||
if (fb_id == 0) { rpm0 |= 0x0001; } if (fb_id == 1) { rpm1 |= 0x0001; }
|
||||
|
||||
if (fb_id == 2) { rpm2 |= 0x0001; } if (fb_id == 3) { rpm3 |= 0x0001; }
|
||||
|
||||
leds |= led0 & 0b00000111;
|
||||
leds |= led0 & 0b00000111;
|
||||
leds |= (led1 & 0b00000111) << 3;
|
||||
leds |= ((uint16_t)(led2 & 0b00000111)) << 6;
|
||||
leds |= ((uint16_t)(led3 & 0b00000111)) << 9;
|
||||
|
||||
data[0] = rpm0; data[1] = rpm1; data[2] = rpm2; data[3] = rpm3; data[4] = leds;
|
||||
return qc_esc_create_packet(ESC_PACKET_TYPE_RPM_CMD, (uint8_t *) & (data[0]), 10, out, out_size);
|
||||
if (ext_rpm > 0) {
|
||||
cmd = ESC_PACKET_TYPE_RPM_DIV2_CMD;
|
||||
data[0] = ((rpm0 / 4) * 2);
|
||||
data[1] = ((rpm1 / 4) * 2);
|
||||
data[2] = ((rpm2 / 4) * 2);
|
||||
data[3] = ((rpm3 / 4) * 2);
|
||||
data[4] = leds;
|
||||
|
||||
} else {
|
||||
data[0] = rpm0; data[1] = rpm1; data[2] = rpm2; data[3] = rpm3; data[4] = leds;
|
||||
}
|
||||
|
||||
//least significant bit is used for feedback request
|
||||
data[0] &= ~(0x0001); data[1] &= ~(0x0001); data[2] &= ~(0x0001); data[3] &= ~(0x0001);
|
||||
|
||||
if (fb_id == 0) { data[0] |= 0x0001; } if (fb_id == 1) { data[1] |= 0x0001; }
|
||||
|
||||
if (fb_id == 2) { data[2] |= 0x0001; } if (fb_id == 3) { data[3] |= 0x0001; }
|
||||
|
||||
return qc_esc_create_packet(cmd, (uint8_t *) & (data[0]), 10, out, out_size);
|
||||
}
|
||||
|
||||
int32_t qc_esc_create_packet(uint8_t type, uint8_t *data, uint16_t size, uint8_t *out, uint16_t out_size)
|
||||
+22
-5
@@ -52,6 +52,11 @@ extern "C" {
|
||||
#define QC_ESC_LED_GREEN_ON 2
|
||||
#define QC_ESC_LED_BLUE_ON 4
|
||||
|
||||
// Define RPM command max and min values
|
||||
#define ESC_RPM_MAX INT16_MAX-1 // 32k
|
||||
#define ESC_RPM_MIN INT16_MIN+1 // -32k
|
||||
#define ESC_RPM_MAX_EXT UINT16_MAX-5 // 65k
|
||||
#define ESC_RPM_MIN_EXT -UINT16_MAX+5 // -65k
|
||||
|
||||
// Header of the packet. Each packet must start with this header
|
||||
#define ESC_PACKET_HEADER 0xAF
|
||||
@@ -142,6 +147,18 @@ typedef struct {
|
||||
} __attribute__((__packed__)) QC_ESC_FB_RESPONSE_V2;
|
||||
|
||||
|
||||
// Definition of the feedback response packet from ESC, which contains battery voltage and total current
|
||||
typedef struct {
|
||||
uint8_t header;
|
||||
uint8_t length;
|
||||
uint8_t type;
|
||||
uint8_t id; //ESC Id (could be used as system ID elsewhere)
|
||||
uint16_t voltage; //Input voltage (Millivolts)
|
||||
int16_t current; //Total Current (8mA resolution)
|
||||
uint16_t crc;
|
||||
} __attribute__((__packed__)) QC_ESC_FB_POWER_STATUS;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//Below are functions for generating packets that would be outgoing to ESCs
|
||||
//-------------------------------------------------------------------------
|
||||
@@ -197,15 +214,15 @@ int32_t qc_esc_create_pwm_packet4_fb(int16_t pwm0, int16_t pwm1, int16_t pwm2, i
|
||||
|
||||
// Create a packet for sending closed-loop RPM command and LED command to 4 ESCs without requesting any feedback
|
||||
// Return value is the length of generated packet (if positive), otherwise error code
|
||||
int32_t qc_esc_create_rpm_packet4(int16_t rpm0, int16_t rpm1, int16_t rpm2, int16_t rpm3,
|
||||
int32_t qc_esc_create_rpm_packet4(int32_t rpm0, int32_t rpm1, int32_t rpm2, int32_t rpm3,
|
||||
uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3,
|
||||
uint8_t *out, uint16_t out_size);
|
||||
uint8_t *out, uint16_t out_size, uint8_t ext_rpm);
|
||||
|
||||
// Create a packet for sending closed-loop RPM command and LED command to 4 ESCs, also request feedback from one ESC (with id=fb_id)
|
||||
// Create a packet for sending closed-loop RPM command (32766 or 65530 max RPM) and LED command to 4 ESCs, also request feedback from one ESC (with id=fb_id)
|
||||
// Return value is the length of generated packet (if positive), otherwise error code
|
||||
int32_t qc_esc_create_rpm_packet4_fb(int16_t rpm0, int16_t rpm1, int16_t rpm2, int16_t rpm3,
|
||||
int32_t qc_esc_create_rpm_packet4_fb(int32_t rpm0, int32_t rpm1, int32_t rpm2, int32_t rpm3,
|
||||
uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3,
|
||||
int32_t fb_id, uint8_t *out, uint16_t out_size);
|
||||
int32_t fb_id, uint8_t *out, uint16_t out_size, uint8_t ext_rpm);
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
+2
@@ -46,6 +46,7 @@
|
||||
#define ESC_PACKET_TYPE_SOUND_CMD 3
|
||||
#define ESC_PACKET_TYPE_STEP_CMD 4
|
||||
#define ESC_PACKET_TYPE_LED_CMD 5
|
||||
#define ESC_PACKET_TYPE_RPM_DIV2_CMD 7
|
||||
#define ESC_PACKET_TYPE_RESET_CMD 10
|
||||
#define ESC_PACKET_TYPE_SET_ID_CMD 11
|
||||
#define ESC_PACKET_TYPE_SET_DIR_CMD 12
|
||||
@@ -69,5 +70,6 @@
|
||||
#define ESC_PACKET_TYPE_TUNE_CONFIG 114
|
||||
#define ESC_PACKET_TYPE_FB_RESPONSE 128
|
||||
#define ESC_PACKET_TYPE_VERSION_EXT_RESPONSE 131
|
||||
#define ESC_PACKET_TYPE_FB_POWER_STATUS 132
|
||||
|
||||
#endif
|
||||
+214
-251
@@ -35,33 +35,32 @@
|
||||
|
||||
#include <px4_platform_common/getopt.h>
|
||||
|
||||
#include "modal_io.hpp"
|
||||
#include "modal_io_serial.hpp"
|
||||
|
||||
// utility for running on VOXL and using driver as a bridge
|
||||
#define MODAL_IO_VOXL_BRIDGE_PORT "/dev/ttyS4"
|
||||
#include "voxl_esc.hpp"
|
||||
#include "voxl_esc_serial.hpp"
|
||||
|
||||
// future use:
|
||||
#define MODALAI_PUBLISH_ESC_STATUS 0
|
||||
|
||||
const char *_device;
|
||||
|
||||
ModalIo::ModalIo() :
|
||||
OutputModuleInterface(MODULE_NAME, px4::serial_port_to_wq(MODAL_IO_DEFAULT_PORT)),
|
||||
VoxlEsc::VoxlEsc() :
|
||||
OutputModuleInterface(MODULE_NAME, px4::serial_port_to_wq(VOXL_ESC_DEFAULT_PORT)),
|
||||
_mixing_output{"VOXL_ESC", VOXL_ESC_OUTPUT_CHANNELS, *this, MixingOutput::SchedulingPolicy::Auto, false, false},
|
||||
_cycle_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": cycle")),
|
||||
_output_update_perf(perf_alloc(PC_INTERVAL, MODULE_NAME": output update interval"))
|
||||
_output_update_perf(perf_alloc(PC_INTERVAL, MODULE_NAME": output update interval")),
|
||||
_battery(1, nullptr, _battery_report_interval, battery_status_s::BATTERY_SOURCE_POWER_MODULE)
|
||||
{
|
||||
_device = MODAL_IO_DEFAULT_PORT;
|
||||
_device = VOXL_ESC_DEFAULT_PORT;
|
||||
|
||||
_mixing_output.setAllFailsafeValues(0);
|
||||
_mixing_output.setAllDisarmedValues(0);
|
||||
|
||||
_esc_status.timestamp = hrt_absolute_time();
|
||||
_esc_status.counter = 0;
|
||||
_esc_status.esc_count = MODAL_IO_OUTPUT_CHANNELS;
|
||||
_esc_status.esc_count = VOXL_ESC_OUTPUT_CHANNELS;
|
||||
_esc_status.esc_connectiontype = esc_status_s::ESC_CONNECTION_TYPE_SERIAL;
|
||||
|
||||
for (unsigned i = 0; i < MODAL_IO_OUTPUT_CHANNELS; i++) {
|
||||
for (unsigned i = 0; i < VOXL_ESC_OUTPUT_CHANNELS; i++) {
|
||||
_esc_status.esc[i].timestamp = 0;
|
||||
_esc_status.esc[i].esc_address = 0;
|
||||
_esc_status.esc[i].esc_rpm = 0;
|
||||
@@ -75,15 +74,12 @@ ModalIo::ModalIo() :
|
||||
_esc_status.esc[i].esc_power = 0;
|
||||
}
|
||||
|
||||
_esc_status_pub.advertise();
|
||||
|
||||
qc_esc_packet_init(&_fb_packet);
|
||||
qc_esc_packet_init(&_uart_bridge_packet);
|
||||
|
||||
_fb_idx = 0;
|
||||
}
|
||||
|
||||
ModalIo::~ModalIo()
|
||||
VoxlEsc::~VoxlEsc()
|
||||
{
|
||||
_outputs_on = false;
|
||||
|
||||
@@ -92,16 +88,11 @@ ModalIo::~ModalIo()
|
||||
_uart_port = nullptr;
|
||||
}
|
||||
|
||||
if (_uart_port_bridge) {
|
||||
_uart_port_bridge->uart_close();
|
||||
_uart_port_bridge = nullptr;
|
||||
}
|
||||
|
||||
perf_free(_cycle_perf);
|
||||
perf_free(_output_update_perf);
|
||||
}
|
||||
|
||||
int ModalIo::init()
|
||||
int VoxlEsc::init()
|
||||
{
|
||||
|
||||
/* Getting initial parameter values */
|
||||
@@ -111,10 +102,15 @@ int ModalIo::init()
|
||||
return ret;
|
||||
}
|
||||
|
||||
_uart_port = new ModalIoSerial();
|
||||
_uart_port_bridge = new ModalIoSerial();
|
||||
_uart_port = new VoxlEscSerial();
|
||||
memset(&_esc_chans, 0x00, sizeof(_esc_chans));
|
||||
|
||||
for (int esc_id = 0; esc_id < VOXL_ESC_OUTPUT_CHANNELS; ++esc_id) {
|
||||
_version_info[esc_id].sw_version = UINT16_MAX;
|
||||
_version_info[esc_id].hw_version = UINT16_MAX;
|
||||
_version_info[esc_id].id = esc_id;
|
||||
}
|
||||
|
||||
//get_instance()->ScheduleOnInterval(10000); //100hz
|
||||
|
||||
ScheduleNow();
|
||||
@@ -122,81 +118,82 @@ int ModalIo::init()
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ModalIo::load_params(modal_io_params_t *params, ch_assign_t *map)
|
||||
int VoxlEsc::load_params(voxl_esc_params_t *params, ch_assign_t *map)
|
||||
{
|
||||
int ret = PX4_OK;
|
||||
|
||||
// initialize out
|
||||
for (int i = 0; i < MODAL_IO_OUTPUT_CHANNELS; i++) {
|
||||
for (int i = 0; i < VOXL_ESC_OUTPUT_CHANNELS; i++) {
|
||||
params->function_map[i] = (int)OutputFunction::Disabled;
|
||||
params->direction_map[i] = 0;
|
||||
params->motor_map[i] = 0;
|
||||
}
|
||||
|
||||
param_get(param_find("MODAL_IO_CONFIG"), ¶ms->config);
|
||||
param_get(param_find("MODAL_IO_MODE"), ¶ms->mode);
|
||||
param_get(param_find("MODAL_IO_BAUD"), ¶ms->baud_rate);
|
||||
param_get(param_find("VOXL_ESC_CONFIG"), ¶ms->config);
|
||||
param_get(param_find("VOXL_ESC_MODE"), ¶ms->mode);
|
||||
param_get(param_find("VOXL_ESC_BAUD"), ¶ms->baud_rate);
|
||||
|
||||
param_get(param_find("MODAL_IO_T_PERC"), ¶ms->turtle_motor_percent);
|
||||
param_get(param_find("MODAL_IO_T_DEAD"), ¶ms->turtle_motor_deadband);
|
||||
param_get(param_find("MODAL_IO_T_EXPO"), ¶ms->turtle_motor_expo);
|
||||
param_get(param_find("MODAL_IO_T_MINF"), ¶ms->turtle_stick_minf);
|
||||
param_get(param_find("MODAL_IO_T_COSP"), ¶ms->turtle_cosphi);
|
||||
param_get(param_find("VOXL_ESC_T_PERC"), ¶ms->turtle_motor_percent);
|
||||
param_get(param_find("VOXL_ESC_T_DEAD"), ¶ms->turtle_motor_deadband);
|
||||
param_get(param_find("VOXL_ESC_T_EXPO"), ¶ms->turtle_motor_expo);
|
||||
param_get(param_find("VOXL_ESC_T_MINF"), ¶ms->turtle_stick_minf);
|
||||
param_get(param_find("VOXL_ESC_T_COSP"), ¶ms->turtle_cosphi);
|
||||
|
||||
param_get(param_find("MODAL_IO_FUNC1"), ¶ms->function_map[0]);
|
||||
param_get(param_find("MODAL_IO_FUNC2"), ¶ms->function_map[1]);
|
||||
param_get(param_find("MODAL_IO_FUNC3"), ¶ms->function_map[2]);
|
||||
param_get(param_find("MODAL_IO_FUNC4"), ¶ms->function_map[3]);
|
||||
param_get(param_find("VOXL_ESC_FUNC1"), ¶ms->function_map[0]);
|
||||
param_get(param_find("VOXL_ESC_FUNC2"), ¶ms->function_map[1]);
|
||||
param_get(param_find("VOXL_ESC_FUNC3"), ¶ms->function_map[2]);
|
||||
param_get(param_find("VOXL_ESC_FUNC4"), ¶ms->function_map[3]);
|
||||
|
||||
param_get(param_find("MODAL_IO_SDIR1"), ¶ms->direction_map[0]);
|
||||
param_get(param_find("MODAL_IO_SDIR2"), ¶ms->direction_map[1]);
|
||||
param_get(param_find("MODAL_IO_SDIR3"), ¶ms->direction_map[2]);
|
||||
param_get(param_find("MODAL_IO_SDIR4"), ¶ms->direction_map[3]);
|
||||
param_get(param_find("VOXL_ESC_SDIR1"), ¶ms->direction_map[0]);
|
||||
param_get(param_find("VOXL_ESC_SDIR2"), ¶ms->direction_map[1]);
|
||||
param_get(param_find("VOXL_ESC_SDIR3"), ¶ms->direction_map[2]);
|
||||
param_get(param_find("VOXL_ESC_SDIR4"), ¶ms->direction_map[3]);
|
||||
|
||||
param_get(param_find("MODAL_IO_RPM_MIN"), ¶ms->rpm_min);
|
||||
param_get(param_find("MODAL_IO_RPM_MAX"), ¶ms->rpm_max);
|
||||
param_get(param_find("VOXL_ESC_RPM_MIN"), ¶ms->rpm_min);
|
||||
param_get(param_find("VOXL_ESC_RPM_MAX"), ¶ms->rpm_max);
|
||||
|
||||
param_get(param_find("MODAL_IO_VLOG"), ¶ms->verbose_logging);
|
||||
param_get(param_find("VOXL_ESC_VLOG"), ¶ms->verbose_logging);
|
||||
param_get(param_find("VOXL_ESC_PUB_BST"), ¶ms->publish_battery_status);
|
||||
|
||||
if (params->rpm_min >= params->rpm_max) {
|
||||
PX4_ERR("Invalid parameter MODAL_IO_RPM_MIN. Please verify parameters.");
|
||||
PX4_ERR("Invalid parameter VOXL_ESC_RPM_MIN. Please verify parameters.");
|
||||
params->rpm_min = 0;
|
||||
ret = PX4_ERROR;
|
||||
}
|
||||
|
||||
if (params->turtle_motor_percent < 0 || params->turtle_motor_percent > 100) {
|
||||
PX4_ERR("Invalid parameter MODAL_IO_T_PERC. Please verify parameters.");
|
||||
PX4_ERR("Invalid parameter VOXL_ESC_T_PERC. Please verify parameters.");
|
||||
params->turtle_motor_percent = 0;
|
||||
ret = PX4_ERROR;
|
||||
}
|
||||
|
||||
if (params->turtle_motor_deadband < 0 || params->turtle_motor_deadband > 100) {
|
||||
PX4_ERR("Invalid parameter MODAL_IO_T_DEAD. Please verify parameters.");
|
||||
PX4_ERR("Invalid parameter VOXL_ESC_T_DEAD. Please verify parameters.");
|
||||
params->turtle_motor_deadband = 0;
|
||||
ret = PX4_ERROR;
|
||||
}
|
||||
|
||||
if (params->turtle_motor_expo < 0 || params->turtle_motor_expo > 100) {
|
||||
PX4_ERR("Invalid parameter MODAL_IO_T_EXPO. Please verify parameters.");
|
||||
PX4_ERR("Invalid parameter VOXL_ESC_T_EXPO. Please verify parameters.");
|
||||
params->turtle_motor_expo = 0;
|
||||
ret = PX4_ERROR;
|
||||
}
|
||||
|
||||
if (params->turtle_stick_minf < 0.0f || params->turtle_stick_minf > 100.0f) {
|
||||
PX4_ERR("Invalid parameter MODAL_IO_T_MINF. Please verify parameters.");
|
||||
PX4_ERR("Invalid parameter VOXL_ESC_T_MINF. Please verify parameters.");
|
||||
params->turtle_stick_minf = 0.0f;
|
||||
ret = PX4_ERROR;
|
||||
}
|
||||
|
||||
if (params->turtle_cosphi < 0.0f || params->turtle_cosphi > 100.0f) {
|
||||
PX4_ERR("Invalid parameter MODAL_IO_T_COSP. Please verify parameters.");
|
||||
PX4_ERR("Invalid parameter VOXL_ESC_T_COSP. Please verify parameters.");
|
||||
params->turtle_cosphi = 0.0f;
|
||||
ret = PX4_ERROR;
|
||||
}
|
||||
|
||||
for (int i = 0; i < MODAL_IO_OUTPUT_CHANNELS; i++) {
|
||||
for (int i = 0; i < VOXL_ESC_OUTPUT_CHANNELS; i++) {
|
||||
if (params->function_map[i] < (int)OutputFunction::Motor1 || params->function_map[i] > (int)OutputFunction::Motor4) {
|
||||
PX4_ERR("Invalid parameter MODAL_IO_FUNCX. Only supports motors 1-4. Please verify parameters.");
|
||||
PX4_ERR("Invalid parameter VOXL_ESC_FUNCX. Only supports motors 1-4. Please verify parameters.");
|
||||
params->function_map[i] = 0;
|
||||
ret = PX4_ERROR;
|
||||
|
||||
@@ -210,11 +207,11 @@ int ModalIo::load_params(modal_io_params_t *params, ch_assign_t *map)
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < MODAL_IO_OUTPUT_CHANNELS; i++) {
|
||||
if (params->motor_map[i] == MODAL_IO_OUTPUT_DISABLED ||
|
||||
params->motor_map[i] < -(MODAL_IO_OUTPUT_CHANNELS) ||
|
||||
params->motor_map[i] > MODAL_IO_OUTPUT_CHANNELS) {
|
||||
PX4_ERR("Invalid parameter MODAL_IO_MOTORX. Please verify parameters.");
|
||||
for (int i = 0; i < VOXL_ESC_OUTPUT_CHANNELS; i++) {
|
||||
if (params->motor_map[i] == VOXL_ESC_OUTPUT_DISABLED ||
|
||||
params->motor_map[i] < -(VOXL_ESC_OUTPUT_CHANNELS) ||
|
||||
params->motor_map[i] > VOXL_ESC_OUTPUT_CHANNELS) {
|
||||
PX4_ERR("Invalid parameter VOXL_ESC_MOTORX. Please verify parameters.");
|
||||
params->motor_map[i] = 0;
|
||||
ret = PX4_ERROR;
|
||||
}
|
||||
@@ -227,7 +224,7 @@ int ModalIo::load_params(modal_io_params_t *params, ch_assign_t *map)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ModalIo::task_spawn(int argc, char *argv[])
|
||||
int VoxlEsc::task_spawn(int argc, char *argv[])
|
||||
{
|
||||
int myoptind = 0;
|
||||
int ch;
|
||||
@@ -244,7 +241,7 @@ int ModalIo::task_spawn(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
ModalIo *instance = new ModalIo();
|
||||
VoxlEsc *instance = new VoxlEsc();
|
||||
|
||||
if (instance) {
|
||||
_object.store(instance);
|
||||
@@ -267,14 +264,31 @@ int ModalIo::task_spawn(int argc, char *argv[])
|
||||
return PX4_ERROR;
|
||||
}
|
||||
|
||||
int ModalIo::flush_uart_rx()
|
||||
int VoxlEsc::flush_uart_rx()
|
||||
{
|
||||
while (_uart_port->uart_read(_read_buf, sizeof(_read_buf)) > 0) {}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ModalIo::read_response(Command *out_cmd)
|
||||
bool VoxlEsc::check_versions_updated()
|
||||
{
|
||||
for (int esc_id = 0; esc_id < VOXL_ESC_OUTPUT_CHANNELS; ++esc_id) {
|
||||
if (_version_info[esc_id].sw_version == UINT16_MAX) { return false; }
|
||||
}
|
||||
|
||||
// PX4_INFO("Got all ESC Version info!");
|
||||
_extended_rpm = true;
|
||||
_need_version_info = false;
|
||||
|
||||
for (int esc_id = 0; esc_id < VOXL_ESC_OUTPUT_CHANNELS; ++esc_id) {
|
||||
if (_version_info[esc_id].sw_version < VOXL_ESC_EXT_RPM) { _extended_rpm = false; }
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int VoxlEsc::read_response(Command *out_cmd)
|
||||
{
|
||||
px4_usleep(_current_cmd.resp_delay_us);
|
||||
|
||||
@@ -297,7 +311,7 @@ int ModalIo::read_response(Command *out_cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ModalIo::parse_response(uint8_t *buf, uint8_t len, bool print_feedback)
|
||||
int VoxlEsc::parse_response(uint8_t *buf, uint8_t len, bool print_feedback)
|
||||
{
|
||||
hrt_abstime tnow = hrt_absolute_time();
|
||||
|
||||
@@ -311,13 +325,13 @@ int ModalIo::parse_response(uint8_t *buf, uint8_t len, bool print_feedback)
|
||||
uint8_t packet_size = qc_esc_packet_get_size(&_fb_packet);
|
||||
|
||||
if (packet_type == ESC_PACKET_TYPE_FB_RESPONSE && packet_size == sizeof(QC_ESC_FB_RESPONSE_V2)) {
|
||||
//PX4_INFO("Got feedback V2 packet!");
|
||||
// PX4_INFO("Got feedback V2 packet!");
|
||||
QC_ESC_FB_RESPONSE_V2 fb;
|
||||
memcpy(&fb, _fb_packet.buffer, packet_size);
|
||||
|
||||
uint32_t id = (fb.id_state & 0xF0) >> 4; //ID of the ESC based on hardware address
|
||||
|
||||
if (id < MODAL_IO_OUTPUT_CHANNELS) {
|
||||
if (id < VOXL_ESC_OUTPUT_CHANNELS) {
|
||||
|
||||
int motor_idx = _output_map[id].number - 1; // mapped motor id.. user defined mapping is 1-4, array is 0-3
|
||||
|
||||
@@ -335,9 +349,9 @@ int ModalIo::parse_response(uint8_t *buf, uint8_t len, bool print_feedback)
|
||||
_esc_chans[id].power_applied = fb.power;
|
||||
_esc_chans[id].state = fb.id_state & 0x0F;
|
||||
_esc_chans[id].cmd_counter = fb.cmd_counter;
|
||||
_esc_chans[id].voltage = fb.voltage * 0.001;
|
||||
_esc_chans[id].current = fb.current * 0.008;
|
||||
_esc_chans[id].temperature = fb.temperature * 0.01;
|
||||
_esc_chans[id].voltage = fb.voltage * 0.001f;
|
||||
_esc_chans[id].current = fb.current * 0.008f;
|
||||
_esc_chans[id].temperature = fb.temperature * 0.01f;
|
||||
_esc_chans[id].feedback_time = tnow;
|
||||
|
||||
// also update our internal report for logging
|
||||
@@ -382,6 +396,13 @@ int ModalIo::parse_response(uint8_t *buf, uint8_t len, bool print_feedback)
|
||||
else if (packet_type == ESC_PACKET_TYPE_VERSION_RESPONSE && packet_size == sizeof(QC_ESC_VERSION_INFO)) {
|
||||
QC_ESC_VERSION_INFO ver;
|
||||
memcpy(&ver, _fb_packet.buffer, packet_size);
|
||||
|
||||
if (_need_version_info) {
|
||||
memcpy(&_version_info[ver.id], &ver, sizeof(QC_ESC_VERSION_INFO));
|
||||
check_versions_updated();
|
||||
break;
|
||||
}
|
||||
|
||||
PX4_INFO("ESC ID: %i", ver.id);
|
||||
PX4_INFO("HW Version: %i", ver.hw_version);
|
||||
PX4_INFO("SW Version: %i", ver.sw_version);
|
||||
@@ -400,83 +421,60 @@ int ModalIo::parse_response(uint8_t *buf, uint8_t len, bool print_feedback)
|
||||
|
||||
PX4_INFO("\tFirmware : version %4d, hash %.12s", ver.sw_version, ver.firmware_git_version);
|
||||
PX4_INFO("\tBootloader : version %4d, hash %.12s", ver.bootloader_version, ver.bootloader_git_version);
|
||||
|
||||
} else if (packet_type == ESC_PACKET_TYPE_FB_POWER_STATUS && packet_size == sizeof(QC_ESC_FB_POWER_STATUS)) {
|
||||
QC_ESC_FB_POWER_STATUS packet;
|
||||
memcpy(&packet, _fb_packet.buffer, packet_size);
|
||||
|
||||
float voltage = packet.voltage * 0.001f; // Voltage is reported at 1 mV resolution
|
||||
float current = packet.current * 0.008f; // Total current is reported at 8mA resolution
|
||||
|
||||
// Limit the frequency of battery status reports
|
||||
if (_parameters.publish_battery_status) {
|
||||
_battery.setConnected(true);
|
||||
_battery.updateVoltage(voltage);
|
||||
_battery.updateCurrent(current);
|
||||
|
||||
hrt_abstime current_time = hrt_absolute_time();
|
||||
|
||||
if ((current_time - _last_battery_report_time) >= _battery_report_interval) {
|
||||
_last_battery_report_time = current_time;
|
||||
_battery.updateAndPublishBatteryStatus(current_time);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else { //parser error
|
||||
switch (ret) {
|
||||
case ESC_ERROR_BAD_CHECKSUM:
|
||||
_rx_crc_error_count++;
|
||||
//PX4_INFO("BAD ESC packet checksum");
|
||||
// PX4_INFO("BAD ESC packet checksum");
|
||||
break;
|
||||
|
||||
case ESC_ERROR_BAD_LENGTH:
|
||||
//PX4_INFO("BAD ESC packet length");
|
||||
// PX4_INFO("BAD ESC packet length");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (len < 4 || buf[0] != ESC_PACKET_HEADER) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (buf[2]) {
|
||||
case ESC_PACKET_TYPE_VERSION_RESPONSE:
|
||||
if (len != sizeof(QC_ESC_VERSION_INFO)) {
|
||||
return -1;
|
||||
|
||||
} else {
|
||||
QC_ESC_VERSION_INFO ver;
|
||||
memcpy(&ver, buf, len);
|
||||
PX4_INFO("ESC ID: %i", ver.id);
|
||||
PX4_INFO("HW Version: %i", ver.hw_version);
|
||||
PX4_INFO("SW Version: %i", ver.sw_version);
|
||||
PX4_INFO("Unique ID: %i", ver.unique_id);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ESC_PACKET_TYPE_FB_RESPONSE:
|
||||
if (len != sizeof(QC_ESC_FB_RESPONSE)) {
|
||||
return -1;
|
||||
|
||||
} else {
|
||||
QC_ESC_FB_RESPONSE fb;
|
||||
memcpy(&fb, buf, len);
|
||||
uint8_t id = (fb.state & 0xF0) >> 4;
|
||||
|
||||
if (id < MODAL_IO_OUTPUT_CHANNELS) {
|
||||
_esc_chans[id].rate_meas = fb.rpm;
|
||||
_esc_chans[id].state = fb.state & 0x0F;
|
||||
_esc_chans[id].cmd_counter = fb.cmd_counter;
|
||||
_esc_chans[id].voltage = 9.0 + fb.voltage / 34.0;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ModalIo::check_for_esc_timeout()
|
||||
int VoxlEsc::check_for_esc_timeout()
|
||||
{
|
||||
hrt_abstime tnow = hrt_absolute_time();
|
||||
|
||||
for (int i = 0; i < MODAL_IO_OUTPUT_CHANNELS; i++) {
|
||||
for (int i = 0; i < VOXL_ESC_OUTPUT_CHANNELS; i++) {
|
||||
// PX4 motor indexed user defined mapping is 1-4, we want to use in bitmask (0-3)
|
||||
uint8_t motor_idx = _output_map[i].number - 1;
|
||||
|
||||
if (motor_idx < MODAL_IO_OUTPUT_CHANNELS) {
|
||||
if (motor_idx < VOXL_ESC_OUTPUT_CHANNELS) {
|
||||
// we are using PX4 motor index in the bitmask
|
||||
if (_esc_status.esc_online_flags & (1 << motor_idx)) {
|
||||
// using index i here for esc_chans enumeration stored in ESC ID order
|
||||
if ((tnow - _esc_chans[i].feedback_time) > MODAL_IO_DISCONNECT_TIMEOUT_US) {
|
||||
if ((tnow - _esc_chans[i].feedback_time) > VOXL_ESC_DISCONNECT_TIMEOUT_US) {
|
||||
// stale data, assume offline and clear armed
|
||||
_esc_status.esc_online_flags &= ~(1 << motor_idx);
|
||||
_esc_status.esc_armed_flags &= ~(1 << motor_idx);
|
||||
@@ -489,7 +487,7 @@ int ModalIo::check_for_esc_timeout()
|
||||
|
||||
}
|
||||
|
||||
int ModalIo::send_cmd_thread_safe(Command *cmd)
|
||||
int VoxlEsc::send_cmd_thread_safe(Command *cmd)
|
||||
{
|
||||
cmd->id = _cmd_id++;
|
||||
_pending_cmd.store(cmd);
|
||||
@@ -504,7 +502,7 @@ int ModalIo::send_cmd_thread_safe(Command *cmd)
|
||||
|
||||
|
||||
|
||||
int ModalIo::custom_command(int argc, char *argv[])
|
||||
int VoxlEsc::custom_command(int argc, char *argv[])
|
||||
{
|
||||
int myoptind = 0;
|
||||
int ch;
|
||||
@@ -530,7 +528,7 @@ int ModalIo::custom_command(int argc, char *argv[])
|
||||
/* start the FMU if not running */
|
||||
if (!strcmp(verb, "start")) {
|
||||
if (!is_running()) {
|
||||
return ModalIo::task_spawn(argc, argv);
|
||||
return VoxlEsc::task_spawn(argc, argv);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -593,7 +591,7 @@ int ModalIo::custom_command(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (!strcmp(verb, "reset")) {
|
||||
if (esc_id < MODAL_IO_OUTPUT_CHANNELS) {
|
||||
if (esc_id < VOXL_ESC_OUTPUT_CHANNELS) {
|
||||
PX4_INFO("Reset ESC: %i", esc_id);
|
||||
cmd.len = qc_esc_create_reset_packet(esc_id, cmd.buf, sizeof(cmd.buf));
|
||||
cmd.response = false;
|
||||
@@ -605,7 +603,7 @@ int ModalIo::custom_command(int argc, char *argv[])
|
||||
}
|
||||
|
||||
} else if (!strcmp(verb, "version")) {
|
||||
if (esc_id < MODAL_IO_OUTPUT_CHANNELS) {
|
||||
if (esc_id < VOXL_ESC_OUTPUT_CHANNELS) {
|
||||
PX4_INFO("Request version for ESC: %i", esc_id);
|
||||
cmd.len = qc_esc_create_version_request_packet(esc_id, cmd.buf, sizeof(cmd.buf));
|
||||
cmd.response = true;
|
||||
@@ -618,7 +616,7 @@ int ModalIo::custom_command(int argc, char *argv[])
|
||||
}
|
||||
|
||||
} else if (!strcmp(verb, "version-ext")) {
|
||||
if (esc_id < MODAL_IO_OUTPUT_CHANNELS) {
|
||||
if (esc_id < VOXL_ESC_OUTPUT_CHANNELS) {
|
||||
PX4_INFO("Request extended version for ESC: %i", esc_id);
|
||||
cmd.len = qc_esc_create_extended_version_request_packet(esc_id, cmd.buf, sizeof(cmd.buf));
|
||||
cmd.response = true;
|
||||
@@ -631,7 +629,7 @@ int ModalIo::custom_command(int argc, char *argv[])
|
||||
}
|
||||
|
||||
} else if (!strcmp(verb, "tone")) {
|
||||
if (esc_id < MODAL_IO_OUTPUT_CHANNELS) {
|
||||
if (esc_id < VOXL_ESC_OUTPUT_CHANNELS) {
|
||||
PX4_INFO("Request tone for ESC mask: %i", esc_id);
|
||||
cmd.len = qc_esc_create_sound_packet(period, duration, power, esc_id, cmd.buf, sizeof(cmd.buf));
|
||||
cmd.response = false;
|
||||
@@ -660,12 +658,12 @@ int ModalIo::custom_command(int argc, char *argv[])
|
||||
}
|
||||
|
||||
} else if (!strcmp(verb, "rpm")) {
|
||||
if (esc_id < MODAL_IO_OUTPUT_CHANNELS) {
|
||||
if (esc_id < VOXL_ESC_OUTPUT_CHANNELS) {
|
||||
PX4_INFO("Request RPM for ESC ID: %i - RPM: %i", esc_id, rate);
|
||||
int16_t rate_req[MODAL_IO_OUTPUT_CHANNELS] = {0, 0, 0, 0};
|
||||
int16_t rate_req[VOXL_ESC_OUTPUT_CHANNELS] = {0, 0, 0, 0};
|
||||
uint8_t id_fb = 0;
|
||||
|
||||
if (esc_id == 0xFF) {
|
||||
if (esc_id == 0xFF) { //WARNING: this condition is not possible due to check 'if (esc_id < VOXL_ESC_OUTPUT_CHANNELS)'.
|
||||
rate_req[0] = rate;
|
||||
rate_req[1] = rate;
|
||||
rate_req[2] = rate;
|
||||
@@ -686,7 +684,8 @@ int ModalIo::custom_command(int argc, char *argv[])
|
||||
0,
|
||||
id_fb,
|
||||
cmd.buf,
|
||||
sizeof(cmd.buf));
|
||||
sizeof(cmd.buf),
|
||||
get_instance()->_extended_rpm);
|
||||
|
||||
cmd.response = true;
|
||||
cmd.repeats = repeat_count;
|
||||
@@ -705,12 +704,12 @@ int ModalIo::custom_command(int argc, char *argv[])
|
||||
}
|
||||
|
||||
} else if (!strcmp(verb, "pwm")) {
|
||||
if (esc_id < MODAL_IO_OUTPUT_CHANNELS) {
|
||||
if (esc_id < VOXL_ESC_OUTPUT_CHANNELS) {
|
||||
PX4_INFO("Request PWM for ESC ID: %i - PWM: %i", esc_id, rate);
|
||||
int16_t rate_req[MODAL_IO_OUTPUT_CHANNELS] = {0, 0, 0, 0};
|
||||
int16_t rate_req[VOXL_ESC_OUTPUT_CHANNELS] = {0, 0, 0, 0};
|
||||
uint8_t id_fb = 0;
|
||||
|
||||
if (esc_id == 0xFF) {
|
||||
if (esc_id == 0xFF) { //WARNING: this condition is not possible due to check 'if (esc_id < VOXL_ESC_OUTPUT_CHANNELS)'.
|
||||
rate_req[0] = rate;
|
||||
rate_req[1] = rate;
|
||||
rate_req[2] = rate;
|
||||
@@ -745,7 +744,7 @@ int ModalIo::custom_command(int argc, char *argv[])
|
||||
return get_instance()->send_cmd_thread_safe(&cmd);
|
||||
|
||||
} else {
|
||||
print_usage("Invalid ESC mask, use 1-15");
|
||||
print_usage("Invalid ESC ID, use 0-3");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -753,7 +752,7 @@ int ModalIo::custom_command(int argc, char *argv[])
|
||||
return print_usage("unknown command");
|
||||
}
|
||||
|
||||
int ModalIo::update_params()
|
||||
int VoxlEsc::update_params()
|
||||
{
|
||||
int ret = PX4_ERROR;
|
||||
|
||||
@@ -772,7 +771,7 @@ int ModalIo::update_params()
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ModalIo::update_leds(vehicle_control_mode_s mode, led_control_s control)
|
||||
void VoxlEsc::update_leds(vehicle_control_mode_s mode, led_control_s control)
|
||||
{
|
||||
int i = 0;
|
||||
uint8_t led_mask = _led_rsc.led_mask;
|
||||
@@ -872,12 +871,12 @@ void ModalIo::update_leds(vehicle_control_mode_s mode, led_control_s control)
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MODAL_IO_OUTPUT_CHANNELS; i++) {
|
||||
for (i = 0; i < VOXL_ESC_OUTPUT_CHANNELS; i++) {
|
||||
_esc_chans[i].led = led_mask;
|
||||
}
|
||||
}
|
||||
|
||||
void ModalIo::mix_turtle_mode(uint16_t outputs[MAX_ACTUATORS])
|
||||
void VoxlEsc::mix_turtle_mode(uint16_t outputs[MAX_ACTUATORS])
|
||||
{
|
||||
bool use_pitch = true;
|
||||
bool use_roll = true;
|
||||
@@ -1052,10 +1051,13 @@ void ModalIo::mix_turtle_mode(uint16_t outputs[MAX_ACTUATORS])
|
||||
}
|
||||
|
||||
/* OutputModuleInterface */
|
||||
bool ModalIo::updateOutputs(bool stop_motors, uint16_t outputs[MAX_ACTUATORS],
|
||||
bool VoxlEsc::updateOutputs(bool stop_motors, uint16_t outputs[MAX_ACTUATORS],
|
||||
unsigned num_outputs, unsigned num_control_groups_updated)
|
||||
{
|
||||
if (num_outputs != MODAL_IO_OUTPUT_CHANNELS) {
|
||||
//in Run() we call _mixing_output.update(), which calls MixingOutput::limitAndUpdateOutputs which calls _interface.updateOutputs (this function)
|
||||
//So, if Run() is blocked by a custom command, this function will not be called until Run is running again
|
||||
|
||||
if (num_outputs != VOXL_ESC_OUTPUT_CHANNELS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1064,11 +1066,18 @@ bool ModalIo::updateOutputs(bool stop_motors, uint16_t outputs[MAX_ACTUATORS],
|
||||
mix_turtle_mode(outputs);
|
||||
}
|
||||
|
||||
for (int i = 0; i < MODAL_IO_OUTPUT_CHANNELS; i++) {
|
||||
for (int i = 0; i < VOXL_ESC_OUTPUT_CHANNELS; i++) {
|
||||
if (!_outputs_on || stop_motors) {
|
||||
_esc_chans[i].rate_req = 0;
|
||||
|
||||
} else {
|
||||
if (_extended_rpm) {
|
||||
if (outputs[i] > VOXL_ESC_RPM_MAX_EXT) { outputs[i] = VOXL_ESC_RPM_MAX_EXT; }
|
||||
|
||||
} else {
|
||||
if (outputs[i] > VOXL_ESC_RPM_MAX) { outputs[i] = VOXL_ESC_RPM_MAX; }
|
||||
}
|
||||
|
||||
if (!_turtle_mode_en) {
|
||||
_esc_chans[i].rate_req = outputs[i] * _output_map[i].direction;
|
||||
|
||||
@@ -1079,6 +1088,7 @@ bool ModalIo::updateOutputs(bool stop_motors, uint16_t outputs[MAX_ACTUATORS],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Command cmd;
|
||||
cmd.len = qc_esc_create_rpm_packet4_fb(_esc_chans[0].rate_req,
|
||||
_esc_chans[1].rate_req,
|
||||
@@ -1090,24 +1100,24 @@ bool ModalIo::updateOutputs(bool stop_motors, uint16_t outputs[MAX_ACTUATORS],
|
||||
_esc_chans[3].led,
|
||||
_fb_idx,
|
||||
cmd.buf,
|
||||
sizeof(cmd.buf));
|
||||
|
||||
sizeof(cmd.buf),
|
||||
_extended_rpm);
|
||||
|
||||
if (_uart_port->uart_write(cmd.buf, cmd.len) != cmd.len) {
|
||||
PX4_ERR("Failed to send packet");
|
||||
return false;
|
||||
}
|
||||
|
||||
// round robin
|
||||
_fb_idx = (_fb_idx + 1) % MODAL_IO_OUTPUT_CHANNELS;
|
||||
// increment ESC id from which to request feedback in round robin order
|
||||
_fb_idx = (_fb_idx + 1) % VOXL_ESC_OUTPUT_CHANNELS;
|
||||
|
||||
|
||||
/*
|
||||
* Here we parse the feedback response. Rarely the packet is mangled
|
||||
* but this means we simply miss a feedback response and will come back
|
||||
* around in roughly 8ms for another... so don't freak out and keep on
|
||||
* trucking I say
|
||||
* Here we read and parse response from ESCs. Since the latest command has just been sent out,
|
||||
* the response packet we may read here is probabaly from previous iteration, but it is totally ok.
|
||||
* uart_read is non-blocking and we will just parse whatever bytes came in up until this point
|
||||
*/
|
||||
|
||||
int res = _uart_port->uart_read(_read_buf, sizeof(_read_buf));
|
||||
|
||||
if (res > 0) {
|
||||
@@ -1135,13 +1145,29 @@ bool ModalIo::updateOutputs(bool stop_motors, uint16_t outputs[MAX_ACTUATORS],
|
||||
|
||||
_esc_status_pub.publish(_esc_status);
|
||||
|
||||
// If any extra external modal io data has been received then
|
||||
// send it over as well
|
||||
while (_voxl2_io_data_sub.updated()) {
|
||||
buffer128_s io_data{};
|
||||
_voxl2_io_data_sub.copy(&io_data);
|
||||
|
||||
// PX4_INFO("Got Modal IO data: %u bytes", io_data.len);
|
||||
// PX4_INFO(" 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x",
|
||||
// io_data.data[0], io_data.data[1], io_data.data[2], io_data.data[3],
|
||||
// io_data.data[4], io_data.data[5], io_data.data[6], io_data.data[7]);
|
||||
if (_uart_port->uart_write(io_data.data, io_data.len) != io_data.len) {
|
||||
PX4_ERR("Failed to send modal io data to esc");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
perf_count(_output_update_perf);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ModalIo::Run()
|
||||
void VoxlEsc::Run()
|
||||
{
|
||||
if (should_exit()) {
|
||||
ScheduleClear();
|
||||
@@ -1164,23 +1190,22 @@ void ModalIo::Run()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
for (int ii=0; ii<9; ii++)
|
||||
{
|
||||
const char * test_str = "Hello World!";
|
||||
_uart_port_bridge->uart_write((char*)test_str,12);
|
||||
px4_usleep(10000);
|
||||
/* Get ESC FW version info */
|
||||
if (_need_version_info) {
|
||||
for (uint8_t esc_id = 0; esc_id < VOXL_ESC_OUTPUT_CHANNELS; ++esc_id) {
|
||||
Command cmd;
|
||||
cmd.len = qc_esc_create_version_request_packet(esc_id, cmd.buf, sizeof(cmd.buf));
|
||||
|
||||
if (_uart_port->uart_write(cmd.buf, cmd.len) == cmd.len) {
|
||||
if (read_response(&_current_cmd) != 0) { PX4_ERR("Failed to parse version request response packet!"); }
|
||||
|
||||
} else {
|
||||
PX4_ERR("Failed to send version request packet!");
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
uint8_t echo_buf[16];
|
||||
int bytes_read = _uart_port_bridge->uart_read(echo_buf,sizeof(echo_buf));
|
||||
if (bytes_read > 0)
|
||||
_uart_port_bridge->uart_write(echo_buf,bytes_read);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
_mixing_output.update();
|
||||
_mixing_output.update(); //calls MixingOutput::limitAndUpdateOutputs which calls updateOutputs in this module
|
||||
|
||||
/* update output status if armed */
|
||||
_outputs_on = _mixing_output.armed().armed;
|
||||
@@ -1222,16 +1247,16 @@ void ModalIo::Run()
|
||||
|
||||
if (!_outputs_on) {
|
||||
|
||||
float setpoint = MODAL_IO_MODE_DISABLED_SETPOINT;
|
||||
float setpoint = VOXL_ESC_MODE_DISABLED_SETPOINT;
|
||||
|
||||
if (_parameters.mode == MODAL_IO_MODE_TURTLE_AUX1) {
|
||||
if (_parameters.mode == VOXL_ESC_MODE_TURTLE_AUX1) {
|
||||
setpoint = _manual_control_setpoint.aux1;
|
||||
|
||||
} else if (_parameters.mode == MODAL_IO_MODE_TURTLE_AUX2) {
|
||||
} else if (_parameters.mode == VOXL_ESC_MODE_TURTLE_AUX2) {
|
||||
setpoint = _manual_control_setpoint.aux2;
|
||||
}
|
||||
|
||||
if (setpoint > MODAL_IO_MODE_THRESHOLD) {
|
||||
if (setpoint > VOXL_ESC_MODE_THRESHOLD) {
|
||||
_turtle_mode_en = true;
|
||||
|
||||
} else {
|
||||
@@ -1240,68 +1265,6 @@ void ModalIo::Run()
|
||||
}
|
||||
}
|
||||
|
||||
if (_parameters.mode == MODAL_IO_MODE_UART_BRIDGE) {
|
||||
if (!_uart_port_bridge->is_open()) {
|
||||
if (_uart_port_bridge->uart_open(MODAL_IO_VOXL_BRIDGE_PORT, 230400) == PX4_OK) {
|
||||
PX4_INFO("Opened UART ESC Bridge device");
|
||||
|
||||
} else {
|
||||
PX4_ERR("Failed openening UART ESC Bridge device");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//uart passthrough test code
|
||||
//run 9 times because i just don't know how to change update rate of the module from 10hz to 100hz..
|
||||
for (int ii = 0; ii < 9; ii++) {
|
||||
uint8_t uart_buf[128];
|
||||
int bytes_read = _uart_port_bridge->uart_read(uart_buf, sizeof(uart_buf));
|
||||
|
||||
if (bytes_read > 0) {
|
||||
_uart_port->uart_write(uart_buf, bytes_read);
|
||||
|
||||
for (int i = 0; i < bytes_read; i++) {
|
||||
int16_t ret = qc_esc_packet_process_char(uart_buf[i], &_uart_bridge_packet);
|
||||
|
||||
if (ret > 0) {
|
||||
//PX4_INFO("got packet of length %i",ret);
|
||||
uint8_t packet_type = qc_esc_packet_get_type(&_uart_bridge_packet);
|
||||
|
||||
//uint8_t packet_size = qc_esc_packet_get_size(&_uart_bridge_packet);
|
||||
//if we received a command for ESC to reset, most likely firmware update is coming, switch to bootloader baud rate
|
||||
if (packet_type == ESC_PACKET_TYPE_RESET_CMD) {
|
||||
int bootloader_baud_rate = 230400;
|
||||
|
||||
if (_uart_port->uart_get_baud() != bootloader_baud_rate) {
|
||||
px4_usleep(5000);
|
||||
_uart_port->uart_set_baud(bootloader_baud_rate);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (_uart_port->uart_get_baud() != _parameters.baud_rate) {
|
||||
px4_usleep(5000);
|
||||
_uart_port->uart_set_baud(_parameters.baud_rate); //restore normal baud rate
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bytes_read = _uart_port->uart_read(uart_buf, sizeof(uart_buf));
|
||||
|
||||
if (bytes_read > 0) {
|
||||
_uart_port_bridge->uart_write(uart_buf, bytes_read);
|
||||
}
|
||||
|
||||
px4_usleep(10000);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (_uart_port_bridge->is_open()) {
|
||||
PX4_INFO("Closed UART ESC Bridge device");
|
||||
_uart_port_bridge->uart_close();
|
||||
}
|
||||
}
|
||||
|
||||
if (!_outputs_on) {
|
||||
@@ -1364,7 +1327,7 @@ void ModalIo::Run()
|
||||
}
|
||||
|
||||
|
||||
int ModalIo::print_usage(const char *reason)
|
||||
int VoxlEsc::print_usage(const char *reason)
|
||||
{
|
||||
if (reason) {
|
||||
PX4_WARN("%s\n", reason);
|
||||
@@ -1384,7 +1347,7 @@ $ todo
|
||||
|
||||
)DESCR_STR");
|
||||
|
||||
PRINT_MODULE_USAGE_NAME("modal_io", "driver");
|
||||
PRINT_MODULE_USAGE_NAME("voxl_esc", "driver");
|
||||
PRINT_MODULE_USAGE_COMMAND_DESCR("start", "Start the task");
|
||||
|
||||
PRINT_MODULE_USAGE_COMMAND_DESCR("reset", "Send reset request to ESC");
|
||||
@@ -1422,7 +1385,7 @@ $ todo
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ModalIo::print_status()
|
||||
int VoxlEsc::print_status()
|
||||
{
|
||||
PX4_INFO("Max update rate: %i Hz", _current_update_rate);
|
||||
PX4_INFO("Outputs on: %s", _outputs_on ? "yes" : "no");
|
||||
@@ -1431,31 +1394,31 @@ int ModalIo::print_status()
|
||||
|
||||
PX4_INFO("");
|
||||
|
||||
PX4_INFO("Params: MODAL_IO_CONFIG: %" PRId32, _parameters.config);
|
||||
PX4_INFO("Params: MODAL_IO_BAUD: %" PRId32, _parameters.baud_rate);
|
||||
PX4_INFO("Params: VOXL_ESC_CONFIG: %" PRId32, _parameters.config);
|
||||
PX4_INFO("Params: VOXL_ESC_BAUD: %" PRId32, _parameters.baud_rate);
|
||||
|
||||
PX4_INFO("Params: MODAL_IO_FUNC1: %" PRId32, _parameters.function_map[0]);
|
||||
PX4_INFO("Params: MODAL_IO_FUNC2: %" PRId32, _parameters.function_map[1]);
|
||||
PX4_INFO("Params: MODAL_IO_FUNC3: %" PRId32, _parameters.function_map[2]);
|
||||
PX4_INFO("Params: MODAL_IO_FUNC4: %" PRId32, _parameters.function_map[3]);
|
||||
PX4_INFO("Params: VOXL_ESC_FUNC1: %" PRId32, _parameters.function_map[0]);
|
||||
PX4_INFO("Params: VOXL_ESC_FUNC2: %" PRId32, _parameters.function_map[1]);
|
||||
PX4_INFO("Params: VOXL_ESC_FUNC3: %" PRId32, _parameters.function_map[2]);
|
||||
PX4_INFO("Params: VOXL_ESC_FUNC4: %" PRId32, _parameters.function_map[3]);
|
||||
|
||||
PX4_INFO("Params: MODAL_IO_SDIR1: %" PRId32, _parameters.direction_map[0]);
|
||||
PX4_INFO("Params: MODAL_IO_SDIR2: %" PRId32, _parameters.direction_map[1]);
|
||||
PX4_INFO("Params: MODAL_IO_SDIR3: %" PRId32, _parameters.direction_map[2]);
|
||||
PX4_INFO("Params: MODAL_IO_SDIR4: %" PRId32, _parameters.direction_map[3]);
|
||||
PX4_INFO("Params: VOXL_ESC_SDIR1: %" PRId32, _parameters.direction_map[0]);
|
||||
PX4_INFO("Params: VOXL_ESC_SDIR2: %" PRId32, _parameters.direction_map[1]);
|
||||
PX4_INFO("Params: VOXL_ESC_SDIR3: %" PRId32, _parameters.direction_map[2]);
|
||||
PX4_INFO("Params: VOXL_ESC_SDIR4: %" PRId32, _parameters.direction_map[3]);
|
||||
|
||||
PX4_INFO("Params: MODAL_IO_RPM_MIN: %" PRId32, _parameters.rpm_min);
|
||||
PX4_INFO("Params: MODAL_IO_RPM_MAX: %" PRId32, _parameters.rpm_max);
|
||||
PX4_INFO("Params: VOXL_ESC_RPM_MIN: %" PRId32, _parameters.rpm_min);
|
||||
PX4_INFO("Params: VOXL_ESC_RPM_MAX: %" PRId32, _parameters.rpm_max);
|
||||
|
||||
PX4_INFO("");
|
||||
|
||||
for( int i = 0; i < MODAL_IO_OUTPUT_CHANNELS; i++){
|
||||
for( int i = 0; i < VOXL_ESC_OUTPUT_CHANNELS; i++){
|
||||
PX4_INFO("-- ID: %i", i);
|
||||
PX4_INFO(" Motor: %i", _output_map[i].number);
|
||||
PX4_INFO(" Direction: %i", _output_map[i].direction);
|
||||
PX4_INFO(" State: %i", _esc_chans[i].state);
|
||||
PX4_INFO(" Requested: %i RPM", _esc_chans[i].rate_req);
|
||||
PX4_INFO(" Measured: %i RPM", _esc_chans[i].rate_meas);
|
||||
PX4_INFO(" Requested: %" PRIi32 " RPM", _esc_chans[i].rate_req);
|
||||
PX4_INFO(" Measured: %" PRIi32 " RPM", _esc_chans[i].rate_meas);
|
||||
PX4_INFO(" Command Counter: %i", _esc_chans[i].cmd_counter);
|
||||
PX4_INFO(" Voltage: %f VDC", (double)_esc_chans[i].voltage);
|
||||
PX4_INFO("");
|
||||
@@ -1469,9 +1432,9 @@ int ModalIo::print_status()
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" __EXPORT int modal_io_main(int argc, char *argv[]);
|
||||
extern "C" __EXPORT int voxl_esc_main(int argc, char *argv[]);
|
||||
|
||||
int modal_io_main(int argc, char *argv[])
|
||||
int voxl_esc_main(int argc, char *argv[])
|
||||
{
|
||||
return ModalIo::main(argc, argv);
|
||||
return VoxlEsc::main(argc, argv);
|
||||
}
|
||||
+59
-42
@@ -41,23 +41,26 @@
|
||||
#include <px4_log.h>
|
||||
#include <px4_platform_common/module.h>
|
||||
|
||||
#include <battery/battery.h>
|
||||
|
||||
#include <uORB/topics/vehicle_control_mode.h>
|
||||
#include <uORB/topics/manual_control_setpoint.h>
|
||||
#include <uORB/topics/actuator_outputs.h>
|
||||
#include <uORB/topics/led_control.h>
|
||||
#include <uORB/topics/esc_status.h>
|
||||
#include <uORB/topics/actuator_test.h>
|
||||
#include <uORB/topics/buffer128.h>
|
||||
|
||||
#include "modal_io_serial.hpp"
|
||||
#include "voxl_esc_serial.hpp"
|
||||
|
||||
#include "qc_esc_packet.h"
|
||||
#include "qc_esc_packet_types.h"
|
||||
|
||||
class ModalIo : public ModuleBase<ModalIo>, public OutputModuleInterface
|
||||
class VoxlEsc : public ModuleBase<VoxlEsc>, public OutputModuleInterface
|
||||
{
|
||||
public:
|
||||
ModalIo();
|
||||
virtual ~ModalIo();
|
||||
VoxlEsc();
|
||||
virtual ~VoxlEsc();
|
||||
|
||||
/** @see ModuleBase */
|
||||
static int task_spawn(int argc, char *argv[]);
|
||||
@@ -100,56 +103,61 @@ public:
|
||||
int send_cmd_thread_safe(Command *cmd);
|
||||
|
||||
private:
|
||||
static constexpr uint32_t MODAL_IO_UART_CONFIG = 1;
|
||||
static constexpr uint32_t MODAL_IO_DEFAULT_BAUD = 250000;
|
||||
static constexpr uint16_t MODAL_IO_OUTPUT_CHANNELS = 4;
|
||||
static constexpr uint16_t MODAL_IO_OUTPUT_DISABLED = 0;
|
||||
static constexpr uint32_t VOXL_ESC_UART_CONFIG = 1;
|
||||
static constexpr uint32_t VOXL_ESC_DEFAULT_BAUD = 250000;
|
||||
static constexpr uint16_t VOXL_ESC_OUTPUT_CHANNELS = 4;
|
||||
static constexpr uint16_t VOXL_ESC_OUTPUT_DISABLED = 0;
|
||||
|
||||
static constexpr uint32_t MODAL_IO_WRITE_WAIT_US = 200;
|
||||
static constexpr uint32_t MODAL_IO_DISCONNECT_TIMEOUT_US = 500000;
|
||||
static constexpr uint32_t VOXL_ESC_WRITE_WAIT_US = 200;
|
||||
static constexpr uint32_t VOXL_ESC_DISCONNECT_TIMEOUT_US = 500000;
|
||||
|
||||
static constexpr uint16_t DISARMED_VALUE = 0;
|
||||
|
||||
static constexpr uint16_t MODAL_IO_PWM_MIN = 0;
|
||||
static constexpr uint16_t MODAL_IO_PWM_MAX = 800;
|
||||
static constexpr uint16_t MODAL_IO_DEFAULT_RPM_MIN = 5000;
|
||||
static constexpr uint16_t MODAL_IO_DEFAULT_RPM_MAX = 17000;
|
||||
static constexpr uint16_t VOXL_ESC_PWM_MIN = 0;
|
||||
static constexpr uint16_t VOXL_ESC_PWM_MAX = 800;
|
||||
static constexpr uint16_t VOXL_ESC_DEFAULT_RPM_MIN = 5000;
|
||||
static constexpr uint16_t VOXL_ESC_DEFAULT_RPM_MAX = 17000;
|
||||
|
||||
static constexpr float MODAL_IO_MODE_DISABLED_SETPOINT = -0.1f;
|
||||
static constexpr float MODAL_IO_MODE_THRESHOLD = 0.0f;
|
||||
static constexpr float VOXL_ESC_MODE_DISABLED_SETPOINT = -0.1f;
|
||||
static constexpr float VOXL_ESC_MODE_THRESHOLD = 0.0f;
|
||||
|
||||
static constexpr uint32_t MODAL_IO_MODE = 0;
|
||||
static constexpr uint32_t MODAL_IO_MODE_TURTLE_AUX1 = 1;
|
||||
static constexpr uint32_t MODAL_IO_MODE_TURTLE_AUX2 = 2;
|
||||
static constexpr uint32_t MODAL_IO_MODE_UART_BRIDGE = 3;
|
||||
static constexpr uint32_t VOXL_ESC_MODE = 0;
|
||||
static constexpr uint32_t VOXL_ESC_MODE_TURTLE_AUX1 = 1;
|
||||
static constexpr uint32_t VOXL_ESC_MODE_TURTLE_AUX2 = 2;
|
||||
|
||||
//static constexpr uint16_t max_pwm(uint16_t pwm) { return math::min(pwm, MODAL_IO_PWM_MAX); }
|
||||
//static constexpr uint16_t max_rpm(uint16_t rpm) { return math::min(rpm, MODAL_IO_RPM_MAX); }
|
||||
static constexpr uint16_t VOXL_ESC_EXT_RPM = 39;
|
||||
static constexpr uint16_t VOXL_ESC_RPM_MAX = INT16_MAX -
|
||||
1; // 32K, Limit max standard range RPM to prevent overflow (rpm packet packing function accepts int32_t)
|
||||
static constexpr uint16_t VOXL_ESC_RPM_MAX_EXT = UINT16_MAX -
|
||||
5; // 65K, Limit max extended range RPM to prevent overflow (rpm packet packing function accepts int32_t)
|
||||
|
||||
ModalIoSerial *_uart_port;
|
||||
ModalIoSerial *_uart_port_bridge;
|
||||
//static constexpr uint16_t max_pwm(uint16_t pwm) { return math::min(pwm, VOXL_ESC_PWM_MAX); }
|
||||
//static constexpr uint16_t max_rpm(uint16_t rpm) { return math::min(rpm, VOXL_ESC_RPM_MAX); }
|
||||
|
||||
VoxlEscSerial *_uart_port;
|
||||
|
||||
typedef struct {
|
||||
int32_t config{MODAL_IO_UART_CONFIG};
|
||||
int32_t mode{MODAL_IO_MODE};
|
||||
int32_t config{VOXL_ESC_UART_CONFIG};
|
||||
int32_t mode{VOXL_ESC_MODE};
|
||||
int32_t turtle_motor_expo{35};
|
||||
int32_t turtle_motor_deadband{20};
|
||||
int32_t turtle_motor_percent{90};
|
||||
float turtle_stick_minf{0.15f};
|
||||
float turtle_cosphi{0.99f};
|
||||
int32_t baud_rate{MODAL_IO_DEFAULT_BAUD};
|
||||
int32_t rpm_min{MODAL_IO_DEFAULT_RPM_MIN};
|
||||
int32_t rpm_max{MODAL_IO_DEFAULT_RPM_MAX};
|
||||
int32_t function_map[MODAL_IO_OUTPUT_CHANNELS] {0, 0, 0, 0};
|
||||
int32_t motor_map[MODAL_IO_OUTPUT_CHANNELS] {1, 2, 3, 4};
|
||||
int32_t direction_map[MODAL_IO_OUTPUT_CHANNELS] {1, 1, 1, 1};
|
||||
int32_t baud_rate{VOXL_ESC_DEFAULT_BAUD};
|
||||
int32_t rpm_min{VOXL_ESC_DEFAULT_RPM_MIN};
|
||||
int32_t rpm_max{VOXL_ESC_DEFAULT_RPM_MAX};
|
||||
int32_t function_map[VOXL_ESC_OUTPUT_CHANNELS] {0, 0, 0, 0};
|
||||
int32_t motor_map[VOXL_ESC_OUTPUT_CHANNELS] {1, 2, 3, 4};
|
||||
int32_t direction_map[VOXL_ESC_OUTPUT_CHANNELS] {1, 1, 1, 1};
|
||||
int32_t verbose_logging{0};
|
||||
} modal_io_params_t;
|
||||
int32_t publish_battery_status{0};
|
||||
} voxl_esc_params_t;
|
||||
|
||||
struct EscChan {
|
||||
int16_t rate_req;
|
||||
int32_t rate_req;
|
||||
uint8_t state;
|
||||
uint16_t rate_meas;
|
||||
uint32_t rate_meas;
|
||||
uint8_t power_applied;
|
||||
uint8_t led;
|
||||
uint8_t cmd_counter;
|
||||
@@ -167,14 +175,14 @@ private:
|
||||
typedef struct {
|
||||
led_control_s control{};
|
||||
vehicle_control_mode_s mode{};
|
||||
uint8_t led_mask;// TODO led_mask[MODAL_IO_OUTPUT_CHANNELS];
|
||||
uint8_t led_mask;// TODO led_mask[VOXL_ESC_OUTPUT_CHANNELS];
|
||||
bool breath_en;
|
||||
uint8_t breath_counter;
|
||||
bool test;
|
||||
} led_rsc_t;
|
||||
|
||||
ch_assign_t _output_map[MODAL_IO_OUTPUT_CHANNELS] {{1, 1}, {2, 1}, {3, 1}, {4, 1}};
|
||||
MixingOutput _mixing_output{"MODAL_IO", MODAL_IO_OUTPUT_CHANNELS, *this, MixingOutput::SchedulingPolicy::Auto, false, false};
|
||||
ch_assign_t _output_map[VOXL_ESC_OUTPUT_CHANNELS] {{1, 1}, {2, 1}, {3, 1}, {4, 1}};
|
||||
MixingOutput _mixing_output;
|
||||
|
||||
perf_counter_t _cycle_perf;
|
||||
perf_counter_t _output_update_perf;
|
||||
@@ -188,13 +196,19 @@ private:
|
||||
uORB::Subscription _parameter_update_sub{ORB_ID(parameter_update)};
|
||||
uORB::Subscription _actuator_test_sub{ORB_ID(actuator_test)};
|
||||
uORB::Subscription _led_update_sub{ORB_ID(led_control)};
|
||||
uORB::Subscription _voxl2_io_data_sub{ORB_ID(voxl2_io_data)};
|
||||
|
||||
uORB::Publication<actuator_outputs_s> _outputs_debug_pub{ORB_ID(actuator_outputs_debug)};
|
||||
uORB::Publication<esc_status_s> _esc_status_pub{ORB_ID(esc_status)};
|
||||
|
||||
modal_io_params_t _parameters;
|
||||
bool _extended_rpm{false};
|
||||
bool _need_version_info{true};
|
||||
QC_ESC_VERSION_INFO _version_info[4];
|
||||
bool check_versions_updated();
|
||||
|
||||
voxl_esc_params_t _parameters;
|
||||
int update_params();
|
||||
int load_params(modal_io_params_t *params, ch_assign_t *map);
|
||||
int load_params(voxl_esc_params_t *params, ch_assign_t *map);
|
||||
|
||||
bool _turtle_mode_en{false};
|
||||
int32_t _rpm_turtle_min{0};
|
||||
@@ -205,11 +219,10 @@ private:
|
||||
Command _current_cmd;
|
||||
px4::atomic<Command *> _pending_cmd{nullptr};
|
||||
|
||||
EscChan _esc_chans[MODAL_IO_OUTPUT_CHANNELS];
|
||||
EscChan _esc_chans[VOXL_ESC_OUTPUT_CHANNELS];
|
||||
Command _esc_cmd;
|
||||
esc_status_s _esc_status;
|
||||
EscPacket _fb_packet;
|
||||
EscPacket _uart_bridge_packet;
|
||||
|
||||
led_rsc_t _led_rsc;
|
||||
int _fb_idx;
|
||||
@@ -219,6 +232,10 @@ private:
|
||||
static const uint8_t READ_BUF_SIZE = 128;
|
||||
uint8_t _read_buf[READ_BUF_SIZE];
|
||||
|
||||
Battery _battery;
|
||||
static constexpr unsigned _battery_report_interval{100_ms};
|
||||
hrt_abstime _last_battery_report_time;
|
||||
|
||||
void update_leds(vehicle_control_mode_s mode, led_control_s control);
|
||||
|
||||
int read_response(Command *out_cmd);
|
||||
+50
-34
@@ -38,23 +38,23 @@
|
||||
*
|
||||
* @reboot_required true
|
||||
*
|
||||
* @group MODAL IO
|
||||
* @group VOXL ESC
|
||||
* @value 0 - Disabled
|
||||
* @value 1 - VOXL ESC
|
||||
* @min 0
|
||||
* @max 1
|
||||
*/
|
||||
PARAM_DEFINE_INT32(MODAL_IO_CONFIG, 0);
|
||||
PARAM_DEFINE_INT32(VOXL_ESC_CONFIG, 0);
|
||||
|
||||
/**
|
||||
* UART ESC baud rate
|
||||
*
|
||||
* Default rate is 250Kbps, which is used in off-the-shelf MoadalAI ESC products.
|
||||
*
|
||||
* @group MODAL IO
|
||||
* @group VOXL ESC
|
||||
* @unit bit/s
|
||||
*/
|
||||
PARAM_DEFINE_INT32(MODAL_IO_BAUD, 250000);
|
||||
PARAM_DEFINE_INT32(VOXL_ESC_BAUD, 250000);
|
||||
|
||||
/**
|
||||
* Motor mappings for ModalAI ESC
|
||||
@@ -68,33 +68,33 @@ PARAM_DEFINE_INT32(MODAL_IO_BAUD, 250000);
|
||||
// The following are auto generated params from control allocator pattern, put here for reference
|
||||
|
||||
// Default ESC1 to motor2
|
||||
//PARAM_DEFINE_INT32(MODAL_IO_FUNC1, 102);
|
||||
//PARAM_DEFINE_INT32(VOXL_ESC_FUNC1, 102);
|
||||
|
||||
//PARAM_DEFINE_INT32(MODAL_IO_FUNC2, 103);
|
||||
//PARAM_DEFINE_INT32(VOXL_ESC_FUNC2, 103);
|
||||
|
||||
//PARAM_DEFINE_INT32(MODAL_IO_FUNC3, 101);
|
||||
//PARAM_DEFINE_INT32(VOXL_ESC_FUNC3, 101);
|
||||
|
||||
//PARAM_DEFINE_INT32(MODAL_IO_FUNC4, 104);
|
||||
//PARAM_DEFINE_INT32(VOXL_ESC_FUNC4, 104);
|
||||
|
||||
/**
|
||||
* UART ESC RPM Min
|
||||
*
|
||||
* Minimum RPM for ESC
|
||||
*
|
||||
* @group MODAL IO
|
||||
* @group VOXL ESC
|
||||
* @unit rpm
|
||||
*/
|
||||
PARAM_DEFINE_INT32(MODAL_IO_RPM_MIN, 5500);
|
||||
PARAM_DEFINE_INT32(VOXL_ESC_RPM_MIN, 5500);
|
||||
|
||||
/**
|
||||
* UART ESC RPM Max
|
||||
*
|
||||
* Maximum RPM for ESC
|
||||
*
|
||||
* @group MODAL IO
|
||||
* @group VOXL ESC
|
||||
* @unit rpm
|
||||
*/
|
||||
PARAM_DEFINE_INT32(MODAL_IO_RPM_MAX, 15000);
|
||||
PARAM_DEFINE_INT32(VOXL_ESC_RPM_MAX, 15000);
|
||||
|
||||
/**
|
||||
* UART ESC Mode
|
||||
@@ -103,7 +103,7 @@ PARAM_DEFINE_INT32(MODAL_IO_RPM_MAX, 15000);
|
||||
*
|
||||
* @reboot_required true
|
||||
*
|
||||
* @group MODAL IO
|
||||
* @group VOXL ESC
|
||||
* @value 0 - None
|
||||
* @value 1 - Turtle Mode enabled via AUX1
|
||||
* @value 2 - Turtle Mode enabled via AUX2
|
||||
@@ -111,108 +111,124 @@ PARAM_DEFINE_INT32(MODAL_IO_RPM_MAX, 15000);
|
||||
* @min 0
|
||||
* @max 2
|
||||
*/
|
||||
PARAM_DEFINE_INT32(MODAL_IO_MODE, 0);
|
||||
PARAM_DEFINE_INT32(VOXL_ESC_MODE, 0);
|
||||
|
||||
/**
|
||||
* UART ESC ID 1 Spin Direction Flag
|
||||
*
|
||||
* @group MODAL IO
|
||||
* @group VOXL ESC
|
||||
* @value 0 - Default
|
||||
* @value 1 - Reverse
|
||||
*/
|
||||
PARAM_DEFINE_INT32(MODAL_IO_SDIR1, 0);
|
||||
PARAM_DEFINE_INT32(VOXL_ESC_SDIR1, 0);
|
||||
|
||||
/**
|
||||
* UART ESC ID 2 Spin Direction Flag
|
||||
*
|
||||
* @group MODAL IO
|
||||
* @group VOXL ESC
|
||||
* @value 0 - Default
|
||||
* @value 1 - Reverse
|
||||
*/
|
||||
PARAM_DEFINE_INT32(MODAL_IO_SDIR2, 0);
|
||||
PARAM_DEFINE_INT32(VOXL_ESC_SDIR2, 0);
|
||||
|
||||
/**
|
||||
* UART ESC ID 3 Spin Direction Flag
|
||||
*
|
||||
* @group MODAL IO
|
||||
* @group VOXL ESC
|
||||
* @value 0 - Default
|
||||
* @value 1 - Reverse
|
||||
*/
|
||||
PARAM_DEFINE_INT32(MODAL_IO_SDIR3, 0);
|
||||
PARAM_DEFINE_INT32(VOXL_ESC_SDIR3, 0);
|
||||
|
||||
/**
|
||||
* UART ESC ID 4 Spin Direction Flag
|
||||
*
|
||||
* @group MODAL IO
|
||||
* @group VOXL ESC
|
||||
* @value 0 - Default
|
||||
* @value 1 - Reverse
|
||||
*/
|
||||
PARAM_DEFINE_INT32(MODAL_IO_SDIR4, 0);
|
||||
PARAM_DEFINE_INT32(VOXL_ESC_SDIR4, 0);
|
||||
|
||||
/**
|
||||
* UART ESC Turtle Mode Crash Flip Motor Percent
|
||||
*
|
||||
* @group MODAL IO
|
||||
* @group VOXL ESC
|
||||
* @min 1
|
||||
* @max 100
|
||||
* @decimal 10
|
||||
* @increment 1
|
||||
*/
|
||||
PARAM_DEFINE_INT32(MODAL_IO_T_PERC, 90);
|
||||
PARAM_DEFINE_INT32(VOXL_ESC_T_PERC, 90);
|
||||
|
||||
/**
|
||||
* UART ESC Turtle Mode Crash Flip Motor Deadband
|
||||
*
|
||||
* @group MODAL IO
|
||||
* @group VOXL ESC
|
||||
* @min 0
|
||||
* @max 100
|
||||
* @decimal 10
|
||||
* @increment 1
|
||||
*/
|
||||
PARAM_DEFINE_INT32(MODAL_IO_T_DEAD, 20);
|
||||
PARAM_DEFINE_INT32(VOXL_ESC_T_DEAD, 20);
|
||||
|
||||
/**
|
||||
* UART ESC Turtle Mode Crash Flip Motor STICK_MINF
|
||||
*
|
||||
* @group MODAL IO
|
||||
* @group VOXL ESC
|
||||
* @min 0.0
|
||||
* @max 100.0
|
||||
* @decimal 10
|
||||
* @increment 1.0
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(MODAL_IO_T_MINF, 0.15);
|
||||
PARAM_DEFINE_FLOAT(VOXL_ESC_T_MINF, 0.15);
|
||||
|
||||
/**
|
||||
* UART ESC Turtle Mode Crash Flip Motor expo
|
||||
*
|
||||
* @group MODAL IO
|
||||
* @group VOXL ESC
|
||||
* @min 0
|
||||
* @max 100
|
||||
* @decimal 10
|
||||
* @increment 1
|
||||
*/
|
||||
PARAM_DEFINE_INT32(MODAL_IO_T_EXPO, 35);
|
||||
PARAM_DEFINE_INT32(VOXL_ESC_T_EXPO, 35);
|
||||
|
||||
/**
|
||||
* UART ESC Turtle Mode Cosphi
|
||||
*
|
||||
* @group MODAL IO
|
||||
* @group VOXL ESC
|
||||
* @min 0.000
|
||||
* @max 1.000
|
||||
* @decimal 10
|
||||
* @increment 0.001
|
||||
*/
|
||||
PARAM_DEFINE_FLOAT(MODAL_IO_T_COSP, 0.990);
|
||||
PARAM_DEFINE_FLOAT(VOXL_ESC_T_COSP, 0.990);
|
||||
|
||||
/**
|
||||
* UART ESC verbose logging
|
||||
*
|
||||
* @reboot_required true
|
||||
*
|
||||
* @group MODAL IO
|
||||
* @group VOXL ESC
|
||||
* @value 0 - Disabled
|
||||
* @value 1 - Enabled
|
||||
* @min 0
|
||||
* @max 1
|
||||
*/
|
||||
PARAM_DEFINE_INT32(MODAL_IO_VLOG, 0);
|
||||
PARAM_DEFINE_INT32(VOXL_ESC_VLOG, 0);
|
||||
|
||||
|
||||
/**
|
||||
* UART ESC Enable publishing of battery status
|
||||
*
|
||||
* Only applicable to ESCs that report total battery voltage and current
|
||||
*
|
||||
* @reboot_required true
|
||||
*
|
||||
* @group VOXL ESC
|
||||
* @value 0 - Disabled
|
||||
* @value 1 - Enabled
|
||||
* @min 0
|
||||
* @max 1
|
||||
*/
|
||||
PARAM_DEFINE_INT32(VOXL_ESC_PUB_BST, 1);
|
||||
+8
-8
@@ -32,20 +32,20 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "string.h"
|
||||
#include "modal_io_serial.hpp"
|
||||
#include "voxl_esc_serial.hpp"
|
||||
|
||||
ModalIoSerial::ModalIoSerial()
|
||||
VoxlEscSerial::VoxlEscSerial()
|
||||
{
|
||||
}
|
||||
|
||||
ModalIoSerial::~ModalIoSerial()
|
||||
VoxlEscSerial::~VoxlEscSerial()
|
||||
{
|
||||
if (_uart_fd >= 0) {
|
||||
uart_close();
|
||||
}
|
||||
}
|
||||
|
||||
int ModalIoSerial::uart_open(const char *dev, speed_t speed)
|
||||
int VoxlEscSerial::uart_open(const char *dev, speed_t speed)
|
||||
{
|
||||
if (_uart_fd >= 0) {
|
||||
PX4_ERR("Port in use: %s (%i)", dev, errno);
|
||||
@@ -110,7 +110,7 @@ int ModalIoSerial::uart_open(const char *dev, speed_t speed)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ModalIoSerial::uart_set_baud(speed_t speed)
|
||||
int VoxlEscSerial::uart_set_baud(speed_t speed)
|
||||
{
|
||||
#ifndef __PX4_QURT
|
||||
|
||||
@@ -134,7 +134,7 @@ int ModalIoSerial::uart_set_baud(speed_t speed)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ModalIoSerial::uart_close()
|
||||
int VoxlEscSerial::uart_close()
|
||||
{
|
||||
#ifndef __PX4_QURT
|
||||
|
||||
@@ -158,7 +158,7 @@ int ModalIoSerial::uart_close()
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ModalIoSerial::uart_write(FAR void *buf, size_t len)
|
||||
int VoxlEscSerial::uart_write(FAR void *buf, size_t len)
|
||||
{
|
||||
if (_uart_fd < 0 || buf == NULL) {
|
||||
PX4_ERR("invalid state for writing or buffer");
|
||||
@@ -172,7 +172,7 @@ int ModalIoSerial::uart_write(FAR void *buf, size_t len)
|
||||
#endif
|
||||
}
|
||||
|
||||
int ModalIoSerial::uart_read(FAR void *buf, size_t len)
|
||||
int VoxlEscSerial::uart_read(FAR void *buf, size_t len)
|
||||
{
|
||||
if (_uart_fd < 0 || buf == NULL) {
|
||||
PX4_ERR("invalid state for reading or buffer");
|
||||
+3
-3
@@ -43,11 +43,11 @@
|
||||
#define FAR
|
||||
#endif
|
||||
|
||||
class ModalIoSerial
|
||||
class VoxlEscSerial
|
||||
{
|
||||
public:
|
||||
ModalIoSerial();
|
||||
virtual ~ModalIoSerial();
|
||||
VoxlEscSerial();
|
||||
virtual ~VoxlEscSerial();
|
||||
|
||||
int uart_open(const char *dev, speed_t speed);
|
||||
int uart_set_baud(speed_t speed);
|
||||
Reference in New Issue
Block a user