Motor doesn't turn in FOC mode

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:

Hi,

Just reading the forum, I posted in the stepper thread but seems I have this exact problem with a stepper. Next week I will try with a BLDC. I’m using a nucleo 144. I also get the high pitch after it locks up.

Hey @lulezi and @Jonathan_Robson,
I have done some testing this weekend and unfortunately I was still not able to replicate the issue you are having.

Did you maybe try the guessing procedure, were you able to make your motor spin?

I am a bit concerned with this bug you are having, I would really like to get to the bottom of this :smiley:

Hi,

I have nothing left to try with the stepper, tomorrow I will have a 3 x PWM compatible inverter to test with on a BLDC motor to see how it compares.

Hey Jonathan, have you tried this?

Hi, no, but when I try it again I will. I will next try a BLDC, I have the driver, just waiting for time to come :wink:

Hi @Antun_Skuric and @Owen_Williams

I finally got around to trying the guessing of the offset. Here’s my code:

/**
 * 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);
}

float target_voltage = 1;

int i = 0;
float guess = 0;

void loop() {
  motor.loopFOC();
  motor.move(target_voltage);
  
  if (i > 2000) {
    i = 0;
    guess += 10.0;
    motor.initFOC(guess, Direction::CW);
    Serial.print("new guess: ");
    Serial.println(guess);
  }

  i++;
}

Does that look right?

The motor moves a tiny little step with every .initFOC() call, but never manages to rotate beyond that. At some points (the offset is not reliably reproducible) it starts to violently shake.

I also tried Direction::CCW, which results in the tiny steps sometimes going into one direction and other times into the other direction, so I guess Direction::CW seems to be correct for the current setup.

I was expecting you to put motor.initFOC in the setup method and manually recompile 20x times with different guess values. Your approach is a clever way to automate this - I’ve not personally called initFOC multiple times but I guess it would work. How long does each i > 2000 take? A few seconds for each guess?

I would set motor.voltage_limit to something sensible for your motor e.g. if motor.voltage_sensor_align = 3; didn’t cause a violent autotune then maybe set it also to 3.

Another experiment you could try is to add a motor.monitor() to your loop and set the target_voltage to zero. The motor shouldn’t move but if you manually turn it the motor.monitor() should print out <voltage> <shaft_angle> <shaft_velocity. If the 2nd and 3rd columns are zero or ‘weird’ then it might shed some light. e.g. sensor works when not linked to motor but stops working when linked to motor.

Hey @lulezi,

Were you able to get around this problem?
I would suggest you not to use the approach that you have shown but just use a function like this:


void changeZeroAngle() {
  
  // 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') {
      
      // chage the guess
      float guess = received_chars.toFloat()*2*_PI/360;
      motor.zero_electric_angle = guess;      
      // reset the command buffer 
      received_chars = "";
    }
  }
}

And then just add this function to your loop():

void loop(){
    ...
   changeZeroAngle();
}

Then you just send a number in between 0 and 360 through serial. This will allow you to guess quicker and more precisely.

Otherwise, since this is very strange problem and it is troubling me a bit I would be happy to sned you an additional SimpleFOCShield hoping that that might resolve the issue :smiley:

Hi @Antun_Skuric

I wanted to try your suggestion yesterday but couldn’t get good readings from the sensor anymore. I saw this post and since I got these exact same sensors I checked my magnets and it seems they are also axially magnetized. So I ordered diametrically magnetized ones and hope they’ll arrive in the next few days.

However: I have no idea how I got proper readings from the sensor last time. Do you have any explanation? Anyway, let’s put this thread on hold until I can check with the right magnets.

Hey @lulezi,

Well spoted, that would explain the behavior that you are having.
I am not really sure how were you able to read any value really :smiley:

I guess that the sensor was able to read some data but this data was no longer well aligned with the electrical rotation of the motor, making the readings still appear correct (each rotation) by eye, but the relative readings were not precise enough to spin the motor in foc mode.

I hope this will resolve this issue! :smiley:

The new magnets arrived — everything works great!

Thanks a lot @Antun_Skuric and @Owen_Williams for your support and sorry for wasting your time on this non-issue.

1 Like

Cool!
I was starting to get worried about this issue :smiley:
I am happy you found your solution!