MCPWM set force level seems to disable generator events

elasticdoor
Posts: 1
Joined: Tue Jun 03, 2025 12:20 pm

MCPWM set force level seems to disable generator events

Postby elasticdoor » Tue Jun 03, 2025 12:31 pm

Hi all,

I am writing ESP32-S3 firmware where I am using the MCPWM module to generate a square wave that is meant to be fed to a stepper motor controller with DIR/STEP pin interface. I have wrapped the MCPWM code in a C++ class. I have implemented an enable(bool) member function, the goal of which is to stop generating the frequency (for when I want the motor to stop). I use

Code: Select all

mcpwm_generator_set_force_level(mGeneratorHandle, 0, true)
to do so. Though, when I try to resume normal frequency generation with

Code: Select all

mcpwm_generator_set_force_level(mGeneratorHandle, -1, false)
, the pin remains forced to a low level. I cannot understand why. Find below more of the code, summarized to the most relevant parts. Variable starting with "m" are class members. "group_in_use" is a global bool array

Code: Select all

void PWMMCPWMImpl::init(unsigned freq_hz, float duty) {
    // Search for available group id, abort if none available
    mGroupId = SOC_MCPWM_GROUPS;
    for (int g = 0; g < SOC_MCPWM_GROUPS; g++) {
        if (!group_in_use[g]) {
            mGroupId = g;
            break;
        }
    }
    assert(mGroupId != SOC_MCPWM_GROUPS);

    mcpwm_timer_config_t timer_conf = {
        .group_id = mGroupId,
        .clk_src = mcpwm_timer_clock_source_t::MCPWM_TIMER_CLK_SRC_DEFAULT,
        .resolution_hz = TIMER_RESOLUTION_HZ,
        .count_mode = mcpwm_timer_count_mode_t::MCPWM_TIMER_COUNT_MODE_UP_DOWN,
        .period_ticks = 0xffff *2, // Maximum period. *2 because internally mcpwm_new_dimer divides by 2 if the mode is UP_DOWN
    };
    ESP_ERROR_CHECK(mcpwm_new_timer(&timer_conf, &mTimerHandle));

    mcpwm_operator_config_t operator_config {
        .group_id = mGroupId,
    };
    ESP_ERROR_CHECK(mcpwm_new_operator(&operator_config, &mOperatorHandle));
    ESP_ERROR_CHECK(mcpwm_operator_connect_timer(mOperatorHandle, mTimerHandle));

    mcpwm_generator_config_t generator_config = {
        .gen_gpio_num = mPin,
    };
    ESP_ERROR_CHECK(mcpwm_new_generator(mOperatorHandle, &generator_config, &mGeneratorHandle));
    mcpwm_gen_timer_event_action_t evt_act = {
        .direction = mcpwm_timer_direction_t::MCPWM_TIMER_DIRECTION_UP,
        .event = mcpwm_timer_event_t::MCPWM_TIMER_EVENT_EMPTY,
        .action = mcpwm_generator_action_t::MCPWM_GEN_ACTION_HIGH,
    };
    ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(mGeneratorHandle, evt_act));
    evt_act = {
        .direction = mcpwm_timer_direction_t::MCPWM_TIMER_DIRECTION_DOWN,
        .event = mcpwm_timer_event_t::MCPWM_TIMER_EVENT_FULL,
        .action = mcpwm_generator_action_t::MCPWM_GEN_ACTION_LOW,
    };
    ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(mGeneratorHandle, evt_act));
    
    ESP_ERROR_CHECK(mcpwm_timer_enable(mTimerHandle));
    ESP_ERROR_CHECK(mcpwm_timer_start_stop(mTimerHandle, MCPWM_TIMER_START_NO_STOP));

    enable(false);
}

void PWMMCPWMImpl::enable(bool en) {

    if (!en) {
        ESP_ERROR_CHECK(mcpwm_generator_set_force_level(mGeneratorHandle, 0, true));
    } else {
        ESP_ERROR_CHECK(mcpwm_generator_set_force_level(mGeneratorHandle, -1, false));
    }
    mEnabled = en;
}

void PWMMCPWMImpl::freq(unsigned freq_hz) {
    if (freq_hz == 0) {
        if (mEnabled) enable(false);
        return;
    }

    freq_hz = std::min(freq_hz, MAX_FREQ);

    uint32_t period_ticks = TIMER_RESOLUTION_HZ / freq_hz;
    if (period_ticks >= (1UL << 17)) {
        if (mEnabled) enable(false);
        return;
    }

    if (!mEnabled) enable(true);
    mcpwm_timer_set_period(mTimerHandle, period_ticks);
}
Note that if I comment out the calls to enable(bool), the frequency is generated correctly. I also tried calling the two mcpwm_generator_set_action_on_timer_event functions when I re-enable the frequency, but that didn't work.

Thank you in advance for your help

Who is online

Users browsing this forum: Bing [Bot], meta-externalagent and 3 guests