目录
一、揭开 B 题神秘面纱:风力摆控制系统
在 2024 年电子设计大赛众多富有挑战性的题目中,B 题 “风力摆控制系统” 吸引了无数参赛者的目光 。这道题就像是一个神秘的宝藏,等待着大家去探索和挖掘。它要求参赛者设计并制作一个风力摆控制系统,通过巧妙地控制风力,让摆锤完成一系列复杂的动作。
从本质上来说,风力摆控制系统是一个集机械结构、电子电路、传感器技术和控制算法于一体的综合性系统。这个系统需要实现对风力摆的精确控制,使其能够按照预设的轨迹运动,比如画出各种形状的线条、完成特定角度的摆动等。这不仅考察了参赛者对硬件设计的能力,还对他们的编程技巧和算法设计能力提出了很高的要求。
为了实现这些功能,参赛者需要深入理解风力摆的运动原理,如同物理学家研究单摆运动那样,精确把握每一个物理量之间的关系。在硬件设计方面,要精心挑选合适的电机、传感器等电子元件,确保它们能够稳定工作,就像搭建一座坚固的桥梁,每一块基石都至关重要。而在软件编程上,需要运用先进的控制算法,如 PID 控制算法,来实现对风力摆的精准控制,这就好比给一艘船设定精确的航线,让它在茫茫大海中准确航行。
二、需求分析:明确任务与目标
在深入研究 B 题 “风力摆控制系统” 后,我们可以将其需求进行细致的拆解和分析。从功能实现的角度来看,风力摆控制系统需要达成一系列具体且具有挑战性的任务。
快速起摆是系统的首要任务之一。这就如同短跑运动员听到枪响后迅速起跑一样,风力摆需要在短时间内从静止状态开始摆动,并且要保证起摆的动作平稳、迅速。为了实现这一目标,需要精确地控制风机的启动速度和风力大小,使摆锤能够顺利地开始摆动。
画线功能是该系统的核心任务之一。系统要能够控制风力摆带动激光笔,在指定的平面上画出各种形状的线条,如直线、曲线等。这对系统的控制精度和稳定性提出了极高的要求。就像一位画家在作画时,需要精准地控制画笔的走向和力度,系统也需要精确地控制风力摆的摆动角度和速度,以确保画出的线条符合要求。例如,在画直线时,要保证风力摆的摆动方向始终保持在直线方向上,并且摆动速度均匀,这样才能画出笔直、流畅的直线。
精确画圆更是对系统控制能力的巨大考验。想象一下,要让风力摆像圆规一样,画出一个完美的圆形,这需要系统对风力摆的运动轨迹进行极其精确的控制。不仅要控制好摆锤的摆动半径,还要保证在整个画圆过程中,摆锤的速度和角度都保持稳定。这就要求系统具备先进的控制算法和高精度的传感器,能够实时监测和调整风力摆的运动状态。
当完成画线或画圆任务后,系统需要使风力摆迅速复位静止,就像演出结束后演员迅速回到后台一样。这需要系统能够快速地调整风机的风力,抵消摆锤的惯性,使摆锤平稳地停止摆动。
除了上述功能需求,人机交互方面的需求也不容忽视。在实际操作中,用户需要通过键盘来设定运行模式和相关角度值。这就好比我们操作电子设备时,通过按键来选择不同的功能和设置参数一样。系统需要能够准确地识别用户输入的指令,并根据指令进行相应的操作。例如,用户可以通过键盘选择风力摆的运动模式,如画线模式、画圆模式等,还可以设置摆动的角度、速度等参数。
为了让用户实时了解风力摆的工作状态,系统还需要通过液晶显示风力摆的角度和运行时间。这就像汽车的仪表盘一样,能够直观地向用户展示车辆的各种信息。液晶显示屏可以清晰地显示风力摆当前的摆动角度,让用户随时掌握其运动状态,同时还能显示系统的运行时间,方便用户进行时间管理和数据分析。
三、涉及知识与技术拆解
3.1 硬件相关知识
在风力摆控制系统的硬件设计中,各种硬件设备各司其职,共同构建起了一个稳定且高效的系统。STM32 单片机控制模块无疑是整个系统的核心,就如同人的大脑一样,负责指挥和协调各个部件的工作。它具备强大的数据处理能力和丰富的外设接口,能够快速地接收和处理来自传感器的数据,并根据预设的算法生成控制指令,精确地控制轴流电机的转速和转向,从而实现对风力摆的精准控制 。例如,在快速起摆的过程中,STM32 单片机可以迅速计算出轴流电机所需的启动速度和加速度,使摆锤能够在短时间内平稳起摆。
MPU-6050 陀螺仪传感器在系统中扮演着至关重要的角色,主要用于采集风力摆的姿态信息。它集成了三轴陀螺仪和三轴加速度计,能够实时测量风力摆的角速度和加速度。其工作原理基于角动量守恒定律,当风力摆发生旋转时,陀螺仪内部的陀螺会因为角动量守恒而保持与初始方向平行,通过检测陀螺与初始方向的偏差,就可以计算出风力摆的旋转方向和角度。加速度计则利用压电效应,通过测量质量块在加速过程中所受的惯性力,根据牛顿第二定律获取加速度值。将陀螺仪和加速度计的数据进行融合处理,就可以得到风力摆精确的姿态信息,为系统的控制提供准确的数据支持 。
轴流电机作为提供风力的关键设备,是实现风力摆运动的动力源。它的工作原理是通过电机驱动叶轮旋转,叶片推动空气沿轴向移动,从而产生风力。轴流电机具有风量大、压力低的特点,非常适合用于风力摆控制系统。在系统中,轴流电机的转速和转向直接影响着风力摆的运动状态,因此需要精确地控制轴流电机的运行。通过改变输入轴流电机的电压或电流,可以调节电机的转速,进而调整风力的大小和方向,实现对风力摆的控制 。
除了上述核心硬件设备外,系统中还可能用到其他一些硬件设备。例如,电源模块负责为整个系统提供稳定的电力供应,就像人体的心脏一样,为各个部件输送能量;通信模块用于实现系统与外部设备之间的数据传输和通信,如蓝牙模块可以实现与手机或电脑的无线通信,方便用户对系统进行远程控制和监测;显示模块如液晶显示屏,用于直观地展示系统的运行状态和参数,让用户能够实时了解风力摆的工作情况 。
3.2 软件算法知识
软件算法在风力摆控制系统中起着灵魂般的作用,它赋予了系统智能和灵活性,使系统能够按照预设的规则和目标运行。PID 算法是风力摆控制系统中应用最为广泛的控制算法之一,它在调整电机转速、控制风力摆姿态方面发挥着关键作用。
PID 算法,即比例 - 积分 - 微分控制算法,通过对系统误差的比例、积分和微分三个环节的运算,来实现对系统的精确控制。在风力摆控制系统中,比例环节(P)根据当前风力摆的实际姿态与目标姿态之间的误差,成比例地调整轴流电机的控制信号。误差越大,比例环节输出的控制信号越强,使电机能够快速响应,减小误差。例如,当风力摆的摆动角度偏离目标角度较大时,比例环节会迅速增大电机的转速,使风力摆尽快回到目标角度。
积分环节(I)主要用于消除系统的稳态误差。在实际运行中,由于各种干扰因素的存在,即使风力摆的实际姿态与目标姿态之间的误差已经很小,但仍然可能存在一个微小的偏差。积分环节通过对误差的累积,不断调整控制信号,直到误差为零,从而保证风力摆能够稳定地保持在目标姿态上。
微分环节(D)则关注误差的变化率,它能够预测系统的未来行为,提前调整控制信号,增加系统的阻尼,提高系统的稳定性和响应速度。当风力摆的姿态变化较快时,微分环节会输出一个较大的控制信号,抑制风力摆的快速变化,使系统更加稳定。
在软件编程实现系统功能时,需要注意多个要点。数据处理是软件编程的重要环节之一。从 MPU - 6050 陀螺仪传感器采集到的原始数据,需要进行一系列的处理,如滤波、校准、姿态解算等,才能得到准确的风力摆姿态信息。滤波可以去除数据中的噪声干扰,提高数据的准确性;校准可以消除传感器的误差,确保数据的可靠性;姿态解算则根据传感器数据计算出风力摆的实际姿态,为后续的控制提供依据。
通信协议的实现也是软件编程的关键要点之一。如果系统需要与外部设备进行通信,如通过蓝牙与手机连接,或者通过串口与上位机通信,就需要实现相应的通信协议。通信协议规定了数据的格式、传输速率、同步方式等,确保系统与外部设备之间能够准确无误地进行数据传输和交互。例如,在蓝牙通信中,需要遵循蓝牙通信协议,将系统的状态信息和控制指令按照规定的格式进行打包和发送,同时正确解析接收到的外部设备的指令,实现远程控制功能 。
软件编程还需要考虑系统的实时性和稳定性。风力摆控制系统是一个实时控制系统,需要对传感器数据进行快速处理和响应,及时调整电机的控制信号,以保证风力摆的稳定运行。因此,在编程时需要合理安排任务优先级,优化算法和代码,减少系统的响应时间,确保系统能够满足实时性要求。同时,要采取一些措施来提高系统的稳定性,如加入错误处理机制,当系统出现异常情况时能够及时进行处理,避免系统崩溃 。
四、难点与挑战解析
4.1 硬件搭建难点
在搭建风力摆的机械结构时,确保稳定性与精度是首要难题。这就好比搭建一座高塔,每一块积木的摆放都至关重要。风力摆的支架需要承受摆锤的重量以及风力产生的作用力,任何微小的晃动都可能影响摆锤的运动轨迹,进而导致系统控制精度下降。为了增强稳定性,参赛者可能需要精心挑选合适的材料,如具有一定强度和重量的金属材料,来制作支架。同时,在安装传感器和电机等关键部件时,要保证它们的位置精确无误,就像钟表匠安装钟表零件一样,容不得丝毫偏差,以确保传感器能够准确地采集风力摆的姿态信息,电机能够稳定地提供风力。
在选择合适的硬件设备时,成本与性能的平衡是一个绕不开的问题。一方面,高性能的硬件设备,如精度更高的传感器、响应速度更快的电机,能够为系统带来更好的性能表现,提高控制精度和响应速度。但另一方面,这些高性能设备往往价格不菲,会增加项目的成本。这就需要参赛者在众多硬件设备中进行权衡和选择,根据项目的实际需求和预算,挑选出性价比最高的硬件设备。例如,在选择传感器时,可能会有多种型号可供选择,它们在精度、价格等方面存在差异。参赛者需要综合考虑系统对精度的要求以及成本限制,选择一款既能满足精度要求,又不会超出预算的传感器。
硬件连接和调试过程中也会出现各种常见问题。硬件连接时,线路的接触不良是一个常见的隐患。就像电路中的 “隐形杀手”,它可能导致信号传输不稳定,使系统出现各种异常现象。为了避免这种情况,在连接线路时,需要确保插头插紧,焊点牢固,必要时可以使用万用表等工具对线路连接进行检测,确保线路导通良好。
不同硬件设备之间的兼容性问题也不容忽视。当将多个硬件设备组合在一起时,可能会出现设备之间无法正常通信或协同工作的情况。这就好比不同品牌的拼图碎片,可能无法完美地拼接在一起。在选择硬件设备时,要充分了解各个设备的技术参数和接口规范,确保它们之间能够相互兼容。如果出现兼容性问题,需要仔细排查问题所在,可能需要调整硬件设备的配置,或者更换部分设备,以实现硬件设备之间的稳定协作。
4.2 软件编程挑战
在软件编程方面,算法优化是提高系统响应速度和控制精度的关键。风力摆控制系统对实时性要求较高,就像赛车比赛中,赛车需要对车手的操控指令做出迅速反应一样,系统需要快速地处理传感器采集到的数据,并及时调整电机的控制信号。然而,在实际编程中,算法的复杂度和计算量可能会影响系统的响应速度。例如,复杂的控制算法可能需要进行大量的数学运算,这会占用较多的处理器资源和时间,导致系统响应延迟。为了提高系统响应速度,需要对算法进行优化,采用高效的算法和数据结构,减少不必要的计算量。可以通过优化 PID 算法的参数调整策略,使其能够更快地收敛,减少系统的调节时间。同时,合理利用处理器的资源,如采用并行计算、中断处理等技术,提高系统的实时性。
多任务处理时,任务冲突和资源分配问题是需要解决的重要挑战。在风力摆控制系统中,软件可能需要同时处理多个任务,如数据采集、数据处理、电机控制、人机交互等。这些任务之间可能存在相互依赖和竞争关系,就像多个工人在一个有限的空间里工作,可能会因为资源分配不均或工作顺序不合理而产生冲突。例如,数据采集任务和电机控制任务可能都需要占用处理器的时间和内存资源,如果不能合理分配这些资源,可能会导致某个任务无法及时完成,影响系统的整体性能。为了解决任务冲突和资源分配问题,需要采用合理的任务调度算法,如优先级调度算法,根据任务的重要性和实时性要求,为不同的任务分配不同的优先级,确保重要和实时性要求高的任务能够优先得到处理。同时,要合理管理系统资源,避免资源的过度竞争和浪费。
软件与硬件协同工作中,通信和时序问题也会给编程带来困难。软件需要与硬件设备进行通信,以获取传感器数据和控制电机等设备的运行。然而,通信过程中可能会出现数据丢失、数据错误等问题,就像在快递运输过程中,包裹可能会丢失或损坏一样。这需要在软件编程中加入可靠的通信协议和错误处理机制,确保数据的准确传输。例如,采用校验和、重传机制等方法,对传输的数据进行校验和纠错,保证数据的完整性。
时序问题也是软件与硬件协同工作中的一个关键问题。硬件设备的响应速度和工作频率可能与软件的控制节奏不一致,这就需要在软件编程中精确地控制时序,确保软件与硬件之间的协同工作顺畅。例如,在读取传感器数据时,要确保软件在传感器数据更新的合适时刻进行读取,避免读取到过时的数据。在控制电机时,要根据电机的启动、停止和调速特性,精确地控制控制信号的发送时机,以实现对电机的精准控制。
五、解决方案思路探讨
5.1 硬件设计方案
在硬件设计的关键抉择中,STM32 单片机的型号选择至关重要。以 STM32F103 为例,它就像是一位全能选手,在众多应用场景中都能大显身手。其丰富的外设资源,如多个定时器、串口、SPI 接口等,为风力摆控制系统的功能扩展提供了广阔的空间。就像一个拥有多种工具的工匠,能够轻松应对各种复杂的任务。较高的性价比也是它的一大优势,在满足系统性能要求的同时,还能有效控制成本,非常适合电子设计大赛这样对成本有一定限制的项目 。强大的处理能力使得它能够快速地处理传感器数据和执行控制算法,确保系统的实时性和稳定性。在快速起摆的过程中,STM32F103 能够迅速根据传感器数据调整电机的控制信号,使摆锤快速、平稳地起摆。
MPU - 6050 传感器的安装和校准对系统精度有着举足轻重的影响。在安装时,就像为精密仪器寻找最佳的观测位置一样,要将其安装在风力摆的重心位置附近,并且保证安装平面与风力摆的运动平面平行,这样才能确保传感器能够准确地感知风力摆的姿态变化。校准过程则像是为天平校准砝码,是消除传感器误差、提高数据准确性的关键步骤。可以采用软件校准的方法,通过采集大量的静止状态下的数据,计算出传感器的零偏值,并在后续的数据处理中进行修正。也可以结合硬件校准,如调整传感器的外部电路参数,进一步提高校准的精度 。
轴流电机驱动电路的设计直接关系到电机的性能和系统的稳定性。H 桥驱动电路是一种常见且有效的选择,它就像一个灵活的交通指挥员,能够控制电机的正反转和转速。通过控制 H 桥电路中四个功率开关管的导通和截止,可以实现对电机电流的方向和大小的精确控制。当需要电机正转时,让 H 桥的一组开关管导通,使电流按照正向流过电机;当需要电机反转时,切换另一组开关管导通,改变电流方向。在选择功率开关管时,要根据电机的工作电流和电压来确定合适的型号,确保开关管能够承受电机的工作电流,并且具有较低的导通电阻,以减少功率损耗 。
除了上述核心硬件模块,电源模块的设计也不容忽视。稳定的电源就像可靠的能源供应站,是整个系统正常工作的基础。要根据系统中各个硬件设备的功耗需求,选择合适的电源芯片和电源电路,确保电源能够提供稳定的电压和足够的电流。可以采用线性稳压电源或开关稳压电源,线性稳压电源具有输出电压稳定、纹波小的优点,但效率相对较低;开关稳压电源则效率较高,但纹波相对较大。在实际设计中,需要根据系统对电源稳定性和效率的要求,选择合适的电源类型 。通信模块的设计也很重要,如果系统需要与外部设备进行通信,如与上位机进行数据传输和控制指令交互,就需要选择合适的通信模块,如蓝牙模块、WiFi 模块或串口通信模块等,并设计相应的通信电路和协议 。
5.2 软件编程策略
PID 参数整定是软件编程中的关键环节,它就像为汽车调整悬挂系统,直接影响着系统的控制性能。常用的 Ziegler - Nichols 方法是一种经典的整定方法,通过实验获取系统的临界比例度和临界周期,然后根据经验公式计算出 PID 控制器的参数。在实际应用中,还需要结合试凑法进行微调,根据系统的实际运行效果,逐步调整 PID 参数,直到系统达到最佳的控制性能。当发现系统的响应速度较慢时,可以适当增大比例系数 P,提高系统的响应速度;如果系统出现振荡,可以减小比例系数 P,或者增大积分时间常数 I 和微分时间常数 D,增强系统的稳定性 。
编写控制程序时,清晰合理的流程和架构是确保系统稳定运行的关键。程序可以采用模块化设计的思想,将不同的功能模块分开编写,如数据采集模块、数据处理模块、控制算法模块、电机驱动模块和人机交互模块等。每个模块都有明确的功能和接口,就像工厂中的各个生产车间,分工明确,协同工作。数据采集模块负责从 MPU - 6050 传感器读取风力摆的姿态数据;数据处理模块对采集到的数据进行滤波、校准等处理,提高数据的准确性;控制算法模块根据处理后的数据,运用 PID 算法计算出电机的控制信号;电机驱动模块将控制信号转换为适合电机驱动的信号,控制电机的运行;人机交互模块则负责与用户进行交互,接收用户的指令,并显示系统的运行状态 。
为了提高代码的效率和稳定性,需要采取一系列优化技巧。在代码编写过程中,要尽量使用高效的算法和数据结构,减少不必要的计算和内存占用。避免使用复杂的循环嵌套和递归函数,因为这些操作可能会占用大量的处理器资源和时间。可以采用中断机制来处理实时性要求较高的任务,如数据采集和电机控制等,确保系统能够及时响应外部事件。在内存管理方面,要合理分配和释放内存,避免内存泄漏和内存碎片的产生,提高系统的稳定性 。
实现人机交互功能时,编程要点在于简洁明了的用户界面设计和准确可靠的指令解析。通过液晶显示屏向用户展示系统的运行状态,如风力摆的角度、运行时间、运行模式等信息,要确保显示的内容清晰易读,就像电子设备的显示屏一样,能够直观地传达信息。在接收用户通过键盘输入的指令时,要对指令进行严格的校验和解析,确保系统能够准确理解用户的意图,并做出正确的响应。如果用户输入的指令格式错误或参数超出范围,系统要能够及时给出提示信息,引导用户正确操作 。
六、基于STM32 的风力摆控制系统的视线
6.1 代码说明
以上代码实现了风力摆控制系统的核心功能,主要包含三个模块:
-
主程序模块(main.c):
- 负责系统初始化和主控制循环
- 实现了五种工作模式的切换逻辑
- 包含画圆轨迹的生成算法
- 处理传感器数据并更新显示
-
PID 控制模块(pid.c):
- 实现了带积分限幅的 PID 控制算法
- 支持参数初始化和控制器复位
- 输出限幅保护电机安全
-
传感器模块(mpu6050.c):
- 实现 MPU6050 的初始化和校准
- 使用互补滤波融合加速度计和陀螺仪数据
- 计算风力摆的实时角度
6.2 使用提示
- 代码中的 PID 参数(kp, ki, kd)需要根据实际硬件进行调试优化
- 电机驱动部分需要根据所使用的电机型号进行适配
- 传感器校准程序需要在系统水平放置时运行
- 可以通过调整画圆轨迹函数中的半径参数改变画圆大小
实际比赛中,还需要根据具体的硬件布局和性能要求对代码进行优化和调整,特别是 PID 参数的整定往往需要多次实验才能达到最佳效果。
6.3 代码实现
<doubaocanvas-part path="main.c" language="c" description="主程序模块,实现系统初始化和模式控制">#include "stm32f10x.h"
#include "mpu6050.h"
#include "pid.h"
#include "motor.h"
#include "lcd1602.h"
#include "key.h"
#include "delay.h"
#include "timer.h"
#include <stdio.h>
// 工作模式定义
#define MODE_IDLE 0 // 空闲模式
#define MODE_SWING_UP 1 // 起摆模式
#define MODE_DRAW_LINE 2 // 画线模式
#define MODE_DRAW_CIRCLE 3 // 画圆模式
#define MODE_RESET 4 // 复位模式
// 全局变量
uint8_t work_mode = MODE_IDLE;
float current_angle_x = 0.0f, current_angle_y = 0.0f;
float target_angle_x = 0.0f, target_angle_y = 0.0f;
uint32_t run_time = 0;
uint8_t circle_step = 0; // 画圆步骤计数器
// PID 控制器实例
PID_Controller pid_x, pid_y;
// 画圆轨迹参数
#define CIRCLE_RADIUS 20.0f // 画圆半径 (度)
#define CIRCLE_STEPS 100 // 圆轨迹分割步数
#define PI 3.1415926f
// 系统初始化
void System_Init (void) {
delay_init ();
NVIC_PriorityGroupConfig (NVIC_PriorityGroup_2);
LCD1602_Init ();
KEY_Init ();
TIM3_Init (99, 7199); // 10ms 定时器
MPU6050_Init ();
Motor_Init ();
// 初始化 PID 控制器
PID_Init (&pid_x, 5.0f, 0.1f, 0.5f, -500, 500, -1000, 1000);
PID_Init (&pid_y, 5.0f, 0.1f, 0.5f, -500, 500, -1000, 1000);
LCD1602_ShowString(1, 1, "Wind Pendulum");
delay_ms(1000);
LCD1602_Clear();
}
// 生成圆轨迹目标角度
void Generate_Circle_Trajectory (void) {
float rad = (2 * PI * circle_step) / CIRCLE_STEPS;
target_angle_x = CIRCLE_RADIUS * cos (rad);
target_angle_y = CIRCLE_RADIUS * sin (rad);
circle_step = (circle_step + 1) % CIRCLE_STEPS;
}
// 模式处理函数
void Mode_Process (void) {
uint8_t key = KEY_Scan (0);
// 模式切换
if (key == KEY1_PRES) {
work_mode = (work_mode + 1) % 5;
PID_Reset (&pid_x);
PID_Reset (&pid_y);
run_time = 0;
circle_step = 0;
delay_ms (200); // 消抖
}
// 模式显示与处理
switch (work_mode) {
case MODE_IDLE:
LCD1602_ShowString (1, 1, "Mode: IDLE");
Motor_Stop ();
break;
case MODE_SWING_UP:
LCD1602_ShowString (1, 1, "Mode: SWING UP");
// 快速起摆逻辑:逐步增加目标角度
target_angle_x = (run_time < 200) ? (run_time * 0.1f) : 20.0f;
target_angle_y = 0.0f;
break;
case MODE_DRAW_LINE:
LCD1602_ShowString (1, 1, "Mode: LINE");
// 画直线轨迹(45 度方向)
target_angle_x = 15.0f * sin (run_time * 0.01f);
target_angle_y = 15.0f * sin (run_time * 0.01f);
break;
case MODE_DRAW_CIRCLE:
LCD1602_ShowString(1, 1, "Mode: CIRCLE");
Generate_Circle_Trajectory();
break;
case MODE_RESET:
LCD1602_ShowString(1, 1, "Mode: RESET");
target_angle_x = 0.0f;
target_angle_y = 0.0f;
break;
}
}
// 更新显示信息
void Update_Display (void) {
char buf [16];
// 显示角度信息
sprintf (buf, "X:%.1f Y:%.1f", current_angle_x, current_angle_y);
LCD1602_ShowString (2, 1, buf);
// 显示运行时间
sprintf (buf, "T:% ds", run_time / 100); // 每 10ms 计数一次
LCD1602_ShowString (1, 11, buf);
}
int main(void) {
System_Init();
while (1) {
// 读取角度数据
MPU6050_GetAngle (¤t_angle_x, ¤t_angle_y);
// 模式处理
Mode_Process ();
// 计算控制量
float output_x = PID_Compute (&pid_x, target_angle_x, current_angle_x);
float output_y = PID_Compute (&pid_y, target_angle_y, current_angle_y);
// 驱动电机
Motor_SetSpeed (output_x, output_y);
// 更新显示
Update_Display ();
delay_ms(10);
}
}
// 定时器中断服务函数(10ms 触发一次)
void TIM3_IRQHandler (void) {
if (TIM_GetITStatus (TIM3, TIM_IT_Update) != RESET) {
run_time++; // 累计运行时间
TIM_ClearITPendingBit (TIM3, TIM_IT_Update);
}
}
<doubaocanvas-part path="pid.c" language="c" description="PID控制模块,实现闭环控制算法">#include "pid.h"
// PID 控制器结构体初始化
void PID_Init (PID_Controller *pid, float kp, float ki, float kd,
float output_min, float output_max,
float integral_min, float integral_max) {
pid->kp = kp;
pid->ki = ki;
pid->kd = kd;
pid->output_min = output_min;
pid->output_max = output_max;
pid->integral_min = integral_min;
pid->integral_max = integral_max;
pid->last_error = 0.0f;
pid->integral = 0.0f;
pid->output = 0.0f;
}
// PID 计算函数
float PID_Compute (PID_Controller *pid, float setpoint, float process_value) {
// 计算误差
float error = setpoint - process_value;
// 比例项
float proportional = pid->kp * error;
// 积分项(带积分限幅)
pid->integral += pid->ki * error;
if (pid->integral > pid->integral_max) {
pid->integral = pid->integral_max;
} else if (pid->integral < pid->integral_min) {
pid->integral = pid->integral_min;
}
// 微分项(带一阶滤波)
float derivative = pid->kd * (error - pid->last_error);
// 计算总输出
pid->output = proportional + pid->integral + derivative;
// 输出限幅
if (pid->output > pid->output_max) {
pid->output = pid->output_max;
} else if (pid->output < pid->output_min) {
pid->output = pid->output_min;
}
// 保存当前误差用于下次计算
pid->last_error = error;
return pid->output;
}
// 重置 PID 控制器
void PID_Reset (PID_Controller *pid) {
pid->last_error = 0.0f;
pid->integral = 0.0f;
pid->output = 0.0f;
}
// 修改 PID 参数
void PID_SetParams (PID_Controller *pid, float kp, float ki, float kd) {
pid->kp = kp;
pid->ki = ki;
pid->kd = kd;
}
<doubaocanvas-part path="pid.h" language="c" description="PID控制模块头文件">#ifndef _PID_H
#define _PID_H
// PID 控制器结构体
typedef struct {
// PID 参数
float kp; // 比例系数
float ki; // 积分系数
float kd; // 微分系数
// 中间变量
float last_error; // 上一次误差
float integral; // 积分项
// 输出限制
float output_min; // 输出最小值
float output_max; // 输出最大值
float integral_min; // 积分最小值
float integral_max; // 积分最大值
// 输出值
float output; // 最终输出
} PID_Controller;
// 函数声明
void PID_Init (PID_Controller *pid, float kp, float ki, float kd,
float output_min, float output_max,
float integral_min, float integral_max);
float PID_Compute (PID_Controller *pid, float setpoint, float process_value);
void PID_Reset (PID_Controller *pid);
void PID_SetParams (PID_Controller *pid, float kp, float ki, float kd);
#endif
七、总结与经验启示
回顾 2024 电子设计大赛 B 题 “风力摆控制系统”,这一题目涵盖了丰富的知识领域和技术要点,从硬件层面的 STM32 单片机控制模块、MPU - 6050 陀螺仪传感器、轴流电机等设备的合理选型与精心搭建,到软件层面的 PID 算法等控制算法的巧妙运用以及程序的高效编写,每一个环节都充满了挑战,同时也蕴含着无限的探索乐趣 。
解决这道题目的关键在于对硬件和软件的深入理解以及二者的紧密协同。在硬件设计中,要充分考虑系统的稳定性、精度和成本等因素,精心挑选硬件设备并合理搭建电路。在软件编程时,优化算法、合理处理多任务以及确保软件与硬件的良好通信和时序配合至关重要 。
参与这样的电子设计竞赛,对于提升电子设计能力有着不可估量的重要性。它就像一场全面的实战演练,让参赛者在实践中深入理解电子设计的原理和方法,锻炼解决实际问题的能力。通过竞赛,参赛者能够接触到前沿的技术和理念,拓宽自己的技术视野,激发创新思维 。
对于有志于在电子设计领域发展的读者来说,积极参与相关竞赛和实践是成长的必经之路。在准备竞赛的过程中,要扎实掌握基础知识,注重理论与实践的结合,多动手、多思考、多尝试。在实践中不断积累经验,提高自己的设计能力和创新能力,为未来的发展打下坚实的基础 。