Motor doesn't turn in FOC mode

Hi everyone

I recently got the SimpleFOCShield but I’m having trouble setting it up and using it with FOC.

Hardware

  • BGM5208-75HS 24N22P
  • AS5600 (in the white PCB version from AliExpress), connected over I2C with 4.7K pull ups
  • Bench Power Supply set to 12V and current limited to under 1A because the motor was getting hot above that

Given these informations, I was setting up the motor and sensor using the following arguments.

BLDCMotor motor = BLDCMotor(9, 10, 6, 11, 8);
MagneticSensorI2C sensor = MagneticSensorI2C(0x36, 12, 0x0E, 4);

From the SimpleFOC examples, I was able to run the magnetic sensor test with stable read outs as well as the open loop voltage control. The find pole pair util example returns a very inconsistent number of pole pairs, almost every run returns a different value. According to its data sheet it’s a 24N22P motor, so I’m assuming the number of pole pairs is 11, is that correct?

Following the docs, I wanted to try voltage control with FOC, however the motor wouldn’t move. As per a suggestion from another thread, I put motor.monitor() into the loop() function and the sensor data seems to be correct.

Do you have any ideas what could be the issue here? I’d appreciate any suggestion.

Cheers,
Lucius

Hey Lucius,

This can very well be a hardware issue.
Did you try to run your motor in the open loop mode?

This should be right, it should have 11 pole pairs.

Try running the velocity open loop library example. The motor should turn smoothly for decent range of velocities (up to 20rad/s).
If it doesn’t, this could suggest either motor or sensor hardware issue.

Thanks Antun!

I’ve tried the open loop example and it works without any problems. I also added motor.linkSensor() and motor.monitor() to the example and it shows seemingly correct values.

Do you know the winding resistance of your motor? Hopefully it is over 2ohms.
Settin psu to 1A is very sensible but should be used like a fuse i.e. you should be avoiding hitting it through your config in software. Do you have a ‘motor.voltage_limit’ ? E.g to a low 1.5 initially. Go back to your working openloop and you’ll notice current on psu will drop.

Are you calling motor.initFOC()? Does it move clockwise then anti clockwise? When call initFOC() you should probably set motor.voltage_sensor_align to something sensible e.g similar to voltage_limit.

The initFOC is supposed to detect whether the natural direction of motor agrees with the natural direction of your sensor, but it might be worth swapping two of your motor cables around to reverse the direction of your motor. Your symptoms might be explained by this.

Thanks Owen!

The winding resistance is about 6 Ω. I just tried motor.voltage_limit = 1.5 in the open loop example. This works up to a target_velocity of 15, after which the motor won’t turn. I increased the limit to 3, which allows the motor to turn without problems even at target_velocity = 20.

Back to the FOC voltage example, I set motor.voltage_sensor_align = 3. It turns in both directions during motor.initFoc(), but does so in “steps” instead of a smooth motion.

Would it make sense to use both voltage_limit and voltage_sensor_align or does one prevent the other from having any impact?

I tried swapping the motor cables around which unfortunately lead to no improvement.

It is an interesting problem. So open-loop works and sensor works but the FOC doesn’t :smiley:
This is very strange.

This is the initialization procedure at this moment. You can override it by adding the parameters to the motor.initFOC(zero_offset, direction) and these two you can get by running the find_sensor_offset_and_direction.ino example.
But for this to work you need a functional FOC algorithm :smiley:

This will not impact much in your case, at least for the moment I think.

Some more questions:

  • What is the microcontroller you are using?
  • What library version are you using?

I’m using an Arduino UNO with SimpleFOC v1.5.0.

Do the motor movements in the video above look correct?

Yes this is correct. The initialization should look that way. Just the last movement when it goes to the right is not good. It should not stop that way.

Could you please show us the output of your serial monitor. You can just dump it here

MOT: Monitor enabled!
MOT: Init pins.
MOT: PWM config.
MOT: Enable.
MOT: Align sensor.
MOT: Absolute zero align.
MOT: Success!
MOT: Motor ready.
Motor ready.
Set the target voltage using serial terminal:

