Weird jump after initialisation

When I’m trying the closed loop velocity control example I see a weird jump. After the initialisation the motor shaft suddenly jumps 90 degrees.

In the application where I’m hoping to use this motor this kind of sudden jump would be bad. So I would like to get rid of it if possible. (video of the jump: )

My current assumption is that I’m doing something wrong, and that causes this jump.
If you could help me get rid of it that would be amazing.

Hardware setup:
microcontroller: an arduino uno (elegoo uno R3)
shield: SimpleFOCShield v2.0.3
motor: Ipower GM2804
encoder: AS5048A Encoder mounted under the motor, magnet mounted on the shaft. (I really hope that it’s the right kind of magnet, the whole set was built together by the manufacturer.)
there is no phsyical load on the motor.
the arduino is powered from usb, the shield is powerd from a bench power supply (12v, constant voltage mode)

Software setup:
I’m using askuric/Simple FOC@^2.1.1. I’m compiling and uploading my code with platformio.

Encoder only test:
As a first experiment I tried a simple encoder test.
The printed sensor values seem sensible and stable to me.
They decrease if I’m rotating the motor’s shaft clockwise, and increase counter clockwise.
If I reset the arduino the value remain unchanged (modulo 2*pi) as one would expect from an absolute sensor.

Based on this test I have concluded that the encoder seems to be functioning correctly.

Openloop velocity test:
I copied the open_loop_velocity_example.ino file.
Modified the pole pair number to 7.
Modified the pwmA, pwmB, pwmC, Enable pins according to how my board is solder jumpered.
(code )

The motor moves very smoothly as commanded. target_velocity=+1.0 moves it counter-clockwise, target_velocity=-1.0 moves it clockwise.
I can sometimes see a small jump of the motor shaft after the arduino reboots, but I think that’s normal in open loop mode.

Based on this test I have concluded that the wiring of the motor seems to be in a good working condition.

Closed loop velocity test:
I believe this is the next test if one wants to proceed methodically.
I copied the velocity_motion_control/magnetic_sensor/velocity_control.ino file.
I have modified the motor pole pair count and pin numbers as above.
I have also modified the sensor setup according to my wiring.

After uploading this code I observe the following behaviour.

The motor first moves slowly counter-clockwise, then slowly clockwise. (I believe this is the initialisation.)
The firmware prints the following to the terminal:

MOT: Monitor enabled!
MOT: Init
MOT: Enable driver.
MOT: Align sensor.
MOT: sensor_direction==CW
MOT: PP check: OK!
MOT: Zero elec. angle: 4.08
MOT: No current sense.
MOT: Ready.
Motor ready.
Set the target velocity using serial terminal:

(I believe this signals that the initialisation was succesfull.)

Do note that the measured zero electric angle seems to vary slightly.
Out of 10 samples I have measured it anywhere from 3.99 to 4.24. (mean: 4.12, stdev: 0.083)
Is this ammount of variability normal? I assumed it is, but I guess it’s best if I ask.

Right after the 1000ms delay elapses and the loop starts to iterate the motor’s shaft start to oscillate.
Just lightly touching the vibrating motor is enough to dampen this oscillation out.
Video of the behaviour:

If I don’t touch the motor then seemingly it keeps oscillating as long as I let it. (Longest I ever let it oscillate was 5 second.)

After the oscillation is stopped the motor responds well to requested velocities. target_velocity=+1.0 rotates it counter-clockwise, target_velocity=-1.0 rotates it clockwise.
Worth mentioning that the movement is not as smooth as the open loop movement was, it seems to “chug” a little periodically.

On a hunch I decreased the motor.PID_velocity.I from the default 20 to 10.

This changes the behaviour of the system. It does the usual initialisation dance, and after the dance and the 1000ms delay the motor’s shaft suddenly jumps clockwise.
Video of the behaviour:

This is the jump I would like to eliminate if possible.

After the jump the motor responds to requested velocities as above. Of course because of the reduced integral term it is chugging a bit more and is slightly more springy.

I made the following observations about the shaft jump:

The jump is actually a rapid change followed by rapidly dampening oscillations. With I=10 these oscillations seems to rapidly decrease in amplitude and the shaft stops very quickly.
I can see these oscillations when I plotted the sensor angles as a function of time.

I believe that the jump happens even when I=20, but the oscillations don’t die out and that hides the jump. That’s why I didn’t notice in that experiment.

I modified the code one more time to print the sensor angle before the jump and after the jump.
I also hardcoded the measured direction and zero electric angle to skip the calibration routine.
(code )

With this code I could see that:

  • the jump when happens always happens to a clockwise direction (decreasing angle values as measured by the sensor)
  • when the sensor angle just after the initialisation is close to zero but is positive there is no jump
  • when the sensor angle is close to zero but negative it jumps about 90 degrees

I put the measured before jump and after jump sensor angles into this spreadsheet:

This is how far I got. I suspect that there is something wrong with how I’m initialising. Something with the sensor maybe?
Any advice, tips, or wisdom is warmly welcome. If I missed some important detail please let me know.
And terribly sorry that my post got this long.

I guess I forgot the most obvious question:

Is that jump expected? Just because it’s undesirable in my application I assumed it must be a bug. But maybe this is just how FOC works?

I think I figured out the root cause of my problem.

It seems that the getVelocity method of the MagneticSensorSPI returns an incorrect huge value for the first time it is called. This huge spike causes the PID controller to overreact and that results in the jump.

The magnitude of the spike is proportional to the absolute position of the encoder. This happens because the angle_prev is not initialised at the first call yet, which makes the difference between angle_c and angle_prev just the position.

From my code I can easily fix this by calling sensor.getVelocity() at the end of my setup function and discarding the value returned. So all is good for me.

From the library’s perspective maybe we should initialize angle_prev to the current position in the init of the magnetic sensor? Just an idea.

Sorry that I was polluting the forum with my long ramblings.

For what it is worth I learned a ton about FOC reading your code and tracing my weird jump issue. So thank you!

Hey @krisoft!

Thanks for the heads-up. We are in the process of restructuring the sensor class and the reading code so we will definitely take in consideration this issue as well. You are absolutely right that this situation has to be handled properly.

I am happy you’ve found your solution :smiley:

This may be unrelated and I may be saying the obvious but SPI is a simultaneous packet exchange. The sensor won’t just read the value when you request it, it will send you whatever is in the register and at the same time receive your request. Perhaps at the very beginning the register contains garbage that needs to be ignored?