Getting closer - Shield setup!

ok…stuck. I can not find any examples that will reliably rotate the motor. I have been working with the open loop example and various poll counts to no avail. I tried to write some code to let me try various poll counts but I am unsure if I did it correctly

clues: the motor will rotate about 90’ when I run the pole pair estimator but when it gets to the point in the program were the motor should run…just buzz, no rotation.

will this code work to change the poll count? IE, can driver.init and motor.init be called more than once in the code?
void restart_motor()
BLDCMotor motor = BLDCMotor(poll_count);

// init motor hardware
Serial.print("poll count: ");

ps. aux question. what is the recommended power on sequence? 12v motor power before or after arduino power via usb. I notice without the 12v the SimpleFOC board led lights dim and the motor seems to have some small amount of power via usb. Is that harmful?

would a video of the “find_pole_pairs_number” help?

obtw…if the ‘pole count’ derived from the above web site instructions is 22…should motor.pole_pairs be set to 11?

another test. I used the “open_loop_velocity_example”. With a value of 11 for pole count. The motor WILL rotate (finally!) up to a value of 17 or 18 but 20 is very jittery. With the pole count at 22 only about 10 results in stable rotation. (negative values result in rotation the opposite direction)

I just found “full_control_serial”…uh, I have NO idea the effect of those parameters on the SimpleFOC controller. 10+ variables. Is there a page that gives some sort of instructions for this? I see this page: but nothing that might indicate what affect something like “P gain” will have on making my motors work. A “motor tuning” page would help.

does this look familiar?

For small, low torque motors with little or no gearing, one procedure you can use to get a good baseline tune is to probe it’s response to a disturbance.

To tune a PID use the following steps:

  1. Set all gains to zero.
  2. Increase the P gain until the response to a disturbance is steady oscillation.
  3. Increase the D gain until the the oscillations go away (i.e. it’s critically damped).
  4. Repeat steps 2 and 3 until increasing the D gain does not stop the oscillations.
  5. Set P and D to the last stable values.
  6. Increase the I gain until it brings you to the setpoint with the number of oscillations desired (normally zero but a quicker response can be had if you don’t mind a couple oscillations of overshoot)

What disturbance you use depends on the mechanism the controller is attached to. Normally moving the mechanism by hand away from the setpoint and letting go is enough. If the oscillations grow bigger and bigger then you need to reduce the P gain.

If you set the D gain too high the system will begin to chatter (vibrate at a higher frequency than the P gain oscillations). If this happens, reduce the D gain until it stops.

…still don’t know what to do with:

    • R: velocity PID controller voltage ramp
    • F: velocity Low pass filter time constant
    • K: angle P controller P gain
    • N: angle P controller velocity limit

Hey @Keshka,

I like how detail oriented you are. And you are making progress!

If your motor is not really moving smoothly in the voltage control mode then you still have a problem of either pole pair count or the sensor. We have discussed few time recently the situations where the as5600 are shipped with wrong magnets. Are your magnets polarized axially or radially? They should be polarized radially. Here is a recent thread

Now in terms of PID, once when everything works i don’t think you’ll have many problems running it. Your guide from the post before will work well.
Simplefoc has some docs in the motion control here is the link:

22 poles means 22 magnets on the rotor. You might be able to count them. The magnets are arranged N S N S etc so if you have 22 poles then you have 11 pole pairs. A pole pair defines an electrical rotation so an 11 pole pair motor undergoes 11 electrical rotations per shaft rotation.

I believe my sensor is working correctly, using “magnetic_sensor_12c_example” shows stable readings for both pos and rate. Values for pos are 0 to roughly 6.2 for one revolution. Rotating in the opposite direction yields -6.2.

if I concentrate on the “open_loop_velocity_example”. The sensor/encoder is not used. It should be able to produce smooth rotation up to the theoretical max rpm of the motor (42kv * 12v). Is this correct?

for pole count. Using the test I mentioned above, with a small voltage applied to one pair of motor wires, rotating the motor gives 11 distinct ‘notches’. As I understand it, that would be 22 poles or 11 pole pairs.

