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

Add granular control for ComplementaryPwm (independent enable/disable of main and complementary outputs) #3710

Open
zephyr-atomi opened this issue Jan 2, 2025 · 0 comments

Comments

@zephyr-atomi
Copy link

Description

The current ComplementaryPwm API in Embassy does not provide fine-grained control over main and complementary outputs. Specifically, the enable(channel) method simultaneously enables both the main (e.g., CHx) and complementary (e.g., CHxN) outputs. Similarly, disable(channel) disables both. This design works well for scenarios like FOC or SVPWM where both outputs are always active with complementary polarity, but it limits the use case for six-step commutation (trapezoidal BLDC control), where:

Only the main output (CHx) or the complementary output (CHxN) is active at any time for a given phase.
Granular control is required to enable/disable CHx and CHxN independently. For example, in six-step commutation, the typical requirement for a phase is:

Step 0: CH1 active (main), CH2N active (complementary), all others off.
Step 1: CH1 active (main), CH3N active (complementary), etc.
This means the API should allow enabling/disabling CHx and CHxN independently for precise control of main and complementary outputs.

Proposed Solution

Add new methods to ComplementaryPwm to independently control the main and complementary outputs:

impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> {
    /// Enable only the main output for a channel (CHx).
    pub fn enable_main(&mut self, channel: Channel) {
        self.inner.enable_complementary_channel(channel, false);
        self.inner.enable_channel(channel, true);
    }

    /// Enable only the complementary output for a channel (CHxN).
    pub fn enable_complementary(&mut self, channel: Channel) {
        self.inner.enable_channel(channel, false);
        self.inner.enable_complementary_channel(channel, true);
    }

    /// Disable both main and complementary outputs for a channel.
    pub fn disable_all(&mut self, channel: Channel) {
        self.inner.enable_channel(channel, false);
        self.inner.enable_complementary_channel(channel, false);
    }
}

Benefits

Support for six-step commutation:

This API addition will enable applications that require trapezoidal BLDC control, a widely used method in motor control.

More flexibility:

The changes will allow Embassy users to use a single timer with complementary PWM for applications that require selective enabling/disabling of main and complementary outputs.

Backward compatibility:

The current enable and disable methods can remain unchanged, ensuring existing users are not impacted.

Appendix

My previous six-step commutation implementation based on stm32f4xx-hal: https://github.com/zephyr-atomi/stm32f4-exp/blob/master/examples/motor-exp.rs

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

No branches or pull requests

1 participant