设计一个速度控制器
设计一个module,使用PID闭环来控制电机速度。实践时请对照 开始
章节如何编写新的模块和设备相关内容。
创建一个新的module
使用./project.py new module speed_control
来创建。
此模块应当有以下文件:
speed_control
├── info.cmake
├── Kconfig
├── mod_speed_control.cpp
└── mod_speed_control.hpp
加入头文件
需要pid和电机类。
mod_speed_control.hpp
#include "comp_pid.hpp"
#include "dev_rm_motor.hpp"
声明speed_control类
namespace Module {
class SpeedControl {
...
};
} // namespace Module
定义配置文件结构体
speed_control的配置文件应当包含pid和motor的配置
typedef struct {
Component::PID::Param pid;
Device::RMMotor::Param motor;
} Param;
成员函数
/* 构造函数 */
SpeedControl(Param& param);
/* 控制函数 */
void Control();
/* 更新电机反馈 */
void UpdateFeedback();
其他变量
float now_; /* 当前时间 */
float dt_; /* 距离上次控制的时间 */
float lask_wakeup_; /* 上次控制的时间 */
float speed_setpoint_; /* 速度目标值 */
float output_; /* 电机输出 */
Component::PID pid_; /* pid对象 */
Device::RMMotor motor_; /* motor对象 */
System::Thread thread_; /* 控制线程 */
运行逻辑
mod_speed_control.cpp
先包含对应头文件和命名空间
#include "mod_speed_control.hpp"
using namespace Module;
声明电机最大速度
#define MOTOR_MAX_ROTATIONAL_SPEED (7000.0f)
构造函数
用初始化列表初始化成员变量,再创建控制线程。
SpeedControl::SpeedControl(Param& param)
:pid_(param.pid, 500), motor_(param.motor, "motor") {
/* 使用lambda创建控制线程函数 */
auto ctrl_thread = [](SpeedControl* speed_ctrl) {
while (1) {
/* 获取控制命令 暂时写死*/
speed_ctrl->speed_setpoint_ = 0.15f;
/* 更新反馈 */
speed_ctrl->UpdateFeedback();
/* 控制电机 */
speed_ctrl->Control();
/* 等待下一次控制 */
speed_ctrl->thread_.SleepUntil(2);
}
};
/* 创建线程 */
this->thread_.Create(ctrl_thread, this, "speed_control", 384,
System::Thread::MEDIUM);
}
获取反馈信息
void SpeedControl::UpdateFeedback() { this->motor_.Update(); }
PID控制
void SpeedControl::Control() {
/* 更新时间 */
this->now_ = bsp_time_get();
this->dt_ = this->now_ - this->lask_wakeup_;
this->lask_wakeup_ = this->now_;
/* 计算PID */
this->output_ = this->pid_.Calculate(
this->speed_setpoint_,
this->motor_.GetSpeed() / MOTOR_MAX_ROTATIONAL_SPEED, this->dt_);
/* 电机输出 */
this->motor_.Control(this->output_);
}
完整代码示例
mod_speed_control.cpp
#include "mod_speed_control.hpp"
using namespace Module;
#define MOTOR_MAX_ROTATIONAL_SPEED (7000.0f)
SpeedControl::SpeedControl(Param& param)
:pid_(param.pid, 500), motor_(param.motor, "motor") {
/* 使用lambda创建控制线程函数 */
auto ctrl_thread = [](SpeedControl* speed_ctrl) {
while (1) {
/* 获取控制命令 暂时写死*/
speed_ctrl->speed_setpoint_ = 0.15f;
/* 更新反馈 */
speed_ctrl->UpdateFeedback();
/* 控制电机 */
speed_ctrl->Control();
/* 等待下一次控制 */
speed_ctrl->thread_.SleepUntil(2);
}
};
/* 创建线程 */
this->thread_.Create(ctrl_thread, this, "speed_control", 384,
System::Thread::MEDIUM);
}
void SpeedControl::UpdateFeedback() { this->motor_.Update(); }
void SpeedControl::Control() {
/* 更新时间 */
this->now_ = bsp_time_get();
this->dt_ = this->now_ - this->lask_wakeup_;
this->lask_wakeup_ = this->now_;
/* 计算PID */
this->output_ = this->pid_.Calculate(
this->speed_setpoint_,
this->motor_.GetSpeed() / MOTOR_MAX_ROTATIONAL_SPEED, this->dt_);
/* 电机输出 */
this->motor_.Control(this->output_);
}
mod_speed_control.hpp
#include "comp_pid.hpp"
#include "dev_rm_motor.hpp"
namespace Module {
class SpeedControl {
public:
typedef struct {
Component::PID::Param pid;
Device::RMMotor::Param motor;
} Param;
/* 构造函数 */
SpeedControl(Param& param);
/* 控制函数 */
void Control();
/* 更新电机反馈 */
void UpdateFeedback();
private:
float now_; /* 当前时间 */
float dt_; /* 距离上次控制的时间 */
float lask_wakeup_; /* 上次控制的时间 */
float speed_setpoint_; /* 速度目标值 */
float output_; /* 电机输出 */
Component::PID pid_; /* pid对象 */
Device::RMMotor motor_; /* motor对象 */
System::Thread thread_; /* 控制线程 */
};
} // namespace Module