0

I’m trying to make a controller with 3 H bridges (N-FET, IR2101 and a Arduino Mega). I’m sure that the problem is in my code but I don’t know how to fix it. I think that the problem is in the PWM.The pwm is the same in all phases. AH, BH and CH have the same wave at the same time. This is my code:


#define THROTTLE_PIN A15
#define THROTTLE_MIN 0
#define THROTTLE_MAX 1023

#define HALL_1_PIN 7 // Azul
#define HALL_2_PIN 8 // Verde
#define HALL_3_PIN 4 // Amarelo

#define AH_PIN 9
#define AL_PIN 6
#define BH_PIN 10
#define BL_PIN 5
#define CH_PIN 11
#define CL_PIN 3

#define PWM_MAX_DUTY      255
#define PWM_MIN_DUTY      100
#define PWM_START_DUTY    100
byte motor_speed = 255;//PWM_START_DUTY;

#define HALL_OVERSAMPLE 11

byte motorState = 0;
uint8_t lastHall = 0;

const byte pwmValues[6][6] = {
  {0, 1, 1, 0, 0, 0},
  {0, 0, 1, 0, 0, 1},
  {1, 0, 0, 0, 0, 1},
  {1, 0, 0, 1, 0, 0},
  {0, 0, 0, 1, 1, 0},
  {0, 1, 0, 0, 1, 0},
};

void setup() {
  Serial.begin(115200);

  pinMode(AH_PIN, OUTPUT);
  pinMode(AL_PIN, OUTPUT);
  pinMode(BH_PIN, OUTPUT);
  pinMode(BL_PIN, OUTPUT);
  pinMode(CH_PIN, OUTPUT);
  pinMode(CL_PIN, OUTPUT);

  pinMode(HALL_1_PIN, INPUT);
  pinMode(HALL_2_PIN, INPUT);
  pinMode(HALL_3_PIN, INPUT);

  Serial.print("De a primeira binbada no motor");
  pinMode(THROTTLE_PIN, INPUT);
  uint8_t hall = getHalls();
  delay(500);
  Serial.print("Primeira posicao do motor: ");
  Serial.print(hall);
}

void loop() {
  uint8_t hall = getHalls();
  
  motor_speed = analogRead(THROTTLE_PIN); // Ler o valor do potenciômetro

  // Calcular os ciclos de trabalho para cada fase com base na velocidade do motor
  uint8_t dutyCycleA = motor_speed;
  uint8_t dutyCycleB = motor_speed;
  uint8_t dutyCycleC = motor_speed;

  // Definir os ciclos de trabalho PWM para cada fase com um dead time de 10 microssegundos
  analogWrite(AH_PIN, pwmValues[motorState][0] * dutyCycleA);
  delayMicroseconds(10);
  analogWrite(AL_PIN, pwmValues[motorState][1] * dutyCycleA);
  delayMicroseconds(10);
  analogWrite(BH_PIN, pwmValues[motorState][2] * dutyCycleB);
  delayMicroseconds(10);
  analogWrite(BL_PIN, pwmValues[motorState][3] * dutyCycleB);
  delayMicroseconds(10);
  analogWrite(CH_PIN, pwmValues[motorState][4] * dutyCycleC);
  delayMicroseconds(10);
  analogWrite(CL_PIN, pwmValues[motorState][5] * dutyCycleC);

  if (hall != lastHall) {
    lastHall = hall;
    motorState = calculateMotorState(hall);

    // Delay para observar a posição (se necessário)
    delay(75);

    Serial.print("Sensores Hall: ");
    Serial.print(hall);
    Serial.print(", Posição do Motor: ");
    Serial.println(motorState);
  }
}

uint8_t calculateMotorState(uint8_t hall) {
  if (hall == 1) {   // 1
    return 1;
  } else if (hall == 3) {   // 3
    return 3;
  } else if (hall == 4) {   // 4
    return 4;
  } else if (hall == 5) {    // 5
    return 5;
  } else if (hall == 6) {  // 6
    return 6;
  } else if (hall == 2) {  // 2
    return 2;
  } else {
    return 0;
  }
}

uint8_t getHalls() {
  uint8_t hallCounts[] = {0, 0, 0};
  for (uint8_t i = 0; i < HALL_OVERSAMPLE; i++) {
    hallCounts[0] += digitalRead(HALL_1_PIN);
    hallCounts[1] += digitalRead(HALL_2_PIN);
    hallCounts[2] += digitalRead(HALL_3_PIN);
  }

  uint8_t hall = 0;

  if (hallCounts[0] >= HALL_OVERSAMPLE / 2)
    hall |= (1 << 0);
  if (hallCounts[1] >= HALL_OVERSAMPLE / 2)
    hall |= (1 << 1);
  if (hallCounts[2] >= HALL_OVERSAMPLE / 2)
    hall |= (1 << 2);

  return hall & 0x7;
}

1 Answers1

2

Well, there are many issues.

I assume AH_PIN and AL_PIN are the two gate drive signals of phase A. So only one of then may be high at any time or there is a so called shoot through where both FETS are conducting and die or blow a fuse.

But you feed them with with independent PWM signals using analogWrite(). This way you just don't know at which time one of them is high or low. There may be a fixed phase relation between them, this depends on the MCU features. The delayMicroseconds() does not help there, the PWM generator library has an internal timing of its own.

You may read this: Gate drive signal solution for one phase

A BLDC motor typically is a fast rotating thing, so you must read the hall sensors and update the phase PWM at least several hundred times per second. It is not possible to call delay(75) or Serial.print(a lot of stuff) in such a moment.

The function calculateMotorState() is useless, it just returns the given value in a time consuming manner.

The value range of the throttle (0..1023) does not match the PWM range (0..255), so you need a /4 downscale there.

Jens
  • 5,598
  • 2
  • 7
  • 28