Hi guys, it 's a great discussion in here!
@Owen_Williams thanks for the fix for the find_pole_pairs
example I have included it to the new version of the code.
@breef Unfortunately, both of your motors are a bit to much for the shield. The board is designed for the motors closer to resistance of 10 ohms, and for currents under 5A peak. And if you would be planning to run this motor with 2A+ you should consider cooling, a heat sink or something similar.
I will try to document this better when I am back, but for now I would like to provide you guys with an example code of the open motor control and one example of how exactly to limit the voltages.
Open loop motor control - motor test
// Open loop motor control example
#include <SimpleFOC.h>
// motor instance
BLDCMotor motor = BLDCMotor(3, 10, 6, 11, 7);
void setup() {
// power supply voltage
// default 12V
motor.voltage_power_supply = 12;
// choose FOC modulation (optional)
motor.foc_modulation = FOCModulationType::SpaceVectorPWM;
// init motor hardware
motor.init();
Serial.begin(115200);
Serial.println("Motor ready!");
_delay(1000);
}
// target voltage to be set to the motor
float target_voltage = 2;
// target voltage to be set to the motor
float target_angle = 2;
void loop() {
// integratiing the angle in real time
// the larger the constant added the faster the movement
target_angle += 0.001;
// set open loop voltage
motor.setPhaseVoltage(target_voltage, target_angle);
}
With this code you can test your driver and you can easily set the limiting voltage you are setting to the motor. Just make sure you change the target_voltage
value. (this value can be negative as well).
In case of your motors you can start form 0.1V and then grow the values.
If you wish to change the velocity of the movement you just add a larger number instead of 0.001
. You can put something like:
target_angle += 0.1;
Voltage limiting
Now when you want to limit the voltage there are 4 things you should know:
-
First thing you should make sure to change is set is the
motor.voltage_power_supply
if you don’t put the real power supply voltage (doesn’t have to be dead on, but at least close) then all of your limiting in future steps will have an error proportional to the error of themotor.voltage_power_supply
. -
First thing to limit is the variable
motor.PI_velocity.voltage_limit = yourVoltageLimit;
as suggestedd by @David_Gonzalez. This is very important. -
When you are running the voltage control then you don’t need any other limits, other than not setting the target voltage higher than you limit.
-
When running position/velocity motion control then you need to set the
motor.PI_velocity.voltage_limit = yourVoltageLimit;
this variable is only used for position and velocity control, not for open loop and voltage control. You can see this on the diagrams in the Motion Control | Arduino-FOC
Here is a voltage control code with voltage limiting:
#include <SimpleFOC.h>
// Magnetic sensor
MagneticSensorI2C sensor = MagneticSensorI2C(0x36, 12, 0x0E, 4);
// Motor instance
BLDCMotor motor = BLDCMotor(9, 5, 6, 11, 8);
void setup() {
// initialise magnetic sensor hardware
sensor.init();
// link the motor to the sensor
motor.linkSensor(&sensor);
// power supply voltage
// default 12V
motor.voltage_power_supply = your power supply;
// aligning voltage
motor.voltage_sensor_align = your limit;
// choose FOC modulation (optional)
motor.foc_modulation = FOCModulationType::SpaceVectorPWM;
// set motion control loop to be used
motor.controller = ControlType::voltage;
// 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();
Serial.println("Motor ready.");
Serial.println("Set the target voltage using serial terminal:");
Serial.println("But dont exceed your limit");
_delay(1000);
}
// target voltage to be set to the motor
float target_voltage = 0;
void loop() {
// main FOC algorithm function
motor.loopFOC();
target_voltage =
// Motion control function
motor.move(target_voltage);
// communicate with the user
serialReceiveUserCommand();
}
// utility function enabling serial communication with the user to set the target values
// this function can be implemented in serialEvent function as well
void serialReceiveUserCommand() {
// a string to hold incoming data
static String received_chars;
while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the string buffer:
received_chars += inChar;
// end of user input
if (inChar == '\n') {
// change the motor target
target_voltage = constrain(received_chars.toFloat();, -your limit, your limit)
Serial.print("Target voltage: ");
Serial.println(target_voltage);
// reset the command buffer
received_chars = "";
}
}
}
And here is a simple example of a velocity control (the limiting part is the same as for the position loop):
// Voltage motion control will placeholders for voltage limit
#include <SimpleFOC.h>
// magnetic sensor instance
MagneticSensorI2C sensor = MagneticSensorI2C(0x36, 12, 0x0E, 4);
// Motor instance
BLDCMotor motor = BLDCMotor(9, 5, 6, 11, 8);
void setup() {
// initialise magnetic sensor hardware
sensor.init();
// link the motor to the sensor
motor.linkSensor(&sensor);
// power supply voltage
// default 12V
motor.voltage_power_supply = your power supply;
// aligning voltage
motor.voltage_sensor_align = your limit;
// set motion control loop to be used
motor.controller = ControlType::velocity;
// velocity PI controller parameters
motor.PI_velocity.P = 0.2;
motor.PI_velocity.I = 20;
// default voltage_power_supply
motor.PI_velocity.voltage_limit = your limit;
// 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();
Serial.println("Motor ready.");
Serial.println("Set the target velocity using serial terminal:");
_delay(1000);
}
// velocity set point variable
float target_velocity = 0;
void loop() {
// main FOC algorithm function
motor.loopFOC();
// Motion control function
motor.move(target_velocity);
// user communication
serialReceiveUserCommand();
}
// utility function enabling serial communication with the user to set the target values
// this function can be implemented in serialEvent function as well
void serialReceiveUserCommand() {
// a string to hold incoming data
static String received_chars;
while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the string buffer:
received_chars += inChar;
// end of user input
if (inChar == '\n') {
// change the motor target
target_velocity = received_chars.toFloat();
Serial.print("Target velocity: ");
Serial.println(target_velocity);
// reset the command buffer
received_chars = "";
}
}
}
I hope it helps, let me know how it goes!
I have released the new version of the library 1.4.1 which has a bit smaller memory footprint so please make sure to use the newest version. This might help with the find_pole_pairs
issue.
I also have one quesstion
@Juxo, you say you are running the i2c sensor with the Nucleo boards, did you need to use pull-ups.