Low speed BLDC issues "Jittery" movement

Hello,

I am currently tuning my motor for closed-loop velocity control but I am having some issues that I am not how to fix them. I am using a GM3506 w/ AS5048A encoder (using Magneticsensor PWM). The issue I am having it seems like at low speeds < 5 rad/s it is vibrating a decent amount and seems somewhat jittery still. I have played with the tuning parameters and below is the code I am currently using:

const int MOT0_PhA = PB1;

const int MOT0_PhB = PB0;

const int MOT0_PhC = PA7;

//Encoder Pins PWM

const int ENC1 = PC0;

const int ENC2 = PC1;

const int ENABLE_PIN = PA4;

//Poles of motor

const int pole_pair = 11; 

// Setting up sensors 

//MagneticSensorAnalog sensor = MagneticSensorAnalog(PC0, 5, 935);

MagneticSensorPWM sensor = MagneticSensorPWM(PC0, 4, 938);

void doPWM(){sensor.handlePWM();};

BLDCDriver3PWM driver = BLDCDriver3PWM(MOT0_PhA, MOT0_PhB, MOT0_PhC, ENABLE_PIN);

// Motor init

BLDCMotor motor = BLDCMotor(pole_pair, 5.57);

// For live tuning

float target = 0.0;

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() {

  // monitoring port

  Serial.begin(115200);

  // initialise magnetic sensor hardware

  sensor.init();

  sensor.enableInterrupt(doPWM);

  motor.linkSensor(&sensor);

  // driver config

  driver.voltage_power_supply = 12;

  driver.init();

  motor.linkDriver(&driver);

  //limiting motor movements

  motor.voltage_limit = 12;

  motor.velocity_limit =  80;

  // set motion control loop to be used

  motor.controller = MotionControlType::velocity;

  // controller configuration 

  // default parameters in defaults.h

  // controller configuration based on the control type 

  // velocity PID controller parameters

  // default P=0.5 I = 10 D =0

  motor.PID_velocity.P = 1;

  motor.PID_velocity.I = 10;

  motor.PID_velocity.D = 0.0001;

  motor.LPF_velocity.Tf = 0.5;

  // jerk control using voltage voltage ramp

  // default value is 300 volts per sec  ~ 0.3V per millisecond

  motor.PID_velocity.output_ramp = 1000;

  // since the phase resistance is provided we set the current limit not voltage

  // default 0.2

  motor.current_limit = 0.5; // Amps

  // 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.");

  _delay(1000);

}

// velocity set point variable

float target_velocity = 1.0; // Rad/s

void loop() {

  serialLoop();

  // main FOC algorithm function

  motor.loopFOC();

  motor.move(target);

  motor.monitor();

}

I am using the serial window to change the speed and below is a snippet of the target velocity (lefts most column) and the measured velocity (3rd column).

1.0000  0.0217  1.0102  5403.2969
1.0000  -0.0032 1.0107  5403.3174
1.0000  0.1265  0.9892  5403.3306
1.0000  0.1542  0.9833  5403.3511
1.0000  0.2395  0.9755  5403.3711
1.0000  0.1591  0.9947  5403.4048
1.0000  0.2281  0.9852  5403.4248
1.0000  0.2085  0.9905  5403.4517
1.0000  0.2452  0.9847  5403.4722
1.0000  0.0755  1.0154  5403.5122
1.0000  -0.0403 1.0327  5403.5459
1.0000  -0.1924 1.0517  5403.5796
1.0000  0.0410  1.0034  5403.5796
1.0000  0.1442  0.9835  5403.5933
1.0000  0.1053  0.9934  5403.6201
1.0000  0.1576  0.9870  5403.6401
1.0000  0.1423  0.9937  5403.6670
1.0000  0.2049  0.9874  5403.6875
1.0000  0.1830  0.9925  5403.7144
1.0000  0.1581  0.9990  5403.7412
1.0000  0.2857  0.9765  5403.7480
1.0000  0.1115  1.0089  5403.7881
1.0000  -0.0138 1.0266  5403.8218
1.0000  0.0102  1.0168  5403.8418
1.0000  0.0273  1.0098  5403.8623
1.0000  0.0753  1.0014  5403.8823
1.0000  0.1247  0.9925  5403.9023
1.0000  0.1734  0.9867  5403.9229
1.0000  0.2416  0.9792  5403.9429
1.0000  0.2231  0.9843  5403.9697
1.0000  0.1294  1.0030  5404.0034
1.0000  0.2892  0.9792  5404.0171
1.0000  0.1039  1.0126  5404.0571
1.0000  0.0609  1.0170  5404.0840

The measured velocity seems pretty unstable and I think that is what is causing the issue but not sure whether its the PID tuning or maybe the accuracy of PWM. Open to any suggestions or questions you may have!

If you can, maybe try the spi interface of the as5048

I may need to if I know there isnt any other way I can improve it at the moment. The only issue is the current sensor I purchased only has the PWM wiring and I would need to buy the other one to use SPI. Does using SPI actually improve the smoothness movement in the motor due to better accuracy?

Hey @DGAQ,

PWM sensor type is arguably the worst performing type of sensors for the simplefoc. One of the reasons why is that we use function micros() to measure the duration of the pulses. As these pulses have the duration of arround 1ms (1kHz), the best resolution you can hope for is 1000 cpr. Which is really low/.

