Link

了解 简易FOC 代码

一旦你安装好了 简易FOC 安装说明,并且拥有了所有必要的 硬件,我们终于可以开始熟悉将运行电机的 Arduino 代码了。以下是编写代码时所有最重要的步骤!

步骤 0. 包含库

让我们从包含库头文件开始:

#include <SimpleFOC.h>

步骤 1. 位置传感器设置

编写代码的第一步是初始化和配置位置传感器。 该库支持以下位置传感器:

选择一个位置传感器用于本示例:

Encoder Magnetic sensor Hall sensors

#include <SimpleFOC.h>

// Encoder(pin_A, pin_B, PPR)
Encoder sensor = Encoder(2, 3, 2048);
// channel A and B callbacks
void doA(){sensor.handleA();}
void doB(){sensor.handleB();}

 
void setup() {  
  // initialize encoder hardware
  sensor.init();
  // hardware interrupt enable
  sensor.enableInterrupts(doA, doB);

}

void loop() {
  
}

作为位置传感器的编码器在 Encoder 类中实现,由以下参数定义:

  • A 和 B 通道引脚号:2 和 3
  • 编码器 PPR(每转脉冲数):2048
  • 索引引脚号(可选)

通过运行 sensor.init() 初始化硬件引脚。

有关设置和所有配置参数的完整文档,请访问 位置传感器文档

步骤 2. 驱动器设置

设置好位置传感器后,我们继续初始化和配置驱动器。该库支持由 BLDCDriver3PWM 和 BLDCDriver6PWM 类处理的 BLDC 驱动器,以及由 StepperDriver2PWM 和 StepperDriver4PWM 类处理的 步进驱动器

BLDC Driver - 3PWM Stepper Driver 4PWM

BLDCDriver3PWM 类通过提供以下参数实例化:

  • 相位 A、B 和 C 的 PWM 引脚
  • 使能 引脚号(可选)

例如:

#include <SimpleFOC.h>

//  BLDCDriver3PWM( pin_pwmA, pin_pwmB, pin_pwmC, enable (optional))
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);

// instantiate sensor 

void setup() {  

  // init sensor

  // pwm frequency to be used [Hz]
  driver.pwm_frequency = 20000;
  // power supply voltage [V]
  driver.voltage_power_supply = 12;
  // Max DC voltage allowed - default voltage_power_supply
  driver.voltage_limit = 12;
  // driver init
  driver.init();

}

void loop() {

}

有关设置和所有配置参数的完整文档,请访问 驱动器文档

步骤 3. 电流检测设置

在位置传感器和驱动器之后,如果有电流检测功能,我们可以继续初始化和配置它。如果没有电流检测功能,可以跳过此步骤。该库支持两种类型的电流检测架构:

  • 串联电流检测 InlineCurrentSense.
  • 低侧电流检测 LowsideCurrentSense.

In-line current sensing Low side current sensing

InlineCurrentSense 类通过提供以下参数实例化:

  • 分流电阻值 shunt_resistance
  • 放大器增益 gain
  • 相位 A、B(可选 C)的模拟引脚号

例如:

#include <SimpleFOC.h>

// instantiate driver
// instantiate sensor

//  InlineCurrentSense(shunt_resistance, gain, adc_a, adc_b)
InlineCurrentSense current_sense = InlineCurrentSense(0.01, 50, A0, A2);


void setup() {  

  // init sensor

  // init driver

  // link the driver with the current sense
  current_sense.linkDriver(&driver);
  // init current sense
  current_sense.init();

}

void loop() {

}

有关设置和所有配置参数的完整文档,请访问 电流检测文档

步骤 4. 电机设置

在位置传感器和驱动器之后,我们继续初始化和配置电机。该库支持由 BLDCMotor 类处理的 BLDC 电机,以及由 StepperMotor 和 HybridStepperMotor 类处理的步进电机。这两个类都通过提供电机的 极对数 以及可选的电机相电阻和 KV 额定值来实例化。

BLDC motor Stepper motor HybridStepper motor

在本示例中,我们将使用 BLDC 电机:

#include <SimpleFOC.h>

//  BLDCMotor( pole_pairs , ( phase_resistance, KV_rating  optional) )
BLDCMotor motor = BLDCMotor(11, 9.75);
 
// instantiate driver
// instantiate sensor 
// instantiate current sensor   

