南邮自动控制原理实验报告:Python仿真与docx自动生成 简介这份南京邮电大学自动控制原理实验报告以 Word 形式整理面向自动化、电气及控制类专业的本科生与考研复习者用于完成课程实验、撰写报告及梳理 MATLAB 仿真思路。全部内容集中于 1 个 docx 文件压缩包约 23KB体积轻巧便于下载、打印或二次编辑。报告覆盖实验一至实验四一阶与二阶系统的时域响应时间常数 T、阻尼比 ζ、自然频率 ωn 对超调与调节时间的影响、线性系统的根轨迹讨论rlocus、rlocfind 求分离点、虚轴交点与临界稳定增益、频率响应与稳定性分析以及连续系统的串联校正。文中给出 MATLAB 指令、传递函数模型与响应曲线截图并记录参数调整后的结论如按 Tr0.56s、Tp1.29s、Ts5.46s、超调不大于 5% 反推自然频率与阻尼比。已有 364 人学习下载适合对照复盘实验流程、核对数据结论与期末复习。1. 南邮自动控制原理实验报告一份 docx 背后要填的技术内容南邮的自动控制原理实验通常分两条线并行一条在模拟实验箱上搭运放电路用信号源给阶跃输入、示波器读响应曲线另一条在 MATLAB 或 Python 里画 Bode 图、根轨迹、Nyquist 图。最后交上去的那份《自动控制原理实验报告.docx》装的其实就是这两条线的数据、曲线、参数标定过程和结论。真正让人反复返工的往往不是理论没学懂而是算出来的阻尼比和示波器上看到的振荡对不上、Bode 图的相角裕度和手算差了一截、报告里十几张图来回调格式。这套流程可以拆成三层先把典型环节和二阶系统的传递函数跟实验箱上的电阻电容对应清楚再用仿真复现曲线做误差比对最后把数据、图、表自动写进 docx。下面按这三层往下走代码给的都能直接跑参数换成自己实验箱的元件值即可。2. 典型环节与二阶系统的建模传递函数怎么和实验箱元件对上2.1 六种典型环节的传递函数与运放电路对应关系自动控制原理实验的第一组内容基本都是典型环节的模拟电路实现。理论课上写的是传递函数实验箱上看到的是运放、电阻、电容中间那一步哪个元件决定哪个系数如果没理清后面整条链路都会晃。常见做法是把每个环节都按反相输入运放来搭输入输出之间用一个电阻或电容网络构成反馈支路。下面这张表把最常考的六种环节和它们的电路实现、典型取值放在一起。环节传递函数运放实现实验箱典型取值比例K反相比例放大器Rf100kΩR1100kΩK-1积分1/(Ts)反相积分器R100kΩC1μFT0.1s惯性K/(Ts1)反相惯性环节Rf100kΩR1100kΩC1μF微分Ts反相微分器C1μFR100kΩT0.1s振荡ωn²/(s²2ζωn·sωn²)双积分回路加比例反馈见 2.2 节延迟e^(-τs)一阶惯性近似或 Pade 近似τ 由 RC 决定需要注意两点。一是反相运放带来的负号串联两级就抵消单级接进回路时要记得把符号带进去否则根轨迹和 Bode 图的相位会整体差 180°判断稳定性时容易得出相反结论。二是积分器和微分器在实验箱上常用近似形式即并联一个大电阻限制低频增益此时传递函数实际是 K/(Ts1) 而不是纯 1/(Ts)低频段实测和理论会有偏差这属于正常现象报告里要说明而不是硬凑数据。2.2 二阶系统的阻尼比与自然频率实验箱上电阻电容怎么配二阶系统是自动控制原理实验的核心因为它同时能演示超调、振荡、调节时间、稳定性这几个概念。最常见的电路是双积分回路两级反相积分器串联再从末级输出经一个比例网络反馈回第一级输入。设积分器的时间常数为 RC反馈系数为 Kf闭环传递函数可以化成标准二阶形式得到两个关键关系ωn 1/(RC)ζ Kf/2。这两个式子决定了怎么改参数。要单独调 ωn就换积分的 R 或 C比如 R 从 100kΩ 降到 50kΩωn 直接从 10 rad/s 翻倍到 20 rad/s振荡频率肉眼可见变快。要单独调 ζ就动反馈支路的电位器Kf 从 0.4 调到 1.4ζ 就从 0.2 走到 0.7超调量跟着从 50% 掉到 5% 左右。这两个旋钮最好分开调、逐个记录报告里的参数表才有对照价值。如果实验箱是固定的元件挡位常见挡位是 ζ 取 0、0.2、0.5、0.707、1.0、2.0 六种。ζ0 时理论上等幅振荡实测会因为运放和电路损耗慢慢衰减ζ0.707 是工程上最常提的最佳阻尼超调约 4.3%ζ≥1 之后变成两个实极点不再有超调但响应变慢。记录数据时至少要把这几组都跑一遍Bode 图上才能看出谐振峰随 ζ 下降的抬升趋势。提示实验箱的积分电容如果是电解电容容值误差可能到 ±20%用万用表实测后再代入公式比直接信标称值靠谱得多。2.3 用 scipy 反算超调量与调节时间验证参数标定算完参数接下来要验证标定对不对。不用等到接线上电先用 scipy 把阶跃响应的特征量算出来跟示波器上的读数一一对照偏差大的地方就是电路参数的问题。下面这段脚本对四组阻尼比批量求超调量和 2% 误差带的调节时间。import numpy as np from scipy import signal def second_order_step(wn, zeta, t_end3.0, n5000): 二阶系统单位阶跃响应返回时间轴与幅值 sys signal.TransferFunction([wn**2], [1, 2*zeta*wn, wn**2]) t np.linspace(0, t_end, n) _, y signal.step(sys, Tt) return t, y def specs(t, y): 提取超调量(%)与 2% 误差带调节时间(s) yss y[-1] # 稳态值单位阶跃下趋近 1 overshoot (y.max() - yss) / yss * 100 band 0.02 * yss idx np.where(np.abs(y - yss) band)[0] # 最后一次超出误差带的时刻 ts t[idx[-1]] if len(idx) else 0.0 return overshoot, ts wn 1 / (100e3 * 1e-6) # R100kΩ, C1μF - wn10 rad/s for zeta in (0.2, 0.5, 0.707, 1.0): t, y second_order_step(wn, zeta) os_, ts_ specs(t, y) print(fzeta{zeta:6} 超调{os_:6.2f}% 调节时间{ts_:.3f}s)这段代码里wn由元件值直接算出zeta从 0.2 扫到 1.0覆盖了实验箱上最常调的那几挡。specs里的band 0.02 * yss就是 2% 误差带工程上默认用这个如果课程要求 5%把系数改成 0.05 即可。idx[-1]取的是最后一次越界时刻而不是第一次这样处理的是阻尼比较小时曲线反复穿越误差带的情况结果和示波器上最后稳定下来的读法一致。跑出来的 ζ0.707 超调应落在 4.3% 附近若实测示波器上是 10% 以上多半是反馈系数偏小或者积分电容实际容值比标称值小。3. 用 python-control 复现阶跃响应与频率特性仿真和实测怎么对齐3.1 环境安装与最小可运行例子理论验证完之后报告里通常还要一节频域分析。这一节用 python-control 最省事因为它把 Bode 图、Nyquist 图、稳定裕度、根轨迹全打包好了比手写传递函数矩阵省一大截代码。装依赖就一行pip install control scipy numpy matplotlib pandas python-docx然后拿一个三阶开环系统跑通最小例子。传递函数取 G(s) 20 / (s(s1)(s5))这是教材里最经典的题型展开分母是 s³6s²5s系数直接填数组。import control as ct import numpy as np # 开环传递函数 G(s) 20 / (s^3 6s^2 5s) G ct.tf([20], [1, 6, 5, 0]) # 闭环单位负反馈的阶跃响应特征 info ct.step_info(ct.feedback(G, 1)) for k, v in info.items(): print(f{k:14s} {v:.4f}) gm, pm, wcg, wcp ct.margin(G) print(f幅值裕度 {20*np.log10(gm):.2f} dB, 相角裕度 {pm:.2f}°)ct.tf的两个参数分别是分子分母系数按 s 的降幂排列缺项要补 0这是最容易出错的地方——上面分母里的0就是 s 的零次项漏掉会直接报维度不匹配。ct.step_info返回的字段包括 RiseTime、SettlingTime、Overshoot 等单位默认是秒直接搬进报告的参数表即可。ct.margin返回四个量注意gm是绝对值不是分贝画表时要么统一取绝对值要么像上面那样转成20*log10(gm)。3.2 Bode 图、Nyquist 图与稳定裕度的批量计算报告里一般要求至少三张频域图Bode 幅频、Bode 相频、Nyquist。用 control 的绘图函数能一次生成还能顺便把裕度点在图上标出来。import matplotlib.pyplot as plt import control as ct fig, (ax_m, ax_p) plt.subplots(2, 1, figsize(7, 6), sharexTrue) ct.bode_plot(G, dBTrue, HzFalse, degTrue, ax[ax_m, ax_p]) # 标注相角裕度对应的穿越频率 ax_p.axvline(wcp, colorr, linestyle--, linewidth0.8) ax_p.text(wcp, ax_p.get_ylim()[0]*0.6, f ωc{wcp:.2f}, colorr, fontsize9) plt.tight_layout() plt.savefig(bode.png, dpi200)dBTrue控制幅频纵轴用分贝HzFalse表示横轴用 rad/s 而不是赫兹这两个开关和教材的坐标系保持一致避免报告里横轴单位对不上。axvline那两行是自己加的辅助线用来在图上直接读出穿越频率比在正文里干说由图可知要有说服力。批量处理多组参数时把 G 换成一个列表逐个传入bode_plot用label区分曲线一次能画出 ζ 或开环增益变化时的对比图。图形常用函数关键参数报告里该标什么Bode 幅频ct.bode_plot(dBTrue)dB、Hz、deg穿越频率、谐振峰Bode 相频ct.bode_plot(degTrue)deg相角裕度对应频率Nyquistct.nyquist_plot()—包围 (-1, j0) 的圈数根轨迹ct.root_locus(G)kvect分离点、虚轴交点阶跃响应ct.step_response()T、T_num超调、调节时间3.3 实测采样数据与仿真曲线的误差评估示波器上的曲线要变成能进报告的数据一般有三种路子截图直接贴、用示波器自带导出成 CSV、或者用数据采集卡连电脑采样。截图放进报告只能定性看趋势想写误差就得用后两种。拿到 CSV 之后实测数据和仿真数据的时间轴通常不一致得先插值对齐再算误差。import numpy as np import pandas as pd from scipy.interpolate import interp1d # 示波器导出的 CSV第一列时间(s)第二列幅值(V) data pd.read_csv(scope.csv, names[t, y], skiprows1) data data.sort_values(t) # 归一化便于和仿真单位阶跃对比 y_meas data[y].to_numpy() / data[y].iloc[-1] t_meas data[t].to_numpy() # 仿真结果已经放在 t_sim / y_sim 里插值到实测时间点上 f_sim interp1d(t_sim, y_sim, kindlinear, fill_valueextrapolate) y_sim_on_meas f_sim(t_meas) mae np.mean(np.abs(y_meas - y_sim_on_meas)) rmse np.sqrt(np.mean((y_meas - y_sim_on_meas) ** 2)) print(fMAE {mae:.4f}, RMSE {rmse:.4f})interp1d的kindlinear在采样率够高时足够用采样点稀疏就换成cubic。fill_valueextrapolate是为了处理实测时间轴比仿真略长的情况不加这个参数超出范围的点会变成 NaN算出来的误差就没意义。归一化那一步不能省示波器上量到的是伏特仿真给的是无量纲的 1不归一化直接相减得到的误差数字没有物理含义。误差一般在 5% 以内算吻合良好超过 10% 就要回到电路里找原因常见是运放偏置、电容漏电或者信号源输出阻抗分压。4. 用 python-docx 把数据、曲线与结论写进《自动控制原理实验报告.docx》4.1 文档骨架样式、标题层级与中文页边距前面所有的数据和图都是中间产物最后要落到 docx 上。与其在 Word 里一张张插图、一遍遍改字体不如用 python-docx 直接生成改参数重跑就行。第一步是把文档骨架搭起来重点是把中文字体设对否则生成出来全是宋体回退或者方框。from docx import Document from docx.shared import Pt, Cm from docx.oxml.ns import qn doc Document() style doc.styles[Normal] style.font.name Times New Roman # 西文字体 style.font.size Pt(10.5) # 五号 style.element.rPr.rFonts.set(qn(w:eastAsia), 宋体) # 中文字体 for section in doc.sections: section.top_margin Cm(2.54) section.bottom_margin Cm(2.54) section.left_margin Cm(3.17) section.right_margin Cm(3.17)关键在qn(w:eastAsia)这一行它写的是 Word 里中文用哪个字体那个属性。只设style.font.name只管西文中文仍然是默认字体这是用 python-docx 排版中文文档最常见的坑。页边距按常见的 2.54 cm 上下、3.17 cm 左右设置接近 Word 默认的普通页边距打印出来不会跑版。实验报告如果学校有模板要求把这几行数值换成模板里的值就行。4.2 插入曲线图、数据表与公式编号骨架搭好后往里填内容。图片用add_picture插入宽度按页宽算别写死像素表格用add_table建再把数据逐格填进去。from docx.shared import Inches from docx.enum.text import WD_ALIGN_PARAGRAPH doc.add_heading(2 二阶系统阶跃响应分析, level1) p doc.add_paragraph(取 ωn 10 rad/s改变阻尼比 ζ 得到如下响应曲线) p.paragraph_format.first_line_indent Pt(21) # 首行缩进两字符 doc.add_picture(step_response.png, widthInches(5.5)) doc.paragraphs[-1].alignment WD_ALIGN_PARAGRAPH.CENTER # 参数表4 行 3 列 table doc.add_table(rows1, cols3) table.style Table Grid hdr table.rows[0].cells hdr[0].text, hdr[1].text, hdr[2].text 阻尼比 ζ, 超调量 σ%, 调节时间 ts/s for zeta, os_, ts_ in [(0.2, 52.7, 0.82), (0.5, 16.3, 0.55), (0.707, 4.3, 0.42), (1.0, 0.0, 0.68)]: row table.add_row().cells row[0].text f{zeta} row[1].text f{os_:.1f} row[2].text f{ts_:.2f} doc.save(自动控制原理实验报告.docx)Inches(5.5)对应正文页宽比 A4 纸宽减去左右页边距略小图片不会溢出到页边距外。表格样式用Table Grid才有边框线默认的 Normal Table 是无线框的看起来像散落的文字。首行缩进用Pt(21)是五号字下两字符的近似值比用Pt(24)更贴近正文实际宽度。注意add_picture传的路径是相对当前工作目录的脚本在别的目录跑会报找不到文件用绝对路径或者先os.chdir到图片所在目录更稳妥。4.3 多组实验数据的批量章节生成实验报告里往往有四五组不同参数的数据手工复制粘贴章节最费时。把章节生成封装成函数用一个参数列表驱动改数据不用动结构。def add_experiment(doc, title, params, img_path, rows): 向文档追加一节实验标题、参数说明、图、数据表 doc.add_heading(title, level2) doc.add_paragraph(f实验参数{params}) doc.add_picture(img_path, widthInches(5.5)) doc.paragraphs[-1].alignment WD_ALIGN_PARAGRAPH.CENTER t doc.add_table(rows1, colslen(rows[0])) t.style Table Grid for i, cell in enumerate(t.rows[0].cells): cell.text rows[0][i] for r in rows[1:]: cells t.add_row().cells for i, v in enumerate(r): cells[i].text str(v) batches [ (3.1 ζ0.2 工况, ωn10 rad/s, ζ0.2, fig/z02.png, [[t/s, y/V], [0, 0], [0.3, 1.42], [0.8, 0.94]]), (3.2 ζ0.707 工况, ωn10 rad/s, ζ0.707, fig/z0707.png, [[t/s, y/V], [0, 0], [0.2, 1.03], [0.6, 1.00]]), ] for title, params, img, rows in batches: add_experiment(doc, title, params, img, rows)这段代码把标题—参数—图—表四件套封成一次调用batches列表里加一行报告里就多一节数据来源也可以改成直接读 CSV连表格内容都不用手写。小节标题用level2对应 Word 里的标题 2生成了目录之后层级不会乱。整套流程跑下来一份包含六七个实验、十几张图、若干数据表的报告从实验数据到 docx 成稿大概几分钟剩下的时间可以花在误差分析和结论上。5. 交付前的进阶检查曲线分辨率、公式一致性与自查清单代码能生成文档之后最后一关是交付质量。常见问题是图片分辨率不够插进 Word 放大就糊。matplotlib 存图时dpi至少给 200印刷用给 300别用默认的 100。曲线里的字号也要跟着调plt.rcParams[font.size] 10配上figsize(7, 4.5)插进 A4 正文里刻度标注才看得清。中文字体在 matplotlib 里默认不显示记得设plt.rcParams[font.sans-serif] [SimHei]并关掉负号显示问题。公式一致性是另一个易翻车点。正文里手算的超调量、脚本算的超调量、表格里填的超调量必须是同一个数位数也要统一到小数点后一位或两位。用 python-docx 生成时表格数据直接从脚本的计算结果传进去不要另外手抄一遍这是避免数字打架最直接的办法。单位也要统一ωn 用 rad/s、t 用秒、幅值用伏特报告里混用赫兹和弧度每秒阅卷时一眼就能看出来。自查清单可以照着下面几条过一遍检查项合格标准常见问题曲线分辨率dpi ≥ 200刻度字可读截图拉伸变糊参数单位全文统一 rad/s、s、V混用 Hz 与 rad/s理论-仿真-实测三处数值一致手抄导致数字不符裕度正负号与 Bode 图标注对应gm 取对数后符号反图表编号与正文引用一一对应插图后忘记改编号中文字体正文宋体、图内黑体生成 docx 后中文变方框最后一步是最容易被忽略的把生成的 docx 用 Word 打开翻一遍检查分页位置有没有把图和表标题拆散表格有没有跨页断行。python-docx 生成的表格默认允许跨页断行在add_table之后设置table.rows[i].allow_break_across_pages False能让每张表尽量完整落在一页里看着比断成两半专业得多。本文还有配套的精品资源点击获取