Troubleshoot modulation / hall effect sensors / STM32 NUCLEO F303RE

Hello!

I’m trying to control a low voltage BLDC (40V) with Simple FOC. The motor spins, but not very efficiently, and is noisy. The phases and current do not look right on the scope. Any help is greatly appreciated!

The code is essentially the same as the example “Motion Control / Torque Control / Hall Sensor / Voltage” using the pins available on the Nucleo F303RE:

#include <SimpleFOC.h>

// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(8);
BLDCDriver3PWM driver = BLDCDriver3PWM(PA8, PA9, PA10, PC10, PC11, PC12);

// hall sensor instance
HallSensor sensor = HallSensor(PA15,PB3,  PB10, 8);

// Interrupt routine intialisation
// channel A and B callbacks
void doA(){sensor.handleA();}
void doB(){sensor.handleB();}
void doC(){sensor.handleC();}

// voltage set point variable
float target_voltage = -5;
//float target_voltage = -10;
//float target_voltage = 10;
// instantiate the commander
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&target_voltage, cmd); }

void setup() { 
  
  // initialize encoder sensor hardware
  sensor.init();
  sensor.enableInterrupts(doA, doB, doC); 
  // link the motor to the sensor
  motor.linkSensor(&sensor);

  // driver config
  // power supply voltage [V]
  driver.voltage_limit = 40;
  driver.voltage_power_supply = 20;
  driver.init();
  // link driver
  motor.linkDriver(&driver);

  // aligning voltage
  motor.voltage_sensor_align = 3;
  
  // choose FOC modulation (optional)
  //motor.foc_modulation = FOCModulationType::SpaceVectorPWM;
  //motor.foc_modulation = FOCModulationType::SinePWM;
  //motor.foc_modulation = FOCModulationType::Trapezoid_120;
  motor.foc_modulation = FOCModulationType::Trapezoid_150;

  // set motion control loop to be used
  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();

  // add target command T
  command.add('T', doTarget, "target voltage");

  Serial.println(F("Motor ready."));
  Serial.println(F("Set the target voltage using serial terminal:"));

  motor.target = 5.0f;
  _delay(1000);
}


void loop() {

  // main FOC algorithm function
  // the faster you run this function the better
  // Arduino UNO loop  ~1kHz
  // Bluepill loop ~10kHz 
  motor.loopFOC();

  // Motion control function
  // velocity, position or voltage (defined in motor.controller)
  // this function can be run at much lower frequency than loopFOC() function
  // You can also use motor.move() and set the motor.target in the code
  motor.move(target_voltage);

  static int lastMillis;
  int newMillis = millis();

  if(newMillis > lastMillis + 2000) {
    lastMillis = newMillis;
    Serial.println(motor.sensor->getVelocity() * 9.549297);
  }

  // user communication
  command.run();
};

SinePWM on scope, 3 phases, and phase A current

Continued: Space Vector PWM

Continued Trapezoid 150, phase A current

Continued Trap 150, phase B current

@Leo

Welcome to the forum.

Could you please also post pictures of the physical setup, wiring, motor, etc?

Did you make sure the pole pairs match your motor?

Did you try tuning the loop?

Did you try other foc_modulation?

Cheers,
Valentine

Hi, and welcome to SimpleFOC @Leo !

For FOC control, don’t use the Trapezoid150 modulation. Best is Sine or SpaceVector.

Also, your driver.voltage_limit is twice your driver.voltage_power_supply. voltage_limit should be less than (or the same as) power supply voltage, it doesn’t make sense to set it higher than the PSU voltage.

To get nicer modulation when using Sine, set motor.voltage_limit equal to 0.5 * driver.voltage_power_supply.

What motor are you using? Does it really have 8PP? It’s quite possible, but an usual number.

Those are the comments I have off-hand…

Let us know if this makes any difference!

1 Like

Welcome to the forum.
Thank you!

Could you please also post pictures of the physical setup, wiring, motor, etc?
I will post some pictures later on, the motor I’m working with is closed, I’ll hook up another one with the lid open and take a picture.

Did you make sure the pole pairs match your motor?
Yes, and they do. Also, 18 coil stators wound like this: AaABbBCcCAaABbBCcC, 3 Hall sensors at 120deg

Did you try tuning the loop?
I would be willing to try, if you point me to instructions?

Did you try other foc_modulation?
I’ve tried the 4 modulation options available, but really looking forward to using Sine or SpaceVector, for efficiency and quiet operation.

Thank you!

