Backspin and coggling on nema 23

Hi All!
I’m new here, first of all I want to say thank you to all the people who worked at this library, this is amazing.
I am facing a strange issue, that I did not saw any kind of related post in the community.
I am trying to control using Angle Mode a Nema 23 to do something similar to a steering wheel, as motor controller I tried with L298N and 2x BTS7960 (same issue with different torque on both) ,as sensor I am using a AS5600 and as microcontroller an Arduino Uno.
The issue is that when trying to rotate the “wheel” offsetting that from it’s target position, the movement is not so smooth and sometimes randomly it starts to spinning in the opposite direction where it should go (the same direction where I am applying force to), with an higher speed than the one limited by the parameters I set.
Sometimes it automatically stop and it goes back to the target point, sometimes it continues spinning until I touch it.
It seems that it happens at the same time when I encounter a coggle on trying to rotate the wheel, the problem reduces (but is still present) when the output voltage is set to very low.
I tried to PID tune the system, I have a bit of experience on it, but the issue seems completely unrelated to the tuning.
Here a video of the issue:
SimpleFoc Coggling and Backspinning
The sensor is giving me back clean and precise data, even when it’s spinning without control.
The code is just the angle control example, with AS5600 i2c sensor setup and stepper driver correctly set up.
Do someone have a clue about what could cause this issue?
Thanks in advance!!

Hey @Pipe,

I think the issue might be the fact that the magnetic sensors have the absolute angle value saved as the relative angle (0-2pi) + number of rotation*2pi
And the code is tracking the angle of the sensor and counting the number of rotations that the motor did by checking the difference in the angle value in between loops.

So at the moment the code which determines when to count the new motor rotation is placed in the Sensor class

You can maybe try to play with the value 0.8 and see if you can exterminate this behavior.

But first it would be good if you can verify if the miscounting is the issue. To do that just output the motor’s shaft angle (you can use monitoring as well) and see if when you hold the motor there are sudden jumps in motor position. The jumps will be N times 2pi in value.

The reason for this could be that since you’re stopping the motor by hand, the current increases and produces a bit of noise in the I2C lines which trigger some sudden big changes in the sensor position readings (and the code thinks that the full rotation happened).

Hey @Antun_Skuric !!
Thank you so much for helping me!
I did a test, debugging in the void loop the sensor angle like this:
Serial.println(sensor.getAngle());
I recorded this test in this video:

But, analysing the video frame by frame, I really can’t spot the miscounting issue, the sensor seems to retrieve clean data.
I did a (not so perfect) 3d printed mount to attach the magnet to the shaft, it’s not perfectly centered, but I did some tests and it seemed to do it’s job.
Could this thing be the cause of the issue? Did you spot something strange in the video?
As you see it starts turning in the wrong direction with a speed waaay higher than the maximum that has been set in the Arduino Code.
Thanks again for your time!

Hey @Pipe,

I’m happy to help, at least to try :smiley:
Ok, so the angle was halpful and it does indeed seem like the angle measurement is pretty smooth and it does not show any obvious issue.

I was wondering could you maybe also log the velocity and voltage output?
This will help us reduce some more the possible issues .:smiley:

Hello @Antun_Skuric .
I am currently trying to debug voltages and velocity, but currently the sensor velocity function is returning always 0.
image
But if I try the Magnetic Sensor i2c example it works pretty fine, this is strange…
Here you can find my current code:

/**
 *
 * Position/angle motion control example
 * Steps:
 * 1) Configure the motor and magnetic sensor
 * 2) Run the code
 * 3) Set the target angle (in radians) from serial terminal
 *
 */
#include <SimpleFOC.h>

// magnetic sensor instance - SPI
//MagneticSensorSPI sensor = MagneticSensorSPI(AS5147_SPI, 10);
// magnetic sensor instance - MagneticSensorI2C
MagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C);
// magnetic sensor instance - analog output
// MagneticSensorAnalog sensor = MagneticSensorAnalog(A1, 14, 1020);

// BLDC motor & driver instance
//BLDCMotor motor = BLDCMotor(11);
//BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);
// Stepper motor & driver instance
StepperMotor motor = StepperMotor(50);
StepperDriver4PWM driver = StepperDriver4PWM(5, 6, 9, 10);

// angle set point variable
float target_angle = 0;
// instantiate the commander
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&target_angle, cmd); }


