Hi, I’m trying to run a BLDC motor using a nucleo-64 . examples were used, and the code was modified little by little to match the motor and encoder I use. However, the number of poles is estimated to be too high, and the motor is inoperative. The current is also too excessive. This is the output of the serial monitor and the code I used. What’s the problem?
==============================================
MOT: Enable driver.
MOT: Align sensor.
MOT: sensor_direction==CCW
MOT: PP check: fail - estimated pp: 93.09
MOT: Zero elec. angle: 4.70
MOT: No current sense.
MOT: Ready.
Motor ready.
Set the target using serial terminal:
==============================================
#include <SimpleFOC.h>
// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(2);
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);
// encoder instance
Encoder encoder = Encoder(2, 3, 512);
// channel A and B callbacks
void doA(){encoder.handleA();}
void doB(){encoder.handleB();}
// instantiate the commander
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&motor.target, cmd); }
void setup() {
// initialize encoder sensor hardware
encoder.init();
encoder.enableInterrupts(doA, doB);
// link the motor to the sensor
motor.linkSensor(&encoder);
// driver config
// power supply voltage [V]
driver.voltage_power_supply = 24;
driver.init();
// link driver
motor.linkDriver(&driver);
// add current limit
motor.phase_resistance = 5; // [Ohm]
motor.current_limit = 1; // [Amps] - if phase resistance defined
// aligning voltage
motor.voltage_sensor_align = 5;
// set motion control loop to be used
motor.torque_controller = TorqueControlType::voltage;
motor.controller = MotionControlType::torque;
// 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();
// set the initial motor target
// motor.target = 0.2; // Amps - if phase resistance defined
motor.target = 2;
// add target command T
// command.add('T', doTarget, "target current"); // - if phase resistance defined
command.add('T', doTarget, "target voltage");
Serial.println(F("Motor ready."));
Serial.println(F("Set the target using serial terminal:"));
_delay(1000);
}
void loop() {
motor.loopFOC();
motor.move();
command.run();
}
Which Nucleo-64 board? I think this just refers to the board size, and not the chip used… maybe all the pinouts are the same but I am not sure. It would be nice to know what board in specific you are using.
Have you tried open loop?
Can you try without setting motor.torque_controller?
Are you sure these pins for your encoder are actually interrupt capable?
Usually with STM32 you will need to use the real pin name (not arduino 2, 3, etc but like PA1, PC12 etc). So your constructors at the start of the program may need adjustment.
Thank you for your reply!!
Yes. I used the open loop example, and the motor works, but it doesn’t turn 360 degrees. It is traveling back and forth between -20 and 20 degrees from the origin. Can you see what the problem is?
// Open loop motor control example
#include <SimpleFOC.h>
// BLDC motor & driver instance
// BLDCMotor( pp number , phase resistance)
BLDCMotor motor = BLDCMotor(2);
BLDCDriver3PWM driver = BLDCDriver3PWM(PC7, PB4, PB10, PA9);
float target_velocity = 2;
// instantiate the commander
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&target_velocity, cmd); }
void doLimit(char* cmd) { command.scalar(&motor.voltage_limit, cmd); }
void setup() {
// driver config
// power supply voltage [V]
driver.voltage_power_supply = 24;
motor.voltage_limit = 5;
driver.voltage_limit = 10;
driver.init();
// link the motor and the driver
motor.linkDriver(&driver);
// limiting motor current (provided resistance)
motor.current_limit = 0.5; // [Amps]
// open loop control config
motor.controller = MotionControlType::velocity_openloop;
// init motor hardware
motor.init();
// motor.initFOC();
// add target command T
command.add('T', doTarget, "target velocity");
command.add('L', doLimit, "voltage limit");
Serial.begin(115200);
Serial.println("Motor ready!");
Serial.println("Set target velocity [rad/s]");
_delay(1000);
}
void loop() {
// motor.loopFOC();
motor.move(target_velocity);
command.run();
}
Yes. Currently, it is attempting to drive a motor using nucleo-64, but previously, it succeeded in driving a motor using Arduino Uno, at which time the pulses per rotation was set to 512. Isn’t that right…?
If only two phases are operational, perhaps you’ll get this behaviour where it moves back and forth 20degrees.
Loose connector to motor? Perhaps one of the pwm isn’t working?
No, everything works fine… Is there any problem with the code?
The faster you set the target_velocty, the faster the round trip speed. I think we just need to make the motor rotate only 360 degrees instead of 20 degrees reciprocating… What are the causes of this movement?
I have to solve this problem as soon as possible… Help me!
Hmmm… you’re saying it does the back/forth motion continuously, also in open loop mode?
This is a strange error, not sure anyone has described this before.
I’m kind of with Owen that this might be due to one of the phases not working correctly (and because it’s a 2PP motor). Are you really getting PWM on all the pins?
You could try switching on debug output:
SimpleFOCDebug::enable(&Serial);
Also you can get extra info for the driver init if you can set the build flag:
Actually, the number of poles of the motor is not accurate. When Arduino Uno ran this code on the same motor, the estimation of the number of poles was 2, so I wrote it as it was. But when I switched to the nucleoboard and did it again, I found that the number of poles was 15. What’s right?
++ Oh, and how can I check if the PWM pin works well? I don’t really know…
Can you see/count the number of magnets? sometimes they are visible through motor case. A motor with 15pp (30 poles) is unusual - perhaps you can post a photo.
To check the PWM you really need an oscilloscope or logic analyser.
If I suspect problems with one phase I sometimes disconnect a motor phase (1 at a time) to see if movement is worse or same. Usually removing a phase makes the motor motion worse meaning that phase might have been ‘good’. Sometimes removing a phase makes motion no worse, meaning the phase isn’t active e.g lose connection or wrong pin number for this phase.
That’s an indication something is not working right with the sensor. Do either of the boards report PP Check: OK ?
→ Normally the output of PP Check should be OK
As Owen has said, checking the PWM is best done with a logic analyser or oscilloscope. But attaching a LED (via a resistor) from the PWM to GND can also give an indication if it is working.