My English is not very good, I hope you can understand it.
I am trying to make the motor skip calibration and keep current angle.
Sometimes is work,
Sometimes the motor keeps going in the same direction.
Sometimes the motor does not rotate(electric current:0.4~0.5A).
Sometimes the motor CCW and CW speeds are different.
driver: L6234
position sensors: AS5048A
microcontroller: ESP32
simplefoc v 2.0.1
My Code
#include <SimpleFOC.h>
#include <SPI.h>
#define BLDC1_MOSI2 23
#define BLDC1_MISO2 19
#define BLDC1_SCLK2 18
#define BLDC1_CS2 5
#define BLDC1_INH_A 25
#define BLDC1_INH_B 26
#define BLDC1_INH_C 27
#define BLDC1_EN_GATE 33
// SPI Magnetic sensor instance (AS5047U example)
// MISO PB14
// MOSI PB15
// SCK PB13
MagneticSensorSPI sensor = MagneticSensorSPI(BLDC1_CS2, 14, 0x3FFF);
//SPIClass SPI_2(BLDC1_MOSI2, BLDC1_MISO2, BLDC1_SCLK2);
SPIClass * SPI_2 = NULL;
// BLDC motor instance
BLDCMotor motor_1 = BLDCMotor(14);
// driver instance
BLDCDriver3PWM driver_1 = BLDCDriver3PWM(BLDC1_INH_A, BLDC1_INH_B, BLDC1_INH_C, BLDC1_EN_GATE);
void initMotor1 () {
//SCLK = 18, MISO = 19, MOSI = 23, SS = 5
SPI_2 = new SPIClass(VSPI);
// initialise magnetic sensor hardware
sensor.init(SPI_2);
Serial.println("initMotor1-1");
// link the motor to the sensor
motor_1.linkSensor(&sensor);
// driver config
// power supply voltage [V]
driver_1.voltage_power_supply = 12 ;
driver_1.init();
// link driver
motor_1.linkDriver(&driver_1);
// choose FOC modulation (optional)
motor_1.foc_modulation = FOCModulationType::SpaceVectorPWM;
// set motion control loop to be used
motor_1.controller = ControlType::angle;
// contoller configuration
// default parameters in defaults.h
// velocity PI controller parameters
motor_1.PID_velocity.P = 1;
motor_1.PID_velocity.I = 110;
motor_1.PID_velocity.D = 0;
motor_1.PID_velocity.output_ramp = 1000;
// maximal voltage to be set to the motor
motor_1.voltage_limit = 6;
// velocity low pass filtering time constant
// the lower the less filtered
motor_1.LPF_velocity.Tf = 0.01;
// angle P controller
motor_1.P_angle.P = 20;
// maximal velocity of the position control
motor_1.velocity_limit = 40;
// comment out if not needed
motor_1.useMonitoring(Serial);
delay(1000);
// initialize motor
motor_1.init();
// align sensor and start FOC
motor_1.initFOC(sensor.getAngle());
// motor_1.target = 0;
// motor_1.shaftAngle();
}
void setup() {
// use monitoring with serial
Serial.begin(115200);
_delay(1000);
initMotor1();
_delay(1000);
Serial.println("Full control example: ");
Serial.println("Run user commands to configure and the motor (find the full command list in docs.simplefoc.com) \n ");
Serial.println("Initial motion control loop is voltage loop.");
Serial.println("Initial target voltage 2V.");
_delay(1000);
}
void loop() {
motor_1.loopFOC();
motor_1.move();
motor_1.command(serialReceiveUserCommand());
}
// utility function enabling serial communication the user
String serialReceiveUserCommand() {
// a string to hold incoming data
static String received_chars;
String command = "";
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') {
// execute the user command
command = received_chars;
// reset the command buffer
received_chars = "";
}
}
return command;
}
Have you tried to run the example for finding zero offset?
There you should find the motor/sensor zero offset and the natural direction. After that you can just provide those values to the initFOC(offset, direction).
Since Arduino doesn’t have permanent memory, we cannot remember that value in between calls.
But if you run the example and copy the values to you code you should be set.
3.6501 is Run example 《find_zero_offset_and_direction》 output value.
And
I don’t know how to keep the current angle when the motor is powered on(ControlType::angle).
But the motor will shake one time after initialization.
All Code
/**
*
* STM32 Bluepill position motion control example with magnetic sensor
*
* The same example can be ran with any STM32 board - just make sure that put right pin numbers.
*
*/
#include <SimpleFOC.h>
#include <SPI.h>
#define BLDC1_MOSI2 23
#define BLDC1_MISO2 19
#define BLDC1_SCLK2 18
#define BLDC1_CS2 5
#define BLDC2_M_PWM 4
#define BLDC2_M_OC 16
#define BLDC2_OC_ADJ 17
#define BLDC1_INH_A 25
#define BLDC1_INH_B 26
#define BLDC1_INH_C 27
#define BLDC1_EN_GATE 33
// SPI Magnetic sensor instance (AS5047U example)
// MISO PB14
// MOSI PB15
// SCK PB13
MagneticSensorSPI sensor = MagneticSensorSPI(BLDC1_CS2, 14, 0x3FFF);
//SPIClass SPI_2(BLDC1_MOSI2, BLDC1_MISO2, BLDC1_SCLK2);
SPIClass * SPI_2 = NULL;
// BLDC motor instance
BLDCMotor motor_1 = BLDCMotor(14);
// driver instance
BLDCDriver3PWM driver_1 = BLDCDriver3PWM(BLDC1_INH_A, BLDC1_INH_B, BLDC1_INH_C, BLDC1_EN_GATE);
void initMotor1 () {
// DRV8302 specific code
// M_OC - enable overcurrent protection
pinMode(BLDC2_M_OC, OUTPUT);
digitalWrite(BLDC2_M_OC, LOW);
// M_PWM - enable 3pwm mode
pinMode(BLDC2_M_PWM, OUTPUT);
digitalWrite(BLDC2_M_PWM, HIGH);
// OD_ADJ - set the maximum overcurrent limit possible
// Better option would be to use voltage divisor to set exact value
pinMode(BLDC2_OC_ADJ, OUTPUT);
digitalWrite(BLDC2_OC_ADJ, HIGH);
//SCLK = 18, MISO = 19, MOSI = 23, SS = 5
SPI_2 = new SPIClass(VSPI);
// initialise magnetic sensor hardware
sensor.init(SPI_2);
Serial.println("initMotor1-1");
// link the motor to the sensor
motor_1.linkSensor(&sensor);
// driver config
// power supply voltage [V]
driver_1.voltage_power_supply = 24 ;
driver_1.init();
// link driver
motor_1.linkDriver(&driver_1);
// choose FOC modulation (optional)
motor_1.foc_modulation = FOCModulationType::SpaceVectorPWM;
// set motion control loop to be used
motor_1.controller = ControlType::angle;
// contoller configuration
// default parameters in defaults.h
// velocity PI controller parameters
motor_1.PID_velocity.P = 0.05;
motor_1.PID_velocity.I = 30;
motor_1.PID_velocity.D = 0;
// maximal voltage to be set to the motor
motor_1.voltage_limit = 6;
// velocity low pass filtering time constant
// the lower the less filtered
motor_1.LPF_velocity.Tf = 0.01;
// angle P controller
motor_1.P_angle.P = 20;
// maximal velocity of the position control
motor_1.velocity_limit = 40;
// comment out if not needed
motor_1.useMonitoring(Serial);
delay(1000);
// initialize motor
motor_1.init();
// align sensor and start FOC
// delay(100);
// motor_1.initFOC();
// motor_1.target = sensor.getAngle();
motor_1.initFOC(3.6501, Direction::CW);
delay(100);
// sensor.initRelativeZero();
motor_1.target = motor_1.shaft_angle;
// motor_1.shaftAngle();
}
void setup() {
// use monitoring with serial
Serial.begin(115200);
_delay(1000);
initMotor1();
_delay(1000);
Serial.println("Full control example: ");
Serial.println("Run user commands to configure and the motor (find the full command list in docs.simplefoc.com) \n ");
Serial.println("Initial motion control loop is voltage loop.");
Serial.println("Initial target voltage 2V.");
_delay(1000);
}
void loop() {
motor_1.loopFOC();
motor_1.move();
motor_1.command(serialReceiveUserCommand());
}
// utility function enabling serial communication the user
String serialReceiveUserCommand() {
// a string to hold incoming data
static String received_chars;
String command = "";
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') {
// execute the user command
command = received_chars;
// reset the command buffer
received_chars = "";
}
}
return command;
}