When it comes to slow movements, the resolution of the sensor plays a great role, basically the more precise the sensor the lower the velocities you will be able to run your motor with.

So there is couple of thins you can try:

  • Try finding better pid parameters. Try using the Commander interface and the SimpleFOCStudio
  • Try to implement better code for the PWM sensor, if you are experienced with embedded programming this should not be too complicated. The implementation should be much more hardware specific than the one we provided.
  • Try adding a bit of angle filtering: try changing motor.LPF_angle.Tf.

If nothing of all these things work, you will probably need to change the sensor :smiley:

1 Like

Hey @Antun_Skuric,

I appreciate the response! Yea based on what I have been reading it does seem like PWM is not the best option to go with in terms of precision…

I will continue to try and tune the PID parameters some more but if that does not work out maybe ill take a stab at implementing some better code. I did try the filtering which helped a bit but still not achieving the smoothness I am looking for at low speeds.

Worse comes to worse may have to find the SPI version of my sensor (Not sure why its difficult to find one with the SPI wringing on it, they only seem to sell the PWM version).

Just as an aside, you can order the AS5048A from AMS - the small evaluation board it comes with standard 2.54mm pitch holes you can easily solder wires or a header to:

I’m finding my velocity output is somewhat unsmooth even with SPI communication:

I’m looking into why.

@runger,

Oh there we go good find! Only downside is I would would probably have to redesign the “backpack” that holds the current sensor in nicely so may make the whole assembly a bit beefier.

Interesting, based on the looks I would have to say it looks about the same as mine (didnt actually plot it but the spread in values seems similar). Was this using the monitoring software?

Hey guys,

@DGAQ you cal also try downsampling the motion control loop. It will take a bit more time in between velocity calculations and the filtering will work better.
motor.motion_downsample = 5; // downsample 5 times

And if you are using an STM chip look into the work of @Chris in this thread
https://community.simplefoc.com/t/magneticsensorpwm/868

He has implemented this sensor “properly”, exploiting all the hardware features of the stm32.

Now regarding the smoothness that you can expect.
With the PWM sensor the highest resolution you can reach is 4096 cpr. And that is really not a lot.
For 1 rad/s velocity you will be passing through ~650 cunts per second and if your loop runs at 1khz then you’ll see 1 count change in each 2 loop calls :smiley:
Which makes for a terrible velocity calculation.

So what you can try to do is leave the FOC loop running at max frequency and calculate the ;motion control loop down-sampled to 5ms per call for example. This you can do with the motion_downsample parameter. At the moment this parameter is a ratio not the time so seting it to 10 means that your motor.move() will be called each tenth time the motor.loopFOC() is called.

Also I have a question, does your motor move smoother in torque mode?

2 Likes

That’s our new SimpleFOCStudio, thanks to @JorgeMaker :smiley_cat:
Give it a shot, its handy for this kind of thing, but of course the monitoring output will also affect performance a little bit.

I have to say I’m puzzling about this, because the angle output is so smooth, but the velocity output just isn’t. It’s smooth enough that velocity mode works, and like Antun said, you can smooth it more with the downsample and the Velocity-LPF, but I have the feeling that it should be smoother, and there is something I’m still missing. I wonder if there is discretisation on the timer side, which paired with the loop frequency used leads to this oscillating output on the velocity… or if it is actually caused by the interaction of the sensor lag and the PID controlling the velocity around the set-point.

1 Like

@Antun_Skuric I see that motion_downsample but did I did read about it and saw that it could help with the overall smoothness. Was just too deep into tuning the PID I didnt end up trying it out.

The post that you linked looks promising based on the the statistics test results he had. I do wonder if he had tried using that in velocity mode or if that’s just the raw output of the sensors?

Hmmm yea I knew going into using the PWM setup it wasn’t going to be the most accurate but I wasn’t looking for the upmost precision. But I guess I am seeing the reasons why it is not the best not. I am working with the Storm32 board and was hesitant to do the modifications that were needed to work with SPI in this post https://community.simplefoc.com/t/code-adaptation-for-storm32-bgc-v1-31-3-x-bldc-motors-with-simplefoclibrary/21.

And when you say run it at the max frequency do you mean adjusting the BLDC driver frequency? On the docs I did find driver.pwm_frequency = 50000; and for the STM32 you can max it out to 100kHz.

Lastly, I have not tried running it in torque mode yet mainly since I took a deep dive into the velocity mode but I will try this also. Wish I had more time to test out all the suggestions so sorry for the delay but will share my findings when I get a chance :sweat_smile:

@Runger,

ahhhh so it is that I was wondering. I am also a little confused because in angle mode I have had the same smoothness but assumed that velocity would be similar. Do you think that the thread @Antun_Skuric pointed me to about the improved STM chip code with PWM sensors may help?

Like I said above thank you all for your help! I wish I had more time to test and try out your suggestions but as soon as I try I will let you know my findings.

It will definately improve the accuracy of the PWM measurements, which as Antun pointed out are not as precise to begin with. On the PWM you get 12bit, vs 14 on SPI… I haven’t done it myself though, so I can’t give you a experience-based answer, I’m sorry…