ESP32 ESC BRUSHLESS


Minatel
Espressif staff
Espressif staff
Posts: 433
Joined: Mon Jan 04, 2021 2:06 pm

Re: ESP32 ESC BRUSHLESS

Postby Minatel » Wed Nov 19, 2025 8:26 am

Hi @h3lyofilho,

Thanks for sharing the videos. Can you please write about your project?

h3lyofilho
Posts: 4
Joined: Sun Nov 02, 2025 1:20 pm

Re: ESP32 ESC BRUSHLESS

Postby h3lyofilho » Wed Nov 19, 2025 9:28 pm

Image

h3lyofilho
Posts: 4
Joined: Sun Nov 02, 2025 1:20 pm

Re: ESP32 ESC BRUSHLESS

Postby h3lyofilho » Sat Nov 22, 2025 4:37 pm

Code: Select all

#ifdef __cplusplus
extern "C"
#endif

#include "esp_adc_cal.h"
#include "driver/ledc.h"

#define PWM_HZ     25000   
#define PWM_BITS       8  

#define A_PWM          0   // # U
#define B_PWM          1   // # V
#define C_PWM          2   // # W

#define A_HIGH        25
#define B_HIGH        26
#define C_HIGH        27

#define A_LOW         14
#define B_LOW         12
#define C_LOW         13

#define A_BEMF        35
#define B_BEMF        34
#define C_BEMF        39

#define POT_SPEED     36
                                   
unsigned int TIMER_STEP = 1000;    // 1000 DEFAULT // EM ms # TEMPO ENTRE ZERO CROSS RISING E ZERO CROSS FALLING ??????
uint8_t PWM_VALUE       = 100;     // 39,215% (DE 50KHZ) OU DE 255 # 30392,5 KHZ DE 50KHZ # 1.294V DE 3.3V
uint16_t FAIL_COUNTER   = 0;       // CONTADOR  DE FALHAS
int SEQUENCE_STEP       = 0;       // SEQUÊNCIA DE STEPS
byte BEMF_ON            = 0;       // INTERRUPÇOES DE BEMF DESABILITADAS

unsigned long TIMER     =  0;
const byte    POLES     = 14;      // NR DE IMÃS NO MOTOR

int POT_VALUE_READ      = 0;


//=====================================================================================
//================================= INTERRUPÇÕES BEMF =================================
//=====================================================================================
void ICACHE_RAM_ATTR A_BEMF_FALLING(){ // FALLING A
FAIL_COUNTER = 0;                      // COLOCA O CONTADOR DE FALHAS EM "0"
byte j = 0;                            // VARIÁVEL "j" QUEBRA O LOOP EM CASO DE FALHA AO SAIR SEM INTERRUPÇÃO.

for(byte i = 0; i < 30; i++){          // 30 = DEBOUNCE COUNT, SE A BOBINA CAIU NA BORDA FALLING, MAS NÃO FORMOU ARCO,
if(digitalRead(A_BEMF))                // ESPERA ATÉ QUE O ARCO TERMINE, OU SEJA, ATÉ QUE O IMÃ ESTEJA CENTRALIZADO.
i -= 1;
j++;
if(j > 500)
break;
}

BLDC_MOVE();                           // ENERGIZA AS BOBINAS DE ACORDO COM A PRÓXIMA SEQUÊNCIA DE STEPS
SEQUENCE_STEP++;                       // INCREMENTA A CONTAGEM DE STEPS EM "1" PARA SE PREPARAR PARA A PRÓXIMA INTERRUPÇÃO

//-------------------------------------------------------------------------------------
if(SEQUENCE_STEP > 6)                  // SE A SEQUÊNCIA DE STEPS FOR MAIOR QUE 6,
SEQUENCE_STEP = 1;                     // REINICIA CONTAGEM
}
//-------------------------------------------------------------------------------------

