Motor moving pole to pole in openloop control

I am driving a motor in openloop velocity control at a fixed speed. I have manually given encoder and IMU inputes without using simpleFOC library. Here is the Void Loop() of my code

void loop() {
uint16_t rawangle = readAS5048A();   //RAW read from the sensor (not in degrees yet)
float realAngle = (float)rawangle * 360.0 / 16384.0; // convert to degrees
//Serial.print("Motor Angle = "); Serial.println(realAngle);
angleDeg = get_x_angle(); // get angle from mpu6050
error = angleDeg-realAngle;
if (error > 180.0f) error -= 360.0f;
if (error < -180.0f) error += 360.0f;
if ( (error > 0)) target_velocity = -2;
else  target_velocity = 2;
if(error>=1.0 || error<=-1.0){ // if error is larger than 1 degree
motor.move(target_velocity);
//Serial.print("Moving to target angle: ");
}
else{
motor.move(0); // stop the motor when close enough to target
}
}

When my motor reaches the target angle, I forcefully rotate the motor. But when I forcefully rotate the motor, The motor moves pole to pole. Like it moves in steps and not smoothly.Why is this happening? Can anyone suggest me how to make the motor move smoothly when i force it to.

Thanks.

Since you have a sensor why not try our closed loop angle mode?

get it working well in closed loop torque voltage mode, then switch to velocity mode and tune the PID for that, and finally try closed loop angle mode… I think it will do more or less exactly what you’re trying to do…

Sure,
I’ll try this. Thanks for the response

Hi @runger
I tried running the example code in closed loop torque control mode. In the initialization, my motor moves a little in both directions but then it shows this error message -

MOT: Enable driver.

MOT: Align sensor.

MOT: Failed to notice movement

MOT: Init FOC failed.

It fails to notice motor movement. I am using an AS5048A magnetic encoder connected via SPI. In the example code I have changed the chipselect pin according to my circuit. I have tested this setup to read angle from my encoder and it works perfectly. Could you please help me out with this?

Update - In my encoder test code I am sending the command 0XFFFF to read angle while in the library code it was .angle_register = 0x3FFF. So I have changed this to 0XFFFF but it still cant detect motor movement.

Yeah, this error means you have a sensor problem.

Most likely it is some kind of issue with the sensor reading.

Another possibility is that the alignment voltage is too low. But if you say the motor is visibly moving during the initialization then this is not the problem.

have you run the sensor test examples to see if the sensor is working by itself?

Hi @runger ,
Sorry for the late response, I was out due to the Indian holidays. Yes I have tested my AS5048A encoder and it works perfectly via SPI. I can assure you that there is no issue with the sensor itself.

Would you mind sharing your code and the output from the serial console?

there seems to be something still wrong with your setup, but it’s hard to say what based on the current information.

The AS5048A is well supported in SinpleFOC, both through the generic MagneticSensorSPI class and the MagneticSensorAS5048A class from our drivers repository. Many people have used it successfully, so it should work for you too.

Sure… Here is the example code I am using. I am also attaching the AS5048A code I have used for testing and its output.
Hardware Setup - I am using a basecam BGC board which uses the ATmega328P microcontroller. The spi lines of the basecam are connected with the AS5048A.

To make the motor move, I type the command - T 200 in the terminal

/***

* 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>

#include <SPI.h>

// Define the chip select pin

const int CSPin = A4;

// SPI settings for AS5048A

SPISettings AS5048ASettings(1000000, MSBFIRST, SPI_MODE1);

// magnetic sensor instance - SPI (config, chip select pin)

MagneticSensorSPI sensor = MagneticSensorSPI(AS5048_SPI, CSPin);

// 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(7);

BLDCDriver3PWM driver = BLDCDriver3PWM(3, 5, 6);

// Stepper motor & driver instance

//StepperMotor motor = StepperMotor(50);

//StepperDriver4PWM driver = StepperDriver4PWM(9, 5, 10, 6,  8);

// angle set point variable

float target_angle = 50;

// instantiate the commander

Commander command = Commander(Serial);

void doTarget(char* cmd) { command.scalar(&target_angle, cmd); }

void setup() {

// use monitoring with serial

Serial.begin(115200);

// enable more verbose output for debugging

// comment out if not needed

SimpleFOCDebug::enable(&Serial);

// 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 = 12;

driver.init();

// link the motor and the driver

motor.linkDriver(&driver);

// choose FOC modulation (optional)

motor.foc_modulation = FOCModulationType::SpaceVectorPWM;

// 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 = 4.0f;

motor.PID_velocity.I = 20;

motor.PID_velocity.D = 3;

// maximal voltage to be set to the motor

motor.voltage_limit = 6;

// 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;

// comment out if not needed

motor.useMonitoring(Serial);

// initialize motor

motor.init();

// align sensor and start FOC

motor.initFOC();

// 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(1000);

}

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

// function intended to be used with serial plotter to monitor motor variables

// significantly slowing the execution down!!!

// motor.monitor();

// user communication

command.run();

}

The output for my code is -

MOT: Monitor enabled!
MOT: Init
MOT: Enable driver.
MOT: Align sensor.
MOT: Failed to notice movement
MOT: Init FOC failed.
Motor ready.
Set the target angle using serial terminal:
Warn: \r detected!
200.000

The Code which works for my AS5048A is -

#include <SPI.h>

// Define the chip select pin

const int CSPin = A4;

// SPI settings for AS5048A

SPISettings AS5048ASettings(1000000, MSBFIRST, SPI_MODE1);

uint16_t readAS5048A() {

uint16_t angle = 0;

// Start SPI transaction

SPI.beginTransaction(AS5048ASettings);

// Pull CS low to select sensor

digitalWrite(CSPin, LOW);

// Send read command (0xFFFF)

SPI.transfer16(0xFFFF);

// Pull CS high

digitalWrite(CSPin, HIGH);

delayMicroseconds(50);

// Pull CS low again to read data

digitalWrite(CSPin, LOW);

// Read the angle data

angle = SPI.transfer16(0xFFFF);

delay(10);

// Pull CS high

digitalWrite(CSPin, HIGH);

// End SPI transaction

SPI.endTransaction();

// Mask to get only 14-bit data (remove parity and error flag bits)

angle = angle & 0x3FFF;

return angle;

}

void setup() {

Serial.begin(115200);

Serial.println(“AS5048A Angle Reader - SPI”);

delay(100);

// Set the chip select pin as output

pinMode(CSPin, OUTPUT);

digitalWrite(CSPin, HIGH);

delay(500);

// Begin SPI communication

SPI.begin();

}

void loop() {

// Read angle from AS5048A

uint16_t rawAngle = readAS5048A();

// Convert to degrees (14-bit resolution)

float angleDegrees = (float)rawAngle * 360.0 / 16384.0;

Serial.print("Raw: "); Serial.print(rawAngle);

Serial.print(" | Angle: "); Serial.print(angleDegrees, 2); Serial.println(“°”);

delay(100);

}

And the output for this encoder read is -

Raw: 7484 | Angle: 164.44°
Raw: 7484 | Angle: 164.44° 
Raw: 7484 | Angle: 164.44° 
Raw: 7482 | Angle: 164.40° 
Raw: 7482 | Angle: 164.40°
Raw: 7481 | Angle: 164.38° 
Raw: 7486 | Angle: 164.49° 
Raw: 7478 | Angle: 164.31° 
Raw: 7480 | Angle: 164.36°