I ran this modified version of “open_loop_velocity_example” and experimented with various pole counts. The motor will run with values of 1 through 17 with the speed increasing with greater pole counts. Above 17 and the motor shakes. Hence, I should be able to use a value of 11 from the earlier tests.


// Open loop motor control example
#include <SimpleFOC.h>

// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(11);
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);

void setup() {

driver.voltage_power_supply = 12;
motor.voltage_limit = 3; // rad/s
motor.velocity_limit = 20; // rad/s
motor.controller = ControlType::velocity_openloop;

Serial.println(“Motor ready!”);

float target_velocity = 13; // rad/s should be about 2 rotations per second
int pole_pair = 11; // start value

void loop() {

void serialReceiveUserCommand() {

static String received_chars;

while (Serial.available()) {
char inChar = (char);
received_chars += inChar;
if (inChar == ‘\n’) {

  // change the motor poles
  pole_pair = received_chars.toInt();
  Serial.print("pole pair ");
  // reset the command buffer 
  received_chars = "";
  motor.pole_pairs = pole_pair;


ugh! I did not understand the “nomenclature”
says 24 coils and 22 magnets.
IE …11 pole pairs.

another note. This motor I have will oscillate badly at voltages higher than 2 with the default pids while sitting on my desk. There for I need to have it anchored down to tune it further.

Hi Keshka,

Is it working for you? I have the 4114 - it has 11 Pole Pairs as you correctly found out.

It works fairly well for me with the default example settings. I don’t need to tune it to get decent commutation at 10V. This is true for different drivers.

Which MCU are you using? SAMD (Arduino MRK and others) is not yet supported. An Arduino Uno in combination with an I2C sensor might be a bit slow for really nice commutation, depending on how much other stuff you’re doing in the main loop…

If open loop is working but closed loop is not, then there is a high probability that it is a sensor problem. Is the I2C address set correctly? Are the I2C pull-ups installed? Is your magnet the right kind - i.e. radially magnetised?

:slight_smile: even if it is not oscillating it needs to be fixed - when changing direction or stopping it moves a lot otherwise. Its quite a heavy beast for a gimbal motor.

Hi Runger;
sorry for the delay. I finished printing all the parts for the reaction wheel and had to wait for eBay to ship bearings. It’s all assembled on my desk now and I am starting the wiring and software. I used “magnetic_sensor_12c_example” to test the AS5600 and it shows stable readings for both pos and rate on the motor sensor. I am using an Arduino Mega2560 to test with and hope it performs well enough for the reaction wheel.

I see in your examples you have two sets of code under “magnetic_sensor_i2c_dual_bus_examples”. One for “esp32” and one for “stm32”. I am not real familiar with those terms. An internet search implies two different processor architectures and it doesn’t look like either apply to the Atmel2560. Do you have a sample for Arduino? I am trying to use a pair of AS5600 sensors for this project.

The code in “magnetic_sensor_12c_example” uses “sensor.init()” to start things with the AS5600 on the standard I2c bus for the Mega. To solve the problem of the AS5600 having a fixed address I could use something like this soft wire library “” but not sure how to attach it to sensor.init and sensor.getAngle and Velocity

The mega2560 is an 8bit 16MHz mcu, similar to Arduino uno with more pins and ram.

You are right about esp and stm32 being alternate architectures. They are 32bit and typically run at 70-240Mhz. Esp32 is dual core.

You have a bunch of factors working against you. Slow mcu, noisy magnetic sensor and dual motor. You should be able to get one motor tuned but will struggle with the second as the atmega is, imho, not fast enough.

And things get slower if you are using a software i2c as a second bus. This is sometimes called bit banging and is less efficient (more mcu cycles). An alternative would be to find a board that has 2nd icu bus or use i2c multiplexer.

Can you take a picture of your mega/driver/motor setup? I’d like to see if you could swap out the atmega for a nucleo or discovery board from ST. I realise that would be a whole new learning curve!

Happy to help see how far you can get with a mega. You’ve probably already seen that the init() method can take an optional TwoWire arg. If that software i2c implements the same interface, it is possible you could pass that on to your second sensor.

I agree with Owen.

I started out using the “SimpleBCG” board, which is a dual BLDC-driver with built-in ATMega328P - like the Arduino Nano. And it was quite easy to set up and program, and in the end I did get 2 motors spinning from I2C sensors.
But I had to modify SimpleFOC’s sensor code to reduce the number of sensor reads (because I2C is slow), and I have the feeling the whole setup is pushing the limits of the ATMega.

My next attempts were with ESP32 and STM32 - both of which are super-powerful, and have enough processing power to drive two motors. Adafruit has some very nice, easy-to-use and set up boards in the “Feather” format for both ESP32 and STM32. And the Nucleo Boards that Owen mentions are also very powerful, some come with Arduino headers and cost less than 20 EUR.
I think ESP32 is maybe a little bit easier to use than STM32, but both can be programmed from the Arduino environment.

I hope that soon we will also be able to recommend SAMD21-based MCUs, like the Arduino MKR1010 WiFi, or the Arduino Nano 33 IoT. I have been working on support for these in my dev branch of the code, and it is looking quite good.

Even if you use a faster MCU, you’ll still have the problem of reading two sensors quickly enough to drive the FOC algorithm for two motors. Software I2C would work, I think, but I think this is not the way to go. The MCUs like STM32 or ESP32 all have 2 or more I2C ports, so you could use 2 different I2C ports to make the AS5600 work for you.
Or you could use another sensor, like the AS5048B, which has I2C but with settable addresses. So then you can run two separate sensors on one I2C bus.

is this the right “thing” for an esp32 board?

It can be programmed with the Arduino ISP?

“C” code …Yes am pretty good at this. C++ …not so much, assembly code, not for decades!


had a bit of a stupid moment and set back. Connected the AS5600 to 5v instead of 3.3v. They got hot and produce garbage for output now…three more ordered.

Owen, you comment that magnetic encoders are “noisy” . Earlier tests I made before “cooking” them seemed pretty stable. What is your experience? There is quite a price jump from ~$4 to ~$15 for a AS5048 and then ~$25 for the AMT103-V encoder.

Careful! I think this link is for the cable only. ESP32 boards are cheap, but $0.86 is a little too cheap. I think this is a misleading offer. In general, I would not prefer eBay for buying electronics if possible. Banggood, AliExpress or of course Mouser/Digikey are better sources, although admittedly sometimes eBay has things no one else does.
But for ESP32, I would go for something like this Wemos ESP32 module:
It is very small, but has 40 pins…

Yes, ESP32 can be programmed with Arduino IDE. I have good experiences doing this, it was quite easy to set up and get everything working. There are examples for using SimpleFOC with ESP32 in the code.

If you need the UNO form-factor, maybe something like this one?
Haven’t tried this myself though, so I don’t know how well supported it will be in terms of the board definitions.

You program it via a Micro USB cable, directly from Arduino IDE.
Once you have flashed your program once, you can include OTA (over the air) update functionality, since the ESP32 has WiFi… this is the nicest way to program, super-fast and no messing with the buttons or USB cables.

I just wanted to confirm that D1 R32 ESP32 boards with Arduino header work well with the library. Especially in combination with SimpleFOCShields, they have a good performance with current sensing as well.

The only real problem I encountered is due to the nonlinear ADC characteristic. But that seems to be the issue of the esp32 in general and not just these boards. Otherwise I recommend them!

My point about noisy sensor is specific to AS5600. It claims 12 bit precision of angular precision but the last 2 bits jump around which is picked up by SimpleFOC as rapid movement and requires Tf smoothing to compensate.

Other sensors are 14 bit e.g as5048, don’t fluctuate as much and tuning is easier.

Does the esp32 have enough pins for dual?
I suspect it should be ok but will need careful thought. 6pwm pins + 4 i2c + current sense pins (if required) If you go by the numbers, it has enough pins but some are reserved for sd, some are analog, etc.

I agree that esp32 is a relatively easy next step from arduino uno. Stm is harder because there are so many variants!