1+
12/*
2- * MCPWM in Espressif v5.x has
3- * - 2x groups (units)
4- * each one has
5- * - 3 timers
6- * - 3 operators (that can be associated with any timer)
7- * which control a 2xPWM signals
8- * - 1x comparator + 1x generator per PWM signal for independent mode
9- * - 1x comparator + 2x generator per pair or PWM signals for complementary mode
10- *
11- * Independent mode:
12- * ------------------
13- * 6 PWM independent signals per unit
14- * unit(0/1) > timer(0-2) > operator(0-2) > comparator(0-1) > generator(0-1) > pwm(A/B)
15- *
16- * group | timer | operator | comparator | generator | pwm
17- * --------------------------------------------------------------------------------
18- * 0-1 | 0-2 | 0 | 0 | 0 | A
19- * 0-1 | 0-2 | 0 | 1(0 complementary) | 1 | B
20- * 0-1 | 0-2 | 1 | 0 | 0 | A
21- * 0-1 | 0-2 | 1 | 1(0 complementary) | 1 | B
22- * 0-1 | 0-2 | 2 | 0 | 0 | A
23- * 0-1 | 0-2 | 2 | 1(0 complementary) | 1 | B
24- *
25- * Complementary mode
26- * ------------------
27- * - : 3 pairs of complementary PWM signals per unit
28- * unit(0/1) > timer(0) > operator(0-2) > comparator(0) > generator(0-1) > pwm(A-B pair)
29- *
30- * group | timer | operator | comparator | generator | pwm
31- * ------------------------------------------------------------------------
32- * 0-1 | 0 | 0 | 0 | 0 | A
33- * 0-1 | 0 | 0 | 0 | 1 | B
34- * 0-1 | 0 | 1 | 0 | 0 | A
35- * 0-1 | 0 | 1 | 0 | 1 | B
36- * 0-1 | 0 | 2 | 0 | 0 | A
37- * 0-1 | 0 | 2 | 0 | 1 | B
38- *
39- * More info
40- * ----------
41- * - timers can be associated with any operator, and multiple operators can be associated with the same timer
42- * - comparators can be associated with any operator
43- * - two comparators per operator for independent mode
44- * - one comparator per operator for complementary mode
45- * - generators can be associated with any comparator
46- * - one generator per PWM signal for independent mode
47- * - two generators per pair of PWM signals for complementary mode
48- * - dead-time can be set for each generator pair in complementary mode
49- *
50- * Docs
51- * -------
52- * More info here: https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf#mcpwm
53- * and here: // https://docs.espressif.com/projects/esp-idf/en/v5.1.4/esp32/migration-guides/release-5.x/5.0/peripherals.html
3+ * MCPWM in espressif v5.x has
4+ * - 2x groups (units)
5+ * each one has
6+ * - 3 timers
7+ * - 3 operators (that can be associated with any timer)
8+ * which control a 2xPWM signals
9+ * - 1x comparator + 1x generator per PWM signal
10+
11+
12+ * Independent mode:
13+ * ------------------
14+ * 6 PWM independent signals per unit
15+ * unit(0/1) > timer(0-2) > operator(0-2) > comparator(0-1) > generator(0-1) > pwm(A/B)
16+ *
17+ * -------------------------------------- Table View -----------------------------
18+ *
19+ * group | timer | operator | comparator | generator | pwm
20+ * --------------------------------------------------------------------------------
21+ * 0-1 | 0-2 | 0 | 0 | 0 | A
22+ * 0-1 | 0-2 | 0 | 1 | 1 | B
23+ * 0-1 | 0-2 | 1 | 0 | 0 | A
24+ * 0-1 | 0-2 | 1 | 1 | 1 | B
25+ * 0-1 | 0-2 | 2 | 0 | 0 | A
26+ * 0-1 | 0-2 | 2 | 1 | 1 | B
27+ *
28+ * ------------------------------------- Example 3PWM ------------------------------
29+ * ┌─ comparator 0 - generator 0 -> pwm A
30+ * ┌─ operator 0 -|
31+ * | └─ comparator 1 - generator 1 -> pmw B
32+ * unit - timer 0-2 -|
33+ * 0-1 └─ operator 1 - comparator 0 - generator 0 - pwm C
34+ *
35+ * ------------------------------------- Example 2PWM ------------------------------
36+ * ┌─ comparator 0 - generator 0 -> pwm A
37+ * unit - timer 0-2 - operator 0 -|
38+ * 0-1 └─ comparator 1 - generator 1 -> pmw B
39+ *
40+ * -------------------------------------- Example 4PWM -----------------------------
41+ * ┌─ comparator 0 - generator 0 -> pwm A
42+ * ┌─ operator 0 -|
43+ * | └─ comparator 1 - generator 1 -> pmw B
44+ * unit - timer 0-2 -|
45+ * 0-1 | ┌─ comparator 0 - generator 0 -> pwm C
46+ * └─ operator 1 -|
47+ * └─ comparator 0 - generator 0 -> pwm D
48+
49+
50+ * Complementary mode
51+ * ------------------
52+ * - : 3 pairs of complementary PWM signals per unit
53+ * unit(0/1) > timer(0) > operator(0-2) > comparator(0-1) > generator(0-1) > pwm(high/low pair)
54+ *
55+ * -------------------------------------- Table View -----------------------------
56+ *
57+ * group | timer | operator | comparator | generator | pwm
58+ * ------------------------------------------------------------------------
59+ * 0-1 | 0 | 0 | 0 | 0 | A
60+ * 0-1 | 0 | 0 | 1 | 1 | B
61+ * 0-1 | 0 | 1 | 0 | 0 | A
62+ * 0-1 | 0 | 1 | 1 | 1 | B
63+ * 0-1 | 0 | 2 | 0 | 0 | A
64+ * 0-1 | 0 | 2 | 1 | 1 | B
65+ *
66+ * -------------------------------------- Example 6PWM -----------------------------
67+ *
68+ * ┌─ comparator 0 - generator 0 -> pwm A_h
69+ * ┌─ operator 0 -|
70+ * | └─ comparator 1 - generator 1 -> pmw A_l
71+ * |
72+ * unit | ┌─ comparator 0 - generator 0 -> pwm B_h
73+ * (group) - timer 0 -|- operator 1 -|
74+ * 0-1 | └─ comparator 1 - generator 1 -> pmw B_l
75+ * |
76+ * | ┌─ comparator 0 - generator 0 -> pwm C_h
77+ * └─ operator 2 -|
78+ * └─ comparator 1 - generator 1 -> pmw C_l
79+ *
80+
81+
82+ * More info
83+ * ----------
84+ * - timers can be associated with any operator, and multiple operators can be associated with the same timer
85+ * - comparators can be associated with any operator
86+ * - two comparators per operator for independent mode
87+ * - one comparator per operator for complementary mode
88+ * - generators can be associated with any comparator
89+ * - one generator per PWM signal for independent mode
90+ * - two generators per pair of PWM signals for complementary mode (not used in simplefoc)
91+ * - dead-time can be set for each generator pair in complementary mode
92+ *
93+ * Docs
94+ * -------
95+ * More info here: https:*www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf#mcpwm
96+ * and here: // https://docs.espressif.com/projects/esp-idf/en/v5.1.4/esp32/migration-guides/release-5.x/5.0/peripherals.html
5497*/
98+
5599#include " ../../hardware_api.h"
56100
57101#if defined(ESP_H) && defined(ARDUINO_ARCH_ESP32) && defined(SOC_MCPWM_SUPPORTED) && !defined(SIMPLEFOC_ESP32_USELEDC)
@@ -195,14 +239,14 @@ int _findBestGroup(int no_pins, long pwm_freq, int* group, int* timer){
195239
196240// configuring center aligned pwm
197241// More info here: https://docs.espressif.com/projects/esp-idf/en/v5.1.4/esp32/api-reference/peripherals/mcpwm.html#symmetric-dual-edge-active-low
198- void _configureCenterAlign (mcpwm_gen_handle_t gena, mcpwm_cmpr_handle_t cmpa, bool inverted = false ){
242+ int _configureCenterAlign (mcpwm_gen_handle_t gena, mcpwm_cmpr_handle_t cmpa, bool inverted = false ){
199243 if (inverted)
200- mcpwm_generator_set_actions_on_compare_event (gena,
244+ return mcpwm_generator_set_actions_on_compare_event (gena,
201245 MCPWM_GEN_COMPARE_EVENT_ACTION (MCPWM_TIMER_DIRECTION_UP, cmpa, MCPWM_GEN_ACTION_HIGH),
202246 MCPWM_GEN_COMPARE_EVENT_ACTION (MCPWM_TIMER_DIRECTION_DOWN, cmpa, MCPWM_GEN_ACTION_LOW),
203247 MCPWM_GEN_COMPARE_EVENT_ACTION_END ());
204248 else
205- mcpwm_generator_set_actions_on_compare_event (gena,
249+ return mcpwm_generator_set_actions_on_compare_event (gena,
206250 MCPWM_GEN_COMPARE_EVENT_ACTION (MCPWM_TIMER_DIRECTION_UP, cmpa, MCPWM_GEN_ACTION_LOW),
207251 MCPWM_GEN_COMPARE_EVENT_ACTION (MCPWM_TIMER_DIRECTION_DOWN, cmpa, MCPWM_GEN_ACTION_HIGH),
208252 MCPWM_GEN_COMPARE_EVENT_ACTION_END ());
@@ -247,6 +291,9 @@ void* _configure6PWMPinsMCPWM(long pwm_frequency, int mcpwm_group, int timer_no,
247291 uint8_t no_operators = 3 ; // use 3 comparators one per pair of pwms
248292 SIMPLEFOC_ESP32_DRV_DEBUG (" Configuring " + String (no_operators) + " operators." );
249293 mcpwm_operator_config_t operator_config = { .group_id = mcpwm_group };
294+ operator_config.intr_priority = 0 ;
295+ operator_config.flags .update_gen_action_on_tep = true ;
296+ operator_config.flags .update_gen_action_on_tez = true ;
250297 for (int i = 0 ; i < no_operators; i++) {
251298 CHECK_ERR (mcpwm_new_operator (&operator_config, ¶ms->oper [i])," Could not create operator " +String (i));
252299 CHECK_ERR (mcpwm_operator_connect_timer (params->oper [i], params->timers [0 ])," Could not connect timer to operator: " + String (i));
@@ -263,6 +310,21 @@ void* _configure6PWMPinsMCPWM(long pwm_frequency, int mcpwm_group, int timer_no,
263310 CHECK_ERR (mcpwm_new_comparator (params->oper [i], &comparator_config, ¶ms->comparator [i])," Could not create comparator: " + String (i));
264311 CHECK_ERR (mcpwm_comparator_set_compare_value (params->comparator [i], (0 )), " Could not set duty on comparator: " + String (i));
265312 }
313+
314+ #else // software dead-time (software 6pwm)
315+ // software dead-time (software 6pwm)
316+ SIMPLEFOC_ESP32_DRV_DEBUG (" Configuring 6PWM with software dead-time" );
317+
318+ int no_pins = 6 ;
319+ SIMPLEFOC_ESP32_DRV_DEBUG (" Configuring " + String (no_pins) + " comparators." );
320+ // Create and configure comparators
321+ mcpwm_comparator_config_t comparator_config = {0 };
322+ for (int i = 0 ; i < no_pins; i++) {
323+ int oper_index = (int )floor (i / 2 );
324+ CHECK_ERR (mcpwm_new_comparator (params->oper [oper_index], &comparator_config, ¶ms->comparator [i])," Could not create comparator: " + String (i));
325+ CHECK_ERR (mcpwm_comparator_set_compare_value (params->comparator [i], (0 )), " Could not set duty on comparator: " + String (i));
326+ }
327+ #endif
266328
267329 int no_generators = 6 ; // one per pwm
268330 SIMPLEFOC_ESP32_DRV_DEBUG (" Configuring " + String (no_generators) + " generators." );
@@ -273,10 +335,14 @@ void* _configure6PWMPinsMCPWM(long pwm_frequency, int mcpwm_group, int timer_no,
273335 int oper_index = (int )floor (i / 2 );
274336 CHECK_ERR (mcpwm_new_generator (params->oper [oper_index], &generator_config, ¶ms->generator [i]), " Could not create generator " + String (i));
275337 }
276-
338+
277339 SIMPLEFOC_ESP32_DRV_DEBUG (" Configuring Center-Aligned 6 pwm." );
278- for (int i = 0 ; i < 3 ; i++) {
279- _configureCenterAlign (params->generator [2 *i],params->comparator [i]);
340+
341+ #if SIMPLEFOC_ESP32_HW_DEADTIME == true // hardware dead-time (hardware 6pwm)
342+ for (int i = 0 ; i < no_operators; i++) {
343+ CHECK_ERR (_configureCenterAlign (params->generator [2 *i],params->comparator [i]), " Failed to configure high-side center align pwm: " + String (2 *i));
344+ CHECK_ERR (_configureCenterAlign (params->generator [2 *i+1 ],params->comparator [i]), " Failed to configure low-side center align pwm: " + String (2 *i+1 ));
345+
280346 }
281347 // only available for 6pwm
282348 SIMPLEFOC_ESP32_DRV_DEBUG (" Configuring dead-time." );
@@ -289,37 +355,17 @@ void* _configure6PWMPinsMCPWM(long pwm_frequency, int mcpwm_group, int timer_no,
289355 dt_config_low.posedge_delay_ticks = 0 ;
290356 dt_config_low.negedge_delay_ticks = dead_time;
291357 dt_config_low.flags .invert_output = SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH;
292- for (int i = 0 ; i < 3 ; i++) {
358+ for (int i = 0 ; i < no_operators ; i++) {
293359 CHECK_ERR (mcpwm_generator_set_dead_time (params->generator [2 *i], params->generator [2 *i], &dt_config_high)," Could not set dead time for generator: " + String (i));
294- CHECK_ERR (mcpwm_generator_set_dead_time (params->generator [2 *i], params->generator [2 *i+1 ], &dt_config_low)," Could not set dead time for generator: " + String (i+1 ));
360+ CHECK_ERR (mcpwm_generator_set_dead_time (params->generator [2 *i+ 1 ], params->generator [2 *i+1 ], &dt_config_low)," Could not set dead time for generator: " + String (i+1 ));
295361 }
296362#else // software dead-time (software 6pwm)
297- SIMPLEFOC_ESP32_DRV_DEBUG (" Configuring 6PWM with software dead-time" );
298- int no_pins = 6 ;
299- SIMPLEFOC_ESP32_DRV_DEBUG (" Configuring " + String (no_pins) + " comparators." );
300- // Create and configure comparators
301- mcpwm_comparator_config_t comparator_config = {0 };
302- for (int i = 0 ; i < no_pins; i++) {
303- int oper_index = (int )floor (i / 2 );
304- CHECK_ERR (mcpwm_new_comparator (params->oper [oper_index], &comparator_config, ¶ms->comparator [i])," Could not create comparator: " + String (i));
305- CHECK_ERR (mcpwm_comparator_set_compare_value (params->comparator [i], (0 )), " Could not set duty on comparator: " + String (i));
306- }
307-
308- SIMPLEFOC_ESP32_DRV_DEBUG (" Configuring " + String (no_pins) + " generators." );
309- // Create and configure generators;
310- mcpwm_generator_config_t generator_config = {};
311- for (int i = 0 ; i < no_pins; i++) {
312- generator_config.gen_gpio_num = pins[i];
313- int oper_index = (int )floor (i / 2 );
314- CHECK_ERR (mcpwm_new_generator (params->oper [oper_index], &generator_config, ¶ms->generator [i]), " Could not create generator " + String (i));
315- }
316-
317- SIMPLEFOC_ESP32_DRV_DEBUG (" Configuring center-aligned pwm." );
318363 for (int i = 0 ; i < 3 ; i++) {
319- _configureCenterAlign (params->generator [2 *i],params->comparator [2 *i], !SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH);
320- _configureCenterAlign (params->generator [2 *i+1 ],params->comparator [2 *i+1 ], SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH);
364+ CHECK_ERR ( _configureCenterAlign (params->generator [2 *i],params->comparator [2 *i], !SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH), " Failed to configure high-side center align pwm: " + String ( 2 *i));
365+ CHECK_ERR ( _configureCenterAlign (params->generator [2 *i+1 ],params->comparator [2 *i+1 ], SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH) , " Failed to configure low-side center align pwm: " + String ( 2 *i+ 1 ) );
321366 }
322367#endif
368+
323369 SIMPLEFOC_ESP32_DRV_DEBUG (" Enabling timer: " +String (timer_no));
324370 // Enable and start timer
325371 CHECK_ERR (mcpwm_timer_enable (params->timers [0 ]), " Failed to enable timer!" );
@@ -389,6 +435,9 @@ void* _configurePinsMCPWM(long pwm_frequency, int mcpwm_group, int timer_no, int
389435 uint8_t no_operators = ceil (no_pins / 2.0 );
390436 SIMPLEFOC_ESP32_DRV_DEBUG (" Configuring " + String (no_operators) + " operators." );
391437 mcpwm_operator_config_t operator_config = { .group_id = mcpwm_group };
438+ operator_config.intr_priority = 0 ;
439+ operator_config.flags .update_gen_action_on_tep = true ;
440+ operator_config.flags .update_gen_action_on_tez = true ;
392441 for (int i = 0 ; i < no_operators; i++) {
393442 if (shared_timer && i == 0 ) { // first operator already configured
394443 params->oper [0 ] = last_operator[mcpwm_group];
@@ -421,7 +470,7 @@ void* _configurePinsMCPWM(long pwm_frequency, int mcpwm_group, int timer_no, int
421470
422471 SIMPLEFOC_ESP32_DRV_DEBUG (" Configuring center-aligned pwm." );
423472 for (int i = 0 ; i < no_pins; i++) {
424- _configureCenterAlign (params->generator [i],params->comparator [i], !SIMPLEFOC_PWM_ACTIVE_HIGH);
473+ CHECK_ERR ( _configureCenterAlign (params->generator [i],params->comparator [i], !SIMPLEFOC_PWM_ACTIVE_HIGH), " Failed to configure center align pwm: " + String (i) );
425474 }
426475
427476 SIMPLEFOC_ESP32_DRV_DEBUG (" Enabling timer: " +String (timer_no));
@@ -446,9 +495,9 @@ void _setDutyCycle(mcpwm_cmpr_handle_t cmpr, uint32_t mcpwm_period, float duty_c
446495
447496// function setting the duty cycle to the MCPWM pin
448497void _forcePhaseState (mcpwm_gen_handle_t generator_high, mcpwm_gen_handle_t generator_low, PhaseState phase_state){
449- // phase state can be forced
450- // https://docs.espressif.com/projects/esp-idf/en/v5.1.4/esp32/api-reference/peripherals/mcpwm.html#generator-force-actions
451- // TODO verify with ACTIVE_HIGH/ACTIVE_LOW flags
498+ // phase state is forced in hardware pwm mode
499+ // esp-idf docs: https://docs.espressif.com/projects/esp-idf/en/v5.1.4/esp32/api-reference/peripherals/mcpwm.html#generator-force-actions
500+ // github issue: https://github.com/espressif/esp-idf/issues/12237
452501 mcpwm_generator_set_force_level (generator_high, (phase_state == PHASE_ON || phase_state == PHASE_HI) ? -1 : 0 , true );
453502 mcpwm_generator_set_force_level (generator_low, (phase_state == PHASE_ON || phase_state == PHASE_LO) ? -1 : 1 , true );
454503}
0 commit comments