Skip to content

Commit

Permalink
Merge branch 'bugfix/mcpwm_bldc_example_v5.1' into 'release/v5.1'
Browse files Browse the repository at this point in the history
mcpwm: test generator force level with dead time module (v5.1)

See merge request espressif/esp-idf!23714
  • Loading branch information
suda-morris committed May 15, 2023
2 parents 6cfc6f5 + a7021c3 commit b7199e8
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 28 deletions.
1 change: 1 addition & 0 deletions components/driver/mcpwm/include/driver/mcpwm_gen.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
50 changes: 50 additions & 0 deletions components/driver/test_apps/mcpwm/main/test_mcpwm_gen.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -104,33 +106,33 @@ 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
// 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+ = 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
// 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);
}

// V+W-
static void bldc_set_phase_vp_wm(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+ = 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
// 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);
}

// U+W- / A+C-
Expand All @@ -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[] = {
Expand Down Expand Up @@ -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)));
Expand All @@ -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");
Expand All @@ -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");
Expand Down

0 comments on commit b7199e8

Please sign in to comment.