Hello everyone,
I've started a project to control a sensorless motor using an ESP32 with the BEMF method. Everything is functioning, and the motor runs, but I encounter an issue during startup. I need to manually assist the motor to ensure it rotates in the correct direction. If I don't do this, the motor tends to spin in the wrong direction, gets stuck, and then starts turning again in the wrong direction...
Could someone please help me identify where I might be going wrong? Here’s my code below:
#include <Arduino.h>
#define SETPOINT_COEFF 1.10*6
#define enable 18
#define setpoint 34
#define i_meas 17
#define i_fault 4
#define tsw_fault 5
#define v_ts 16
#define v_bus 33
#define v_u 39
#define v_v 35
#define v_w 32
#define U_H 13
#define V_H 14
#define W_H 26
#define U_L 12
#define V_L 27
#define W_L 25
void bldc_start();
void bldc_move();
void phase1();
void phase2();
void phase3();
void phase4();
void phase5();
void phase6();
int bldc_step=0;
unsigned int i_start;
uint16_t motor_reset=0;
byte changeINT_flag=0;
uint8_t motor_speed=100;
void IRAM_ATTR intU_FALLING()
{
motor_reset=0;
byte j=0; // Cette variable est utilisée pour rompre la boucle en cas d'échec de sortie de l'interruption.
for(byte i = 0; i < 30; i++) // si l'enroulement U tombe sur le front descendant mais qu'un arc se produit quand même,
{ // il attend que l'arc se termine, c'est-à-dire que l'enroulement centre exactement l'aimant.
if(digitalRead(v_u)) i -= 1;
j++;
if(j>200)break;
}
bldc_move(); // alimenter les enroulements dans la séquence de phases suivante.
bldc_step++;
if(bldc_step>6) bldc_step=1;
}
void IRAM_ATTR intU_RISING()
{
motor_reset=0;
byte j=0;
for(byte i = 0; i < 30; i++)
{
if(!digitalRead(v_u)) i -= 1;
j++;
if(j>200)break;
}
bldc_move();
bldc_step++;
if(bldc_step>6) bldc_step=1;
}
void IRAM_ATTR intV_FALLING()
{
motor_reset=0;
byte j=0;
for(byte i = 0; i < 30; i++)
{
if(digitalRead(v_v)) i -= 1;
j++;
if(j>200)break;
}
bldc_move();
bldc_step++;
if(bldc_step>6) bldc_step=1;
}
void IRAM_ATTR intV_RISING()
{
byte j=0;
motor_reset=0;
for(byte i = 0; i < 30; i++)
{
if(!digitalRead(v_v)) i -= 1;
j++;
if(j>200)break;
}
bldc_move();
bldc_step++;
if(bldc_step>6) bldc_step=1;
}
void IRAM_ATTR intW_FALLING()
{
byte j=0;
motor_reset=0;
for(byte i = 0; i < 30; i++)
{
if(digitalRead(v_w)) i -= 1;
j++;
if(j>200)break;
}
bldc_move();
bldc_step++;
if(bldc_step>6) bldc_step=1;
}
void IRAM_ATTR intW_RISING()
{
motor_reset=0;
byte j=0;
for(byte i = 0; i < 30; i++)
{
if(!digitalRead(v_w)) i -= 1;
j++;
if(j>200) break;
}
bldc_move();
bldc_step++;
if(bldc_step>6) bldc_step=1;
}
void phase1()
{
digitalWrite(U_L,LOW);
digitalWrite(V_L,HIGH);
digitalWrite(W_L,LOW);
ledcWrite(0,motor_speed);
ledcWrite(1,0);
ledcWrite(2,0);
if(changeINT_flag==0)
{
detachInterrupt(v_u);
detachInterrupt(v_v);
attachInterrupt(v_w, intW_FALLING, FALLING);
}
}
void phase2()
{
digitalWrite(U_L,LOW);
digitalWrite(V_L,LOW);
digitalWrite(W_L,HIGH);
ledcWrite(0,motor_speed);
ledcWrite(1,0);
ledcWrite(2,0);
if(changeINT_flag==0)
{
detachInterrupt(v_u);
detachInterrupt(v_w);
attachInterrupt(v_v, intV_RISING, RISING);
}
}
void phase3()
{
digitalWrite(U_L,LOW);
digitalWrite(V_L,LOW);
digitalWrite(W_L,HIGH);
ledcWrite(0,0);
ledcWrite(1,motor_speed);
ledcWrite(2,0);
if(changeINT_flag==0)
{
detachInterrupt(v_v);
detachInterrupt(v_w);
attachInterrupt(v_u, intU_FALLING, FALLING);
}
}
void phase4()
{
digitalWrite(U_L,HIGH);
digitalWrite(V_L,LOW);
digitalWrite(W_L,LOW);
ledcWrite(0,0);
ledcWrite(1,motor_speed);
ledcWrite(2,0);
if(changeINT_flag==0)
{
detachInterrupt(v_u);
detachInterrupt(v_v);
attachInterrupt(v_w, intW_RISING, RISING);
}
}
void phase5()
{
digitalWrite(U_L,HIGH);
digitalWrite(V_L,LOW);
digitalWrite(W_L,LOW);
ledcWrite(0,0);
ledcWrite(1,0);
ledcWrite(2,motor_speed);
if(changeINT_flag==0)
{
detachInterrupt(v_u);
detachInterrupt(v_w);
attachInterrupt(v_v, intV_FALLING, FALLING);
}
}
void phase6()
{
digitalWrite(U_L,LOW);
digitalWrite(V_L,HIGH);
digitalWrite(W_L,LOW);
ledcWrite(0,0);
ledcWrite(1,0);
ledcWrite(2,motor_speed);
if(changeINT_flag==0)
{
detachInterrupt(v_v);
detachInterrupt(v_w);
attachInterrupt(v_u, intU_RISING, RISING);
}
}
void bldc_move()
{
switch(bldc_step)
{
case 1: phase1(); break;
case 2: phase2(); break;
case 3: phase3(); break;
case 4: phase4(); break;
case 5: phase5(); break;
case 6: phase6(); break;
default: break;
}
}
void bldc_start()
{
i_start=5000; // La commutation est d'abord appliquée aux enroulements à intervalles de 8 ms.
bldc_step=0;
while(i_start>500) // La commutation appliquée aux enroulements s'effectue en la diminuant à 1 ms.
{
bldc_step++;
if(bldc_step>6) bldc_step=1;
bldc_move();
delayMicroseconds(i_start);
i_start-=20; // Le temps entre chaque phase en commutation est réduit de 20 uS.
}
}
/*------------------------------------------------------------------------*/
void setup()
{
pinMode(setpoint, INPUT);
pinMode(i_meas, INPUT);
pinMode(i_fault, INPUT);
pinMode(tsw_fault, INPUT);
pinMode(v_ts, INPUT);
pinMode(v_bus, INPUT);
pinMode(v_u, INPUT);
pinMode(v_v, INPUT);
pinMode(v_w, INPUT);
pinMode(U_L,OUTPUT);
pinMode(V_L,OUTPUT);
pinMode(W_L,OUTPUT);
pinMode(enable, OUTPUT);
digitalWrite(enable, HIGH);
Serial.begin(115200);
delay(1000);
ledcAttachPin(U_H, 0);
ledcAttachPin(V_H, 1);
ledcAttachPin(W_H, 2);
ledcSetup(0, 50000, 8);
ledcSetup(1, 50000, 8);
ledcSetup(2, 50000, 8);
changeINT_flag=1;
bldc_start();
changeINT_flag=0;
bldc_step=6;
attachInterrupt(v_u, intU_RISING, RISING);
}
/*------------------------------------------------------------------------*/
void loop()
{
static unsigned long lastEventTime1 = millis();
static const unsigned long INTERVAL1_MS = 500;
if ((millis() - lastEventTime1) > INTERVAL1_MS)
{
float setpointREAD=SETPOINT_COEFF*3.3*(float(analogRead(setpoint))/4095);
motor_speed=setpointREAD*10;
if(motor_speed>=100) motor_speed=100;
if(motor_speed<=25) motor_speed=25;
Serial.print("PWM=");Serial.println(motor_speed);
if(motor_speed<=25 || digitalRead(v_ts)==LOW || digitalRead(tsw_fault)==LOW) digitalWrite(enable, HIGH);
else digitalWrite(enable, LOW);
motor_reset++;
if(motor_reset>10)
{
motor_reset=0;
changeINT_flag=1;
detachInterrupt(v_u); detachInterrupt(v_v); detachInterrupt(v_w);
motor_speed=100;
bldc_start();
changeINT_flag=0;
bldc_step=6;
attachInterrupt(v_u, intU_RISING, RISING);
}
lastEventTime1 = millis();
}
}