一个基于粒子群优化算法(PSO)的上位机工具,用于自动化优化下位机的PID参数。
通过迭代评估系统性能指标,自动寻找最优PID参数组合,提高调参效率。
运行 demo.py 可查看仿真示例。
- Python 3.10.x
- 依赖库:
pip install pyserial numpy parse matplotlib scipy
- 或者直接使用项目自带的venv虚拟环境
-
安装环境
安装Python 3.10及上述依赖库。 -
配置通信接口
默认使用串口通信。若需其他通信方式(如TCP/IP),请继承CommunicationInterface类实现自定义接口。 -
运行优化程序
python One_click_Start.py
程序启动后,根据提示选择运行模式,确保通信正常,程序将自动迭代直至完成。
没有安装Python请在release页面下载可执行文件直接运行
程序支持以下三种运行模式:
- 使用场景:适合开发调试阶段,无需硬件设备
- 工作流程:
- 每次迭代时由用户手动在控制台输入性能指标(ITAE、超调量、调节时间、稳态误差)
- 上位机基于输入数据通过PSO算法计算优化方向
- 适合算法验证和小规模参数优化测试
- 使用场景:实际硬件自动化优化,下位机具备性能指标计算能力
- 工作流程:
- 上位机通过串口发送PID参数至下位机
- 下位机执行PID控制,实时计算ITAE、超调量、调节时间、稳态误差等指标
- 下位机返回计算结果至上位机
- 上位机通过PSO算法迭代优化参数
- 使用场景:实际硬件自动化优化,上位机分析原始数据
-
工作流程:
- 上位机通过串口发送PID参数至下位机
- 下位机执行PID控制,返回目标值(TARGET)和实际输出值(OUTPUT)等原始数据
- 上位机接收数据并根据配置的控制周期
$\Delta t$ 计算性能指标 - 上位机通过PSO算法迭代优化参数
程序支持自定义数据解析格式,使用Parse库语法:
模式2数据格式示例:
下位机返回: ITAE:0.1234,OVERSHOOT:2.34,SETTLING:1.0,SSE:0.0456
解析格式: "ITAE:{itae:f},OVERSHOOT:{overshoot:f},SETTLING:{settling:f},SSE:{sse:f}"
解析格式中的
itae、overshoot、setting、sse(小写部分)不可修改
模式3数据格式示例:
下位机返回: TARGET:100.0,OUTPUT:98.5
解析格式: "TARGET:{target:f},OUTPUT:{output:f}"
解析格式中的
target、output(小写部分)不可修改
模式2(下位机计算指标):
下位机需计算以下性能指标并返回:
- ITAE(时间乘以绝对误差积分)
- 超调量(%)
- 调节时间
- 稳态误差
模式3(上位机计算指标):
下位机需返回:
- TARGET(目标值)
- OUTPUT(PID输出值)
- 上位机发送PID参数至下位机:
KP:value,KI:value,KD:value\n - 下位机执行控制过程,计算性能指标或返回原始数据
- 通信格式需与上位机解析器匹配
具体过程参考
PID_Helper.py→FastPSO_PID_Optimizer→optimize()和evaluate_particle()
如需非串口通信(如TCP/IP、UDP等),请按以下示例实现:
from PID_Helper.CommunicationInterface import CommunicationInterface
class CustomCommunication(CommunicationInterface):
def open(self, port: str, baud_rate: int) -> bool:
# 实现自定义打开逻辑
pass
def read_line(self, decode: str = "ascii") -> str | None:
# 实现自定义读取逻辑
pass
def write(self, data: str, encode: str = "ascii") -> bool:
# 实现自定义写入逻辑
pass
def close(self) -> bool:
# 实现自定义关闭逻辑
pass连续形式: $$ \text{ITAE} = \int_{t_{start}}^{t_{stop}} t \cdot |e(t)| , dt $$
离散形式: $$ \text{ITAE} = \sum_{i=0}^{n} |e_i| \cdot t_i \cdot \Delta t $$
C语言实现示例:
// 全局变量
float itae = 0;
float pid_time = 0;
// PID运行代码
void pid_run(float dt) {
// ... PID计算 ...
pid_time += dt;
itae += fabsf(pid.error) * pid_time * dt;
}
// PID停止代码
void pid_stop() {
// 串口输出ITAE
printf("ITAE:%.4f\n", itae);
// 重置变量
itae = 0;
pid_time = 0;
}$$ \text{超调量} =
\begin{cases}
\frac{\max(\text{Measure}) - \text{Target}}{\text{Target}} \times 100%, & \text{if } \max(\text{Measure}) > \text{Target} \ 0%, & \text{otherwise}
\end{cases} $$
C语言实现示例:
// 全局变量
float overshoot = 0;
float max_measure = 0;
// PID运行代码
void pid_run(float dt) {
// ... PID计算 ...
// 更新最大测量值
if (pid.measure > max_measure) {
max_measure = pid.measure;
}
}
// PID停止代码
void pid_stop() {
// 计算超调量(百分比)
if (max_measure > pid.target) {
overshoot = (max_measure - pid.target) / pid.target * 100.0f;
} else {
overshoot = 0;
}
// 串口输出超调量
printf("OVERSHOOT:%.4f\n", overshoot);
// 重置变量
overshoot = 0;
max_measure = 0;
}系统响应进入并保持在目标值±2%误差带内所需的时间。
C语言实现示例:
// 全局变量
float settling_time = 0;
float pid_time = 0;
// PID运行代码
void pid_run(float dt) {
// ... PID计算 ...
pid_time += dt;
// 如果超出误差带,更新调节时间
if (!(pid.measure > pid.target * 0.98f && pid.measure < pid.target * 1.02f)) {
settling_time = pid_time;
}
}
// PID停止代码
void pid_stop() {
// 串口输出调节时间
printf("SETTLING:%.4f\n", settling_time);
// 重置变量
settling_time = 0;
pid_time = 0;
}可根据实际需求调整误差带范围(默认2%,可在代码中修改)
取响应过程最后10%时间段内的平均误差。
C语言实现示例:
// 全局变量
float sse = 0;
float evaluate_time = 5.0f; // 评估时间(秒)
float start_cal_sse_time = evaluate_time * 0.9f; // 开始计算SSE的时间
float sse_timer = 0;
int16_t cal_sse_tick = 0; // 计算SSE期间经历PID计算的次数
// PID运行代码
void pid_run(float dt) {
// ... PID计算 ...
sse_timer += dt;
if (sse_timer > start_cal_sse_time) {
sse += fabsf(pid.error);
cal_sse_tick++;
}
}
// PID停止代码
void pid_stop() {
// 计算平均稳态误差
if (cal_sse_tick > 0) {
sse = sse / cal_sse_tick;
}
// 串口输出稳态误差
printf("SSE:%.4f\n", sse);
// 重置变量
sse = 0;
sse_timer = 0;
cal_sse_tick = 0;
}也可采用其他稳态误差计算方法
| 参数 | 说明 | 默认值 | 建议范围 |
|---|---|---|---|
pop_size |
粒子群大小 | 10 | 10-15 |
max_iter |
最大迭代次数 | 20 | 20-30 |
inertia_weight |
惯性权重 | 0.7298 | 0.4-0.9 |
c1 |
个体学习因子 | 1.49618 | 1.0-2.0 |
c2 |
社会学习因子 | 1.49618 | 1.0-2.0 |
evaluation_delay |
评估延迟(秒) | 0.5 | 0.1-1.0 |
max_evaluation_time |
最大评估时间(秒) | 5.0 | 3.0-10.0 |
- 日志文件:自动保存至
logs/目录,格式为{module_name}-{timestamp}.log - 优化结果:支持保存为JSON格式,包含最优参数、适应度历史和配置信息
结果文件示例:
{
"best_parameters": {
"Kp": 1.2345,
"Ki": 0.5678,
"Kd": 0.0123
},
"best_fitness": 0.123456,
"fitness_history": [1.23, 0.98, 0.76, ...],
"config": { ... }
}- 确保通信稳定,避免数据丢失或格式错误
- 下位机计算性能指标时需与上位机定义的时间基准一致(特别是模式3)
- 可调整PSO算法参数以平衡收敛速度与精度
- 第一次运行建议使用模式1验证数据格式和算法流程
- 手动输入模式下,输入浮点数时需要加上
.0后缀(如1.0而不是1) - 若串口无法打开,请检查:
- 设备是否正确连接
- 串口号是否正确(Windows: COM1, Linux: /dev/ttyUSB0)
- 波特率是否匹配
- 是否安装了必要的驱动程序
- 是否有其他程序占用该串口
PIDHelper/
├── One_click_Start.py # 主启动程序
├── demo.py # 仿真示例
├── PID_Helper/
│ ├── __init__.py
│ ├── PID_Helper.py # PSO优化器核心
│ ├── CommunicationInterface.py # 通信接口
│ └── Log.py # 日志模块
├── logs/ # 日志文件目录
└── README.md # 本文档
开源项目,遵循 Apache-2.0 许可证。