Everything is fine in the log.
I am really not sure what to suggest as a next step.

Could you check also what is the percentage of the Arduino memory used with this example for your Arduino. Sometimes is memory related problems cause the problems that are not easy to debug.

And also, since there aren’t many things left. can you put your show us your full code.

Here’s the memory status on upload:

Sketch uses 17606 bytes (54%) of program storage space. Maximum is 32256 bytes.
Global variables use 1374 bytes (67%) of dynamic memory, leaving 674 bytes for local variables. Maximum is 2048 bytes.

And the code as I just ran it:

/**
 * Torque control example using voltage control loop.
 * 
 * Most of the low-end BLDC driver boards doesn't have current measurement therefore SimpleFOC offers 
 * you a way to control motor torque by setting the voltage to the motor instead hte current. 
 * 
 * This makes the BLDC motor effectively a DC motor, and you can use it in a same way.
 */
#include <SimpleFOC.h>

BLDCMotor motor = BLDCMotor(9, 10, 6, 11, 8);
MagneticSensorI2C sensor = MagneticSensorI2C(0x36, 12, 0x0E, 4);

void setup() {

  // initialise magnetic sensor hardware
  sensor.init();
  // link the motor to the sensor
  motor.linkSensor(&sensor);

  // power supply voltage
  // default 12V
  motor.voltage_power_supply = 12;
  // aligning voltage 
  motor.voltage_sensor_align = 3;
  
  // choose FOC modulation (optional)
  motor.foc_modulation = FOCModulationType::SpaceVectorPWM;

  // set motion control loop to be used
  motor.controller = ControlType::voltage;

  // use monitoring with serial 
  Serial.begin(115200);
  // comment out if not needed
  motor.useMonitoring(Serial);

  // initialize motor
  motor.init();
  // align sensor and start FOC
  motor.initFOC();

  Serial.println("Motor ready.");
  Serial.println("Set the target voltage using serial terminal:");
  _delay(1000);
}

// target voltage to be set to the motor
float target_voltage = 2;

void loop() {

  // main FOC algorithm function
  // the faster you run this function the better
  // Arduino UNO loop  ~1kHz
  // Bluepill loop ~10kHz 
  motor.loopFOC();

  // Motion control function
  // velocity, position or voltage (defined in motor.controller)
  // this function can be run at much lower frequency than loopFOC() function
  // You can also use motor.move() and set the motor.target in the code
  motor.move(target_voltage);
  
  // communicate with the user
  serialReceiveUserCommand();
}


// utility function enabling serial communication with the user to set the target values
// this function can be implemented in serialEvent function as well
void serialReceiveUserCommand() {
  
  // a string to hold incoming data
  static String received_chars;
  
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the string buffer:
    received_chars += inChar;
    // end of user input
    if (inChar == '\n') {
      
      // change the motor target
      target_voltage = received_chars.toFloat();
      Serial.print("Target voltage: ");
      Serial.println(target_voltage);
      
      // reset the command buffer 
      received_chars = "";
    }
  }
}

I am not sure what is really happening here.

Could you please show us motor.monitor() output for this behavior.
Maybe is it some kind of I2C problem, where sensor stops working.

Also, what happens when the motor stops. Is it locked in the position or you can move it. Does it ever diverge - starts rotating very fast in some direction?

I pasted the output of motor.monitor() into a gist.

When the motor stops, I need quite some force to turn it by hand. One time the motor was jerking back and forth like crazy at target_voltage = 10.0, but I couldn’t reproduce that behaviour. Normally, it doesn’t move at all.

Edit: Just to clarify, the changing values in the output above are caused by me turning the motor by hand.

I saw that SimpleFOC also works with the ESP32. I’ll give that a try tomorrow. If there’s no difference, I’ll order the motor again to rule out a hardware issue. The sensor is not the problem — I’ve already tried another one.

I’ve tried your code on my simplefoc board (which is connected to an esp32). I’m using an as5600 with a turnigy 2804 10ohm gimbal.