void setup() {  
  // init sensor
  // link the motor to the sensor
  motor.linkSensor(&sensor);

  // init driver
  // link the motor to the driver
  motor.linkDriver(&driver);
  // link driver and the current sense
  
  // link the motor to current sense
  motor.linkCurrentSense(&current_sense);

  // set control loop type to be used
  motor.controller = MotionControlType::velocity;
  // initialize motor
  motor.init();

  // init current sense
  

}

void loop() {

}

创建电机 motor 的实例后,我们需要将电机与传感器 motor.linkSensor() 链接,并将电机类与它所连接的驱动器 motor.linkDriver() 链接。
下一步是配置步骤,为了本示例的目的,我们将只配置我们将要使用的运动控制环:

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

为了完成 motor 设置,我们运行 motor.init() 函数。

有关设置和所有配置参数的完整文档,请访问 电机文档

步骤 5. FOC 程序和实时运动控制

当我们初始化了位置传感器、驱动器和电机之后,在运行 FOC 算法之前,我们需要对齐电机和传感器。这通过调用 motor.initFOC() 来完成。此步骤之后,我们有一个功能正常的位置传感器,我们已经配置了电机,并且我们的 FOC 算法知道如何根据位置传感器测量值设置适当的电压。

对于 FOC 算法的实时程序,我们需要在 Arduino loop() 中添加 motor.loopFOC() 和 motor.move(target) 函数。

  • motor.loopFOC(): FOC 算法执行 - 应尽可能快地执行 > 1kHz
  • motor.move(target): 运动控制程序 - 取决于 motor.controller 参数

代码如下所示:

#include <SimpleFOC.h>

// instantiate motor
// instantiate driver
// instantiate sensor 
// instantiate current sensor   

