Skip to content

fix(bldc_motor): Remove use of static in init / calibration function; fix some copy-pasta in constructor; improve open-loop control#656

Open
finger563 wants to merge 1 commit into
mainfrom
fix/bldc-motor-bugs
Open

fix(bldc_motor): Remove use of static in init / calibration function; fix some copy-pasta in constructor; improve open-loop control#656
finger563 wants to merge 1 commit into
mainfrom
fix/bldc-motor-bugs

Conversation

@finger563

@finger563 finger563 commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes five issues in the BLDC motor FOC control code (components/bldc_motor/include/bldc_motor.hpp), found during a review of the control logic. The FOC math itself (Park/Clarke, SVPWM, trapezoidal commutation) was correct; the bugs were concentrated in the open-loop and calibration paths plus a couple of initialization footguns.

  1. Open-loop timestamp shared across motor instances. Both velocity_openloop() and angle_openloop() used a function-local static timestamp to compute the sample time Ts. For a templated BldcMotor, that static is shared by all instances of the same type, so two motors (e.g. the dual-motor MotorGo Mini) clobbered each other's timing and computed a wrong Ts, corrupting open-loop velocity/angle integration. Replaced with a per-instance member openloop_timestamp_.

  2. Open-loop functions ignored their target argument. velocity_openloop(float target) and angle_openloop(float target) integrated the member target_shaft_velocity_ / target_shaft_angle_ instead of the passed target. This is harmless on the normal move() path (which sets the member first), but it broke search_absolute_zero(), which calls angle_openloop(1.5f * _2PI) to sweep the motor — the argument was discarded, the motor never moved, and the index-search while loop could spin forever for sensors whose needs_zero_search() stays true. The functions now use target.

  3. Bare abs() on floats in angle_openloop(). Unqualified abs(...) on float operands can bind to the integer ::abs (truncating the values) depending on which headers are in scope. Changed to std::abs(...), matching the rest of the file.

  4. Wrong PID config in the constructor init list. pid_velocity_ and pid_angle_ were both constructed from config.current_pid_config. They were corrected by later change_gains() calls, so behavior was correct today, but it was a copy-paste trap. They are now constructed from config.velocity_pid_config and config.angle_pid_config respectively.

  5. Provided sensor direction ignored unless a non-zero offset was also given. In init_foc() the sensor direction was only applied inside the if (zero_electric_offset) block, so initialize(0, SOME_DIRECTION) discarded the direction and re-ran direction detection. The sensor direction and the electrical zero offset are now applied independently (each skips only its own calibration step), and init_foc()'s default sensor_direction parameter is now UNKNOWN to match initialize() instead of silently forcing CLOCKWISE.

Motivation and Context

These are correctness bugs in the motor control / calibration code. (1) affects any multi-motor board using two BldcMotor instances of the same type (most notably MotorGo Mini), where open-loop modes would behave erratically due to the shared timing state. (2) (compounded by (3)) could hang the index-search calibration for index-based encoders. (4) and (5) are robustness/API-correctness fixes that prevent silently-wrong configuration. The control code is a port of SimpleFOC; 1, 2, and 5 restore behavior that matches the upstream design (per-object open-loop timestamp, target-driven open-loop functions, independently-applied direction/offset).

How has this been tested?

  • Environment: ESP-IDF v6.0.1, macOS host, target esp32s3.
  • Built the bldc_motor example — clean build.
  • Built the motorgo-mini (dual-motor) example, the consumer most affected by the shared-timestamp fix — clean build.
  • Reviewed each change against the SimpleFOC reference implementation to confirm the open-loop timing, target handling, and direction/offset calibration now match upstream semantics.

Screenshots (if appropriate, e.g. schematic, board, console logs, lab pictures):

N/A

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation Update
  • Hardware (schematic, board, system design) change
  • Software change

Checklist:

  • My change requires a change to the documentation.
  • I have added / updated the documentation related to this change via either README or WIKI

Software

  • I have added tests to cover my changes.
  • I have updated the .github/workflows/build.yml file to add my new test to the automated cloud build github action.
  • All new and existing tests passed.
  • My code follows the code style of this project.

… fix some copy-pasta in constructor; improve open-loop control
@github-actions

Copy link
Copy Markdown

✅Static analysis result - no issues found! ✅

@finger563 finger563 self-assigned this Jun 26, 2026
@finger563 finger563 added bug Something isn't working bldc Related to Brushless DC Motors labels Jun 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bldc Related to Brushless DC Motors bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant