Page 1 of 1

Tri-state MCPWM outputs

Posted: Mon Jun 24, 2024 1:52 pm
by twadek
Hello,

I have an application where it would be ideal to tri-state one of my MCPWM outputs. Instead of push-pull PWM toggle, I would like the PWM to go high on the timer event and go high impedance (Hi-Z) rather than low on the compare event. As far as I can tell, this is not supported in "esp-idf/components/hal/include/hal/mcpwm_types.h".

There appears to be four defined actions:

Code: Select all

typedef enum {
    MCPWM_GEN_ACTION_KEEP,   /*!< Generator action: Keep the same level */
    MCPWM_GEN_ACTION_LOW,    /*!< Generator action: Force to low level */
    MCPWM_GEN_ACTION_HIGH,   /*!< Generator action: Force to high level */
    MCPWM_GEN_ACTION_TOGGLE, /*!< Generator action: Toggle level */
} mcpwm_generator_action_t;
Which I then can choose from when I define my generator actions (currently push-pull using ACTION_HIGH and ACTION_LOW):

Code: Select all

static void set_generator_actions(mcpwm_gen_handle_t generators[3][2], mcpwm_cmpr_handle_t comparators[]) {
    ESP_LOGI(TAG, "Set generator actions");
    for (int i = 0; i < 3; i++) {
     
        // Motor output actions
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(generators[i][PWM_GEN_INDEX_HIGH_SIDE], MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH)));
        ESP_ERROR_CHECK(mcpwm_generator_set_action_on_compare_event(generators[i][PWM_GEN_INDEX_HIGH_SIDE], MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, comparators[i], MCPWM_GEN_ACTION_LOW)));
    }
}
My code is adapted from "esp-idf/examples/peripherals/mcpwm/mcpwm_bldc_hall_control/main/mcpwm_bldc_hall_control_example_main.c".

My question is whether anyone has insight on how I may force the output into high impedance when the compare event is triggered. In essence, the closest equivalent to implementing a "MCPWM_GEN_ACTION_HIGH_IMPEDANCE". Even if a relatively low-level workaround, it will likely be worth it for my application.

I'm not well versed in the implementation of MCPWM, but my first instinct was to somehow hijack the compare interrupt and set the assigned pin to high impedance (maybe by disabling output?) at the register level.

I've been digging into the Technical Reference Manual and it seems like I should be able to use some combination of the steps outlined in section 6.5.2 to access the pin.

I would need to unroute MCPWM from the pin and set as input on the compare event, then reroute and reset the pin on a timer event.

Now the question is - does anyone know how I can do this when a compare/timer event is triggered? I assume it would have to be done before the generator action is taken by MCPWM.

One option (that seems less than ideal) would be to start an identical timer to the MCPWM timer with a high priority, low level interrupt that decouples MCPWM from the pin as stated above.

Thank you for any help you can provide.