Moving from open-loop to closed-loop (Arduino UNO, L298N, BLDC motor)

Good Afternoon,

I’m looking for some help in getting the torque control mode to work for a BLDC motor.

Hardware:

  • Arduino UNO R3
  • L298N (I know this is not ideal for BLDC motors, but it’s what I have right now)
  • 3pp bldc motor with hall sensors motor datasheet

Circuit: right now I am powering everything off of the arduino 5V, I plan on getting a 12V power supply soon. Software interrupts are used for the hall sensors.
image

I am following the tutorial linked here: https://www.youtube.com/watch?v=ENGGh0ajE2M

I’ve been able to:

  • Use open loop velocity to spin the motor up to 15 rad/s
  • Read that the sensor measures 6.28 for a rotation of the motor

I’ve been trying to:

  • Use the torque controller (motor doesn’t spin at all)
  • Use the closed loop velocity controller (motor vibrates)

When the initFOC runs, the motor spins back and forth a few degrees, stops, and I get the following message:

MOT: Init
MOT: Monitor enabled!
MOT: Init
MOT: Enable driver.
MOT: Align sensor.
MOT: sensor_direction==CW
MOT: PP check: fail - estimated pp: 4.50
MOT: Zero elec. angle: 1.05
MOT: No current sense.
MOT: Ready.
Setup complete

Any help is greatly appreciated.

Code is largely copy+paste but is shown below:

#include <SimpleFOC.h>
#include <PciManager.h>
#include <PciListenerImp.h>

HallSensor sensor = HallSensor(2, 3, 4, 3); // hA, hB, hC, pole pairs

BLDCMotor motor = BLDCMotor(3);
BLDCDriver3PWM driver = BLDCDriver3PWM(11, 10, 9);

void doA(){sensor.handleA();}
void doB(){sensor.handleB();}
void doC(){sensor.handleC();}

PciListenerImp listenA(sensor.pinA, doA);
PciListenerImp listenB(sensor.pinB, doB);
PciListenerImp listenC(sensor.pinC, doC);

float target = 0.5;

void serialLoop() {
  static String received_chars;
  while (Serial.available()) {
    char inChar = (char) Serial.read();
    received_chars += inChar;
    if (inChar == '\n') {
      target = received_chars.toFloat();
      Serial.print("Target = "); Serial.println(target);
      received_chars = "";
    }
  }
}

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

  // Sensor setup
  sensor.pullup = Pullup::USE_INTERN;
  sensor.velocity_max = 500;
  sensor.init();
  PciManager.registerListener(&listenA);
  PciManager.registerListener(&listenB);
  PciManager.registerListener(&listenC);

  // deactivate the OUT4 output
  pinMode(8,OUTPUT);
  digitalWrite(8,LOW);

  // Motor Setup
  driver.voltage_power_supply = 5;
  driver.voltage_limit = 5;
  driver.init();
  // link the motor and the driver
  motor.linkDriver(&driver);
  motor.voltage_limit = 5;   // [V]
  motor.velocity_limit = 18; // [rad/s]
  //motor.voltage_sensor_align = 1;
  motor.linkSensor(&sensor);
  //motor.PID_velocity.P = 1.0;
  //motor.PID_velocity.I = 0.0;
  //motor.LPF_velocity.Tf = 0.01;
  //motor.controller = MotionControlType::velocity;
  motor.torque_controller = TorqueControlType::voltage;
  motor.controller = MotionControlType::torque;
  //motor.controller = MotionControlType::velocity_openloop;
  motor.useMonitoring(Serial);
  motor.init();
  motor.initFOC();
  
  Serial.println("Setup complete");
  delay(1000);
}

void loop() {
  serialLoop();

  //motor.PID_velocity.P = target;
  motor.loopFOC();
  motor.move(target);
  
  //sensor.update();
  //Serial.print(sensor.getAngle());
  //Serial.print("\t");
  //Serial.println(sensor.getVelocity());

  motor.monitor();
}

hey,

I’m in no way good at SimpleFOC yet and the only simalarity i have is that i’ve also been using an adruino uno and that i have hall sensors. I can point some things out which might be of help.

polar pair number looks good as the datasheet says it has 6 pole numbers so i geuss it should have then 3 polar pairs. what i do see is that youre saying it has a hall sensor but what i’m seeing in the datasheet is that it has an encoder.

Pin 2 and 3 are already interrupt pins so you dont have to make digital interrupt pins out of them. doubt that this comment helps, but still its something i see. :sweat_smile:

There are actually some great example codes for reading hall sensors/encoders provided by the library. what i did first was to see if i could get the sensor working befor moving on to closed_loop torque.

hope it helps

Hi,

I appreciate your reply!

I had actually ordered that motor because it came with an encoder, however the encoder cable was not included :frowning: , for that reason I’ve been trying to make it work with the hall sensors while I wait on the encoder cable to arrive (2-3 weeks).

I’ll remove the pin interrupt stuff for pins 2 and 3, thanks.

Get the pole pair check working first. I encountered a number of difficulties with this. There is a separate example to check pole pair, I found that worked better, compared the difference and that corrected the issue with the torque control example on the uno, that was using the simplefoc shield however.

Now that I know a bit more, I can suggest you open up the library files, look through them to follow the flow of the program to see what is happening during the driver init, and put Serial.println or whatever statements in strategeic areas to sneak information about what is happening out.

Real developers use debugging tools to do this and if you are going to do much, my plan was to use atmel studio the next time I had to do something like this. It may seem like overkill but it might save you a lot of time actually.

Update: Now that the encoder cables have arrived I’ve been able to run both the torque and closed loop velocity controllers :slight_smile: !

3 Likes