Skip to content
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

[WIP] Bidirectional DroneCAN ESC #21656

Open
wants to merge 16 commits into
base: main
Choose a base branch
from

Conversation

henrykotze
Copy link

Context

In certain vehicles, it is advantageous to have propellers that can rotate in both directions. This is possible with symmetrical propellers or other propeller designs that can generate thrust regardless of the rotating direction.

BeliHeli ESCs and VESC ESCs have the capability to rotate motors in both directions, provided they are correctly tuned and set up. Previously, we used BeliHeli ESCs, where we set the throttle range from 0% at 1500PWM to maximum forward at 2000PWM and maximum reverse at 1000PWM. However, we have now transitioned to using DroneCAN with VESC ESCs.

DroneCAN's ESC commands (uavcan::equipment::esc::RawCommand) are mapped from -8191 to 8191, representing the maximum throttle in the negative and positive directions, respectively. However, the PX4 mixer module only supports positive integers for its outputs (link).

As a result, we are unable to command the ESC to control the motor in both directions. Although it is possible to override the parameters and use negative integers, the negative value is interpreted as an unsigned integer.

Implementation

To address this issue, I have modified the mixer_module by changing the minimum, maximum, and failsafe types to int16_t, allowing the module to output values in the negative range. However, this change affects all output drivers that use unsigned types. Initially, I explored ways to limit the negative range only in the uavcan driver, but I found this approach less desirable, as some outputs would reside outside of the mixer_module. It is preferable to keep all of this functionality within the class.

Since the output parameters (MIN, MAX, FAIL) determine the mixing output, changing them to int16_t seemed appropriate to me.

Test

I have tested this implementation on a DroneCAN VESC ESC by providing commands in both directions, and it resulted in the desired behavior. However, I have not tested the drivers that use unsigned types, such as pwm_output.

I have created this work-in-progress (WIP) PR to gather feedback on the implementation.

@DronecodeBot
Copy link

This pull request has been mentioned on Discussion Forum for PX4, Pixhawk, QGroundControl, MAVSDK, MAVLink. There might be relevant details there:

https://discuss.px4.io/t/px4-community-q-a-may-31-2023/32396/2

@DronecodeBot
Copy link

This pull request has been mentioned on Discussion Forum for PX4, Pixhawk, QGroundControl, MAVSDK, MAVLink. There might be relevant details there:

https://discuss.px4.io/t/px4-community-q-a-may-31-2023/32396/1

Copy link

@Sidzeppelin95 Sidzeppelin95 left a comment

Choose a reason for hiding this comment

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

maybe try adding this to convert int type to float.
for key, label, param_suffix, description in standard_params_array:
if key in standard_params:
# convert minimum and maximum values to floats
min_val = float(standard_params[key]['min'])
max_val = float(standard_params[key]['max'])
# values must be within a reasonable range
if min_val < 0.0 or max_val > 1e6:
raise Exception('values for {:} must be within the range of 0 to 1e6'.format(key))
# ensure minimum value is less than or equal to maximum value
if min_val > max_val:
raise Exception('minimum value for {:} must be less than or equal to maximum value'.format(key))

@vertiq-jordan
Copy link
Contributor

Hi there! I'm the author of the issue here that you commented on yesterday. I was playing around with this branch just with some bench testing, and found a potential issue. Before, the default DISARMED_OUTPUT_VALUE in esc.hpp was set to UINT16_MAX. This is now getting interpreted as -1 as the output on the bus. This could possibly cause issues in the future with people accidentally arming motors they don't want spinning.

@henrykotze
Copy link
Author

@vertiq-jordan Thanks for raising this! Yeah I agree. We should change it to 0. -1 is still a very small percentage of the entire range, so I wont think motors would spin up, however changing it to zero would be more clearer for majority of people since they might not understand how it is reinterpreted to int16

@henrykotze henrykotze force-pushed the pr-can-esc-reverse-range branch from 387ee18 to e6ac66f Compare July 17, 2023 20:39
henrykotze added 10 commits August 5, 2023 15:18
- Currently, this changes the updateOutputs parameters type to int16_t
as well as changing the min,max, and failsafe values to int16_t.  This
has knock on effects in PWMOutput, PX4io, and DSHOT, which has not been
tested.

Currently looking at beter methods to implement
@henrykotze henrykotze force-pushed the pr-can-esc-reverse-range branch from 3e10ac8 to 287e525 Compare August 5, 2023 13:19
@henrykotze
Copy link
Author

Here is quick demo with the following QGC: mavlink/qgroundcontrol#10778
Will try and test PWM motors soon.

@bkueng @dagar

Any comments to push this further would be appreciated.

bidirectional_control.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants