简介:一份基于自由摆的平板控制系统设计学士论文,面向电子信息工程、自动化等专业学生,可作为毕业设计、课程设计或单片机竞赛项目的参考资料。内容以STC12C5A60S2单片机和MMA7455倾角传感器为核心,完整论述系统方案选型、平板状态理论分析、电源与电机驱动电路设计、查表法实现激光笔照射中心线、TFT触摸屏交互,以及通过控制平板运动使硬币在自由摆过程中保持静止的方法。论文还涉及系统测试与误差分析,有助于理解从传感器数据采集、步进电机驱动到控制逻辑编程的完整实现链路。资源包内为单个doc文档,大小约222KB,便于直接阅读和引用。目前已有122人学习,适合想要快速掌握单片机测量控制类项目整体框架的读者。
1. 自由摆平板控制系统:强扰动对象,别指望纯 PID
做自动控制课程设计或电子设计竞赛的,多半都被自由摆平板控制系统折磨过:一根摆杆自由摆动,末端舵机上顶着一块平板,硬币放在板面上。任务不是简单的"保持平衡"——摆杆每时每刻都在改变平板的加速度环境,纯位置反馈只能跟在误差后面跑,摆幅一大硬币照样滑出去。这个题目背后是一条完整的设计链路:先把摆杆-平板-硬币写成方程,再决定传感器、执行机构和控制律,最后用衰减实验和阶跃响应把论文里的曲线做实。对嵌入式、自动化和竞赛方向的从业者,它也是观察"前馈解耦 + 串级 PID"如何在强扰动对象上落地的现成样本。
2. 自由摆平板控制系统的建模与测角:把扰动写进方程
建模的价值不是算得准,而是告诉你前馈应该补偿什么。我见过不少方案上来就调 PID,调了三天发现摆幅一大就发散,根本原因是方程里那个随摆杆运动的扰动项没被识别出来。这节把三个物理量讲清楚:摆杆角 θ、舵机相对摆杆的转角 α、硬币在板面上的位置 x,然后给出一个能直接指导代码的线性化模型。
2.1 摆杆-硬币模型线性化:"扰动只剩阻尼"这个反直觉结论
坐标系约定:θ 为摆杆偏离铅垂线的角度,最低点为零,向右摆为正;α 为舵机让平板相对摆杆转过的角,满足 β = θ + α,β 是平板在惯性系中的世界倾角;x 为硬币沿板面的位移,平板中点为原点。摆杆含舵机和平板的质量后是一个物理摆,线性化方程为:
θ'' + 2ζω·θ' + ω²·θ = 0,其中 ω = √(g / L_eff)
L_eff 是等效摆长,不要拿尺子量杆长,因为平板和舵机的质量分布会让质心偏移,常见做法是用周期反推:L_eff = g·T² / (4π²)。
硬币的运动方程写在平板的非惯性系里。重力沿板面的分量是 -mg·sinβ ≈ -mg(θ+α);摆杆端点牵连加速度沿板面的分量近似为 L_eff·θ'',对应的惯性力是 -m·L_eff·θ'';滚动摩擦按线性阻尼 -c·x' 近似。合并后:
x'' ≈ -g·(θ+α) - L_eff·θ'' - c·x'
把摆杆方程代进去,-gθ - L_eff·θ'' = -gθ + L_eff·(ω²θ + 2ζωθ') = (L_eff·ω² - g)·θ + 2ζωL_eff·θ'。因为 L_eff·ω² = g,第一项对消,最终得到:
x'' ≈ -g·α + 2ζωL_eff·θ' - c·x'
这个式子的信息量很大。理想无阻尼摆(ζ=0)下,硬币的动力学与摆杆角度 θ 完全解耦,扰动项只剩 2ζωL_eff·θ',正比于摆杆角速度而不是角位置。影响有二:其一,前馈量该用角速度构造,用角位置做前馈在相位上就是错的;其二,摆杆轴摩擦越大、ζ 越大,系统越难稳,竞赛里换轴承比调参数更有效。位置环保留积分项,是为了对付 c·x' 这一项代表的静摩擦。
2.2 摆杆角度测量:编码器为主,IMU 只补角速度
摆杆角度是前馈和扰动观测的共同输入,选型上优先级很清楚。
| 传感器 | 能测什么 | 精度与噪声 | 在摆杆上的问题 |
|---|---|---|---|
| 电位器 | 绝对角度 | 约 0.5°,有接触噪声 | 磨损后噪声变大,必须滤波 |
| 增量编码器 | 相对角度 | 0.1° 以内 | 上电要找零,掉脉冲会累积 |
| MPU6050 | 角速度/加速度 | 角速度可用,角度有漂移 | 加速度计读数混入平板动作分量 |
角速度不要用编码器角度做差分,一阶差分会把量化噪声放大一个数量级,带宽稍高就会出现前馈毛刺。我一般把 600 线编码器装摆杆轴上量角度,MPU6050 的陀螺仪 z 轴量角速度,两者各干各的,不做姿态融合。陀螺输出经过一阶低通再接进控制环:
#define GYRO_LPF 0.2f // 采样率 1kHz,截止频率约 2Hz;滤波后的 gyro_f 供控制环使用 gyro_f = GYRO_LPF * gyro_raw + (1.0f - GYRO_LPF) * gyro_f;低通系数 0.2 是按 1kHz 采样给的经验值,控制周期 10ms 时角速度信号已经足够平滑。若减到 0.1,相位滞后变大,前馈的补偿时刻会偏晚。
只有 IMU 可用的场合,用互补滤波把陀螺积分和加速度计求角合并,交叉频率取 0.5Hz 左右:
#define TAU 0.5f float angle = 0.0f, rate = 0.0f; void IMU_Update(float ax, float az, float gz, float dt) { float acc_angle = atan2f(ax, az); // 重力方向与摆杆轴的夹角 angle = TAU/(TAU+dt) * (angle + gz*dt) + dt/(TAU+dt) * acc_angle; rate = gz; // 陀螺原始角速度,单位 rad/s }注意 acc_angle 在摆杆摆动时混入切向加速度,动态下不可信,所以 TAU 取大一点,让陀螺积分占主导。
2.3 硬币位置检测:电阻触摸屏的读数与线性标定
硬币位置的可选方案里,电阻触摸屏是投入产出比最高的:XPT2046/ADS7846 这类芯片 SPI 读取,更新率毫秒级,成本几块钱。电容屏对非导体不响应,摄像头方案帧率低还要处理畸变,激光对射阵列分辨率受间距限制。电阻屏的代价是表面磨损,贴一层 PET 膜即可。
// XPT2046 单轴读取:命令字选通道,0x90/0xD0 对应 X/Y,以手头屏幕手册为准 uint16_t tp_raw(uint8_t cmd) { CS_LOW(); SPI_Send(cmd); uint16_t v = ((uint16_t)SPI_Read() << 8) | SPI_Read(); CS_HIGH(); return v >> 3; // 12bit 右对齐 }命令字 X/Y 的对应关系因屏幕丝印和接法而异,上电后两个通道各打 50 个数,看哪个通道数值随硬币左右移动明显变化,就用哪个。读数做 8 次采样去最大最小再平均,等效一个抗脉冲的低通,触摸噪声主要是接触瞬间的跳变。
标定在摆杆锁死铅垂、平板水平的状态下做:硬币放在平板中心读 raw0,再放到左右两个已知位置读 raw,得到 mm/LSB 比例:
float mm_per_lsb = 120.0f / (raw_right - raw_left); // 左右间距 120mm float x_mm = (float)(raw - raw0) * mm_per_lsb;电阻屏边缘非线性明显,标定只覆盖 ±60mm 工作区,超出区域不做位置闭环,只用它做过限保护。
3. 平板驱动执行机构:自由摆平板控制系统的舵机与 PWM 链路
执行机构决定了控制周期的下限和外环能吃到多少增益。自由摆平板控制系统的平板惯量小、转角范围只要 ±60°、响应要给位置环让路,这套约束下舵机是主流选择,但舵机的回程间隙和供电方式是两个最常见的翻车点。
3.1 舵机还是步进:从回程间隙和负载惯量看
| 项目 | 舵机 | 步进电机 |
|---|---|---|
| 控制接口 | PWM 脉宽 | 脉冲+方向或总线 |
| 位置反馈 | 内置电位器闭环 | 开环,需外置编码器 |
| 回程间隙 | 金属齿约 0.5°~1° | 接近 0 |
| 扭矩/体积 | 中,体积小 | 扭矩大,偏重 |
| 过载表现 | 堵转 | 丢步 |
步进的优势在重复定位精度,但那是开环下的精度;平板端负载轻、转速低,步进反而暴露低速爬行和共振区的问题。要上步进就得配闭环,成本直接翻倍。舵机的短板是回差,后面 3.3 节专门处理。
3.2 舵机 PWM 与 10ms 控制周期的时序配合
模拟舵机的 PWM 周期是 20ms,脉宽 500~2500μs 对应满行程,1500μs 是中位。数字舵机更新率可以到 330Hz,但便宜方案里模拟舵机占多数。控制周期我固定取 10ms,理由是两个:一是模拟舵机 50Hz 的物理更新率决定了 10ms 一次指令已经饱和,跑到 1kHz 只会放大噪声还发热;二是前馈和反馈在同一周期内先采样后输出,避免多一拍的相位滞后。
// TIM2: PSC=71, ARR=19999,计数频率 1MHz,PWM 周期 20ms void Servo_SetDeg(float deg) { deg = CLAMP(deg, -60.0f, 60.0f); // 机械限位保护 int cmp = 1500 + (int)(deg / 90.0f * 1000.0f); // 0° 对应 1500μs __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, cmp); }不同舵机的中位和行程有离散,上电先发 1500μs 让舵机停在物理中位,再缓慢扫描确认行程,不要一上来给满幅跳变,会撞限位。供电是最容易被低估的:MG996R 堵转电流接近 2.5A,必须用独立的 5~6V 电源给舵机,控制板只取信号,两套电源共地。共用 USB 供电导致的随机复位和曲线毛刺,九成是这里。
// 控制环主程序 10ms 定时中断 void Loop_10ms(void) { float th = Enc_GetTheta(); // 摆杆角,铅垂为 0,rad float w = Gyro_GetRate(); // 摆杆角速度,rad/s,已低通 float x = TP_GetX(); // 硬币位置,m float a = Svo_GetAngle(); // 舵机当前角,rad float ff = Kff * w; // 角速度前馈 float e = x_ref - x; // 外环位置误差 if (fabsf(e) < 0.08f) err_sum += e * Ts; // 误差大于 80mm 时积分分离 err_sum = CLAMP(err_sum, -0.5f, 0.5f); // 积分限幅,防饱和 float dd = kp_o*e + ki_o*err_sum + kd_o*(e - e_prev)/Ts; e_prev = e; float a_ref = CLAMP(dd + ff, -1.05f, 1.05f); // ≈ ±60° float u = kp_i*(a_ref - a) - kd_i*servo_rate; // 内环角 PD Servo_SetPwm(u); }采样集中在中断开头,输出放在结尾,避免采样与输出的时序错位。外环输出的是目标平板相对摆杆转角 a_ref,前馈在同一个量纲上叠加,限幅放在合成之后,防止摆幅大时舵机一直抱死。
3.3 回程间隙与极限环:三招压掉稳态抖动
舵机齿轮回差在换向时产生 0.5°~1° 的死区。外环积分的视角是"有误差但执行器不动",于是积分慢慢累积,累积到越过死区就大幅过冲,换向后再来一轮,形成等幅极限环。听感是舵机"咔哒咔哒"响,曲线上是稳态段的锯齿波。
| 现象 | 直接原因 | 处理办法 |
|---|---|---|
| 稳态高频抖动 | 内环增益过高 | 内环 Kp 降 30%,或加 0.5° 死区 |
| 低频极限环 | 回差 + 积分累积 | 积分分离,误差小于 2mm 时积分清零 |
| 换向明显滞后 | 齿轮回差 | 换数字舵机,或平板轴加编码器闭环 |
死区补偿是典型的工程手法:角度误差落在死区内就保持上次输出,不追误差,避免积分在那里空转。
float alpha_err = a_ref - a_meas; float u; if (fabsf(alpha_err) < 0.5f) // 0.5° 角度死区 u = u_last; else { u = kp_in*alpha_err - kd_in*omega_meas; u_last = u; }死区阈值从 0 开始每次加 0.1° 试,加到抖动消失就停;加过大会让小角度跟踪出现粘滞,外环觉得"指挥不动"。
4. 自由摆平板控制系统的控制律:角速度前馈与串级 PID 的参数落地
这一章是核心。第 2 章的方程最后落在 x'' ≈ -gα + 2ζωL_eff·θ' - c·x',控制律就是照着这个式子搭:前馈抵消 2ζωL_eff·θ',串级 PID 处理 c·x' 和模型误差。
4.1 前馈系数来自阻尼辨识:先测 ζ 和 ω,再算 Kff
前馈的目标是让控制量在硬币产生位移之前就把扰动抵消掉。对 x'' = -gα + d 这个对象,取 α_ff = Kff·θ',令 Kff·g = 2ζωL_eff,得到:
Kff = 2·ζ·ω·L_eff / g
Kff 的单位是秒,数值一般在 0.05~0.3s 量级。ζ 和 ω 不能靠猜,用自由衰减实验辨识:摆杆拉到 30°~40° 释放,记录角度波形 10 秒,然后取峰值序列算对数衰减率。
from scipy.signal import find_peaks import numpy as np t, th = np.loadtxt('swing.csv', delimiter=',', unpack=True) # th 单位 rad p, _ = find_peaks(th, height=0.05) A = th[p] T = np.median(np.diff(t[p])) # 摆动周期,单位 s delta = np.log(A[:-1] / A[1:]).mean() # 对数衰减率 zeta = delta / np.sqrt(4*np.pi**2 + delta**2) w = 2*np.pi / T L_eff = 9.81 * T**2 / (4*np.pi**2) # 等效摆长,不必量杆长 Kff = 2*zeta*w*L_eff / 9.81 print(zeta, w, Kff)find_peaks 的 height=0.05 是为了丢掉噪声小峰;A[:-1]/A[1:] 是相邻峰值之比,取均值能抑制单点误差。滚动轴承的 ζ 通常在 0.05 以下,铜套或塑料轴会到 0.1 以上。如果算出的 Kff 大于 0.5,先检查单位是不是混了:角速度用 rad/s,角度用 rad,全部走 SI。上板后还有一步符号确认:推一下摆杆看硬币漂移方向,如果加前馈后漂得更快,把 Kff 取反。
4.2 串级结构:内环角 PD、外环位置 PID 的落地实现
反馈回路的取舍有两档。简单方案是单环:位置 PID 直接输出舵机 PWM,前馈叠加在输出上。它的前提是舵机回差小、目标运动慢,外环增益上不去时稳态性能就受限于执行器非线性。更稳的做法是串级:内环用舵机输出的实际转角做 PD 反馈,把回差、饱和、温漂这些非线性包在里面,外环面对的是一个近似一阶的跟随器,增益可以放开。代价是平板轴要加第二路角度反馈,没有的话就退回单环。
实现见 2.2 节末尾的控制主程序,这里补三点说明。第一,外环的 kd_o 是对误差做差分,噪声敏感,位置读数已经做过 8 次平均,可以接受;如果仍有毛刺,把差分改成 (e - e_prev)/(Ts) 前加一阶低通。第二,内环微分项用的是舵机角速度,不要对角度误差求导再乘系数,符号和量纲都会乱。第三,a_ref 的限幅 ±1.05rad 是保护,摆幅大时舵机到不了目标角,误差全压在积分上,所以积分限幅一定要有。
4.3 PID 初值表与调参顺序
| 参数 | 含义 | 初值范围 | 调大后的表现 |
|---|---|---|---|
| kp_i | 内环比例 | 5~15 | 响应快,超调、抖动 |
| kd_i | 内环微分 | 0.2~0.8s | 阻尼增强,过大则高频放热 |
| kp_o | 外环比例 | 0.5~2.0 1/s | 跟踪加快,超调增大 |
| ki_o | 外环积分 | 0.1~0.5 1/s² | 稳态误差变小,易极限环 |
| kd_o | 外环微分 | 0.05~0.2s | 抑制超调,噪声敏感 |
| Kff | 前馈增益 | 辨识算出,不手调 | 过大则反向过冲 |
调参顺序固定成四步:第一步,机械锁死摆杆,整内环,给 a_ref 阶跃,调 kp_i、kd_i 到无超调;第二步,摆杆仍锁死,整外环,先加 kp_o 到临界振荡的 60%,再加 kd_o,最后加 ki_o,积分永远是最后上的;第三步,松开摆杆小幅摆动,只加前馈看硬币漂移;第四步,摆幅逐步加到 30°,若抖动,回头降内环 kp_i,而不是外环 kp_o。这个顺序能筛掉九成以上的调参问题,出问题的往往是跳过第一步直接把外环增益拉高。
5. 自由摆平板控制系统的标定与验收实验:数据怎么才算数
调通是一回事,论文和验收是另一回事。自由摆平板控制系统的评审看的是三件事:传感器标定有没有做、实验数据是否有可复现性、曲线是否对齐。这节给出可照做的流程。
5.1 三步标定的先后顺序
标定顺序不能乱。第一步零位:摆杆用铅垂线对到 0°,编码器清零,平板放数字角度计调到水平,舵机中位对齐,这两件事错一个,后面的数据全是歪的。第二步触摸屏映射,此时平板必须水平,硬币在中心、左右两点标定 mm/LSB。第三步阻尼辨识,按 4.1 的衰减实验算 ζ、ω、Kff。先对象后传感器,每步结果记录到配置文件,避免每次上电重来。
5.2 三类验收实验与合格线
| 实验 | 操作 | 合格建议 |
|---|---|---|
| 摆动镇定 | 摆杆拉至 30° 释放 | 硬币最大位移 ≤5mm,不滑落 |
| 位置阶跃 | 目标 0 → 80mm | 调节时间 ≤2s,超调 ≤15% |
| 圆轨迹跟踪 | 半径 60mm,周期 4s | RMSE ≤8mm |
每组实验连续做 5 次,报告里给均值加减极差。数据必须带统一时间戳,摆杆角、舵机角、硬币位置、目标值四路同时记录,否则论文里画不出可对照的曲线。
5.3 记录对齐与 Python 出图
一个实用技巧:用摆杆角速度过零点做触发。每次实验从摆杆摆到最低点、角速度由正变负的时刻记为 t=0,多次实验叠加平均,曲线包络干净得多,比对着示波器截图可信。
import pandas as pd import matplotlib.pyplot as plt df = pd.read_csv('run.csv', names=['t','theta','alpha','x','ref']) df.t = df.t - df.t[0] # 对齐到 0 时刻 plt.figure(figsize=(8, 4.2)) plt.plot(df.t, df.x*1000, lw=1.2, label='x') plt.plot(df.t, df.ref*1000, '--', lw=1.2, label='ref') plt.xlabel('t / s'); plt.ylabel('x / mm') plt.legend(); plt.grid(alpha=0.3) plt.savefig('step.pdf', bbox_inches='tight')曲线画完先看两处:阶跃响应上升沿是否只有一个过冲,摆动镇定段的硬币位置是否在 ±5mm 带内。若过冲不止一个,返回到第 4.3 节从内环重调;若稳态带内抖动有周期,量一下抖动频率,接近摆杆频率就回到前馈,接近舵机频率就回到死区。
本文还有配套的精品资源,点击获取