3#if defined(ESP_H) && defined(ARDUINO_ARCH_ESP32) && defined(SOC_MCPWM_SUPPORTED) && !defined(SIMPLEFOC_ESP32_USELEDC)
6#include "esp_idf_version.h"
8#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
9#error SimpleFOC: ESP-IDF version 4 or lower detected. Please update to ESP-IDF 5.x and Arduino-esp32 3.0 (or higher)
12#include "../../../drivers/hardware_specific/esp32/esp32_driver_mcpwm.h"
13#include "../../../drivers/hardware_specific/esp32/mcpwm_private.h"
15#include "driver/mcpwm_prelude.h"
16#include "soc/mcpwm_reg.h"
17#include "soc/mcpwm_struct.h"
24#ifdef SIMPLEFOC_ESP32_INTERRUPT_DEBUG
25#include "driver/gpio.h"
28#ifdef CONFIG_IDF_TARGET_ESP32S3
35#define GPIO_NUM (gpio_num_t)((int)GPIO_NUM_0 + DEBUGPIN)
38#ifndef SIMPLEFOC_CS_PRETRIGGER_US
39#define SIMPLEFOC_CS_PRETRIGGER_US 5
51 ESP32CurrentSenseParams* p = (ESP32CurrentSenseParams*)
cs_params;
53 for(
int i=0; i < 3; i++){
54 if(!
_isset(p->pins[i]))
continue;
56 return p->adc_buffer[no_channel] * p->adc_voltage_conv;
71 ESP32MCPWMDriverParams *p = (ESP32MCPWMDriverParams*)driver_params;
72 mcpwm_timer_t* t = (mcpwm_timer_t*) p->timers[0];
76 if(t->on_full !=
nullptr){
77 SIMPLEFOC_ESP32_CS_DEBUG(
"ERROR: Low side callback is already set. Cannot set it again for timer: "+String(t->timer_id)+
", group: "+String(t->group->group_id));
82 ESP32CurrentSenseParams*
params =
new ESP32CurrentSenseParams{};
83 int no_adc_channels = 0;
88 for (
int i = 0; i < 3; i++){
90 if(!adcInit(adc_pins[i])){
91 SIMPLEFOC_ESP32_CS_DEBUG(
"ERROR: Failed to initialise ADC pin: "+String(adc_pins[i]) + String(
", maybe not an ADC pin?"));
100 params->no_adc_channels = no_adc_channels;
104static bool IRAM_ATTR _mcpwmTriggerADCCallback(mcpwm_timer_handle_t tim,
const mcpwm_timer_event_data_t* edata,
void* user_data){
105 ESP32CurrentSenseParams *p = (ESP32CurrentSenseParams*)user_data;
106#ifdef SIMPLEFOC_ESP32_INTERRUPT_DEBUG
107 gpio_set_level(GPIO_NUM,1);
113 p->adc_buffer[p->buffer_index] = adcRead(p->pins[p->buffer_index]);
117 if(p->buffer_index >= p->no_adc_channels){
121#ifdef SIMPLEFOC_ESP32_INTERRUPT_DEBUG
122 gpio_set_level(GPIO_NUM,0);
130static bool IRAM_ATTR _mcpwmComparatorADCCallback(mcpwm_cmpr_handle_t cmpr,
const mcpwm_compare_event_data_t* edata,
void* user_data){
132 if(edata->direction != MCPWM_TIMER_DIRECTION_UP){
136 ESP32CurrentSenseParams *p = (ESP32CurrentSenseParams*)user_data;
137#ifdef SIMPLEFOC_ESP32_INTERRUPT_DEBUG
138 gpio_set_level(GPIO_NUM,1);
144 p->adc_buffer[p->buffer_index] = adcRead(p->pins[p->buffer_index]);
148 if(p->buffer_index >= p->no_adc_channels){
152#ifdef SIMPLEFOC_ESP32_INTERRUPT_DEBUG
153 gpio_set_level(GPIO_NUM,0);
159#ifdef SIMPLEFOC_ESP32_INTERRUPT_DEBUG
160 pinMode(DEBUGPIN, OUTPUT);
162 ESP32MCPWMDriverParams *p = (ESP32MCPWMDriverParams*)driver_params;
163 mcpwm_timer_t* t = (mcpwm_timer_t*) p->timers[0];
164 int group_id = p->group_id;
167 ESP32CurrentSenseParams *cs = (ESP32CurrentSenseParams*)
cs_params;
169 SIMPLEFOC_ESP32_CS_DEBUG(
"ERROR: cs_params is null");
173 SIMPLEFOC_ESP32_CS_DEBUG(
"Configuring sync with comparator...");
177 mcpwm_comparator_config_t cmp_config = {0};
178 cmp_config.flags.update_cmp_on_tez =
true;
179 for(
int i=2; i>=0; i--){
180 if(p->oper[i] ==
nullptr)
continue;
181 if(mcpwm_new_comparator(p->oper[i], &cmp_config, (mcpwm_cmpr_handle_t*)&cs->pretrig_comparator) == ESP_OK){
187 if (cs->pretrig_comparator){
190 uint32_t pwm_duty_cycle = p->mcpwm_period * (0.75 - ((float)p->pwm_frequency*SIMPLEFOC_CS_PRETRIGGER_US)/1e6/2.0);
192 CHECK_CS_ERR(mcpwm_comparator_set_compare_value((mcpwm_cmpr_handle_t)cs->pretrig_comparator, pwm_duty_cycle),
193 "Failed to set pretrigger compare value");
196 mcpwm_comparator_event_callbacks_t cmp_cbs = {
197 .on_reach = _mcpwmComparatorADCCallback
200 CHECK_CS_ERR(mcpwm_comparator_register_event_callbacks((mcpwm_cmpr_handle_t)cs->pretrig_comparator, &cmp_cbs,
cs_params),
201 "Failed to register comparator callback");
203 SIMPLEFOC_ESP32_CS_DEBUG(
"MCPWM"+String(group_id)+
" Timer "+String(t->timer_id)+
" pretrigger comparator configured.");
205 _notifyLowSideUsingComparator(group_id);
209 SIMPLEFOC_ESP32_CS_DEBUG(
"WARN: Failed to create comparator!");
210 SIMPLEFOC_ESP32_CS_DEBUG(
"Configuring sync with on_full callback (less accurate)...");
214 if(t->on_full !=
nullptr){
215 SIMPLEFOC_ESP32_CS_DEBUG(
"ERROR: Low side callback is already set. Cannot set it again for timer: "+String(t->timer_id)+
", group: "+String(t->group->group_id));
224 auto cbs = mcpwm_timer_event_callbacks_t{
225 .on_full = _mcpwmTriggerADCCallback,
227 SIMPLEFOC_ESP32_CS_DEBUG(
"Timer "+String(t->timer_id)+
" enable interrupt callback.");
231 t->fsm = MCPWM_TIMER_FSM_INIT;
233 CHECK_CS_ERR(mcpwm_timer_register_event_callbacks(t, &cbs,
cs_params),
"Failed to set low side callback");
235 t->fsm = MCPWM_TIMER_FSM_ENABLE;
236 CHECK_CS_ERR(esp_intr_enable(t->intr),
"Failed to enable low-side interrupts!");
238 SIMPLEFOC_ESP32_CS_DEBUG(
"MCPWM"+String(group_id)+
" Timer "+String(t->timer_id)+
" on_full callback configured.");
#define SIMPLEFOC_DEBUG(msg,...)
void * _driverSyncLowSide(void *driver_params, void *cs_params)
#define SIMPLEFOC_CURRENT_SENSE_INIT_FAILED
void * _configureADCLowSide(const void *driver_params, const int pinA, const int pinB, const int pinC=NOT_SET)
float _readADCVoltageLowSide(const int pinA, const void *cs_params)
const int const int const int pinC
GenericCurrentSenseParams * params