The motor is vibrating around setpoint

Hi,

I have the following setup:
Motor: MY-4021F (http://www.jdpowersky.com/en/p-info.aspx?cid=1&id=47)
Sensor: AS5270B – PWM
Driver: SimpleFOCShield v2.0.3
MCU: Nucleo-144 STMF767zi

I have been struggling with this setup for some days now, without removing the vibration in the motor. Thus, wondered if anyone in this community has come across something similar before?

Here is a video of the vibration: https://youtu.be/MwfljzbmEFM

I have tuned the angle P and velocity PI(D) controllers without achieving a better result, so I don’t believe this is a pure tuning case. I have noticed that I use a relatively high value for TF compared to other examples, but this is necessary to avoid the system oscillate and become unstable. This may indicate that there is too much noise from the sensor?

Here is a plot with angle and velocity:

FOC

Here is the code I currently use:

#include <SimpleFOC.h>

MagneticSensorPWM sensorBot = MagneticSensorPWM(10, 4, 512);
void doPWMBot() { sensorBot.handlePWM(); }

BLDCMotor motor = BLDCMotor(11);
BLDCDriver3PWM driver = BLDCDriver3PWM(5, 9, 6, 8);

float target = 3;

Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&target, cmd); }
void doPidAngle(char* cmd) { command.pid(&motor.P_angle, cmd); }
void doPidVelo(char* cmd) { command.pid(&motor.PID_velocity, cmd); }
void doLpf(char* cmd) { command.lpf(&motor.LPF_velocity, cmd); }
void doMotor(char* cmd) { command.motor(&motor, cmd); }

void setup() {
	sensorBot.init();
	sensorBot.enableInterrupt(doPWMBot);
	motor.linkSensor(&sensorBot);

	driver.voltage_power_supply = 24;
	driver.init();
	motor.linkDriver(&driver);
	
	motor.foc_modulation = FOCModulationType::SpaceVectorPWM;
	motor.controller = MotionControlType::angle;
	motor.voltage_limit = 6;

	motor.PID_velocity.P = 1.5;
	motor.PID_velocity.I = 5;
	motor.PID_velocity.D = 0;
	motor.LPF_velocity.Tf = 0.1;
	motor.PID_velocity.output_ramp = 1000;

	motor.P_angle.P = 5;
	motor.velocity_limit = 5;

	Serial.begin(115200);
	motor.useMonitoring(Serial);

	motor.init();
	motor.initFOC();

	command.add('T', doTarget, "target angle");
	command.add('C', doPidVelo, "PID vel");
	command.add('A', doPidAngle, "PID angle");
	command.add('L', doLpf, "LPF vel");
	command.add('M', doMotor, "Motor");

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

void loop() {
	Serial.print(motor.shaft_angle);
	Serial.print('\t');
	Serial.print(motor.shaft_angle_sp);
	Serial.print('\t');
	Serial.print(motor.shaft_velocity);
	Serial.print('\t');
	Serial.print(motor.shaft_velocity_sp);
	Serial.print('\n');

	motor.loopFOC();
	motor.move(target);
	command.run();
}

Hoping for some good suggestions that can help me further with the project.

Hey @Voilaa,

The pwm sensors are really the worst performing ones we support. If you have any other way of connecting them I’d suggest you to switch :smiley:
And the main reason is the noise.

No in terms of tuning. I’d say that your velocity P gain is too high, try smaller values there and you can remove the I value until you get better results.
Here are some more things you can try:

  • use angle lpf: motor.LPF_angle.Tf = 0.001; (monitor command AF) start small and try seeing if it makes things better. The issue here is that filtering the angle value can cause the motor misalignment and instability so try keeping it as low as you can.
  • use motion downsampling motor.motion_downsample = 10; (monitor command CD) Since your nucleo F7 is very very fast and it only makes sense to read the sensor value each 1ms (because these sensors work on 1kHz ( ma 2.2khz in your case I suppose ) then you can downsample the motion control and speed calculation. The higher the number the more time in between velocity calculation. It is necessary sometimes even with encoders for fast mcus.
  • Check that you have a good max and min values, that there is no jump in angle value when you cross the 0 position

Also I am happy to hear that you’re using the nucleo-144, have you had any trouble with the library to make it work?
I would love to support the nucleo-144 officially with the library but I do not have one on my hands. So if you have any suggestions/problems about the current implementation let us know :smiley:

Hey @Antun_Skuric,

Thanks for the complementary answer. I have now tested with motor.LPF_angle.Tf and motor.motion_downsample , both in combination and separately, as well as tuning the controller again afterward. But the motor is still vibrating.

So I have ordered another sensor to see if it solves the problem in the first place. Although it is desirable to use the AS5270 to make it redundant.

There has not been any challenge with the nucleo-144 to make it work with the library. The only drawback with the card, in my opinion, is that the analog inputs only read 3.3V and not 5V. Thus the idea was to use PWM for reading sensor data.

That sounds great, thanks for the info!

I know it is not pretty but have you considered using a voltage divider, to be able to use the 5V analog output?

For the PID controllers, I’d suggest you to put I and D values to 0 and tune only P values + velocity and angle LPF. If this cannot be smooth then using the integrative and derivative component will not help.