Position control example using SimpleFOCShield and Stm32 Nucleo-64

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.enableInterrupts(doA, doB);
  // link the motor to the sensor

  // driver config
  // power supply voltage [V]
  driver.voltage_power_supply = 24;
  // link 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
  // comment out if not needed

  // initialize motor
  // align sensor and start FOC

  // 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:"));


void loop() {




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.

This is F103RB!! How can I solve this problem…? I still haven’t solved this problem…

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.

Really? I’ll try it right now!! Thank you~

I changed the pin number and proceeded, but it still doesn’t work… Do you have any further advice?

did you try the other things I suggested?
does the simplefoc serial debug output tell you anything interesting?

Are you confident about the pulses per rotation of 512? I wonder if you need to 4x that to 2048 (e.g for quadrature encoding).

Might be worth running sensor code alone and see how many pulses you get if you rotate 360 manually

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;

  // link the motor and the 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.initFOC();

  // add target command T
  command.add('T', doTarget, "target velocity");
  command.add('L', doLimit, "voltage limit");

  Serial.println("Motor ready!");
  Serial.println("Set target velocity [rad/s]");

void loop() {

  // motor.loopFOC();



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!

Is your motor really 2pp? Maybe the commutation is not right because your electrical angle is very large compared to what it should be.

So I tried to set the pp to 2, 4, 9, 11, etc., but it didn’t work…

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:


Also you can get extra info for the driver init if you can set the build flag:


Thank you for your reply!

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.