1
+
1
2
/*
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
54
97
*/
98
+
55
99
#include " ../../hardware_api.h"
56
100
57
101
#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){
195
239
196
240
// configuring center aligned pwm
197
241
// 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 ){
199
243
if (inverted)
200
- mcpwm_generator_set_actions_on_compare_event (gena,
244
+ return mcpwm_generator_set_actions_on_compare_event (gena,
201
245
MCPWM_GEN_COMPARE_EVENT_ACTION (MCPWM_TIMER_DIRECTION_UP, cmpa, MCPWM_GEN_ACTION_HIGH),
202
246
MCPWM_GEN_COMPARE_EVENT_ACTION (MCPWM_TIMER_DIRECTION_DOWN, cmpa, MCPWM_GEN_ACTION_LOW),
203
247
MCPWM_GEN_COMPARE_EVENT_ACTION_END ());
204
248
else
205
- mcpwm_generator_set_actions_on_compare_event (gena,
249
+ return mcpwm_generator_set_actions_on_compare_event (gena,
206
250
MCPWM_GEN_COMPARE_EVENT_ACTION (MCPWM_TIMER_DIRECTION_UP, cmpa, MCPWM_GEN_ACTION_LOW),
207
251
MCPWM_GEN_COMPARE_EVENT_ACTION (MCPWM_TIMER_DIRECTION_DOWN, cmpa, MCPWM_GEN_ACTION_HIGH),
208
252
MCPWM_GEN_COMPARE_EVENT_ACTION_END ());
@@ -247,6 +291,9 @@ void* _configure6PWMPinsMCPWM(long pwm_frequency, int mcpwm_group, int timer_no,
247
291
uint8_t no_operators = 3 ; // use 3 comparators one per pair of pwms
248
292
SIMPLEFOC_ESP32_DRV_DEBUG (" Configuring " + String (no_operators) + " operators." );
249
293
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 ;
250
297
for (int i = 0 ; i < no_operators; i++) {
251
298
CHECK_ERR (mcpwm_new_operator (&operator_config, ¶ms->oper [i])," Could not create operator " +String (i));
252
299
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,
263
310
CHECK_ERR (mcpwm_new_comparator (params->oper [i], &comparator_config, ¶ms->comparator [i])," Could not create comparator: " + String (i));
264
311
CHECK_ERR (mcpwm_comparator_set_compare_value (params->comparator [i], (0 )), " Could not set duty on comparator: " + String (i));
265
312
}
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
266
328
267
329
int no_generators = 6 ; // one per pwm
268
330
SIMPLEFOC_ESP32_DRV_DEBUG (" Configuring " + String (no_generators) + " generators." );
@@ -273,10 +335,14 @@ void* _configure6PWMPinsMCPWM(long pwm_frequency, int mcpwm_group, int timer_no,
273
335
int oper_index = (int )floor (i / 2 );
274
336
CHECK_ERR (mcpwm_new_generator (params->oper [oper_index], &generator_config, ¶ms->generator [i]), " Could not create generator " + String (i));
275
337
}
276
-
338
+
277
339
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
+
280
346
}
281
347
// only available for 6pwm
282
348
SIMPLEFOC_ESP32_DRV_DEBUG (" Configuring dead-time." );
@@ -289,37 +355,17 @@ void* _configure6PWMPinsMCPWM(long pwm_frequency, int mcpwm_group, int timer_no,
289
355
dt_config_low.posedge_delay_ticks = 0 ;
290
356
dt_config_low.negedge_delay_ticks = dead_time;
291
357
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++) {
293
359
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 ));
295
361
}
296
362
#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." );
318
363
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 ) );
321
366
}
322
367
#endif
368
+
323
369
SIMPLEFOC_ESP32_DRV_DEBUG (" Enabling timer: " +String (timer_no));
324
370
// Enable and start timer
325
371
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
389
435
uint8_t no_operators = ceil (no_pins / 2.0 );
390
436
SIMPLEFOC_ESP32_DRV_DEBUG (" Configuring " + String (no_operators) + " operators." );
391
437
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 ;
392
441
for (int i = 0 ; i < no_operators; i++) {
393
442
if (shared_timer && i == 0 ) { // first operator already configured
394
443
params->oper [0 ] = last_operator[mcpwm_group];
@@ -421,7 +470,7 @@ void* _configurePinsMCPWM(long pwm_frequency, int mcpwm_group, int timer_no, int
421
470
422
471
SIMPLEFOC_ESP32_DRV_DEBUG (" Configuring center-aligned pwm." );
423
472
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) );
425
474
}
426
475
427
476
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
446
495
447
496
// function setting the duty cycle to the MCPWM pin
448
497
void _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
452
501
mcpwm_generator_set_force_level (generator_high, (phase_state == PHASE_ON || phase_state == PHASE_HI) ? -1 : 0 , true );
453
502
mcpwm_generator_set_force_level (generator_low, (phase_state == PHASE_ON || phase_state == PHASE_LO) ? -1 : 1 , true );
454
503
}
0 commit comments