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

RPM sensing from GPIO (PWM pin) pulses #24041

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

RPM sensing from GPIO (PWM pin) pulses #24041

wants to merge 21 commits into from

Conversation

MaEtUgR
Copy link
Member

@MaEtUgR MaEtUgR commented Nov 26, 2024

Solved Problem

When wokring on helicopter rpm control I found that RPM sensing is "easily" possible but requires work. @bkueng provided the nice configurable capture part for that effort and I used the output directly in the heli-specific controller. But now I think we should enable generic RPM capturing for use in control, log, UI reporting.

Solution

As a draft, I added the hardcoded logic we used to process the RPM.
Note: This doesn't work well out of the box because it cannot detect a timeout if the interrupt is never called anymore.

The solution in the meantime has:

  • timeout
  • outlier rejection
  • pule per revolution configuration

Thanks for all the help from @oravla5, @sfuhrer and @bresch behind the scenes.

Changelog Entry

Feature: Easy to use RPM sensing from GPIO pulses

Test coverage

This logic was used on a heli to control RPM before porting it to latest main and moving the processing to the rpm capture driver. EDIT: and changing it completely again.

We need to follow up with further testing, settling the interface, implementing the timeout... FYI @sfuhrer
We did testing on an RC helicopter with high pulse per revolution count + noisy signal and a combustion engine with outliers.

@MaEtUgR MaEtUgR self-assigned this Nov 26, 2024
@MaEtUgR MaEtUgR changed the title [WIP] RPM sensing [WIP] Easy to use RPM sensing from GPIO pulses Nov 26, 2024
@sfuhrer
Copy link
Contributor

sfuhrer commented Dec 6, 2024

We need to get better with rejecting outliers:
image

@oravla5
Copy link
Contributor

oravla5 commented Dec 10, 2024

We need to get better with rejecting outliers: image

@sfuhrer
Do you by any chance still have this ulog?

@MaEtUgR MaEtUgR changed the title [WIP] Easy to use RPM sensing from GPIO pulses RPM sensing from GPIO (PWM pin) pulses Dec 10, 2024
@PX4 PX4 deleted a comment from github-actions bot Dec 10, 2024
Copy link

github-actions bot commented Dec 10, 2024

🔎 FLASH Analysis

px4_fmu-v5x [Total VM Diff: 148 byte (0.01 %)]
    FILE SIZE        VM SIZE    
--------------  -------------- 
+0.0%    +144  +0.0%    +144    .text
  +0.1%    +113  +0.1%    +113    ROMFS/nsh_romfsimg.c
  +0.0%     +16  +0.0%     +16    src/modules/mavlink/modules__mavlink_unity.cpp
  +0.0%     +12  +0.0%     +12    [section .text]
  +0.2%      +3  +0.2%      +3    ../../src/systemcmds/ver/ver.cpp
+0.1%      +4  +0.1%      +4    .data
   +20%      +4   +20%      +4    ../../platforms/nuttx/src/px4/stm/stm32_common/io_pins/io_timer.c
+0.0%     +56  [ = ]       0    .debug_abbrev
   +11%     +56  [ = ]       0    ../../src/lib/version/version.c
-0.0%      -8  [ = ]       0    .debug_aranges
  -5.0%      -8  [ = ]       0    ../../src/lib/version/version.c