void setup() {

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

  // driver config
  // power supply voltage [V]
  driver.voltage_power_supply = 24;
  driver.init();
  // link the motor and the driver
  motor.linkDriver(&driver);

  // choose FOC modulation (optional)
  motor.foc_modulation = FOCModulationType::SpaceVectorPWM;
  //motor.foc_modulation = FOCModulationType::SinePWM;

  // set motion control loop to be used
  motor.controller = MotionControlType::angle;

  // contoller configuration
  // default parameters in defaults.h

  // velocity PI controller parameters
  motor.PID_velocity.P = 0.2f;
  motor.PID_velocity.I = 20;
  motor.PID_velocity.D = 0;
  // maximal voltage to be set to the motor
  motor.voltage_limit = 9;

  // velocity low pass filtering time constant
  // the lower the less filtered
  motor.LPF_velocity.Tf = 0.01f;

  // angle P controller
  motor.P_angle.P = 20;
  // maximal velocity of the position control
  motor.velocity_limit = 20;

  // 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(4.83, Direction::CW);

  //add target command T
 command.add('T', doTarget, "target angle");

  

  Serial.println(F("Motor ready."));
  Serial.println(F("Set the target angle using serial terminal:"));

  _delay(100);
}


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_angle);

  Serial.print("Angle: ");
  Serial.print(sensor.getAngle());
  
  Serial.print(" Velocity: ");
  Serial.print(sensor.getVelocity());
  
  Serial.print(" U_Alpha: ");
  Serial.print(motor.Ualpha);
  Serial.print(" U_Beta: ");
  Serial.println(motor.Ubeta);
  

   
  // function intended to be used with serial plotter to monitor motor variables
  // significantly slowing the execution down!!!!
  // motor.monitor();

  // user communication
  command.run();
}```

This is mostly the angle example…
If you think that at least the voltages could be useful I could easily record the video (ps Am I accessing to the correct parameters with motor.UAlpha and beta?)
Thanks Again!

Hi!

You can try to print:

Serial.print(motor.shaft_angle);

to maybe see the values. The sensor.getVelocity() can be sensitive to the time elapsed between calls to getAngle() and getVelocity()

Hey @Pipe
Please use the motor.shaft_angle and motor.shaft_velocity when using the sensor with FOC.
When the sensor is used for some standalone application then it makes sense to call getAngle and getVelocity. But when using it with FOC the sensor variables are used in the algorithm and the motor variables are updated with them, calling the sensor getAngle and getVelocity outside the algorithm can result in some strange behavior, as you’ve already seen.

So I’d suggest you add this in your loop:

Serial.print(motor.shaft_angle);
Serail.print("\t");
Serial.print(motor.shaft_velocity);
Serail.print("\t");
Serial.println(motor.voltage.q);

Or even better is using the monitoring:


void setup(){
....
  // comment out if not needed
  motor.useMonitoring(Serial);
  motor.monitoring_downsample=1;
  motor.monitor_variables = _MON_VOLT_Q | _MON_VEL | _MON_ANGLE;
....
}
void loop(){
....
  motor.monitor();
....
}

Hello @Antun_Skuric and @runger!
So I tried with the monitor, but it seems that when I activate it, the code slows so down that the backspin stops happening, but the coggling becomes worse.
So here a video with printed the data you asked for:
(angle + velocity in the first part of the video, angle and voltage in the second one, all three in the third part, as you can see the issue stop happening when the Arduino slows down because of the 6 serial print at the end.)
Simple FOC Backward Spin issue with Angle,Velocity and Voltage Log - YouTube
Do you have some idea?
Thanks again!!!

Hey @Pipe,

Thanks for the video.
I am really not sure what is going on but from the data in the video it seems like there is some kind of misalignment that’s happening.
This can be due to a high current peak that is interfering with the I2C communication. Can you try to lower the voltage limit and see if this happens still.
I see in the video that your voltage limit is 9V and the current is raising to somewhere around 1Amp, so you could try reducing the voltage limit to 5V and see if the issue diapers. If it does that means its most likely the I2C communication if not then we continue investigating :smiley:

Yes I already tried lowering the voltage, the issue mostly disappears, but I have to go very low (around 4v) and the torque is not enough for me.
What I could do to try filtering this interferences? Could be useful using an optocoupler between the power source and Arduino? Or it could be more complex than that?
In this project I would like using a magnetic encoder such as as5600 or as5048, could they be connected in some other way where I don’t face this kind of issue?
I saw in another post where @runger was suggesting to use the as5048 instead of 5600 to avoid coggling and having a more smooth result, even at low voltages I still have a lot of cogging, could be the use of the AS5600 the cause of them?
Really thanks for your time…