1#include "../../hardware_api.h"
3#if defined(ESP_H) && defined(ARDUINO_ARCH_ESP32) && ( !defined(SOC_MCPWM_SUPPORTED) || defined(SIMPLEFOC_ESP32_USELEDC) )
6#pragma message("SimpleFOC: compiling for ESP32 LEDC driver")
9#include "driver/ledc.h"
10#include "esp_idf_version.h"
14#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
15#error SimpleFOC: ESP-IDF version 4 or lower detected. Please update to ESP-IDF 5.x and Arduino-esp32 3.0 (or higher)
18#define _PWM_FREQUENCY 25000
19#define _PWM_FREQUENCY_MAX 38000
20#define _PWM_RES_BIT 10
28#include "soc/soc_caps.h"
29#ifdef SOC_LEDC_SUPPORT_HS_MODE
30#define LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM<<1)
32#define LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM)
35#define LEDC_CHANNELS_GROUP0 (LEDC_CHANNELS < 8 ? LEDC_CHANNELS : 8)
36#define LEDC_CHANNELS_GROUP1 (LEDC_CHANNELS < 8 ? 0 : LEDC_CHANNELS - 8)
46int group_channels_used[2] = {0};
49typedef struct ESP32LEDCDriverParams {
50 ledc_channel_t channels[6];
51 ledc_mode_t groups[6];
54} ESP32LEDCDriverParams;
58int esp32_gpio_nr(
int pin) {
59 #if defined(BOARD_HAS_PIN_REMAP) && !defined(BOARD_USES_HW_GPIO_NUMBERS)
60 return digitalPinToGPIONumber(pin);
81bool _ledcAttachChannelAdvanced(uint8_t pin,
int _channel,
int _group, uint32_t freq, uint8_t resolution,
bool inverted) {
84 ledc_channel_t channel =
static_cast<ledc_channel_t
>(_channel);
85 ledc_mode_t group =
static_cast<ledc_mode_t
>(_group);
87 ledc_timer_bit_t res =
static_cast<ledc_timer_bit_t
>(resolution);
88 ledc_timer_config_t ledc_timer;
89 memset(&ledc_timer, 0,
sizeof(ledc_timer));
90 ledc_timer.speed_mode = group;
91 ledc_timer.timer_num = LEDC_TIMER_0;
92 ledc_timer.duty_resolution = res;
93 ledc_timer.freq_hz = freq;
94 ledc_timer.clk_cfg = LEDC_AUTO_CLK;
95 if (ledc_timer_config(&ledc_timer) != ESP_OK) {
96 SIMPLEFOC_DEBUG(
"EP32-DRV: ERROR - Failed to configure the timer:", LEDC_TIMER_0);
102 if (inverted) pin_high_level = !pin_high_level;
104 uint32_t duty = ledc_get_duty(group, channel);
105 ledc_channel_config_t ledc_channel;
106 ledc_channel.speed_mode = group;
107 ledc_channel.sleep_mode = LEDC_SLEEP_MODE_KEEP_ALIVE;
108 ledc_channel.channel = channel;
109 ledc_channel.timer_sel = LEDC_TIMER_0;
110 ledc_channel.intr_type = LEDC_INTR_DISABLE;
111 ledc_channel.gpio_num = esp32_gpio_nr(pin);
112 ledc_channel.duty = duty;
113 ledc_channel.hpoint = 0;
114 ledc_channel.flags.output_invert = pin_high_level;
115 if (ledc_channel_config(&ledc_channel)!= ESP_OK) {
116 SIMPLEFOC_DEBUG(
"EP32-DRV: ERROR - Failed to attach channel:", _channel);
125int _availableGroupChannels(
int group){
126 if(group == 0)
return LEDC_CHANNELS_GROUP0 - group_channels_used[0];
127 else if(group == 1)
return LEDC_CHANNELS_GROUP1 - group_channels_used[1];
136int _findGroupWithChannelsAvailable(
int no_channels){
137 if(no_channels <= _availableGroupChannels(0))
return 0;
138 if(no_channels <= _availableGroupChannels(1))
return 1;
144 if(!pwm_frequency || !
_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY;
145 else pwm_frequency =
_constrain(pwm_frequency, 0, _PWM_FREQUENCY_MAX);
149 int group = _findGroupWithChannelsAvailable(1);
157 group_channels_used[group] += 1;
158 if(!_ledcAttachChannelAdvanced(
pinA, group_channels_used[group], group, pwm_frequency, _PWM_RES_BIT,
false)){
164 ESP32LEDCDriverParams*
params =
new ESP32LEDCDriverParams {
165 .channels = {
static_cast<ledc_channel_t
>(group_channels_used[group]) },
166 .groups = { (ledc_mode_t)group },
167 .pwm_frequency = pwm_frequency
169 SIMPLEFOC_DEBUG(
"EP32-DRV: 1PWM setup successful in group: ", (group));
181 if(!pwm_frequency || !
_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY;
182 else pwm_frequency =
_constrain(pwm_frequency, 0, _PWM_FREQUENCY_MAX);
187 int group = _findGroupWithChannelsAvailable(2);
194 ESP32LEDCDriverParams*
params =
new ESP32LEDCDriverParams {
195 .channels = {
static_cast<ledc_channel_t
>(0)},
196 .groups = { (ledc_mode_t)0 },
197 .pwm_frequency = pwm_frequency
201 for(
int i = 0; i < 2; i++){
202 group_channels_used[group]++;
203 if(!_ledcAttachChannelAdvanced(pins[i], group_channels_used[group], group, pwm_frequency, _PWM_RES_BIT,
false)){
204 SIMPLEFOC_DEBUG(
"EP32-DRV: ERROR - Failed to configure pin:", pins[i]);
208 params->channels[i] =
static_cast<ledc_channel_t
>(group_channels_used[group]);
209 params->groups[i] = (ledc_mode_t)group;
211 SIMPLEFOC_DEBUG(
"EP32-DRV: 2PWM setup successful in group: ", (group));
218 if(!pwm_frequency || !
_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY;
219 else pwm_frequency =
_constrain(pwm_frequency, 0, _PWM_FREQUENCY_MAX);
224 int group = _findGroupWithChannelsAvailable(3);
231 ESP32LEDCDriverParams*
params =
new ESP32LEDCDriverParams {
232 .channels = {
static_cast<ledc_channel_t
>(0)},
233 .groups = { (ledc_mode_t)0 },
234 .pwm_frequency = pwm_frequency
238 for(
int i = 0; i < 3; i++){
239 if(!_ledcAttachChannelAdvanced(pins[i], group_channels_used[group], group, pwm_frequency, _PWM_RES_BIT,
false)){
240 SIMPLEFOC_DEBUG(
"EP32-DRV: ERROR - Failed to configure pin:", pins[i]);
244 params->channels[i] =
static_cast<ledc_channel_t
>(group_channels_used[group]);
245 params->groups[i] = (ledc_mode_t)group;
246 group_channels_used[group]++;
248 SIMPLEFOC_DEBUG(
"EP32-DRV: 3PWM setup successful in group: ", (group));
255 if(!pwm_frequency || !
_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY;
256 else pwm_frequency =
_constrain(pwm_frequency, 0, _PWM_FREQUENCY_MAX);
259 ESP32LEDCDriverParams*
params =
new ESP32LEDCDriverParams {
260 .channels = {
static_cast<ledc_channel_t
>(0)},
261 .groups = { (ledc_mode_t)0 },
262 .pwm_frequency = pwm_frequency
267 int group = _findGroupWithChannelsAvailable(4);
271 if(_availableGroupChannels(0) >=2 && _availableGroupChannels(1) >=2){
273 SIMPLEFOC_DEBUG(
"EP32-DRV: WARNING: Not enough available ledc channels for 4pwm in a single group! Using two groups!");
275 params->groups[2] = (ledc_mode_t)1;
276 params->groups[3] = (ledc_mode_t)1;
278 SIMPLEFOC_DEBUG(
"EP32-DRV: ERROR - Not enough available ledc channels for 4pwm!");
283 params->groups[0] = (ledc_mode_t)group;
284 params->groups[1] = (ledc_mode_t)group;
285 params->groups[2] = (ledc_mode_t)group;
286 params->groups[3] = (ledc_mode_t)group;
292 for(
int i = 0; i < 4; i++){
293 group_channels_used[
params->groups[i]]++;
294 if(!_ledcAttachChannelAdvanced(pins[i], group_channels_used[
params->groups[i]],
params->groups[i], pwm_frequency, _PWM_RES_BIT,
false)){
295 SIMPLEFOC_DEBUG(
"EP32-DRV: ERROR - Failed to configure pin:", pins[i]);
298 params->channels[i] =
static_cast<ledc_channel_t
>(group_channels_used[
params->groups[i]]);
305void IRAM_ATTR _writeDutyCycle(
float dc,
void*
params,
int index){
306 ledc_set_duty_with_hpoint(((ESP32LEDCDriverParams*)
params)->groups[index],((ESP32LEDCDriverParams*)
params)->channels[index], _PWM_RES*dc, _PWM_RES/2.0*(1.0-dc));
307 ledc_update_duty(((ESP32LEDCDriverParams*)
params)->groups[index],((ESP32LEDCDriverParams*)
params)->channels[index]);
311 _writeDutyCycle(dc_a,
params, 0);
317 _writeDutyCycle(dc_a,
params, 0);
324 _writeDutyCycle(dc_a,
params, 0);
332 _writeDutyCycle(dc_1a,
params, 0);
340 if(!pwm_frequency || !
_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY;
341 else pwm_frequency =
_constrain(pwm_frequency, 0, _PWM_FREQUENCY_MAX);
344 SIMPLEFOC_DEBUG(
"EP32-DRV: WARNING - 6PWM on LEDC is poorly supported and not tested, consider using MCPWM driver instead!");
346 int group = _findGroupWithChannelsAvailable(6);
352 ESP32LEDCDriverParams*
params =
new ESP32LEDCDriverParams {
353 .channels = {
static_cast<ledc_channel_t
>(0)},
354 .groups = { (ledc_mode_t)group },
355 .pwm_frequency = pwm_frequency,
362 int pin_pairs[6][2] = {
368 for(
int i = 0; i < 3; i++){
369 group_channels_used[group]++;
370 if(!_ledcAttachChannelAdvanced(pin_pairs[i][0], group_channels_used[group], group, pwm_frequency, _PWM_RES_BIT, high_side_invert)){
371 SIMPLEFOC_DEBUG(
"EP32-DRV: ERROR - Failed to configure pin:", pin_pairs[i][0]);
375 params->channels[2*i] =
static_cast<ledc_channel_t
>(group_channels_used[group]);
376 params->groups[2*i] = (ledc_mode_t)group;
378 group_channels_used[group]++;
379 if(!_ledcAttachChannelAdvanced(pin_pairs[i][1], group_channels_used[group], group, pwm_frequency, _PWM_RES_BIT, low_side_invert)){
380 SIMPLEFOC_DEBUG(
"EP32-DRV: ERROR - Failed to configure pin:", pin_pairs[i][0]);
384 params->channels[2*i+1] =
static_cast<ledc_channel_t
>(group_channels_used[group]);
385 params->groups[2*i+1] = (ledc_mode_t)group;
388 SIMPLEFOC_DEBUG(
"EP32-DRV: 6PWM setup successful in group: ", (group));
392void IRAM_ATTR _setPwmPairDutyCycle(
void*
params,
int ind_h,
int ind_l,
float val,
float dead_time,
PhaseState ps){
393 float pwm_h =
_constrain(val - (dead_time * 0.5), 0, 1.0);
394 float pwm_l =
_constrain(val + (dead_time * 0.5), 0, 1.0);
399 _writeDutyCycle(0,
params, ind_h);
401 _writeDutyCycle(pwm_h,
params, ind_h);
404 _writeDutyCycle(0,
params, ind_l);
406 _writeDutyCycle(pwm_l,
params, ind_l);
#define SIMPLEFOC_DEBUG(msg,...)
const int const int const int pinC
GenericCurrentSenseParams * params
#define SIMPLEFOC_PWM_ACTIVE_HIGH
void * _configure4PWM(long pwm_frequency, const int pin1A, const int pin1B, const int pin2A, const int pin2B)
void * _configure6PWM(long pwm_frequency, float dead_zone, const int pinA_h, const int pinA_l, const int pinB_h, const int pinB_l, const int pinC_h, const int pinC_l)
void * _configure2PWM(long pwm_frequency, const int pinA, const int pinB)
void _writeDutyCycle2PWM(float dc_a, float dc_b, void *params)
void _writeDutyCycle1PWM(float dc_a, void *params)
#define SIMPLEFOC_DRIVER_INIT_FAILED
void _writeDutyCycle4PWM(float dc_1a, float dc_1b, float dc_2a, float dc_2b, void *params)
void * _configure3PWM(long pwm_frequency, const int pinA, const int pinB, const int pinC)
#define SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH
void _writeDutyCycle6PWM(float dc_a, float dc_b, float dc_c, PhaseState *phase_state, void *params)
void * _configure1PWM(long pwm_frequency, const int pinA)
#define SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH
void _writeDutyCycle3PWM(float dc_a, float dc_b, float dc_c, void *params)
float const int const int const int pinB_h
float const int const int const int const int pinB_l
float const int const int const int const int const int pinC_h
float float PhaseState * phase_state
float const int const int const int const int const int const int pinC_l
float const int const int pinA_l
#define _constrain(amt, low, high)