+0.0%      +4  [ = ]       0    .debug_frame
+0.0%    +208  [ = ]       0    .debug_info
  +0.2%      +6  [ = ]       0    ../../platforms/nuttx/src/px4/stm/stm32_common/dshot/dshot.c
  +0.1%      +6  [ = ]       0    ../../platforms/nuttx/src/px4/stm/stm32_common/io_pins/input_capture.c
  +0.1%      +6  [ = ]       0    ../../platforms/nuttx/src/px4/stm/stm32_common/io_pins/io_timer.c
  +0.2%      +6  [ = ]       0    ../../platforms/nuttx/src/px4/stm/stm32_common/io_pins/pwm_servo.c
  +0.3%      +6  [ = ]       0    ../../platforms/nuttx/src/px4/stm/stm32_common/io_pins/pwm_trigger.c
  +0.1%      +6  [ = ]       0    ../../src/drivers/camera_trigger/interfaces/src/gpio.cpp
  +0.0%      +7  [ = ]       0    ../../src/drivers/dshot/DShot.cpp
  +0.0%      +7  [ = ]       0    ../../src/drivers/pwm_out/PWMOut.cpp
  +0.0%      +7  [ = ]       0    ../../src/drivers/px4io/px4io.cpp
  +0.0%      +7  [ = ]       0    ../../src/drivers/uavcan/actuators/esc.cpp
  +0.0%      +7  [ = ]       0    ../../src/drivers/uavcan/actuators/servo.cpp
  +0.0%      +7  [ = ]       0    ../../src/drivers/uavcan/uavcan_main.cpp
  +0.0%      +7  [ = ]       0    ../../src/drivers/uavcan/uavcan_servers.cpp
  +0.0%      +7  [ = ]       0    ../../src/lib/mixer_module/actuator_test.cpp
  +0.0%      +7  [ = ]       0    ../../src/lib/mixer_module/mixer_module.cpp
  -0.2%      -4  [ = ]       0    ../../src/lib/version/version.c
  +0.0%      +7  [ = ]       0    ../../src/modules/simulation/pwm_out_sim/PWMSim.cpp
  +0.4%     +42  [ = ]       0    msg/topics_sources/rpm.cpp
  -0.0%      -5  [ = ]       0    msg/topics_sources/uORBMessageFieldsGenerated.cpp
  +0.0%     +69  [ = ]       0    src/modules/mavlink/modules__mavlink_unity.cpp
+0.0%     +20  [ = ]       0    .debug_line
  +0.8%     +36  [ = ]       0    ../../src/drivers/camera_capture/camera_capture.cpp
  -1.3%     -25  [ = ]       0    ../../src/lib/version/version.c
  +0.0%      +8  [ = ]       0    src/modules/mavlink/modules__mavlink_unity.cpp
  +0.1%      +1  [ = ]       0    task/task_cancelpt.c
-0.0%    -118  [ = ]       0    .debug_loc
  -0.4%     -13  [ = ]       0    ../../src/drivers/camera_capture/camera_capture.cpp
  -0.1%     -15  [ = ]       0    ../../src/drivers/px4io/px4io.cpp
  -0.0%     -15  [ = ]       0    ../../src/drivers/uavcan/uavcan_main.cpp
  -0.0%     -15  [ = ]       0    ../../src/drivers/uavcan/uavcan_servers.cpp
  -0.1%     -15  [ = ]       0    ../../src/lib/mixer_module/mixer_module.cpp
  -0.0%     -30  [ = ]       0    [section .debug_loc]
  -0.0%     -15  [ = ]       0    src/modules/mavlink/modules__mavlink_unity.cpp
+0.0%    +119  [ = ]       0    .debug_ranges
   +18%    +128  [ = ]       0    ../../src/drivers/camera_capture/camera_capture.cpp
  -2.6%      -8  [ = ]       0    ../../src/lib/version/version.c
  -1.5%      -1  [ = ]       0    task/task_cancelpt.c
+0.0%     +27  [ = ]       0    .debug_str
  +1.8%     +20  [ = ]       0    ../../src/drivers/camera_trigger/interfaces/src/gpio.cpp
  +0.1%     +10  [ = ]       0    ../../src/drivers/dshot/DShot.cpp
  -0.0%      -3  [ = ]       0    src/modules/mavlink/modules__mavlink_unity.cpp
-1.1%    -144  [ = ]       0    [Unmapped]
+0.0%    +312  +0.0%    +148    TOTAL

px4_fmu-v6x [Total VM Diff: 40 byte (0 %)]
    FILE SIZE        VM SIZE    
--------------  -------------- 
+0.0%     +40  +0.0%     +40    .text
  +0.0%     +25  +0.0%     +25    ROMFS/nsh_romfsimg.c
  +0.0%     +16  +0.0%     +16    src/modules/mavlink/modules__mavlink_unity.cpp
  -0.0%      -1  -0.0%      -1    [section .text]
+0.0%     +56  [ = ]       0    .debug_abbrev
   +11%     +56  [ = ]       0    ../../src/lib/version/version.c
-0.0%      -8  [ = ]       0    .debug_aranges
  -5.0%      -8  [ = ]       0    ../../src/lib/version/version.c
