Skip to content

Commit bbd8017

Browse files
committed
added the support for phase state for 6pwm in haredware-6pwm mode + returning error if no low-side
1 parent 69eb707 commit bbd8017

File tree

3 files changed

+145
-90
lines changed

3 files changed

+145
-90
lines changed

src/current_sense/hardware_specific/generic_mcu.cpp

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "../hardware_api.h"
2+
#include "../../communication/SimpleFOCDebug.h"
23

34
// function reading an ADC value and returning the read voltage
45
__attribute__((weak)) float _readADCVoltageInline(const int pinA, const void* cs_params){
@@ -24,18 +25,23 @@ __attribute__((weak)) void* _configureADCInline(const void* driver_params, cons
2425

2526
// function reading an ADC value and returning the read voltage
2627
__attribute__((weak)) float _readADCVoltageLowSide(const int pinA, const void* cs_params){
27-
return _readADCVoltageInline(pinA, cs_params);
28+
SIMPLEFOC_DEBUG("ERR: Low-side cs not supported!");
29+
return 0.0;
2830
}
2931

3032
// Configure low side for generic mcu
3133
// cannot do much but
3234
__attribute__((weak)) void* _configureADCLowSide(const void* driver_params, const int pinA,const int pinB,const int pinC){
33-
return _configureADCInline(driver_params, pinA, pinB, pinC);
35+
SIMPLEFOC_DEBUG("ERR: Low-side cs not supported!");
36+
return SIMPLEFOC_CURRENT_SENSE_INIT_FAILED;
3437
}
3538

3639
// sync driver and the adc
3740
__attribute__((weak)) void* _driverSyncLowSide(void* driver_params, void* cs_params){
3841
_UNUSED(driver_params);
3942
return cs_params;
4043
}
44+
45+
// function starting the ADC conversion for the high side current sensing
46+
// only necessary for certain types of MCUs
4147
__attribute__((weak)) void _startADC3PinConversionLowSide(){ }

src/drivers/hardware_specific/esp32/esp32_driver_mcpwm.cpp

+136-87
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,101 @@
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, &params->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, &params->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, &params->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, &params->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, &params->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, &params->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
448497
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
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
}

src/drivers/hardware_specific/esp32/esp32_driver_mcpwm.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ int _findBestGroup(int no_pins, long pwm_freq, int* group, int* timer);
103103
* @param cmpa - mcpwm comparator handle
104104
* @param inverted - true if the signal is inverted, false otherwise
105105
*/
106-
void _configureCenterAlign(mcpwm_gen_handle_t gena, mcpwm_cmpr_handle_t cmpa, bool inverted);
106+
int _configureCenterAlign(mcpwm_gen_handle_t gena, mcpwm_cmpr_handle_t cmpa, bool inverted);
107107

108108
/**
109109
* function calculating the pwm period

0 commit comments

Comments
 (0)