Initial Testing. Motor not moving. Arduino Uno R4 with dev branch

I’ve just started experimenting with SimpleFOCShield 2.0.4 with an Arduino Uno R4. I downloaded the dev branch of SimpleFOC and installed it in the Arduino IDE.

I am using this motor: BLWS231S-24V-2000
BLWS23 - Brushless DC Motors (anaheimautomation.com)

The motor is 4 poles, with Hall Sensors.

I am trying to run in closed loop velocity mode at 25 rad/sec (aka 250RPM) with no / minimal load. Current required is well within 5A, and should be around 0.2A per phase I think. (at least that is what I see with another controller). Voltage per phase should be pretty low as well, maybe 2-3 Volts. Pretty sure this is all within the capabilities of the SimpleFOCShield.

The code compiles and I get output from the Hall Sensors when I manually move the motor, but the motor does not rotate on its own. Am I missing something in the setup/configuration?

I am using the following code to test:

#include <Arduino.h>
#include <SimpleFOC.h>

// BLDC motor instance BLDCMotor(polepairs, (R), (KV))
BLDCMotor motor = BLDCMotor(2, 6.2);

// BLDC driver instance BLDCDriver3PWM(phA, phB, phC, (en))
BLDCDriver3PWM driver = BLDCDriver3PWM(5, 9, 6);

// position / angle sensor instance HallSensor(hallA, hallB , hallC , pole pairs)
HallSensor sensor = HallSensor(3, 2, 4, 2);
void doA(){sensor.handleA();}
void doB(){sensor.handleB();}
void doC(){sensor.handleC();}

void setup() {
      Serial.println("Setup Started.");
    
    // USE_EXTERN is default (1k - 5k recommended), change to USE_INTERN if needed
    sensor.pullup = Pullup::USE_EXTERN;
    // initialize sensor
    sensor.init();
    // enable Hall effect interrupts
    sensor.enableInterrupts(doA, doB, doC);
    // link sensor to motor
    motor.linkSensor(&sensor);


    // pwm frequency to be used [Hz]
    //driver.pwm_frequency = 20000;
    // set power supply voltage
    driver.voltage_power_supply = 19.5;
    // set driver voltage limit, this phase voltage
    driver.voltage_limit = 20;
    // initialize driver
    driver.init();
    // link driver to motor
    motor.linkDriver(&driver);

    // set motion control type to velocity
    motor.controller = MotionControlType::velocity;

    // set torque control type to voltage (default)
    motor.torque_controller = TorqueControlType::voltage;

    // set FOC modulation type to sinusoidal
    motor.foc_modulation = FOCModulationType::SinePWM;

    // velocity PID controller
    motor.PID_velocity.P = 0.2;
    motor.PID_velocity.I = 10;
    motor.PID_velocity.D = 0;
    // angle / position P controller
    //motor.P_angle.P = ;
    
    // set motor voltage limit, this limits Vq
    motor.voltage_limit = 12;
    // set motor velocity limit
    motor.velocity_limit = 100;

    // initialize motor
    motor.init();

    // align sensor and start FOC
    motor.initFOC();
 
    Serial.println("Motor ready.");

    _delay(1000);
}

void loop() {
    // main FOC algorithm function
    // the faster you run this function the better
      sensor.update();
  // display the angle and the angular velocity to the terminal
  Serial.print(sensor.getAngle());
  Serial.print("\t");
  Serial.println(sensor.getVelocity());
    motor.loopFOC();

    // this function can be run at much lower frequency than loopFOC()
    motor.move(25);

}

Does the PP check pass? Are there any SFOC debug statements that are funny?
Also the print statements in the main loop will slow things down a lot, you should remove this and call it every 50 loops or so to lower the overhead on the serial port.

Hi,

Please add a

Serial.begin(115200);
SimpleFOCDebug::enable(&Serial);
delay(5000); // connect the serial console within 5s of booting
Serial.println("Setup Started.");

at the start of your setup.

You should now see a bunch of output from driver.init() regarding the pin assignments for the PWM. If you would be so kind as to share that output with us here.

Another thing:

    driver.voltage_power_supply = 19.5;
    // set driver voltage limit, this phase voltage
    driver.voltage_limit = 20;

driver.voltage_limit should never be higher than driver.voltage_power_supply.

Please use:

    driver.voltage_power_supply = 19.5f;
    // set driver voltage limit, this phase voltage
    driver.voltage_limit = driver.voltage_power_supply;
    motor.voltage_limit = driver.voltage_limit/2.0f;

Regarding the pins, you are not free to choose any pins.

Here are the UNO R4 pins and all their PWM channels. For the simpleFOC shield, you have to use 3 pins that are on different channels. It doesn’t matter if you use output A or B, but you can’t use the same channel twice.

Your pins, 5, 9 and 6 are ok to use. I assume you have set the solder-pads of the SimpleFOC shield to the same values? Also can you add the enable signal, for example using pin 8?

BLDCDriver3PWM driver = BLDCDriver3PWM(5, 9, 6, 8);

Yes, the pins are as configured / soldered on the back of the SimpleFOCShield. Adding Pin 8 for the enable signal worked (to a degree). Now the motor just holds in place, resists movement (stall lock). I also reduced the power supply to a 12V /1.8A supply, and adjusted the values as suggested by Runger above (now using 12.0f instead of 19.5f)

I suspect I now just need to figure out the right combo of PID values for the motor to get it to spin properly?

That could be the problem…

Often a “locking up” type of behaviour also results if the number of pole-pairs is set incorrectly, or the sensor initialisation is failing.

2-PP motors are unusual for us. I would recommend using a low value for motor.voltage_sensor_align. I think there could be issues with the initialisation of such a low PP motor.

Please use the

motor.controller = MotionControlType::torque;
motor.torque_controller = TorqueControlType::voltage;

for first tests. If this mode is working well, then you can switch to velocity mode and check the PID tunings.

Note that for torque-voltage and/or velocity mode you need a sensor, they are closed loop modes. To use them you also have to call motor.initFOC() in the setup and motor.loopFOC() in the main loop.

Note also that you can’t print at every loop iteration like you’re doing in the code you posted above. This will flood the serial port buffers and cause a blocking I/O operation, and then the motor control will not work properly.
You can only print very little in the main loop, and only print once every 1000 iterations or something like that.

Thank you for the insight. I will try the torque control method first

Re: the serial prints in the loop() statement, I only tried that once to make sure I was getting a reading from the hall sensors. I took it out after that, recognizing that serial coms would slow down the process way too much.