+0.0%      +4  [ = ]       0    .debug_frame
+0.0%    +201  [ = ]       0    .debug_info
  +0.2%      +6  [ = ]       0    ../../platforms/nuttx/src/px4/stm/stm32_common/dshot/dshot.c
  +0.1%      +6  [ = ]       0    ../../platforms/nuttx/src/px4/stm/stm32_common/io_pins/input_capture.c
  +0.1%      +6  [ = ]       0    ../../platforms/nuttx/src/px4/stm/stm32_common/io_pins/io_timer.c
  +0.2%      +6  [ = ]       0    ../../platforms/nuttx/src/px4/stm/stm32_common/io_pins/pwm_servo.c
  +0.3%      +6  [ = ]       0    ../../platforms/nuttx/src/px4/stm/stm32_common/io_pins/pwm_trigger.c
  +0.1%      +6  [ = ]       0    ../../src/drivers/camera_trigger/interfaces/src/gpio.cpp
  +0.0%      +7  [ = ]       0    ../../src/drivers/dshot/DShot.cpp
  +0.0%      +7  [ = ]       0    ../../src/drivers/pwm_out/PWMOut.cpp
  +0.0%      +7  [ = ]       0    ../../src/drivers/px4io/px4io.cpp
  +0.0%      +7  [ = ]       0    ../../src/drivers/uavcan/actuators/esc.cpp
  +0.0%      +7  [ = ]       0    ../../src/drivers/uavcan/actuators/servo.cpp
  +0.0%      +7  [ = ]       0    ../../src/drivers/uavcan/uavcan_main.cpp
  +0.0%      +7  [ = ]       0    ../../src/drivers/uavcan/uavcan_servers.cpp
  +0.0%      +7  [ = ]       0    ../../src/lib/mixer_module/actuator_test.cpp
  +0.0%      +7  [ = ]       0    ../../src/lib/mixer_module/mixer_module.cpp
  -0.2%      -4  [ = ]       0    ../../src/lib/version/version.c
  +0.4%     +42  [ = ]       0    msg/topics_sources/rpm.cpp
  -0.0%      -5  [ = ]       0    msg/topics_sources/uORBMessageFieldsGenerated.cpp
  +0.0%     +69  [ = ]       0    src/modules/mavlink/modules__mavlink_unity.cpp
+0.0%     +23  [ = ]       0    .debug_line
  +0.8%     +36  [ = ]       0    ../../src/drivers/camera_capture/camera_capture.cpp
  -1.3%     -25  [ = ]       0    ../../src/lib/version/version.c
  +0.0%      +8  [ = ]       0    src/modules/mavlink/modules__mavlink_unity.cpp
  +0.4%      +4  [ = ]       0    task/task_cancelpt.c
-0.0%     -14  [ = ]       0    .debug_loc
  -0.4%     -13  [ = ]       0    ../../src/drivers/camera_capture/camera_capture.cpp
  +0.1%     +15  [ = ]       0    ../../src/drivers/px4io/px4io.cpp
  -0.0%     -13  [ = ]       0    ../../src/drivers/uavcan/uavcan_main.cpp
  -0.0%     -17  [ = ]       0    ../../src/drivers/uavcan/uavcan_servers.cpp
  -0.1%     -16  [ = ]       0    ../../src/lib/mixer_module/mixer_module.cpp
  +0.0%     +30  [ = ]       0    [section .debug_loc]
+0.0%    +119  [ = ]       0    .debug_ranges
   +18%    +128  [ = ]       0    ../../src/drivers/camera_capture/camera_capture.cpp
  -2.6%      -8  [ = ]       0    ../../src/lib/version/version.c
  -1.5%      -1  [ = ]       0    task/task_cancelpt.c
+0.0%     +27  [ = ]       0    .debug_str
  +1.8%     +20  [ = ]       0    ../../src/drivers/camera_trigger/interfaces/src/gpio.cpp
  +0.1%     +10  [ = ]       0    ../../src/drivers/dshot/DShot.cpp
  -0.0%      -3  [ = ]       0    src/modules/mavlink/modules__mavlink_unity.cpp