void setup() {  
  
  // init sensor
  // link motor and sensor

  // init driver
  // link motor and driver
  // link driver and the current sense

  // link motor and current sense

  // configure motor
  // init motor

  // init current sense

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

void loop() {
  // FOC algorithm function
  motor.loopFOC();

  // velocity control loop function
  // setting the target velocity to 2rad/s
  motor.move(2);
}

有关 BLDC 电机的设置和所有配置参数的完整文档,请访问 BLDCMotor 文档 ,对于步进电机,请访问 StepperMotor 文档

步骤 6. 监控

BLDCMotor 和 StepperMotor 类提供监控功能。要启用监控功能,请确保调用 motor.useMonitoring() 并传入你想要输出的 Serial 端口实例。它使用 Serial 类在 motor.init() 函数以及 motor.initFOC() 函数期间输出电机初始化状态。

如果你有兴趣实时输出电机状态变量(尽管这会影响性能 - 写入 Serial 端口很慢!),请将 motor.monitor() 函数调用添加到 Arduino loop() 函数中。

#include <SimpleFOC.h>

// instantiate motor
// instantiate driver
// instantiate senor

void setup() {
  
  // init the serial port
  Serial.begin(115200);

  // init sensor
  // link motor and sensor

  // init driver
  // link motor and driver
  // link driver and the current sense


  // init current sense
  // link motor and current sense

  // use monitoring with the BLDCMotor
  Serial.begin(115200);
  // monitoring port
  motor.useMonitoring(Serial);
  
  // configure motor
  // init motor

  // init current sense
  
  // align encoder and start FOC
}

void loop() {
  
  // FOC execution
  // motion control loop

  // monitoring function outputting motor variables to the serial terminal 
  motor.monitor();
}

有关 BLDCMotor 和 StepperMotor 监控的更多文档,请参见 监控文档

步骤 7. 调试输出

简易FOC库 提供了一个信息丰富的调试接口,可以通过调用 SimpleFOCDebug::enable(&Serial) 函数启用。此函数启用库到 Serial 端口的调试输出。

此调试接口将输出更详细的信息,包括:

  • 驱动器初始化(在 driver.init() 函数期间)
  • 电流检测初始化(在 current_sense.init() 函数期间)
  • 电机初始化(在 motor.init() 函数期间)
  • 电机 FOC 初始化(在 motor.initFOC() 函数期间)

调试输出将提供有关电机、驱动器和电流检测在初始化过程中及之后的状态的更多信息,并将帮助你调试设置。

它还将提供特定于 MCU 架构的信息,例如哪些定时器和通道用于 PWM 生成,哪些 ADC 用于电流检测,TIME-ADC 同步是否工作等。

📢 我们强烈建议在开始使用 简易FOC 时使用调试模式。 它提供的信息比标准监控输出多得多,有助于排查潜在问题,甚至是特定于 MCU 架构的问题。

内存使用

调试输出是字符串,可能会占用相当多的内存空间,因此不建议在最终应用程序中使用它。

调试输出默认是禁用的,可以通过在任何 driver、sensor、current_sense 或 motor 初始化(init 调用)之前调用 SimpleFOCDebug::enable(&Serial) 函数来启用。最好将 SimpleFOCDebug::enable(&Serial) 函数调用放在 setup() 函数的开头。

#include <SimpleFOC.h>

// instantiate motor
// instantiate driver
// instantiate senor

void setup() {
  
  // init the serial port
  // enable the debugging output
  SimpleFOCDebug::enable(&Serial);

  // init sensor
  // link motor and sensor

  // init driver
  // link motor and driver
  // link driver and the current sense


  // init current sense
  // link motor and current sense

  // enable monitoring
  
  // configure motor
  // init motor

  // init current sense
  
  // align encoder and start FOC
}

void loop() {
  
  // FOC execution
  // motion control loop
  // monitor variables
}

有关 简易FOC库 调试功能的更多文档,请参见 调试文档

步骤 8. 命令器接口

最后,为了以用户友好的方式配置控制算法、设置目标值和获取状态变量(不仅仅是像使用 motor.monitor() 时那样 dumping),简易FOC库 以 Commander 类的形式为你提供了类似 g 代码的通信接口。

Full motor commander Only motor target value Motion control target + Led control

以下代码是与用户的完整通信接口的一个基本实现:

#include <SimpleFOC.h>

// instantiate motor
// instantiate senor

//instantiate commander
Commander commander = Commander(Serial);
void doMotor(char* cmd){commander.motor(&motor, cmd);}

void setup() {  
  
  // init the serial port
  // enable the debugging output

  // init sensor
  // link motor and sensor

  // init driver
  // link motor and driver
  // link driver and the current sense


  // init current sense
  // link motor and current sense
  
  // enable monitoring
  
  // subscribe motor to the commands
  commander.add('M',doMotor,"motor");

  // init motor

  // init current sense
  
  // align encoder and start FOC
}

void loop() {
  
  // FOC execution
  // motion control loop
  // monitor variables

  // read user commands
  commander.run();
}

有关设置和所有配置参数的完整文档,请访问 通信文档

步骤 9. 循序渐进的入门指南

现在你已经熟悉了 简易FOC库 代码的结构,你终于可以开始编写自己的应用程序了。为了使这一步不那么复杂,我们为你提供了详细的循序渐进指南。当你第一次使用该库时,一定要浏览我们的循序渐进入门指南。

🎨 示例的完整 Arduino 代码

上面,你已经了解了 Arduino 程序的所有部分及其用途。以下是带有一些额外配置的完整代码示例。请仔细阅读代码,以更好地理解如何将前面介绍的所有部分集成到一个代码中。这是库示例 motor_full_control_serial_examples/magnetic_sensor/full_control_serial.ino 的代码。

#include <SimpleFOC.h>

// magnetic sensor instance - SPI
MagneticSensorSPI sensor = MagneticSensorSPI(AS5147_SPI, 10);

// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(11);
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);

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

void setup() {
  // monitoring port
  Serial.begin(115200);
  // enable the debugging output
  SimpleFOCDebug::enable(&Serial);

  // initialise magnetic sensor hardware
  sensor.init();
  // link the motor to the sensor
  motor.linkSensor(&sensor);

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

  // set control loop type to be used
  motor.controller = MotionControlType::torque;

  // contoller configuration based on the control type 
  motor.PID_velocity.P = 0.2;
  motor.PID_velocity.I = 20;
  motor.PID_velocity.D = 0;
  // default voltage_power_supply
  motor.voltage_limit = 12;

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

  // angle loop controller
  motor.P_angle.P = 20;
  // angle loop velocity limit
  motor.velocity_limit = 50;

  // use monitoring with serial for motor init
  // 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 = 2;

  // define the motor id
  command.add('A', 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 of the FOC phase voltage
  motor.loopFOC();

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

库源代码

如果你有兴趣扩展和改编 简易FOC库 源代码,你可以在 库源代码文档 中找到完整的文档。