The only thing I changed were the motor to match my pins and pole pairs (BLDCMotor(17,16,4,7,0))

It worked.

I have a couple of suggestions. Change:

float target_voltage = 0.5;

Why? For me starting at 2 is already fast for my motor. Yours will be faster because your resistance is lower (6 ohms). Thinking about this - I don’t think this is likely to help as I think closed loop shouldn’t be affected by ‘acceleration’ issues.

The other suggestion is to start again. Get your velocity_openloop working. Separately get your i2c working. Check that you’ve not accidentally copied over the wrong motor/sensor config or moved a wire. Still good?

Go back to the voltage test you pasted above and set voltage to zero. Now manually rotate motor. You should see second column of motor.monitor() data show angle in radians. Does this look ok? Does it change by 6.2 (radians) for one rotation?

You are almost there!

Hey @lulezi

The monitoring log seems fine. For me this kinds of problems are either based on sensor being missaligned ( but this seems to work fine from the video and the monitor output) or on the driver problem (but if open loop works fine then the driver works as well).

Now there are few things that are left:

  • I2C communication - but this is very unlikely because if you would have lost the communication you would not reestablish it until the MCU restart, and in your case it seems to be present the whole time
  • The second thing could maybe be a problem of commutation, could you please remove the line:
  // choose FOC modulation (optional)
  motor.foc_modulation = FOCModulationType::SpaceVectorPWM;
  • The last thing that is left for me is the pole pairs number. If it is wrong that would explain why open loop works and sensor works but the closed loop doesnt. But the problem is that from the pictures it seems that it is indeen 11 pole pairs motor :smiley:
    So could you please try to run your motor in open loop and see if you set an angle of 6.28 (2PI) radians if the motor will do a full circle. If it does that means the pole pair number is good as well.

Thanks for the suggestions @Antun_Skuric and @Owen_Williams — keep’em coming! :slight_smile:

I tried smaller target_voltage between 0.1 and 1, no movement.

I started from the beginning, the velocity_openloop example worked like a charm — so did the magnetic_sensor example.

Go back to the voltage test you pasted above and set voltage to zero. Now manually rotate motor.

One rotation is pretty much exactly 6.2. Turning it back is 0.

I commented out the motor.foc_modulation line — no change.

As mentioned above, one rotation by hand results in a radian of around 6.2. I also tried it the open_loop_position example with several values like 6.2, 62, 0, -6.2 leading to the expected rotations.

One more thing I noticed in the voltage_control example, after repeating the following procedure a couple of times:

  • set the voltage to 0
  • turn the motor by hand to a random position
  • set the voltage to 1
  • motor rotates a couple of degrees

It seems that the motor always stops at the same couple of positions (maybe 3, could be more). It looks like there are «steps» where it just wouldn’t rotate any further. Have you experienced something like this?

I also setup the ESP32 but to no success. Almost exactly the same behaviour — with the exception of a very high pitched sound emitted by the motor when controlled by the ESP32.

Can you swap two of your motor cables around? (if it’s a 3 way connector you can flip it 180 degrees) and retry voltage mode.

It sounds like the alignSensor() method (inside initFOC) is not doing its job of detecting zero_electric_offset and/or sensor_direction properly.

You could provide these yourself but the values are hard to guess.

float offset = float(PI / 100.0) * guess;  //where guess = somewhere between 0 to 200.
Direction direction = Direction::CW; // or Direction::CCW!
motor.initFOC(offset, direction);

if you provide optional offset,direction then it won’t do the clockwise/anticlockwise calibration on startup to determine zero_electric_offset and sensor_direction but will use values you provide. If you guess the offset value within about 20 degrees and get the direction correct it should work.

This is very strange behavior. I am really looking forward to know what might be behind this.

As Owen said, it might be that alignSensor() is not doing it’s job. Basically motor.initFOC() is not aligning well. Therefore you can try his suggestion and try setting the target voltage to 2 volts and then try imputing guess through the serial terminal.
After a bit of trial and error you should have your motor moving, if that is the problem indeed.

But we are running out of candidates :smiley: