2
2
#include " ../../../drivers/hardware_api.h"
3
3
#include " ../../../drivers/hardware_specific/esp32/esp32_driver_mcpwm.h"
4
4
5
- #if defined(ESP_H) && defined(ARDUINO_ARCH_ESP32) && defined(SOC_MCPWM_SUPPORTED) && !defined(SIMPLEFOC_ESP32_USELEDC)
5
+ #if defined(ESP_H) && defined(ARDUINO_ARCH_ESP32) && defined(SOC_MCPWM_SUPPORTED) && !defined(SIMPLEFOC_ESP32_USELEDC) && 0
6
6
7
7
#include " esp32_adc_driver.h"
8
8
9
- #include " driver/mcpwm_prelude .h"
9
+ #include " driver/mcpwm .h"
10
10
#include " soc/mcpwm_reg.h"
11
11
#include " soc/mcpwm_struct.h"
12
+
12
13
#include < soc/sens_reg.h>
13
14
#include < soc/sens_struct.h>
14
- #include " esp_idf_version.h"
15
-
16
- // version check - this mcpwm driver is specific for ESP-IDF 5.x and arduino-esp32 3.x
17
- #if ESP_IDF_VERSION_MAJOR < 5
18
- #error SimpleFOC: ESP-IDF version 4 or lower detected. Please update to ESP-IDF 5.x and Arduino-esp32 3.0 (or higher)
19
- #endif
20
15
21
16
#define _ADC_VOLTAGE 3 .3f
22
17
#define _ADC_RESOLUTION 4095 .0f
23
18
24
- // set the pin 19 in high during the adc interrupt
25
- // #define SIMPLEFOC_ESP32_INTERRUPT_DEBUG
26
19
27
20
typedef struct ESP32MCPWMCurrentSenseParams {
28
21
int pins[3 ];
29
22
float adc_voltage_conv;
30
- int adc_buffer[3 ] = {};
31
- int buffer_index = 0 ;
32
- int no_adc_channels = 0 ;
23
+ mcpwm_unit_t mcpwm_unit;
24
+ int buffer_index;
33
25
} ESP32MCPWMCurrentSenseParams;
34
26
35
27
@@ -44,8 +36,8 @@ float _readADCVoltageInline(const int pinA, const void* cs_params){
44
36
45
37
// function reading an ADC value and returning the read voltage
46
38
void * _configureADCInline (const void * driver_params, const int pinA, const int pinB, const int pinC){
39
+ _UNUSED (driver_params);
47
40
48
- SIMPLEFOC_DEBUG (" ESP32-CS: Configuring ADC inline" );
49
41
if ( _isset (pinA) ) pinMode (pinA, INPUT);
50
42
if ( _isset (pinB) ) pinMode (pinB, INPUT);
51
43
if ( _isset (pinC) ) pinMode (pinC, INPUT);
@@ -59,15 +51,30 @@ void* _configureADCInline(const void* driver_params, const int pinA, const int p
59
51
}
60
52
61
53
54
+
55
+ /* *
56
+ * Low side adc reading implementation
57
+ */
58
+
59
+ static void IRAM_ATTR mcpwm0_isr_handler (void *);
60
+ static void IRAM_ATTR mcpwm1_isr_handler (void *);
61
+ byte currentState = 1 ;
62
+ // two mcpwm units
63
+ // - max 2 motors per mcpwm unit (6 adc channels)
64
+ int adc_pins[2 ][6 ]={0 };
65
+ int adc_pin_count[2 ]={0 };
66
+ uint32_t adc_buffer[2 ][6 ]={0 };
67
+ int adc_read_index[2 ]={0 };
68
+
62
69
// function reading an ADC value and returning the read voltage
63
70
float _readADCVoltageLowSide (const int pin, const void * cs_params){
64
- ESP32MCPWMCurrentSenseParams* p = (ESP32MCPWMCurrentSenseParams*)cs_params;
65
- int no_channel = 0 ;
66
- for ( int i= 0 ; i < 3 ; i++){
67
- if (! _isset (p-> pins [i])) continue ;
68
- if (pin == p-> pins [i]) // found in the buffer
69
- return p-> adc_buffer [no_channel] * p-> adc_voltage_conv ;
70
- else no_channel++ ;
71
+ mcpwm_unit_t unit = (( ESP32MCPWMCurrentSenseParams*)cs_params)-> mcpwm_unit ;
72
+ int buffer_index = ((ESP32MCPWMCurrentSenseParams*)cs_params)-> buffer_index ;
73
+ float adc_voltage_conv = ((ESP32MCPWMCurrentSenseParams*)cs_params)-> adc_voltage_conv ;
74
+
75
+ for ( int i= 0 ; i < adc_pin_count[unit]; i++){
76
+ if ( pin == ((ESP32MCPWMCurrentSenseParams*)cs_params)-> pins [i]) // found in the buffer
77
+ return adc_buffer[unit][buffer_index + i] * adc_voltage_conv ;
71
78
}
72
79
// not found
73
80
return 0 ;
@@ -76,68 +83,83 @@ float _readADCVoltageLowSide(const int pin, const void* cs_params){
76
83
// function configuring low-side current sensing
77
84
void * _configureADCLowSide (const void * driver_params, const int pinA,const int pinB,const int pinC){
78
85
79
- SIMPLEFOC_DEBUG (" ESP32-CS: Configuring ADC low-side" );
80
- // check if driver timer is already running
81
- // fail if it is
82
- // the easiest way that I've found to check if timer is running
83
- // is to start it and stop it
84
- ESP32MCPWMDriverParams *p = (ESP32MCPWMDriverParams*)driver_params;
85
- if (mcpwm_timer_start_stop (p->timers [0 ], MCPWM_TIMER_START_NO_STOP) != ESP_ERR_INVALID_STATE){
86
- // if we get the invalid state error it means that the timer is not enabled
87
- // that means that we can configure it for low-side current sensing
88
- SIMPLEFOC_DEBUG (" ESP32-CS: ERR - The timer is already enabled. Cannot be configured for low-side current sensing." );
89
- return SIMPLEFOC_CURRENT_SENSE_INIT_FAILED;
90
- }
86
+ mcpwm_unit_t unit = ((ESP32MCPWMDriverParams*)driver_params)->mcpwm_unit ;
87
+ int index_start = adc_pin_count[unit];
88
+ if ( _isset (pinA) ) adc_pins[unit][adc_pin_count[unit]++] = pinA;
89
+ if ( _isset (pinB) ) adc_pins[unit][adc_pin_count[unit]++] = pinB;
90
+ if ( _isset (pinC) ) adc_pins[unit][adc_pin_count[unit]++] = pinC;
91
91
92
+ if ( _isset (pinA) ) pinMode (pinA, INPUT);
93
+ if ( _isset (pinB) ) pinMode (pinB, INPUT);
94
+ if ( _isset (pinC) ) pinMode (pinC, INPUT);
92
95
93
- ESP32MCPWMCurrentSenseParams* params = new ESP32MCPWMCurrentSenseParams{};
94
- int no_adc_channels = 0 ;
95
- if ( _isset (pinA) ){
96
- pinMode (pinA, INPUT);
97
- params->pins [no_adc_channels++] = pinA;
98
- }
99
- if ( _isset (pinB) ){
100
- pinMode (pinB, INPUT);
101
- params->pins [no_adc_channels++] = pinB;
102
- }
103
- if ( _isset (pinC) ){
104
- pinMode (pinC, INPUT);
105
- params->pins [no_adc_channels++] = pinC;
106
- }
96
+ ESP32MCPWMCurrentSenseParams* params = new ESP32MCPWMCurrentSenseParams {
97
+ .pins = { pinA, pinB, pinC },
98
+ .adc_voltage_conv = (_ADC_VOLTAGE)/(_ADC_RESOLUTION),
99
+ .mcpwm_unit = unit,
100
+ .buffer_index = index_start
101
+ };
107
102
108
- params->adc_voltage_conv = (_ADC_VOLTAGE)/(_ADC_RESOLUTION);
109
- params->no_adc_channels = no_adc_channels;
110
103
return params;
111
104
}
112
105
113
106
114
107
void _driverSyncLowSide (void * driver_params, void * cs_params){
115
- #ifdef SIMPLEFOC_ESP32_INTERRUPT_DEBUG
116
- pinMode (19 , OUTPUT);
117
- #endif
118
- ESP32MCPWMDriverParams *p = (ESP32MCPWMDriverParams*)driver_params;
108
+
109
+ mcpwm_dev_t * mcpwm_dev = ((ESP32MCPWMDriverParams*)driver_params)->mcpwm_dev ;
110
+ mcpwm_unit_t mcpwm_unit = ((ESP32MCPWMDriverParams*)driver_params)->mcpwm_unit ;
111
+
112
+ // low-side register enable interrupt
113
+ mcpwm_dev->int_ena .timer0_tep_int_ena = true ;// A PWM timer 0 TEP event will trigger this interrupt
114
+ // high side registers enable interrupt
115
+ // mcpwm_dev->int_ena.timer0_tep_int_ena = true;//A PWM timer 0 TEZ event will trigger this interrupt
116
+
117
+ // register interrupts (mcpwm number, interrupt handler, handler argument = NULL, interrupt signal/flag, return handler = NULL)
118
+ if (mcpwm_unit == MCPWM_UNIT_0)
119
+ mcpwm_isr_register (mcpwm_unit, mcpwm0_isr_handler, NULL , ESP_INTR_FLAG_IRAM, NULL ); // Set ISR Handler
120
+ else
121
+ mcpwm_isr_register (mcpwm_unit, mcpwm1_isr_handler, NULL , ESP_INTR_FLAG_IRAM, NULL ); // Set ISR Handler
122
+ }
123
+
124
+ static void IRAM_ATTR mcpwm0_isr_handler (void *) __attribute__ ((unused));
125
+
126
+ // Read currents when interrupt is triggered
127
+ static void IRAM_ATTR mcpwm0_isr_handler (void *){
128
+ // // high side
129
+ // uint32_t mcpwm_intr_status = MCPWM0.int_st.timer0_tez_int_st;
119
130
120
- mcpwm_timer_event_callbacks_t cbs_timer = {
121
- .on_full = [](mcpwm_timer_handle_t tim, const mcpwm_timer_event_data_t * edata, void * user_data){
122
- ESP32MCPWMCurrentSenseParams *p = (ESP32MCPWMCurrentSenseParams*)user_data;
123
- #ifdef SIMPLEFOC_ESP32_INTERRUPT_DEBUG
124
- digitalWrite (19 , HIGH);
125
- #endif
126
- // increment buffer index
127
- p->buffer_index = (p->buffer_index + 1 ) % p->no_adc_channels ;
128
- // sample the phase currents one at a time
129
- p->adc_buffer [p->buffer_index ] = adcRead (p->pins [p->buffer_index ]);
130
- #ifdef SIMPLEFOC_ESP32_INTERRUPT_DEBUG
131
- digitalWrite (19 , LOW);
132
- #endif
133
- return true ;
134
- }
135
- };
136
- if (mcpwm_timer_register_event_callbacks (p->timers [0 ], &cbs_timer, cs_params) != ESP_OK){
137
- SIMPLEFOC_DEBUG (" ESP32-CS: ERR - Failed to sync ADC and driver" );
138
- }
131
+ // low side
132
+ uint32_t mcpwm_intr_status = MCPWM0.int_st .timer0_tep_int_st ;
133
+ if (mcpwm_intr_status){
134
+ adc_buffer[0 ][adc_read_index[0 ]] = adcRead (adc_pins[0 ][adc_read_index[0 ]]);
135
+ adc_read_index[0 ]++;
136
+ if (adc_read_index[0 ] == adc_pin_count[0 ]) adc_read_index[0 ] = 0 ;
137
+ }
138
+ // low side
139
+ MCPWM0.int_clr .timer0_tep_int_clr = mcpwm_intr_status;
140
+ // high side
141
+ // MCPWM0.int_clr.timer0_tez_int_clr = mcpwm_intr_status_0;
139
142
}
140
143
144
+ static void IRAM_ATTR mcpwm1_isr_handler (void *) __attribute__ ((unused));
145
+
146
+ // Read currents when interrupt is triggered
147
+ static void IRAM_ATTR mcpwm1_isr_handler (void *){
148
+ // // high side
149
+ // uint32_t mcpwm_intr_status = MCPWM1.int_st.timer0_tez_int_st;
150
+
151
+ // low side
152
+ uint32_t mcpwm_intr_status = MCPWM1.int_st .timer0_tep_int_st ;
153
+ if (mcpwm_intr_status){
154
+ adc_buffer[1 ][adc_read_index[1 ]] = adcRead (adc_pins[1 ][adc_read_index[1 ]]);
155
+ adc_read_index[1 ]++;
156
+ if (adc_read_index[1 ] == adc_pin_count[1 ]) adc_read_index[1 ] = 0 ;
157
+ }
158
+ // low side
159
+ MCPWM1.int_clr .timer0_tep_int_clr = mcpwm_intr_status;
160
+ // high side
161
+ // MCPWM1.int_clr.timer0_tez_int_clr = mcpwm_intr_status_0;
162
+ }
141
163
142
164
143
165
#endif
0 commit comments