Skip to content

Voxl2_io driver expand to 8 channel pwm output #52

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: voxl-dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/drivers/actuators/voxl_esc/module.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ parameters:
reboot_required: true
num_instances: 1
instance_start: 1
default: 0
default: 0
2 changes: 1 addition & 1 deletion src/drivers/voxl2_io/module.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ actuator_output:
- param_prefix: VOXL2_IO
group_label: 'PWMs'
channel_label: 'PWM Channel'
num_channels: 4
num_channels: 8

58 changes: 35 additions & 23 deletions src/drivers/voxl2_io/voxl2_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ int Voxl2IO::load_params(voxl2_io_params_t *params)
param_get(param_find("VOXL2_IO_FUNC2"), &params->function_map[1]);
param_get(param_find("VOXL2_IO_FUNC3"), &params->function_map[2]);
param_get(param_find("VOXL2_IO_FUNC4"), &params->function_map[3]);
param_get(param_find("VOXL2_IO_FUNC5"), &params->function_map[4]);
param_get(param_find("VOXL2_IO_FUNC6"), &params->function_map[5]);
param_get(param_find("VOXL2_IO_FUNC7"), &params->function_map[6]);
param_get(param_find("VOXL2_IO_FUNC8"), &params->function_map[7]);

/* Validate PWM min and max values */
if (params->pwm_min > params->pwm_max){
Expand Down Expand Up @@ -286,8 +290,8 @@ bool Voxl2IO::updateOutputs(bool stop_motors, uint16_t outputs[input_rc_s::RC_IN

//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
int16_t _rate_req[VOXL2_IO_OUTPUT_CHANNELS] = {0, 0, 0, 0};
uint8_t _led_req[VOXL2_IO_OUTPUT_CHANNELS] = {0, 0, 0, 0};
int16_t _rate_req[VOXL2_IO_OUTPUT_CHANNELS] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t _led_req[VOXL2_IO_OUTPUT_CHANNELS] = {0, 0, 0, 0, 0, 0, 0, 0};
int32_t _fb_idx = -1;

if (num_outputs != VOXL2_IO_OUTPUT_CHANNELS) {
Expand All @@ -313,8 +317,8 @@ bool Voxl2IO::updateOutputs(bool stop_motors, uint16_t outputs[input_rc_s::RC_IN
}

Command cmd;
cmd.len = voxl2_io_create_pwm_packet4_fb(_rate_req[0], _rate_req[1], _rate_req[2], _rate_req[3],
_led_req[0], _led_req[1], _led_req[2], _led_req[3],
cmd.len = voxl2_io_create_pwm_packet4_fb(_rate_req[0], _rate_req[1], _rate_req[2], _rate_req[3], _rate_req[4], _rate_req[5], _rate_req[6], _rate_req[7],
_led_req[0], _led_req[1], _led_req[2], _led_req[3], _led_req[4], _led_req[5], _led_req[6], _led_req[7],
_fb_idx, cmd.buf, sizeof(cmd.buf));
if (_pwm_on && _debug){
PX4_INFO("Mixer outputs");
Expand All @@ -324,7 +328,7 @@ bool Voxl2IO::updateOutputs(bool stop_motors, uint16_t outputs[input_rc_s::RC_IN
outputs[12], outputs[13], outputs[14], outputs[15], outputs[16], outputs[17]
);

// Debug messages for PWM 400Hz values sent to M0065
// Debug messages for PWM 400Hz values sent to M0065
uint16_t tics_1 = (_parameters.pwm_min + (_pwm_fullscale * ((double)outputs[0]/VOXL2_IO_MIXER_MAX))) * VOXL2_IO_TICS;
PX4_INFO("\tPWM CH1: %hu::%uus::%u tics", outputs[0], tics_1/24, tics_1);
uint16_t tics_2 = (_parameters.pwm_min + (_pwm_fullscale *((double)outputs[1]/VOXL2_IO_MIXER_MAX))) * VOXL2_IO_TICS;
Expand Down Expand Up @@ -712,13 +716,13 @@ int Voxl2IO::task_spawn(int argc, char *argv[])

bool Voxl2IO::stop_all_pwms()
{
int16_t _rate_req[VOXL2_IO_OUTPUT_CHANNELS] = {0, 0, 0, 0};
int16_t _led_req[VOXL2_IO_OUTPUT_CHANNELS] = {0, 0, 0, 0};
int16_t _rate_req[VOXL2_IO_OUTPUT_CHANNELS] = {0, 0, 0, 0, 0, 0, 0, 0};
int16_t _led_req[VOXL2_IO_OUTPUT_CHANNELS] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t _fb_idx = 0;

Command cmd;
cmd.len = voxl2_io_create_pwm_packet4_fb(_rate_req[0], _rate_req[1], _rate_req[2], _rate_req[3],
_led_req[0], _led_req[1], _led_req[2], _led_req[3],
cmd.len = voxl2_io_create_pwm_packet4_fb(_rate_req[0], _rate_req[1], _rate_req[2], _rate_req[3], _rate_req[4], _rate_req[5], _rate_req[6], _rate_req[7],
_led_req[0], _led_req[1], _led_req[2], _led_req[3], _led_req[4], _led_req[5], _led_req[6], _led_req[7],
_fb_idx, cmd.buf, sizeof(cmd.buf));

if (_uart_port->uart_write(cmd.buf, cmd.len) != cmd.len) {
Expand Down Expand Up @@ -770,11 +774,11 @@ int Voxl2IO::calibrate_escs(){

/* PWM MAX 3 seconds */
PX4_INFO("Writing PWM MAX for 3 seconds!");
int16_t max_pwm[4]{VOXL2_IO_MIXER_MAX, VOXL2_IO_MIXER_MAX, VOXL2_IO_MIXER_MAX, VOXL2_IO_MIXER_MAX};
if (_debug) PX4_INFO("%i %i %i %i", max_pwm[0], max_pwm[1], max_pwm[2], max_pwm[3]);
int16_t led_cmd[4]{0,0,0,0};
cmd.len = voxl2_io_create_pwm_packet4_fb(max_pwm[0], max_pwm[1], max_pwm[2], max_pwm[3],
led_cmd[0], led_cmd[1], led_cmd[2], led_cmd[3],
int16_t max_pwm[8]{VOXL2_IO_MIXER_MAX, VOXL2_IO_MIXER_MAX, VOXL2_IO_MIXER_MAX, VOXL2_IO_MIXER_MAX, VOXL2_IO_MIXER_MAX, VOXL2_IO_MIXER_MAX, VOXL2_IO_MIXER_MAX, VOXL2_IO_MIXER_MAX};
// if (_debug) PX4_INFO("%i %i %i %i %i %i %i %i", max_pwm[0], max_pwm[1], max_pwm[2], max_pwm[3], max_pwm[4], max_pwm[5], max_pwm[6], max_pwm[7]);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This debug statement had to be commented out due to compiler warning for formatting (too many format prints?)

int16_t led_cmd[8]{0,0,0,0,0,0,0,0};
cmd.len = voxl2_io_create_pwm_packet4_fb(max_pwm[0], max_pwm[1], max_pwm[2], max_pwm[3], max_pwm[4], max_pwm[5], max_pwm[6], max_pwm[7],
led_cmd[0], led_cmd[1], led_cmd[2], led_cmd[3], led_cmd[4], led_cmd[5], led_cmd[6], led_cmd[7],
fb_idx, cmd.buf, sizeof(cmd.buf));

if (_uart_port->uart_write(cmd.buf, cmd.len) != cmd.len) {
Expand All @@ -792,10 +796,10 @@ int Voxl2IO::calibrate_escs(){

/* PWM MIN 4 seconds */
PX4_INFO("Writing PWM MIN for 4 seconds!");
int16_t min_pwm[4]{VOXL2_IO_MIXER_MIN, VOXL2_IO_MIXER_MIN, VOXL2_IO_MIXER_MIN, VOXL2_IO_MIXER_MIN};
if (_debug) PX4_INFO("%i %i %i %i", min_pwm[0], min_pwm[1], min_pwm[2], min_pwm[3]);
cmd.len = voxl2_io_create_pwm_packet4_fb(min_pwm[0], min_pwm[1], min_pwm[2], min_pwm[3],
led_cmd[0], led_cmd[1], led_cmd[2], led_cmd[3],
int16_t min_pwm[8]{VOXL2_IO_MIXER_MIN, VOXL2_IO_MIXER_MIN, VOXL2_IO_MIXER_MIN, VOXL2_IO_MIXER_MIN, VOXL2_IO_MIXER_MIN, VOXL2_IO_MIXER_MIN, VOXL2_IO_MIXER_MIN, VOXL2_IO_MIXER_MIN};
// if (_debug) PX4_INFO("%i %i %i %i %i %i %i %i", min_pwm[0], min_pwm[1], min_pwm[2], min_pwm[3], min_pwm[4], min_pwm[4], min_pwm[5], min_pwm[6], min_pwm[7]);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

cmd.len = voxl2_io_create_pwm_packet4_fb(min_pwm[0], min_pwm[1], min_pwm[2], min_pwm[3], min_pwm[4], min_pwm[5], min_pwm[6], min_pwm[7],
led_cmd[0], led_cmd[1], led_cmd[2], led_cmd[3], led_cmd[4], led_cmd[5], led_cmd[6], led_cmd[7],
fb_idx, cmd.buf, sizeof(cmd.buf));

if (_uart_port->uart_write(cmd.buf, cmd.len) != cmd.len) {
Expand Down Expand Up @@ -920,22 +924,26 @@ int Voxl2IO::custom_command(int argc, char *argv[])
PX4_INFO("Rate: %i", rate);
if (output_channel < VOXL2_IO_OUTPUT_CHANNELS) {
PX4_INFO("Request PWM for Output Channel: %i - PWM: %i", output_channel, rate);
int16_t rate_req[VOXL2_IO_OUTPUT_CHANNELS] = {0, 0, 0, 0};
int16_t rate_req[VOXL2_IO_OUTPUT_CHANNELS] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t id_fb = 0;

if (output_channel == 0xFF) { //WARNING: this condition is not possible due to check 'if (esc_id < MODAL_IO_OUTPUT_CHANNELS)'.
rate_req[0] = rate;
rate_req[1] = rate;
rate_req[2] = rate;
rate_req[3] = rate;
rate_req[4] = rate;
rate_req[5] = rate;
rate_req[6] = rate;
rate_req[7] = rate;

} else {
rate_req[output_channel] = rate;
id_fb = output_channel;
}

cmd.len = voxl2_io_create_pwm_packet4_fb(rate_req[0], rate_req[1], rate_req[2], rate_req[3],
0, 0, 0, 0,
cmd.len = voxl2_io_create_pwm_packet4_fb(rate_req[0], rate_req[1], rate_req[2], rate_req[3], rate_req[4], rate_req[5], rate_req[6], rate_req[7],
0, 0, 0, 0, 0, 0, 0, 0,
id_fb, cmd.buf, sizeof(cmd.buf));

cmd.response = false;
Expand All @@ -955,7 +963,7 @@ int Voxl2IO::custom_command(int argc, char *argv[])
get_instance()->_packets_sent++;
}
} else {
print_usage("Invalid Output Channel, use 0-3");
print_usage("Invalid Output Channel, use 0-7");
return 0;
}
}
Expand All @@ -981,7 +989,11 @@ int Voxl2IO::print_status()
PX4_INFO("Params: VOXL2_IO_FUNC2: %" PRId32, _parameters.function_map[1]);
PX4_INFO("Params: VOXL2_IO_FUNC3: %" PRId32, _parameters.function_map[2]);
PX4_INFO("Params: VOXL2_IO_FUNC4: %" PRId32, _parameters.function_map[3]);

PX4_INFO("Params: VOXL2_IO_FUNC5: %" PRId32, _parameters.function_map[4]);
PX4_INFO("Params: VOXL2_IO_FUNC6: %" PRId32, _parameters.function_map[5]);
PX4_INFO("Params: VOXL2_IO_FUNC7: %" PRId32, _parameters.function_map[6]);
PX4_INFO("Params: VOXL2_IO_FUNC8: %" PRId32, _parameters.function_map[7]);

perf_print_counter(_cycle_perf);
perf_print_counter(_output_update_perf);
PX4_INFO("");
Expand Down
6 changes: 3 additions & 3 deletions src/drivers/voxl2_io/voxl2_io.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class Voxl2IO final : public ModuleBase<Voxl2IO>, public OutputModuleInterface
static constexpr uint32_t VOXL2_IO_BOARD_CONFIG_SIZE = 4; // PWM_MIN, PWM_MAX, 4 bytes
static constexpr uint32_t VOXL2_IO_ESC_CAL_SIZE = 1;
static constexpr uint32_t VOXL2_IO_DEFAULT_BAUD = 921600;
static constexpr uint16_t VOXL2_IO_OUTPUT_CHANNELS = 4;
static constexpr uint16_t VOXL2_IO_OUTPUT_CHANNELS = 8;
static constexpr uint16_t VOXL2_IO_OUTPUT_DISABLED = 0;

static constexpr uint32_t VOXL2_IO_WRITE_WAIT_US = 200;
Expand Down Expand Up @@ -160,7 +160,7 @@ class Voxl2IO final : public ModuleBase<Voxl2IO>, public OutputModuleInterface
int32_t pwm_failsafe{VOXL2_IO_DEFAULT_FAILSAFE};
int32_t param_rc_input_proto{0};
int32_t param_rc_rssi_pwm_chan{0};
int32_t function_map[VOXL2_IO_OUTPUT_CHANNELS] {0, 0, 0, 0};
int32_t function_map[VOXL2_IO_OUTPUT_CHANNELS] {0, 0, 0, 0, 0, 0, 0, 0};
int32_t verbose_logging{0};
} voxl2_io_params_t;
voxl2_io_params_t _parameters;
Expand Down Expand Up @@ -202,7 +202,7 @@ class Voxl2IO final : public ModuleBase<Voxl2IO>, public OutputModuleInterface

bool _pwm_on{false};
int32_t _pwm_fullscale{0};
int16_t _pwm_values[VOXL2_IO_OUTPUT_CHANNELS] = {0, 0, 0, 0};
int16_t _pwm_values[VOXL2_IO_OUTPUT_CHANNELS] = {0, 0, 0, 0, 0, 0, 0, 0};
bool _outputs_disabled{false};

perf_counter_t _cycle_perf;
Expand Down
59 changes: 35 additions & 24 deletions src/drivers/voxl2_io/voxl2_io_packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,21 +75,22 @@ int32_t voxl2_io_create_set_id_packet(uint8_t id, uint8_t *out, uint16_t out_siz
return voxl2_io_create_packet(VOXL2_IO_PACKET_TYPE_SET_ID_CMD, (uint8_t *)&id, 1, out, out_size);
}

int32_t voxl2_io_create_pwm_packet4(int16_t pwm0, int16_t pwm1, int16_t pwm2, int16_t pwm3,
uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3,
int32_t voxl2_io_create_pwm_packet4(int16_t pwm0, int16_t pwm1, int16_t pwm2, int16_t pwm3, int16_t pwm4, int16_t pwm5, int16_t pwm6, int16_t pwm7,
uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3, uint8_t led4, uint8_t led5, uint8_t led6, uint8_t led7,
uint8_t *out, uint16_t out_size)
{
return voxl2_io_create_pwm_packet4_fb(pwm0, pwm1, pwm2, pwm3, led0, led1, led2, led3, -1, out, out_size);
return voxl2_io_create_pwm_packet4_fb(pwm0, pwm1, pwm2, pwm3, pwm4, pwm5, pwm6, pwm7, led0, led1, led2, led3, led4, led5, led6, led7, -1, out, out_size);
}

int32_t voxl2_io_create_pwm_packet4_fb(int16_t pwm0, int16_t pwm1, int16_t pwm2, int16_t pwm3,
uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3,
int32_t voxl2_io_create_pwm_packet4_fb(int16_t pwm0, int16_t pwm1, int16_t pwm2, int16_t pwm3, int16_t pwm4, int16_t pwm5, int16_t pwm6, int16_t pwm7,
uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3, uint8_t led4, uint8_t led5, uint8_t led6, uint8_t led7,
int32_t fb_id, uint8_t *out, uint16_t out_size)
{
uint16_t data[5];
uint16_t data[9];
uint16_t leds = 0;
uint16_t input_size = sizeof(data);

if (fb_id != -1) { fb_id = fb_id % 4; }
if (fb_id != -1) { fb_id = fb_id % 8; }

//limit the pwm commands

Expand All @@ -101,38 +102,51 @@ int32_t voxl2_io_create_pwm_packet4_fb(int16_t pwm0, int16_t pwm1, int16_t pwm2,

if (pwm3 > 800) { pwm3 = 800; } if (pwm3 < -800) { pwm3 = -800; }

//least significant bit is used for feedback request
pwm0 &= ~(0x0001); pwm1 &= ~(0x0001); pwm2 &= ~(0x0001); pwm3 &= ~(0x0001);
if (pwm4 > 800) { pwm4 = 800; } if (pwm4 < -800) { pwm4 = -800; }

if (pwm5 > 800) { pwm5 = 800; } if (pwm5 < -800) { pwm5 = -800; }

if (pwm6 > 800) { pwm6 = 800; } if (pwm6 < -800) { pwm6 = -800; }

if (pwm7 > 800) { pwm7 = 800; } if (pwm7 < -800) { pwm7 = -800; }

//least significant bit is used for feedback request
pwm0 &= ~(0x0001); pwm1 &= ~(0x0001); pwm2 &= ~(0x0001); pwm3 &= ~(0x0001); pwm4 &= ~(0x0001); pwm5 &= ~(0x0001); pwm6 &= ~(0x0001); pwm7 &= ~(0x0001);

if (fb_id == 0) { pwm0 |= 0x0001; } if (fb_id == 1) { pwm1 |= 0x0001; }

if (fb_id == 2) { pwm2 |= 0x0001; } if (fb_id == 3) { pwm3 |= 0x0001; }

if (fb_id == 4) { pwm4 |= 0x0001; } if (fb_id == 5) { pwm5 |= 0x0001; }

if (fb_id == 6) { pwm6 |= 0x0001; } if (fb_id == 7) { pwm7 |= 0x0001; }

leds |= led0 & 0b00000111;
leds |= (led1 & 0b00000111) << 3;
leds |= ((uint16_t)(led2 & 0b00000111)) << 6;
leds |= ((uint16_t)(led3 & 0b00000111)) << 9;

data[0] = pwm0; data[1] = pwm1; data[2] = pwm2; data[3] = pwm3; data[4] = leds;
return voxl2_io_create_packet(VOXL2_IO_PACKET_TYPE_PWM_CMD, (uint8_t *) & (data[0]), 10, out, out_size);
data[0] = pwm0; data[1] = pwm1; data[2] = pwm2; data[3] = pwm3; data[4] = pwm4; data[5] = pwm5; data[6] = pwm6, data[7] = pwm7; data[8] = leds;
return voxl2_io_create_packet(VOXL2_IO_PACKET_TYPE_PWM_CMD, (uint8_t *) & (data[0]), input_size, out, out_size);
}


int32_t voxl2_io_create_rpm_packet4(int16_t rpm0, int16_t rpm1, int16_t rpm2, int16_t rpm3,
uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3,
int32_t voxl2_io_create_rpm_packet4(int16_t rpm0, int16_t rpm1, int16_t rpm2, int16_t rpm3, int16_t rpm4, int16_t rpm5, int16_t rpm6, int16_t rpm7,
uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3, uint8_t led4, uint8_t led5, uint8_t led6, uint8_t led7,
uint8_t *out, uint16_t out_size)
{
return voxl2_io_create_rpm_packet4_fb(rpm0, rpm1, rpm2, rpm3, led0, led1, led2, led3, -1, out, out_size);
int32_t feedback_id = -1
return voxl2_io_create_rpm_packet4_fb(rpm0, rpm1, rpm2, rpm3, rpm4, rpm5, rpm6, rpm7, led0, led1, led2, led3, led4, led5, led6, led7, feedback_id, out, out_size);
}

int32_t voxl2_io_create_rpm_packet4_fb(int16_t rpm0, int16_t rpm1, int16_t rpm2, int16_t rpm3,
uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3,
int32_t voxl2_io_create_rpm_packet4_fb(int16_t rpm0, int16_t rpm1, int16_t rpm2, int16_t rpm3, int16_t rpm4, int16_t rpm5, int16_t rpm6, int16_t rpm7,
uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3, uint8_t led4, uint8_t led5, uint8_t led6, uint8_t led7,
int32_t fb_id, uint8_t *out, uint16_t out_size)
{
uint16_t data[5];
uint16_t data[9];
uint16_t leds = 0;

if (fb_id != -1) { fb_id = fb_id % 4; }
uint16_t input_size = sizeof(data);
if (fb_id != -1) { fb_id = fb_id % 8; }

//least significant bit is used for feedback request
rpm0 &= ~(0x0001); rpm1 &= ~(0x0001); rpm2 &= ~(0x0001); rpm3 &= ~(0x0001);
Expand All @@ -146,8 +160,8 @@ int32_t voxl2_io_create_rpm_packet4_fb(int16_t rpm0, int16_t rpm1, int16_t rpm2,
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 voxl2_io_create_packet(VOXL2_IO_PACKET_TYPE_RPM_CMD, (uint8_t *) & (data[0]), 10, out, out_size);
data[0] = rpm0; data[1] = rpm1; data[2] = rpm2; data[3] = rpm3; data[4] = rpm4; data[5] = rpm5; data[6]=rpm6; data[7] = rpm7; data[8] = leds;
return voxl2_io_create_packet(VOXL2_IO_PACKET_TYPE_RPM_CMD, (uint8_t *) & (data[0]), input_size, out, out_size);
}

int32_t voxl2_io_create_packet(uint8_t type, uint8_t *data, uint16_t size, uint8_t *out, uint16_t out_size)
Expand All @@ -172,9 +186,6 @@ int32_t voxl2_io_create_packet(uint8_t type, uint8_t *data, uint16_t size, uint8
return packet_size;
}




//feed in a character and see if we got a complete packet
int16_t voxl2_io_packet_process_char(uint8_t c, VOXL2_IOPacket *packet)
{
Expand Down
16 changes: 8 additions & 8 deletions src/drivers/voxl2_io/voxl2_io_packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,26 +198,26 @@ int32_t voxl2_io_create_set_id_packet(uint8_t id, uint8_t *out, uint16_t out_siz

// Create a packet for sending open-loop 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 voxl2_io_create_pwm_packet4(int16_t pwm0, int16_t pwm1, int16_t pwm2, int16_t pwm3,
uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3,
int32_t voxl2_io_create_pwm_packet4(int16_t pwm0, int16_t pwm1, int16_t pwm2, int16_t pwm3, int16_t pwm4, int16_t pwm5, int16_t pwm6, int16_t pwm7,
uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3, uint8_t led4, uint8_t led5, uint8_t led6, uint8_t led7,
uint8_t *out, uint16_t out_size);

// Create a packet for sending open-loop command 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 voxl2_io_create_pwm_packet4_fb(int16_t pwm0, int16_t pwm1, int16_t pwm2, int16_t pwm3,
uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3,
int32_t voxl2_io_create_pwm_packet4_fb(int16_t pwm0, int16_t pwm1, int16_t pwm2, int16_t pwm3, int16_t pwm4, int16_t pwm5, int16_t pwm6, int16_t pwm7,
uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3, uint8_t led4, uint8_t led5, uint8_t led6, uint8_t led7,
int32_t fb_id, uint8_t *out, uint16_t out_size);

// 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 voxl2_io_create_rpm_packet4(int16_t rpm0, int16_t rpm1, int16_t rpm2, int16_t rpm3,
uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3,
int32_t voxl2_io_create_rpm_packet4(int16_t rpm0, int16_t rpm1, int16_t rpm2, int16_t rpm3, int16_t rpm4, int16_t rpm5, int16_t rpm6, int16_t rpm7,
uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3, uint8_t led4, uint8_t led5, uint8_t led6, uint8_t led7,
uint8_t *out, uint16_t out_size);

// 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)
// Return value is the length of generated packet (if positive), otherwise error code
int32_t voxl2_io_create_rpm_packet4_fb(int16_t rpm0, int16_t rpm1, int16_t rpm2, int16_t rpm3,
uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3,
int32_t voxl2_io_create_rpm_packet4_fb(int16_t rpm0, int16_t rpm1, int16_t rpm2, int16_t rpm3, int16_t rpm4, int16_t rpm5, int16_t rpm6, int16_t rpm7,
uint8_t led0, uint8_t led1, uint8_t led2, uint8_t led3, uint8_t led4, uint8_t led5, uint8_t led6, uint8_t led7,
int32_t fb_id, uint8_t *out, uint16_t out_size);


Expand Down