-0.1%     -40  [ = ]       0    [Unmapped]
+0.0%    +408  +0.0%     +40    TOTAL

Updated: 2024-12-12T14:45:05

@MaEtUgR
Copy link
Member Author

MaEtUgR commented Dec 10, 2024

I rebased on main, fixed the screw up with the unwanted, unused RpmControl.hpp file I added and was changed for quick tests instead of the real logic. And added all our latest changes we came up with @oravla5.

We did testing on an RC helicopter with high pulse per revolution count + noisy signal and a combustion engine with outliers.

Here's the plot from the small RC heli spinning the motor without blades open loop:
grafik

@MaEtUgR MaEtUgR marked this pull request as ready for review December 10, 2024 19:05
@MaEtUgR MaEtUgR requested review from sfuhrer and oravla5 December 10, 2024 19:05
/**
* RPM Capture Enable
*
* Enables the RPM capture module on FMU channel 5.
Copy link
Contributor

Choose a reason for hiding this comment

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

Before merging, shall we check if we could use other channels different from 5? If so, we should update the comment accordingly.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes definitely. I always used 5 so far because of that comment...

Copy link
Member Author

Choose a reason for hiding this comment

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

I quickly asked the ST experts and the interrupt should be independent of timers and configuring the pin for input interrupt should be possible on most pins but probably depends on the board. So the assumption is it should work also on the other FMU PWM pins.

Copy link
Contributor

@oravla5 oravla5 Dec 11, 2024

Choose a reason for hiding this comment

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

Confirmed on v5x FMU 👌

Copy link
Contributor

Choose a reason for hiding this comment

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

@bkueng are you aware of other boards in which only channel 5 would work? Otherwise, would you be ok with removing the channel 5 part of the description?

Copy link
Member

Choose a reason for hiding this comment

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

Channel 5 has history reasons. This is now more flexible as any pin can be configured, so the comment does not apply anymore.

@oravla5 oravla5 self-requested a review December 11, 2024 08:40
Copy link
Contributor

@oravla5 oravla5 left a comment

Choose a reason for hiding this comment

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

LGTM once we check if we can do RPM sensing in other channels that are not 5.

@oravla5
Copy link
Contributor

oravla5 commented Dec 11, 2024

I confrimed that RPM capture works on other AUX GPIO pins. It's not available in the MAIN pins.

I also played around with the parameters of the alpha and medium filters:

  • Increasing the median filter window makes the rpm estimate significantly smoother for the small heli noisy raw RPM, but also slower. A value of 7 seems to be a good compromise.
  • Increasing the alpha filter factor does not have a significant effect.

Find attached the logs for:

  • Alpha filter 0.5, median filter window 5
  • Alpha filter 0.5, median filter window 11
  • Alpha filter 0.5, median filter window 7
  • Alpha filter 0.7, median filter window 7

alpha0.5_median5
alpha0.5_median11
alpha0.5_median7
alpha0.7_median7

rpm_caputure_filter_tests.zip

Copy link
Member

@bresch bresch left a comment

Choose a reason for hiding this comment

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

Just a bit of nitpicking, otherwise looks good

src/drivers/rpm_capture/CMakeLists.txt Outdated Show resolved Hide resolved
msg/Rpm.msg Outdated Show resolved Hide resolved
msg/Rpm.msg Outdated Show resolved Hide resolved
src/drivers/rpm_capture/RPMCapture.cpp Outdated Show resolved Hide resolved
src/drivers/rpm_capture/RPMCapture.cpp Outdated Show resolved Hide resolved
src/drivers/rpm_capture/RPMCapture.cpp Outdated Show resolved Hide resolved
src/drivers/rpm_capture/RPMCapture.cpp Outdated Show resolved Hide resolved
src/drivers/rpm_capture/RPMCapture.hpp Outdated Show resolved Hide resolved
@MaEtUgR
Copy link
Member Author

MaEtUgR commented Dec 12, 2024

@bresch Thanks for the thorough review 👍 I rebased on main, addressed all your comments in new commits (not one each but they're referenced) and added 375cd55 on top because I saw that was only necessary before 15fece7#diff-21b8564105b699e09127da22888e7b35b845e53be24c30a6f921ea1f9e82f821L84.

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

Successfully merging this pull request may close these issues.

5 participants