Hi, and welcome to SimpleFOC @Leo !
Thank you!

For FOC control, don’t use the Trapezoid150 modulation. Best is Sine or SpaceVector.
Yes, Sine or SpaceVector is definitely the goal, I posted the other pictures / modulations in case it helps figure out the problem.

Also, your driver.voltage_limit is twice your driver.voltage_power_supply. voltage_limit should be less than (or the same as) power supply voltage, it doesn’t make sense to set it higher than the PSU voltage.
To get nicer modulation when using Sine, set motor.voltage_limit equal to 0.5 * driver.voltage_power_supply.

I just did that, here’s the resulting SinePWM modulation on the scope:

What motor are you using? Does it really have 8PP? It’s quite possible, but an usual number.
Yes, it’s a Chinese motor for fan applications. I’ll post pictures of it later.

Those are the comments I have off-hand…
Let us know if this makes any difference!e
I appreciate any help, everything counts!

Thank you, Leo

Hey Leo,

Those voltages now look a lot more like they should, one can see the commutation pattern being set to the motor.
The current waveform looks less convincing :frowning: I assume this is an inline current shunt that’s being measured via a current sense amp, or using a hall-effect current sensor? (since its a single ended measurement on the scope?)

May I ask what driver you’re using? Is it possible currents are rising too high, causing over-current protection to trigger? What’s the phase resistance on this motor?
What happens if you set a fairly low motor.voltage_limit, say 5V or 3V?

I would probably go a step further and just try simple open loop with only 10% of the input voltage and low speed, like 1 rad/s.

Pictures of the driver would be very helpful.

Cheers,
Valentine

Hello Runger,

Yes, the current waveform looks very far from the beautiful sine wave I’m looking for.

I have a Micsig current probe around one of the phase wires coming from the Nucleo board into the motor, connected to channel 4 of the scope.

I am using a Rigol power source, 20V 3A, current is running around 0.09A, overcurrent is never triggered.

I calculated R = 1.6, and KV = 20, but running with these values or using the default NOT_SET parameters does not change things much.

In the next couple of hours I’ll switch to the other motor setup to send pictures, meanwhile here’s the SinePWM modulation using 3V voltage limit:

Thank you!

@Leo

I’m a little confused, why are you measuring the current from Nucleo board to the motor? In fact why is even there a phase wire from Nucleo into the motor? Do you mean one of the the phase wires from the driver? Pictures of the entire setup would be really helpful.

Cheers,
Valentine

we are using a driver shield attached to the nucleo board, the IHM07M1. this is what Leo is referring to

Exactly:

The picture is very poor and doesn’t show the rest of the setup, but from the very little I see, this is a high quality original ST X-NUCLEO-IHM07M1 eval board.

Why are you piping the phase wires through a ferrite core? That core is probably so oversaturated it won’t do anything, you just warm up the air and mess up your phase current.

I would say try with open loop to control the motor, get rid of the funny ferrite core, and make sure you make the motor spin smoothly open loop before you attempt anything else.

Are you sure you don’t trigger the overcurrent protection of L6230? That driver can barely drive may be 3A max before you trip it. I know you say you don’t trigger the overcurrent, just asking.

The ferrite works as choke, helps removes EMI noise, but the current shape is the same with or without it (it also helps bunch the wires together).

The power supply is limited to 3A, but I could limit it to 2A and it still wouldn’t trigger overcurrent.

The motor runs pretty well, actually I can get 600+ RPM from it, still under 2A. The problem is the current modulation is far from sinusoidal, and the motor is noisy, you can hear the click-click-click during commutation.

Below is a picture of the open motor:

Thank you!

And a diagram of the actual Hall effect sensor placement (the solid Yellow, Blue, and Red dots)

Thank you!

Hello Runger, please see the motor picture and Hall diagram I just posted, I am setting up the other motor to try to run it in open loop. Thank you!

Let’s first see the other motor in open loop. Please read this before you run open loop:

Cheers,
Valentine

Please correct me if I’m wrong, since this looks like a manually wound-up custom motor, however, the number of pole pairs is usually higher than the number of windings. Here I see 18 coils, so your pole pairs should be around 11 if I’m not mistaken.

Could you please count the number of PM and divide by 2?

If you manage to run the motor smoothly open velocity with 1 pp, and it stutters when you close the loop with 8 pp, I would probably guess the number of pole pairs may have something to do with it.

Either this or the hall sensors are having problems, you may want to check the signals from the hall sensors too?

Cheers,
Valentine