Heavy Vibrations and current overdraw when using foc_current control

Before anything. We truly appreciate all the efforts you guys are putting into this. This community is one of the best I have ever come across.

I was trying to get foc_current torque_controller using current sense on my board. It uses the same AD8418 referred here (similar to VESC 6) with a 0.0005 ohm shunt. The start-up sequence of simpleFOC gives me a success 1 for Current Sense and gives the Motor Ready on the Serial Monitor.
However, the motor starts vibrating vehemently and draws too much current. The same board (uses a STM32G473) works great with closed-loop position control (in voltage mode torque control).
I had tried the foc_current mode with the B-G431B-ESC1 on this motor and it worked great.
But not sure why the motor is vibrating in foc_current mode for this other board. Any idea on where I should start troubleshooting?

Below is my code setup:

#include <Arduino.h>
#include "Wire.h"
#include "SPI.h"
#include <SimpleFOC.h>
#include "SimpleFOCDrivers.h"
#include "encoders/stm32hwencoder/STM32HWEncoder.h"


// BLDCMotor motor = BLDCMotor(21, 0.10, 66.67, 0.000022); // this didn't work either
BLDCMotor motor = BLDCMotor(21);
BLDCDriver3PWM driver = BLDCDriver3PWM(PE9, PE11, PE13);
InlineCurrentSense currentSense = InlineCurrentSense(0.0005f, 20.0f, PC3, PA1, PA0);

// Encoder encoder = Encoder(PB5, PB4, 500); //uses software interrupt
STM32HWEncoder encoder = STM32HWEncoder(500, PB5, PB4);

// void doA(){encoder.handleA();} // not used for HardwareEncoder
// void doB(){encoder.handleB();} // not used for HardwareEncoder

Commander command = Commander(Serial);
// void doTarget(char* cmd) { command.scalar(&motor.velocity_limit, cmd); }
void doMotor(char* cmd) { command.motor(&motor, cmd); }

void setup() { 

  encoder.init();
  motor.linkSensor(&encoder);

  driver.voltage_power_supply = 24;
  driver.init();
  motor.linkDriver(&driver);

  // link current sense and the driver
  currentSense.linkDriver(&driver);
  

  // current sensing
  currentSense.init();
  currentSense.skip_align = true;
  currentSense.gain_a *= -1; 
  currentSense.gain_b *= -1;
  currentSense.gain_c *= -1;
  motor.linkCurrentSense(&currentSense);
  // aligning voltage [V]
  motor.voltage_sensor_align = 3;
  // index search velocity [rad/s]
  motor.velocity_index_search = 3;

  // Control loop setup
  motor.controller = MotionControlType::angle;
  motor.torque_controller = TorqueControlType::foc_current;
  // velocity PI controller parameters
  motor.PID_velocity.P = 0.2;
  motor.PID_velocity.I = 20;
  motor.voltage_limit = 8;
  motor.PID_velocity.output_ramp = 1000;
 
  // velocity low pass filtering time constant
  motor.LPF_velocity.Tf = 0.01;

  // angle P controller
  motor.P_angle.P = 20;
  //  maximal velocity of the position control
  motor.current_limit = 6; // Amps
  motor.velocity_limit = 10; 

  Serial.begin(115200);
  command.add('M',doMotor,"motor");
  motor.init();
  motor.initFOC();

Hey,

Do I understand you correctly that the same code works fine for the torque-voltage mode?

In this case, I would suggest the following:

  • run the motor in velocity mode to tune the velocity PID, make sure this is working as expected too
  • check the current sense without using foc-current mode - make sure the values returned make sense by printing them to serial and plotting them.
  • I notice you are skipping over the initialisation - have you tried letting it initialise the current sense? The initialisation will invert gains and swap phases as needed, and find the 0-offsets by measurement.

Hi @runger,

Thank you for getting back and helping out on this.
Basically, the board is working great with closed_loop position control (torque control using voltage , not foc_current).
But I’m running into issues with getting the current sense working.
I tried running the torque control loop with foc_current today with no luck yet . It starts vibrating heavily as soon as it leaves the calibration stage and goes into loopFOC().

  // set torque mode:
  motor.torque_controller = TorqueControlType::foc_current; 
  // set motion control loop to be used
  motor.controller = MotionControlType::torque;

I tried reading the current sense values without foc and noticed, only one of the pins gave reasonable values (PC3). I am not sure what I should expect in terms of values. Only the PC3 values would change if I manually tried to move the motor by hand. The other two values wouldn’t change. I then changed the pinNames and tried calling them with their alternate pin assignments (PC3 → PC3_ALT1, PA1-> 21, PA0->20). Only then I would see the current values vary as I would manually move the motor by hand. I would read 0.14, 0.14 and ~3.40 on the three phases when there is no movement on the shaft.

I did try the current sense align and in some codes I would receive Success=1 (when I gave PC3, PA1, PA0 as pin assignments) and Success=3 or 4 when I would use their alternate pinNames. But the motor would still vibrate after leaving the calibration sequence.
Not sure where the misalignment is happening (if that’s what is happening).

Hi,

Ok, well you definately need clean signals on all the pins, so it would seem the alternate pin-names are better. I am not sure the code it correctly set up to handle atlternate pin names in all situations though, perhaps that can be a problem…

Once there is a good signal on all the ADC channels and the alignment is running well, then it should be a matter of tuning the PID values. Normally, STM32 boards should be fast enough to have enough bandwidth to achieve current control, assuming decent signals.

Hi @runger
Thank you for advising.
Do you happen to know how are the clean signals supposed to look like . I’m reading around 0.14, 0.14 and ~3.40 from the current_sense.getPhaseCurrents() function.

But another issue I noticed yesterday was: After I gave the alternate pin assignments to the InlineCurrentSense() initialization. For some reason the motor.initFOC() function would hang up and I noticed it getting stuck just after Encoder alignment (when it’s about to start current sense alignment).
Only if I skip current sense alignment, things would proceed further. Not sure what is holding the code. This only happens when I use alternate pin assignments (PC3_ALT1, 21, 20) and seem to work okay when I give the default pin assignments (PC3, PA1, PA0).
Moreover, when I run the alignment with PC3, PA1, PA0, it gives me a good Success of 1.

Any clue on this.

Hi @mizzi_labs,

i’ll reply to you in this post, regarding what i remember of the problems encountered in my case with the VESC 6 board.

I had similar problems to yours, as you can see from this post.

As far as I remember, it was just a matter of correctly calibrating the motor parameters and setting the right pins used for current sense.

The subsequent problems that I encountered and described in multiple posts (this one, for example) and then in my thesis, were due to a bug related to the getVelocity() function in which a division by zero occurred that I had correctly found and i was able to mitigate it but without solve the problem from the source.

That problem should have been recently fixed in this commit.

For what concerns this post, i’ve never found the cause of the difference of current between the VESC firmware and the SimpleFOC one. To solve it quickly, I remember that I increased the gain value so that I had approximately the same current value that the VESC firmware was reporting, and the performance of the control then improved, because for some reason, the gain value was too low.

Here you can find one of the last version of the project that i’ve made with the VESC 6 where you can find the main.cpp and the board_vesc_6.h that could help you to find the right setup.

1 Like