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)Code: Select all
mcpwm_generator_set_force_level(mGeneratorHandle, -1, false)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);
}
Thank you in advance for your help