//*************************************************************************************
//*************************************************************************************
void ICACHE_RAM_ATTR A_BEMF_RISING(){
FAIL_COUNTER = 0;
byte j = 0;

for(byte i = 0; i < 30; i++){
if(!digitalRead(A_BEMF))
i -= 1;
j++;
if(j > 500)
break;
}

BLDC_MOVE();
SEQUENCE_STEP++;
//-------------------------------------------------------------------------------------
if(SEQUENCE_STEP > 6)
SEQUENCE_STEP = 1;
}
//************************************************************************************************
//************************************************************************************************
void ICACHE_RAM_ATTR B_BEMF_FALLING(){
FAIL_COUNTER = 0;
byte j = 0;

for(byte i = 0; i < 30; i++){
if(digitalRead(B_BEMF))
i -= 1;
j++;
if(j > 500)
break;
}

BLDC_MOVE();
SEQUENCE_STEP++;
//-------------------------------------------------------------------------------------
if(SEQUENCE_STEP > 6)
SEQUENCE_STEP = 1;
}
//*************************************************************************************
//*************************************************************************************
void ICACHE_RAM_ATTR B_BEMF_RISING(){
FAIL_COUNTER = 0;
byte j = 0;

for(byte i = 0; i < 30; i++){
if (!digitalRead(B_BEMF))
i -= 1;
j++;
if(j > 500)
break;
}

BLDC_MOVE();
SEQUENCE_STEP++;
//-------------------------------------------------------------------------------------
if(SEQUENCE_STEP > 6)
SEQUENCE_STEP = 1;
}
//*************************************************************************************
//*************************************************************************************
void ICACHE_RAM_ATTR C_BEMF_FALLING(){
FAIL_COUNTER = 0;
byte j = 0;

for(byte i = 0; i < 30; i++){
if(digitalRead(C_BEMF))
i -= 1;
j++;
if(j > 500)
break;
}

BLDC_MOVE();
SEQUENCE_STEP++;
//-------------------------------------------------------------------------------------
if(SEQUENCE_STEP > 6)
SEQUENCE_STEP = 1;
}
//*************************************************************************************
//*************************************************************************************
void ICACHE_RAM_ATTR C_BEMF_RISING(){
FAIL_COUNTER = 0;
byte j = 0;

for(byte i = 0; i < 30; i++){
if(!digitalRead(C_BEMF))
i -= 1;
j++;
if(j > 500)
break;
}

BLDC_MOVE();
SEQUENCE_STEP++;
//-------------------------------------------------------------------------------------
if(SEQUENCE_STEP > 6)
SEQUENCE_STEP = 1;
}

//=====================================================================================
//================================= COMUTAÇÕES DAS BOBINAS ============================
//=====================================================================================
void BH_CL(){
digitalWrite(A_LOW, LOW);
digitalWrite(B_LOW, LOW);
digitalWrite(C_LOW,HIGH);

ledcWrite(A_PWM,0);
ledcWrite(B_PWM,PWM_VALUE);
ledcWrite(C_PWM,0);

if(BEMF_ON == 0){
detachInterrupt(B_BEMF);
detachInterrupt(C_BEMF);
attachInterrupt(A_BEMF, A_BEMF_FALLING, FALLING);
}
}
//*************************************************************************************
//*************************************************************************************
void CH_BL(){
digitalWrite(A_LOW, LOW);
digitalWrite(B_LOW,HIGH);
digitalWrite(C_LOW, LOW);

ledcWrite(A_PWM,0);
ledcWrite(B_PWM,0);
ledcWrite(C_PWM,PWM_VALUE);

if(BEMF_ON == 0){
detachInterrupt(B_BEMF);
detachInterrupt(C_BEMF);
attachInterrupt(A_BEMF, A_BEMF_RISING, RISING);
}
}
//*************************************************************************************
//*************************************************************************************
void CH_AL(){
digitalWrite(A_LOW,HIGH);
digitalWrite(B_LOW, LOW);
digitalWrite(C_LOW, LOW);

ledcWrite(A_PWM,0);
ledcWrite(B_PWM,0);
ledcWrite(C_PWM,PWM_VALUE);

if(BEMF_ON == 0){
detachInterrupt(A_BEMF);
detachInterrupt(C_BEMF);
attachInterrupt(B_BEMF, B_BEMF_FALLING, FALLING);
}
}
//*************************************************************************************
//*************************************************************************************
void AH_CL(){
digitalWrite(A_LOW, LOW);
digitalWrite(B_LOW, LOW);
digitalWrite(C_LOW,HIGH);

ledcWrite(A_PWM,PWM_VALUE);
ledcWrite(B_PWM,0);
ledcWrite(C_PWM,0);

if(BEMF_ON == 0){
detachInterrupt(A_BEMF);
detachInterrupt(C_BEMF);
attachInterrupt(B_BEMF, B_BEMF_RISING, RISING);
}
}
//*************************************************************************************
//*************************************************************************************
void AH_BL(){
digitalWrite(A_LOW, LOW);
digitalWrite(B_LOW,HIGH);
digitalWrite(C_LOW, LOW);

ledcWrite(A_PWM,PWM_VALUE);
ledcWrite(B_PWM,0);
ledcWrite(C_PWM,0);

if(BEMF_ON == 0){
detachInterrupt(A_BEMF);
detachInterrupt(B_BEMF);
attachInterrupt(C_BEMF, C_BEMF_FALLING, FALLING);
}
}
//*************************************************************************************
//*************************************************************************************
void BH_AL(){
digitalWrite(A_LOW,HIGH);
digitalWrite(B_LOW,LOW);
digitalWrite(C_LOW,LOW);

ledcWrite(A_PWM,0);
ledcWrite(B_PWM,PWM_VALUE);
ledcWrite(C_PWM,0);

if(BEMF_ON == 0){
detachInterrupt(A_BEMF);
detachInterrupt(B_BEMF);
attachInterrupt(C_BEMF, C_BEMF_RISING, RISING);
}
}
//*************************************************************************************
//*************************************************************************************


