Skip to content

Commit

Permalink
dshot: convert period to RPM
Browse files Browse the repository at this point in the history
This calculates the actual RPM from the period transmitted via dshot to
based on the pole count.

Signed-off-by: Julian Oes <[email protected]>
  • Loading branch information
julianoes committed Apr 27, 2023
1 parent 647bd84 commit c1fad98
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 15 deletions.
23 changes: 17 additions & 6 deletions platforms/nuttx/src/px4/stm/stm32_common/dshot/dshot.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@ static int _channels_init_mask = 0;

// We only support capture on the first timer (usually 4 channels) for now.
static uint32_t _motor_to_capture = 0;
static uint32_t _erpms[4] = {};
static int32_t _erpms[4] = {};

static void(*_erpm_callback)(uint32_t[], size_t, void *) = NULL;
static void(*_erpm_callback)(int32_t[], size_t, void *) = NULL;
static void *_erpm_callback_context = NULL;

uint8_t nibbles_from_mapped(uint8_t mapped)
Expand Down Expand Up @@ -500,9 +500,20 @@ void process_capture_results(void *arg)
(uintptr_t)dshot_capture_buffer +
sizeof(dshot_capture_buffer));

// TODO: fix order
// TODO: convert from period to erpm
_erpms[_motor_to_capture] = calculate_period();
const unsigned period = calculate_period();

if (period == 0) {
// If the parsing failed, we get 0.
_erpms[_motor_to_capture] = 0;

} else if (period == 65408) {
// For still, we get this magic 65408 value.
_erpms[_motor_to_capture] = 0;

} else {
// from period in us to eRPM
_erpms[_motor_to_capture] = 1000000 * 60 / period;
}

for (unsigned channel = 0; channel < MAX_TIMER_IO_CHANNELS; channel++) {
if (_channels_init_mask & (1 << channel)) {
Expand Down Expand Up @@ -576,7 +587,7 @@ int up_dshot_arm(bool armed)
IO_TIMER_ALL_MODES_CHANNELS);
}

void up_dshot_set_erpm_callback(void(*callback)(uint32_t[], size_t, void *), void *context)
void up_dshot_set_erpm_callback(void(*callback)(int32_t[], size_t, void *), void *context)
{
_erpm_callback = callback;
_erpm_callback_context = context;
Expand Down
2 changes: 1 addition & 1 deletion src/drivers/drv_dshot.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ __EXPORT extern int up_dshot_arm(bool armed);

__EXPORT extern bool up_dshot_get_periods(uint32_t periods[], size_t num_periods);

__EXPORT extern void up_dshot_set_erpm_callback(void(*callback)(uint32_t[], size_t, void *), void *context);
__EXPORT extern void up_dshot_set_erpm_callback(void(*callback)(int32_t[], size_t, void *), void *context);

__EXPORT extern void print_driver_stats(void);

Expand Down
11 changes: 5 additions & 6 deletions src/drivers/dshot/DShot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -614,26 +614,25 @@ void DShot::update_params()
}
}

void DShot::erpm_trampoline(uint32_t erpms[], size_t num_erpms, void *context)
void DShot::erpm_trampoline(int32_t erpms[], size_t num_erpms, void *context)
{
DShot *self = static_cast<DShot *>(context);
self->erpm(erpms, num_erpms);
}

void DShot::erpm(uint32_t erpms[], size_t num_erpms)
void DShot::erpm(int32_t erpms[], size_t num_erpms)
{
// TODO: this is hard-coded to 4 motors
esc_status_s &esc_status = _esc_status_pub.get();
esc_status = {};
esc_status.timestamp = hrt_absolute_time();
esc_status.counter = _esc_status_counter++;
esc_status.esc_count = 4;
esc_status.esc_count = num_erpms;
esc_status.esc_connectiontype = esc_status_s::ESC_CONNECTION_TYPE_DSHOT;
esc_status.esc_armed_flags = _outputs_on;

This comment has been minimized.

Copy link
@WshgL

WshgL May 8, 2023

If esc_armed_flags not equals to esc_count, pre-flight check can not pass, and motor can not arm.
Refer to ESC telemetry:

esc_status.esc_online_flags = (1 << esc_status.esc_count) - 1;
esc_status.esc_armed_flags = (1 << esc_status.esc_count) - 1;

This comment has been minimized.

Copy link
@julianoes

julianoes May 8, 2023

Author Contributor

Right thanks for the hint. The PR only works for 4 motors at the moment. There is still some work to be done to extend that.


for (unsigned i = 0; i < 4 && i < esc_status_s::CONNECTED_ESC_MAX; ++i) {
for (unsigned i = 0; i < num_erpms && i < esc_status_s::CONNECTED_ESC_MAX; ++i) {
esc_status.esc[i].timestamp = hrt_absolute_time();
esc_status.esc[i].esc_rpm = erpms[i];
esc_status.esc[i].esc_rpm = erpms[i] / (_param_mot_pole_count.get() / 2);
}

_esc_status_pub.update();
Expand Down
4 changes: 2 additions & 2 deletions src/drivers/dshot/DShot.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ class DShot final : public ModuleBase<DShot>, public OutputModuleInterface

void handle_vehicle_commands();

static void erpm_trampoline(uint32_t erpms[], size_t num_erpms, void *context);
void erpm(uint32_t erpms[], size_t num_erpms);
static void erpm_trampoline(int32_t erpms[], size_t num_erpms, void *context);
void erpm(int32_t erpms[], size_t num_erpms);

MixingOutput _mixing_output {PARAM_PREFIX, DIRECT_PWM_OUTPUT_CHANNELS, *this, MixingOutput::SchedulingPolicy::Auto, false, false};
uint32_t _reversible_outputs{};
Expand Down

0 comments on commit c1fad98

Please sign in to comment.