Merge branch 'bugfix/mcpwm_bldc_example' into 'master'

mcpwm: test generator force level with dead time module

See merge request espressif/esp-idf!23649
This commit is contained in:
morris 2023-05-12 12:11:17 +08:00
commit a7d79456e2
3 changed files with 102 additions and 38 deletions

View File

@ -59,6 +59,7 @@ esp_err_t mcpwm_del_generator(mcpwm_gen_handle_t gen);
* @note The force level will be applied to the generator immediately, regardless any other events that would change the generator's behaviour.
* @note If the `hold_on` is true, the force level will retain forever, until user removes the force level by setting the force level to `-1`.
* @note If the `hold_on` is false, the force level can be overridden by the next event action.
* @note The force level set by this function can be inverted by GPIO matrix or dead-time module. So the level set here doesn't equal to the final output level.
*
* @param[in] gen MCPWM generator handle, allocated by `mcpwm_new_generator()`
* @param[in] level GPIO level to be applied to MCPWM generator, specially, -1 means to remove the force level

View File

@ -77,6 +77,56 @@ TEST_CASE("mcpwm_generator_force_level_hold_on", "[mcpwm]")
TEST_ESP_OK(mcpwm_del_operator(oper));
}
// mcpwm_generator_set_force_level acts before the dead time module
// so the value output on the generator is a combined result
TEST_CASE("mcpwm_force_level_and_dead_time", "[mcpwm]")
{
printf("create operator and generators\r\n");
mcpwm_oper_handle_t oper = NULL;
mcpwm_operator_config_t operator_config = {
.group_id = 0,
};
TEST_ESP_OK(mcpwm_new_operator(&operator_config, &oper));
mcpwm_gen_handle_t gen_a = NULL;
mcpwm_gen_handle_t gen_b = NULL;
const int gen_a_gpio = 0;
const int gen_b_gpio = 2;
mcpwm_generator_config_t generator_config = {
.gen_gpio_num = gen_a_gpio,
.flags.io_loop_back = true, // loop back for test
};
TEST_ESP_OK(mcpwm_new_generator(oper, &generator_config, &gen_a));
generator_config.gen_gpio_num = gen_b_gpio;
generator_config.flags.invert_pwm = true; // Inversion add to the GPIO matrix
TEST_ESP_OK(mcpwm_new_generator(oper, &generator_config, &gen_b));
mcpwm_dead_time_config_t dt_config = {
.posedge_delay_ticks = 5,
};
ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(gen_a, gen_a, &dt_config));
dt_config = (mcpwm_dead_time_config_t) {
.negedge_delay_ticks = 5,
.flags.invert_output = true, // Inversion applied by the dead time module
};
ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(gen_b, gen_b, &dt_config));
printf("add force level to the generator, hold on");
for (int i = 0; i < 10; i++) {
TEST_ESP_OK(mcpwm_generator_set_force_level(gen_b, 0, true));
vTaskDelay(pdMS_TO_TICKS(10));
TEST_ASSERT_EQUAL(0, gpio_get_level(gen_b_gpio));
TEST_ESP_OK(mcpwm_generator_set_force_level(gen_b, 1, true));
vTaskDelay(pdMS_TO_TICKS(10));
TEST_ASSERT_EQUAL(1, gpio_get_level(gen_b_gpio));
}
printf("delete generator and operator\r\n");
TEST_ESP_OK(mcpwm_del_generator(gen_a));
TEST_ESP_OK(mcpwm_del_generator(gen_b));
TEST_ESP_OK(mcpwm_del_operator(oper));
}
TEST_CASE("mcpwm_generator_force_level_recovery", "[mcpwm]")
{
printf("create mcpwm timer\r\n");

View File

@ -61,24 +61,26 @@ static void bldc_set_phase_up_vm(mcpwm_gen_handle_t (*gens)[2])
// U+ = PWM, U- = _PWM_
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_HIGH], -1, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_LOW], -1, true);
// V+ = 0, V- = 1
// V+ = 0, V- = 1 --[because gen_low is inverted by dead time]--> V+ = 0, V- = 0
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_LOW], 1, true);
// W+ = 0, W- = 0
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_LOW], 0, true);
// W+ = 0, W- = 0 --[because gen_low is inverted by dead time]--> W+ = 0, W- = 1
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_LOW], 0, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_LOW], 1, true);
}
// W+U-
static void bldc_set_phase_wp_um(mcpwm_gen_handle_t (*gens)[2])
{
// U+ = 0, U- = 1
// U+ = 0, U- = 1 --[because gen_low is inverted by dead time]--> U+ = 0, U- = 0
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_LOW], 1, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_LOW], 0, true);
// V+ = 0, V- = 0
// V+ = 0, V- = 0 --[because gen_low is inverted by dead time]--> V+ = 0, V- = 1
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_LOW], 0, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_LOW], 1, true);
// W+ = PWM, W- = _PWM_
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_HIGH], -1, true);
@ -88,13 +90,13 @@ static void bldc_set_phase_wp_um(mcpwm_gen_handle_t (*gens)[2])
// W+V-
static void bldc_set_phase_wp_vm(mcpwm_gen_handle_t (*gens)[2])
{
// U+ = 0, U- = 0
// U+ = 0, U- = 0 --[because gen_low is inverted by dead time]--> U+ = 0, U- = 1
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_LOW], 0, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_LOW], 1, true);
// V+ = 0, V- = 1
// V+ = 0, V- = 1 --[because gen_low is inverted by dead time]--> V+ = 0, V- = 0
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_LOW], 1, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_LOW], 0, true);
// W+ = PWM, W- = _PWM_
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_HIGH], -1, true);
@ -104,23 +106,7 @@ static void bldc_set_phase_wp_vm(mcpwm_gen_handle_t (*gens)[2])
// V+U-
static void bldc_set_phase_vp_um(mcpwm_gen_handle_t (*gens)[2])
{
// U+ = 0, U- = 1
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_LOW], 1, true);
// V+ = PWM, V- = _PWM_
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_HIGH], -1, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_LOW], -1, true);
// W+ = 0, W- = 0
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_LOW], 0, true);
}
// V+W-
static void bldc_set_phase_vp_wm(mcpwm_gen_handle_t (*gens)[2])
{
// U+ = 0, U- = 0
// U+ = 0, U- = 1 --[because gen_low is inverted by dead time]--> U+ = 0, U- = 0
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_LOW], 0, true);
@ -128,11 +114,27 @@ static void bldc_set_phase_vp_wm(mcpwm_gen_handle_t (*gens)[2])
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_HIGH], -1, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_LOW], -1, true);
// W+ = 0, W- = 1
// W+ = 0, W- = 0 --[because gen_low is inverted by dead time]--> W+ = 0, W- = 1
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_LOW], 1, true);
}
// V+W-
static void bldc_set_phase_vp_wm(mcpwm_gen_handle_t (*gens)[2])
{
// U+ = 0, U- = 0 --[because gen_low is inverted by dead time]--> U+ = 0, U- = 1
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_LOW], 1, true);
// V+ = PWM, V- = _PWM_
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_HIGH], -1, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_LOW], -1, true);
// W+ = 0, W- = 1 --[because gen_low is inverted by dead time]--> W+ = 0, W- = 0
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_LOW], 0, true);
}
// U+W- / A+C-
static void bldc_set_phase_up_wm(mcpwm_gen_handle_t (*gens)[2])
{
@ -140,13 +142,13 @@ static void bldc_set_phase_up_wm(mcpwm_gen_handle_t (*gens)[2])
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_HIGH], -1, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_U][BLDC_MCPWM_GEN_INDEX_LOW], -1, true);
// V+ = 0, V- = 0
// V+ = 0, V- = 0 --[because gen_low is inverted by dead time]--> V+ = 0, V- = 1
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_LOW], 0, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_V][BLDC_MCPWM_GEN_INDEX_LOW], 1, true);
// W+ = 0, W- = 1
// W+ = 0, W- = 1 --[because gen_low is inverted by dead time]--> W+ = 0, W- = 0
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_LOW], 1, true);
mcpwm_generator_set_force_level(gens[BLDC_MCPWM_OP_INDEX_W][BLDC_MCPWM_GEN_INDEX_LOW], 0, true);
}
static const bldc_hall_phase_action_t s_hall_actions[] = {
@ -255,6 +257,8 @@ void app_main(void)
}
ESP_LOGI(TAG, "Set generator actions");
// gen_high and gen_low output the same waveform after the following configuration
// we will use the dead time module to add edge delay, also make gen_high and gen_low complementary
for (int i = 0; i < 3; i++) {
ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(generators[i][BLDC_MCPWM_GEN_INDEX_HIGH],
MCPWM_GEN_TIMER_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_TIMER_EVENT_EMPTY, MCPWM_GEN_ACTION_HIGH)));
@ -264,6 +268,15 @@ void app_main(void)
MCPWM_GEN_BRAKE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_CBC, MCPWM_GEN_ACTION_LOW)));
ESP_ERROR_CHECK(mcpwm_generator_set_action_on_brake_event(generators[i][BLDC_MCPWM_GEN_INDEX_HIGH],
MCPWM_GEN_BRAKE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_CBC, MCPWM_GEN_ACTION_LOW)));
ESP_ERROR_CHECK(mcpwm_generator_set_action_on_timer_event(generators[i][BLDC_MCPWM_GEN_INDEX_LOW],
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][BLDC_MCPWM_GEN_INDEX_LOW],
MCPWM_GEN_COMPARE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, comparators[i], MCPWM_GEN_ACTION_LOW)));
ESP_ERROR_CHECK(mcpwm_generator_set_action_on_brake_event(generators[i][BLDC_MCPWM_GEN_INDEX_LOW],
MCPWM_GEN_BRAKE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_CBC, MCPWM_GEN_ACTION_LOW)));
ESP_ERROR_CHECK(mcpwm_generator_set_action_on_brake_event(generators[i][BLDC_MCPWM_GEN_INDEX_LOW],
MCPWM_GEN_BRAKE_EVENT_ACTION(MCPWM_TIMER_DIRECTION_UP, MCPWM_OPER_BRAKE_MODE_CBC, MCPWM_GEN_ACTION_LOW)));
}
ESP_LOGI(TAG, "Setup deadtime");
@ -278,14 +291,14 @@ void app_main(void)
.flags.invert_output = true,
};
for (int i = 0; i < 3; i++) {
ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(generators[i][BLDC_MCPWM_GEN_INDEX_HIGH], generators[i][BLDC_MCPWM_GEN_INDEX_LOW], &dt_config));
ESP_ERROR_CHECK(mcpwm_generator_set_dead_time(generators[i][BLDC_MCPWM_GEN_INDEX_LOW], generators[i][BLDC_MCPWM_GEN_INDEX_LOW], &dt_config));
}
ESP_LOGI(TAG, "Turn off all the gates");
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
ESP_ERROR_CHECK(mcpwm_generator_set_force_level(generators[i][j], 0, true));
}
ESP_ERROR_CHECK(mcpwm_generator_set_force_level(generators[i][BLDC_MCPWM_GEN_INDEX_HIGH], 0, true));
// because gen_low is inverted by dead time module, so we need to set force level to 1
ESP_ERROR_CHECK(mcpwm_generator_set_force_level(generators[i][BLDC_MCPWM_GEN_INDEX_LOW], 1, true));
}
ESP_LOGI(TAG, "Create Hall sensor capture channels");