//*************************************************************************************
//*************************************************************************************
//*************************************************************************************
//*************************************************************************************
void BLDC_MOVE(){       // FUNÇÃO DE COMUTAÇÃO DAS BOBINAS
switch (SEQUENCE_STEP){ // A FUNÇÃO QUE ENERGIZA AS BOBINAS E PREPARA AS INTERRUPÇOES DE ACORDO COM A SEQUÊNCIA DE STEPS

case 1: AH_BL(); break;
case 2: AH_CL(); break;
case 3: BH_CL(); break;
case 4: BH_AL(); break;
case 5: CH_AL(); break;
case 6: CH_BL(); break;

default: break;
}
}
//=====================================================================================
//=================================== COMUTAÇÃO INICIAL ===============================
//=====================================================================================
void INITIAL_COMUTATION(){ // 800000 = TESTE LENTO VISÍVEL
TIMER_STEP = 8000;       // 8000us = 8ms // 125 HZ # A COMUTAÇÃO DAS BOBINAS É INICIADA EM INTERVALOS DE 8ms
SEQUENCE_STEP = 0;                         // SEQUÊNCIA DE STEPS DEFINIDO COMO "0"
while(TIMER_STEP > 1000){ // 1000us = 1ms  // ENQUANTO INTERVALO DE COMUTAÇÃO FOR MAIOR QUE 1ms (1 KHZ)
SEQUENCE_STEP++;                           // INCREMENTA SEQUENCIA DE STEPS EM 1
if(SEQUENCE_STEP > 6)                      // SE A SEQUÊNCIA DE STEPS FOR MAIOR QUE 6...
SEQUENCE_STEP = 1;                         // REINICIA A CONTAGEM.
BLDC_MOVE();                               // CONTINUA PARA O PRÓXIMO STEP
delayMicroseconds(TIMER_STEP);             // DELAY ENTRE UM STEP E OUTRO
TIMER_STEP -= 1000;                        // SUBTRAI (1000)DE TIME_STEP (8000) AYÉ CHEGAR A 1000
}
}
//=====================================================================================
//=================================== GIRO DO MOTOR ===================================
//=====================================================================================
void MOTOR_SPINNER(){
int POT_VALUE = analogRead(POT_SPEED); // O VALOR LIDO NO POTENCIÔMETRO É PROPORCIONAL AO VALOR DO PWMM, (0-4095) # (0-255)
PWM_VALUE = POT_VALUE / 16;            // PWM_VALUE = # (4096 / 256 = 16) # (16 / 16 = 1)
if(PWM_VALUE < 5)PWM_VALUE = 15;       // É GARANTIDO QUE O VALOR PWM NÃO FIQUE ABAIXO DE 20,(PARA QUE O MOTOR NÃO PARE)
FAIL_COUNTER++;                        // CONTADOR DE FALHAS USADO PARA BLOQUEAR SE O MOTOR ESTIVER TRAVADO POR QUALQUER MOTIVO
if(FAIL_COUNTER > 250){                // ESTE CONTADOR DE FALHAS É ZERADO SEMPRE QUE OCORRER UMA INTERRUPÇÃO, SE O CONTADOR FOR > QUE 200,
FAIL_COUNTER = 0;                      // ZERA O CONTADOR DE STEPS
BEMF_ON = 1;                           // BEMF HABILITADO
detachInterrupt(A_BEMF);               // INTERRUPÇÕES DE BEMF DEABILITADAS...
detachInterrupt(B_BEMF);               // INTERRUPÇÕES DE BEMF DESABILITADAS...
detachInterrupt(C_BEMF);               // INTERRUPÇÕES DE BEMF DESABILITADAS...
PWM_VALUE = 30;                        // INICIA O MOTOR COM PWM EM 20
INITIAL_COMUTATION();                  // ...E A COMUTAÇÃO É REALIZADA NOVAMENTE NO MODO MOTOR DE PASSO (SEM INTERRUPÇÕES).
BEMF_ON = 0;                           // BEMF DESABILITADAS
SEQUENCE_STEP = 6;
attachInterrupt(digitalPinToInterrupt(A_BEMF), A_BEMF_RISING, RISING);
}
}
//=====================================================================================
//==================================== VOID SETUP =====================================
//=====================================================================================
void setup(){
Serial.begin(115200);
pinMode(A_HIGH,  OUTPUT);
pinMode(B_HIGH,  OUTPUT);
pinMode(C_HIGH,  OUTPUT);

pinMode(A_LOW,   OUTPUT);
pinMode(B_LOW,   OUTPUT);
pinMode(C_LOW,   OUTPUT);

pinMode(A_BEMF,  INPUT_PULLUP);
pinMode(B_BEMF,  INPUT_PULLUP);
pinMode(C_BEMF,  INPUT_PULLUP);

ledcAttachPin(A_HIGH, A_PWM);
ledcAttachPin(B_HIGH, B_PWM);
ledcAttachPin(C_HIGH, C_PWM);

ledcSetup(A_PWM, PWM_HZ, PWM_BITS);  
ledcSetup(B_PWM, PWM_HZ, PWM_BITS); 
ledcSetup(C_PWM, PWM_HZ, PWM_BITS); 



//=====================================================================================
//==================================== VOID LOOP ======================================
//=====================================================================================
void loop() {
MOTOR_SPINNER();
}

Who is online

Users browsing this forum: No registered users and 3 guests