Current limitation for velocity control

Hey guys!

I am pretty new to the FOC and I have a small problem with my motor control.

In my project I am using an ESP32, a Thrustmaster steering wheel and an arduino. My goal is to control the speed of the motor with the pedals of the steering wheel. This works already but my problem is, that when I step on the gas pedal really quickly the current increases more than it should. Is there any solution for this problem?

#include <SimpleFOC.h>

#include <Wire.h>

int U_EN = 18; // inhu

int V_EN = 5; // inhv

int W_EN = 17; // inhw

float target_velocity = 12.54;

int gas = 0;

int bremse = 0;

int lenkung = 0;

int turn = 0;

// Motor instance

BLDCMotor motor = BLDCMotor(11);

// driver instance

BLDCDriver3PWM driver = BLDCDriver3PWM(16, 4, 32);

HallSensor sensor = HallSensor(25, 26, 27, 11);

// Interrupt routine initialization

// channel A, B and C callbacks

void doA(){sensor.handleA();}

void doB(){sensor.handleB();}

void doC(){sensor.handleC();}

// instantiate the commander

Commander command = Commander(Serial);

void doTarget(char* cmd) { command.scalar(&target_velocity, cmd); }

void receiveData(int byteCount){

gas = Wire.read();

bremse = Wire.read();

lenkung = Wire.read();

turn = Wire.read();

if (turn == 1){

gas = gas \* (-1);

}

}

void setup() {

pinMode(U_EN, OUTPUT);

pinMode(V_EN, OUTPUT);

pinMode(W_EN, OUTPUT);

digitalWrite(U_EN, HIGH);

digitalWrite(V_EN, HIGH);

digitalWrite(W_EN, HIGH);

Serial.begin(115200);

//I2C

Wire.begin(8);

Wire.onReceive(receiveData);

SimpleFOCDebug::enable(&Serial);

// initialize sensor hardware

sensor.init();

// hardware interrupt enable

sensor.enableInterrupts(doA, doB, doC);

// link the motor and the sensor

motor.linkSensor(&sensor);

// driver config

// power supply voltage [V]

driver.voltage_power_supply = 12;

// driver init

if(!driver.init()){

Serial.println("Driver init failed!");

return;

}

// link driver

motor.linkDriver(&driver);

// set motion control loop to be used

motor.controller = MotionControlType::velocity;

// aligning voltage [V]

motor.voltage_sensor_align = 0.5f;

// velocity PI controller parameters

motor.PID_velocity.P = 0.1f;

motor.PID_velocity.I = 1;

motor.PID_velocity.D = 0;

// default voltage_power_supply

motor.voltage_limit = 12;

// jerk control using voltage voltage ramp

// default value is 300 volts per sec ~ 0.3V per millisecond

motor.PID_velocity.output_ramp = 30;

// velocity low pass filtering time constant

motor.LPF_velocity.Tf = 0.01f;

// 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 velocity using serial terminal:”));

_delay(1000);

}

void loop() {

// main FOC algorithm function

motor.loopFOC();

motor.move(gas);

command.run();

}

This is the code I am currently running. The value for motor.move is between 0-100.

Kind regards

Leon

Hi @leon1 , welcome to SimpleFOC!

You’re using velocity control, whose behaviour is governed by the PID settings.

I’m not exactly sure what you mean by “current increases more than it should”… but I assume you mean the currents are getting higher than you want them to.

So in particular if you press the gas quickly, the difference between the actual velocity and the target velocity will be large, and so the P-term of your PID will result in a larger response than if the difference is only small because you press the gas slowly.

There are some different solutions you can try out: you can reduce the P term, but this might result in different response and dynamics you don’t like.

You can try to use a lower voltage limit to prevent the current from rising as high. That might be a good idea anyway for safety, if you don’t need the full voltage…

Or you could add a low pass filter to the target velocity (your “gas” variable), for example by using our LowPassFilter class… I’d strongly recommend trying that, and playing with the filter constant until you get a nice response, but without the sharp currents caused by step-changes in the target…

Thanks for the reply!

Could you maybe give me an example how to implement the low pass filter on this variable?

Sure, perhaps something like this:

// filter time constant determines how quickly target 
LowPassFilter target_lpf = LowPassFilter(0.5f);
float target = 0.0f;


void setup() {
  ...

  target_lpf(target); // initialise

  ...
}


void loop() {
  ...

  motor.loopFOC();
  motor.move(target_lpf(target));

  // obtain new target value
  target = readSomeKindOfInputWithoutBlocking();

  ...
}