Skip to content

Commit 5d4187a

Browse files
committed
added the current sensing + phase state for driver
1 parent aa8591e commit 5d4187a

22 files changed

+390
-225
lines changed

src/current_sense/LowsideCurrentSense.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ int LowsideCurrentSense::init(){
4747
// if init failed return fail
4848
if (params == SIMPLEFOC_CURRENT_SENSE_INIT_FAILED) return 0;
4949
// sync the driver
50-
_driverSyncLowSide(driver->params, params);
50+
void* r = _driverSyncLowSide(driver->params, params);
51+
if(r == SIMPLEFOC_CURRENT_SENSE_INIT_FAILED) return 0;
5152
// calibrate zero offsets
5253
calibrateOffsets();
5354
// set the initialized flag

src/current_sense/hardware_api.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ float _readADCVoltageLowSide(const int pinA, const void* cs_params);
5959
* function syncing the Driver with the ADC for the LowSide Sensing
6060
* @param driver_params - driver parameter structure - hardware specific
6161
* @param cs_params - current sense parameter structure - hardware specific
62+
*
63+
* @return void* - returns the pointer to the current sense parameter structure (unchanged)
64+
* - returns SIMPLEFOC_CURRENT_SENSE_INIT_FAILED if the init fails
6265
*/
63-
void _driverSyncLowSide(void* driver_params, void* cs_params);
66+
void* _driverSyncLowSide(void* driver_params, void* cs_params);
6467

6568
#endif

src/current_sense/hardware_specific/esp32/esp32_adc_driver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include "esp32_adc_driver.h"
22

3-
#if defined(ESP_H) && defined(ARDUINO_ARCH_ESP32) && defined(SOC_MCPWM_SUPPORTED) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(SIMPLEFOC_ESP32_USELEDC) && 0
3+
#if defined(ESP_H) && defined(ARDUINO_ARCH_ESP32) && defined(SOC_MCPWM_SUPPORTED) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(SIMPLEFOC_ESP32_USELEDC)
44

55
#include "freertos/FreeRTOS.h"
66
#include "freertos/task.h"

src/current_sense/hardware_specific/esp32/esp32_adc_driver.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
#include "Arduino.h"
77

8-
#if defined(ESP_H) && defined(ARDUINO_ARCH_ESP32) && defined(SOC_MCPWM_SUPPORTED) && !defined(SIMPLEFOC_ESP32_USELEDC) && 0
8+
#if defined(ESP_H) && defined(ARDUINO_ARCH_ESP32) && defined(SOC_MCPWM_SUPPORTED) && !defined(SIMPLEFOC_ESP32_USELEDC)
99
/*
1010
* Get ADC value for pin
1111
* */
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
#include "../../hardware_api.h"
2+
#include "../../../drivers/hardware_api.h"
3+
#include "../../../drivers/hardware_specific/esp32/esp32_driver_mcpwm.h"
4+
#include "../../../drivers/hardware_specific/esp32/mcpwm_private.h"
5+
6+
#if defined(ESP_H) && defined(ARDUINO_ARCH_ESP32) && defined(SOC_MCPWM_SUPPORTED) && !defined(SIMPLEFOC_ESP32_USELEDC)
7+
8+
// check the version of the ESP-IDF
9+
#include "esp_idf_version.h"
10+
11+
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
12+
#error SimpleFOC: ESP-IDF version 4 or lower detected. Please update to ESP-IDF 5.x and Arduino-esp32 3.0 (or higher)
13+
#endif
14+
15+
16+
#include "esp32_adc_driver.h"
17+
18+
#include "driver/mcpwm_prelude.h"
19+
#include "soc/mcpwm_reg.h"
20+
#include "soc/mcpwm_struct.h"
21+
22+
#include <soc/sens_reg.h>
23+
#include <soc/sens_struct.h>
24+
25+
#ifdef SIMPLEFOC_ESP32_INTERRUPT_DEBUG
26+
#include "driver/gpio.h"
27+
#endif
28+
29+
#define _ADC_VOLTAGE 3.3f
30+
#define _ADC_RESOLUTION 4095.0f
31+
32+
33+
34+
#define SIMPLEFOC_ESP32_CS_DEBUG(str)\
35+
SIMPLEFOC_ESP32_DEBUG("CS", str);\
36+
37+
#define CHECK_CS_ERR(func_call, message) \
38+
if ((func_call) != ESP_OK) { \
39+
SIMPLEFOC_ESP32_CS_DEBUG("ERROR - " + String(message)); \
40+
return SIMPLEFOC_CURRENT_SENSE_INIT_FAILED; \
41+
}
42+
43+
typedef struct ESP32MCPWMCurrentSenseParams {
44+
int pins[3];
45+
float adc_voltage_conv;
46+
int adc_buffer[3] = {};
47+
int buffer_index = 0;
48+
int no_adc_channels = 0;
49+
} ESP32MCPWMCurrentSenseParams;
50+
51+
52+
/**
53+
* Inline adc reading implementation
54+
*/
55+
// function reading an ADC value and returning the read voltage
56+
float _readADCVoltageInline(const int pinA, const void* cs_params){
57+
uint32_t raw_adc = adcRead(pinA);
58+
return raw_adc * ((ESP32MCPWMCurrentSenseParams*)cs_params)->adc_voltage_conv;
59+
}
60+
61+
// function reading an ADC value and returning the read voltage
62+
void* _configureADCInline(const void* driver_params, const int pinA, const int pinB, const int pinC){
63+
64+
65+
if( _isset(pinA) ) pinMode(pinA, INPUT);
66+
if( _isset(pinB) ) pinMode(pinB, INPUT);
67+
if( _isset(pinC) ) pinMode(pinC, INPUT);
68+
69+
ESP32MCPWMCurrentSenseParams* params = new ESP32MCPWMCurrentSenseParams {
70+
.pins = { pinA, pinB, pinC },
71+
.adc_voltage_conv = (_ADC_VOLTAGE)/(_ADC_RESOLUTION)
72+
};
73+
74+
return params;
75+
}
76+
77+
78+
/**
79+
* Low side adc reading implementation
80+
*/
81+
82+
83+
// function reading an ADC value and returning the read voltage
84+
float _readADCVoltageLowSide(const int pin, const void* cs_params){
85+
ESP32MCPWMCurrentSenseParams* p = (ESP32MCPWMCurrentSenseParams*)cs_params;
86+
int no_channel = 0;
87+
for(int i=0; i < 3; i++){
88+
if(!_isset(p->pins[i])) continue;
89+
if(pin == p->pins[i]) // found in the buffer
90+
return p->adc_buffer[no_channel] * p->adc_voltage_conv;
91+
else no_channel++;
92+
}
93+
// not found
94+
return 0;
95+
}
96+
97+
98+
// function configuring low-side current sensing
99+
void* _configureADCLowSide(const void* driver_params, const int pinA,const int pinB,const int pinC){
100+
// check if driver timer is already running
101+
// fail if it is
102+
// the easiest way that I've found to check if timer is running
103+
// is to start it and stop it
104+
ESP32MCPWMDriverParams *p = (ESP32MCPWMDriverParams*)driver_params;
105+
mcpwm_timer_t* t = (mcpwm_timer_t*) p->timers[0];
106+
107+
// check if low side callback is already set
108+
// if it is, return error
109+
if(t->on_full != nullptr){
110+
SIMPLEFOC_ESP32_CS_DEBUG("Low side callback is already set. Cannot set it again for timer: "+String(t->timer_id)+", group: "+String(t->group->group_id));
111+
return SIMPLEFOC_CURRENT_SENSE_INIT_FAILED;
112+
}
113+
114+
ESP32MCPWMCurrentSenseParams* params = new ESP32MCPWMCurrentSenseParams{};
115+
int no_adc_channels = 0;
116+
if( _isset(pinA) ){
117+
pinMode(pinA, INPUT);
118+
params->pins[no_adc_channels++] = pinA;
119+
}
120+
if( _isset(pinB) ){
121+
pinMode(pinB, INPUT);
122+
params->pins[no_adc_channels++] = pinB;
123+
}
124+
if( _isset(pinC) ){
125+
pinMode(pinC, INPUT);
126+
params->pins[no_adc_channels++] = pinC;
127+
}
128+
129+
t->user_data = params;
130+
params->adc_voltage_conv = (_ADC_VOLTAGE)/(_ADC_RESOLUTION);
131+
params->no_adc_channels = no_adc_channels;
132+
return params;
133+
}
134+
135+
void* _driverSyncLowSide(void* driver_params, void* cs_params){
136+
#ifdef SIMPLEFOC_ESP32_INTERRUPT_DEBUG
137+
pinMode(19, OUTPUT);
138+
#endif
139+
ESP32MCPWMDriverParams *p = (ESP32MCPWMDriverParams*)driver_params;
140+
mcpwm_timer_t* t = (mcpwm_timer_t*) p->timers[0];
141+
142+
// check if low side callback is already set
143+
// if it is, return error
144+
if(t->on_full != nullptr){
145+
SIMPLEFOC_ESP32_CS_DEBUG("Low side callback is already set. Cannot set it again for timer: "+String(t->timer_id)+", group: "+String(t->group->group_id));
146+
return SIMPLEFOC_CURRENT_SENSE_INIT_FAILED;
147+
}
148+
149+
// set the callback for the low side current sensing
150+
// mcpwm_timer_event_callbacks_t can be used to set the callback
151+
// for three timer events
152+
// - on_full - low-side
153+
// - on_empty - high-side
154+
// - on_sync - sync event (not used with simplefoc)
155+
auto cbs = mcpwm_timer_event_callbacks_t{
156+
.on_full = [](mcpwm_timer_handle_t tim, const mcpwm_timer_event_data_t* edata, void* user_data){
157+
ESP32MCPWMCurrentSenseParams *p = (ESP32MCPWMCurrentSenseParams*)user_data;
158+
#ifdef SIMPLEFOC_ESP32_INTERRUPT_DEBUG
159+
gpio_set_level(GPIO_NUM_19,1); //cca 250ns for on+off
160+
#endif
161+
// increment buffer index
162+
p->buffer_index = (p->buffer_index + 1) % p->no_adc_channels;
163+
// sample the phase currents one at a time
164+
// adc read takes around 10us which is very long
165+
// so we are sampling one phase per call
166+
p->adc_buffer[p->buffer_index] = adcRead(p->pins[p->buffer_index]);
167+
#ifdef SIMPLEFOC_ESP32_INTERRUPT_DEBUG
168+
gpio_set_level(GPIO_NUM_19,0); //cca 250ns for on+off
169+
#endif
170+
return true;
171+
},
172+
};
173+
SIMPLEFOC_ESP32_CS_DEBUG("Timer "+String(t->timer_id)+" enable interrupt callback.");
174+
// set the timer state to init (so that we can call the `mcpwm_timer_register_event_callbacks` )
175+
// this is a hack, as this function is not supposed to be called when the timer is running
176+
// the timer does not really go to the init state!
177+
t->fsm = MCPWM_TIMER_FSM_INIT;
178+
// set the callback
179+
CHECK_CS_ERR(mcpwm_timer_register_event_callbacks(t, &cbs, cs_params), "Failed to set low side callback");
180+
// set the timer state to enabled again
181+
t->fsm = MCPWM_TIMER_FSM_ENABLE;
182+
SIMPLEFOC_ESP32_CS_DEBUG("Timer "+String(t->timer_id)+" enable interrupts.");
183+
CHECK_CS_ERR(esp_intr_enable(t->intr), "Failed to enable low-side interrupts!");
184+
185+
return cs_params;
186+
}
187+
188+
189+
#endif

src/current_sense/hardware_specific/esp32/esp32_mcu.cpp

Lines changed: 0 additions & 165 deletions
This file was deleted.

0 commit comments

Comments
 (0)