Merge angle controll, velocity control code in single code

hello people!
i done my all testing of simple foc code for angle controll mode and velocity control mode on 24V. the hardware i used is esp32 controller and driver ic is IR2184 3PWM. the code working absolutly fine. now i want to change into my code i wanted angle and velocity in single code. i am new to simple foc so anybuddy can guide me, it will be much helpfull .
guide me how to give command velocity and angle in single code as well as how to set two seprate PID in single code of simple foc for angle controll & velocity control.

Hi,

Its not quite clear what you are asking?

Would you like to control position while limiting velocity? You can use the motor.velocity_limit for thisā€¦

Would you like to switch between angle and velocity control?
You can change the motor.controller dynamically, but you will have to also manage the set-point at the same time, as it has different meanings in these two modes.

Are you trying to implement motion planning? This is kind of out of scope of SimpleFOC itself, but we have an example of simple trapezoidal limiting in our driver library:

Does any of that help?

thanks for listening me !
but i want to controll motor by single , currently there is, you have to choose mode of controll type nd set PID accordingly choosen controll mode like angle, velocity else torque. my quetion is can i run motor with single code by that code i controll angle parameter as well velocity.

Hey,

Still not sure what you mean, but it sounds like something like the trapezoidal planner is what you wantā€¦ where you can set an angle target, but control the maximum velocity and acceleration used?

I want to write code that conroll both parameter angle as well as velocity. currenty there are seprate code - closed loop velocity controll 2ndly angle controll closed loop code. i want to merge this code and by single code i can change velocity as well as get angle. although for that i tried simple foc code full serial command encoder which give target both velocity and angle by single command. that looks quite good.
the code is below
#include <SimpleFOC.h>

// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(2);
BLDCDriver3PWM driver = BLDCDriver3PWM(25, 26, 27, 32);
// Stepper motor & driver instance
//StepperMotor motor = StepperMotor(50);
//StepperDriver4PWM driver = StepperDriver4PWM(9, 5, 10, 6, 8);

// encoder instance
Encoder encoder = Encoder(15, 4, 1024);

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

// commander interface
Commander command = Commander(Serial);
void onMotor(char* cmd){ command.motor(&motor, cmd); }

void setup() {

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

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

// choose FOC modulation
motor.foc_modulation = FOCModulationType::SpaceVectorPWM;
// set control loop type to be used
motor.controller = MotionControlType::angle;
// angle PID controller
// default P=20
motor.P_angle.P = 0.21;
motor.P_angle.I = 0.11; // usually only P controller is enough
motor.P_angle.D = 0; // usually only P controller is enough

// default voltage_power_supply
motor.voltage_limit = 24;

// velocity low pass filtering time constant

motor.LPF_angle.Tf = 0.1; // default 0
// angle loop controller
motor.P_angle.P = 20;
// angle loop velocity limit
//motor.velocity_limit = 190;

// use monitoring with serial for motor init
// monitoring port
Serial.begin(115200);
// comment out if not needed
motor.useMonitoring(Serial);

// initialise motor
motor.init();
// align encoder and start FOC
motor.initFOC();

// set the inital target value
motor.target = 1;

// define the motor id
command.add(ā€˜Mā€™, onMotor, ā€œmotorā€);

// Run user commands to configure and the motor (find the full command list in docs.simplefoc.com)
Serial.println(F(ā€œMotor commands sketch | Initial motion control > torque/voltage : target 2V.ā€));

_delay(1000);
}

void loop() {
// iterative setting FOC phase voltage
motor.loopFOC();

// iterative function setting the outter loop target
// velocity, position or voltage
// if tatget not set in parameter uses motor.target variable
motor.move();

// user communication
command.run();
}
now i want to add also velocity PID and and its LF constant.

Go ahead and add those settings then :slight_smile:

Angle mode also uses the velocity PID, and tuning that one is actually usually more important than the angle PID, where usually a simple P-controller is enough

Yes itā€™s working good in angle mode but there any way to give angle command in degree. Generallly simple foc code give angle in radian/s

No, SimpleFOC works in radians, or rad/s for velocity.

But itā€™s simple to convert the units in your own codeā€¦

there is no way we can move motor with degree scale?

No. Just convert degrees to radians.

I tested above code . happily, it works good in angle controll mode. I got angle as my wish, but motorā€™s velocity speed not going to above 50rad/s. There is no effect of increseing veocity , i gave velocity command 2500rad/s, but my motor still moving with speed of 50rad/s. So there is any solution that i can incresed my motorā€™s velocity as angle.

Hmm thatā€™s not even 500RPM - whatā€™s the KV value of your motor?

my motor KV value is 144.

and one another suggestion i needed is i tried this encoder simple foc velocity controll mode with DRIVER 6PWM Ic IR2133S , controller is same ESP32 but it run in open loop but not responding encoder code. I checked encoder pulse with DSO and its fine. so any suggestion how i can operate it with velocity controlll loop. the code i used is given below
#include <SimpleFOC.h>
#define SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH true
#define SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH false
// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(2);
BLDCDriver6PWM driver = BLDCDriver6PWM(25, 26, 27, 14, 12, 13, 32);

// encoder instance
Encoder encoder = Encoder(4, 5, 1024);

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

// velocity set point variable
float target_velocity = 1.5;
// instantiate the commander
Commander command = Commander(Serial);
void doTarget(char* cmd) { command.scalar(&target_velocity, cmd); }

void setup() {
// initialize the pushbutton pin as an input:
pinMode(4, INPUT_PULLUP);
// initialize the pushbutton pin as an input:
pinMode(5, INPUT_PULLUP);
// initialize encoder sensor hardware
encoder.init();
encoder.enableInterrupts(doA, doB); //, doC);

// link the motor to the sensor
motor.linkSensor(&encoder);

// driver config
// power supply voltage [V]
driver.voltage_power_supply = 24;
driver.init();
// link the motor and the driver
motor.linkDriver(&driver);

// aligning voltage [V]
motor.voltage_sensor_align = 3;

// set motion control loop to be used
motor.controller = MotionControlType::velocity;

// contoller configuration
// default parameters in defaults.h

// velocity PI controller parameters
motor.PID_velocity.P = 0.035f;
motor.PID_velocity.I = 0.40;
motor.PID_velocity.D = 0;
// default voltage_power_supply
motor.voltage_limit = 24;
// jerk control using voltage voltage ramp
// default value is 300 volts per sec ~ 0.3V per millisecond
motor.PID_velocity.output_ramp = 1000;

// velocity low pass filtering time constant
motor.LPF_velocity.Tf = 0.01f;

// 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 velocity using serial terminal:ā€));
_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_velocity);

// function intended to be used with serial plotter to monitor motor variables
// significantly slowing the execution down!!!
// motor.monitor();

// user communication
command.run();
}

If you donā€™t mind, could you post code using back-ticks so it is easily readable?

You canā€™t #define SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH
in your code, you have to define it in the platformio.ini or your board definition files so the compiler applies it to all the code it compilesā€¦

hey thanks for listening,
I removed this SIMPLEFOC_PWM_HIGHSIDE_ACTIVE_HIGH from code, make other changes. And now Code working good with 6pwm Encoder on this board too.

1 Like