无线遥控的四轴电机驱动模块的设计_第1页
无线遥控的四轴电机驱动模块的设计_第2页
无线遥控的四轴电机驱动模块的设计_第3页
无线遥控的四轴电机驱动模块的设计_第4页
无线遥控的四轴电机驱动模块的设计_第5页
已阅读5页,还剩70页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

-69-第一章绪论第一节课题背景1.1.1遥控的发展概况这些年来,无线通信技术与人们的生活中息息相关,遥控是无线通信技术中最主要的产品之一。目前遥控器主要分为红外遥控器和无线电遥控器两种,两者各有不同的优势,应用的领域也有所区别。红外遥控器的电路调试简单,编码容易,成本较低,不受周边环境影响,不干扰其他电器设备,但是控制范围较短(一般在10米以内),而且是有方向性的,不能穿透障碍物。所以一般用于家用电器(电视、空调遥控器等等)。无线电遥控器的控制范围较高,没有特定的方向,穿透力较强,但是发射功率大耗电大,容易受到电磁的干扰,通常用于汽车遥控、智能家居等等。1.1.2四轴飞行器的发展概况四轴飞行器又称四旋翼、四转子,是一种多轴飞行器,有四个旋翼来悬停、维持姿态及平飞。和固定翼飞机不同,它通过旋翼提供的推力使飞机升空。它的四个旋翼大小相同,分布位置接近对称。对于简单的设计来说,仅仅通过调整不同旋翼之间的相对速度来调节不同位置的推力,并克服每个旋翼之间的反扭力矩,就可以控制飞机维持姿态和完成各种机动飞行。这一点和直升机不同,常见的直升机就有两个旋翼,尾桨只起到抵消主旋翼产生的扭矩和控制飞机偏航运动的作用。随着科技不断发展进步,尤其是MEMS技术的发展和电机技术的使用,还有数学算法和建模的成熟,创造出了小巧、稳定、结构简单的四轴飞行器。其中微型四轴飞行器的成本十分低廉(可以做到百元内)。四轴飞行器的应用非常广泛,可以用于军事、科学研究和民用。在民用领域,四轴飞行器可以用于影视航拍、农业植保、渔业监管、个人玩具等等。国内比较知名的无人机公司有深圳市大疆创新科技有限公司等等。第二章工作原理第1节飞行原理2.1.1坐标系统飞行器的坐标系统是二维空间指教坐标系统,分别是地理坐标系和机体坐标系。地理坐标系是固定的,连接在地面上的坐标系。机体坐标系也是固定的,连接在飞行器上的坐标系。由于四旋翼飞行器的运动范围比较小,所以可以不考虑地面曲率。人们习惯性上将地面假设为惯性系。坐标地理使用Y轴上北下、X轴南左西右东、Z轴上天下地,坐标零点位于机架中心板中心。如图2-1所示为坐标示意图。图2-1坐标示意图X、Y、Z轴与各个选择轴之间符合右手螺旋定则。各个旋转方向命名为PIT(俯仰)、ROL(横滚)、YAW(偏航)。由于四轴的运动基本是由于倾斜后的分力在起作用,因此后面主要的解算和分析都是围绕着这几个旋转量。2.1.2力学原理四轴飞行器通常有两种模式,十字模式与X字模式。本次设计采用的是X字模式。四轴飞行器通过改变自身四个旋翼的转速,可以比较灵活地进行各种飞行动作。主要依据的运动原理是力的合成与分解,以及空气转动扭矩的反向性。为了描述方便,将四个电机编号为1-4号。如下图2-2所示X字模式的电机旋转方向和编号。图2-2X字模式的电机旋转方向和编号四个电机相邻的两个旋翼的转动方向相反,而在对角线上的两个电机转动方向相同。1、4两个电机都是顺时针转动,而2、3电机是逆时针转动。这样一来,为了保证它们产生的升力都是向上的,1、4电机需要使用的螺旋桨是正桨,一般指顺时针转动时能产生向上升力的桨;而2、3电机使用的螺旋桨是反桨,即逆时针时产生向上升力的桨。四个旋翼都是向下吹风的,以便都提供向上的拉力。顺时针转动的桨在转动时,空气会产生是的四轴逆时针转动的反向扭矩。而当1、4同方向,2、3同方向的时候,这两个扭矩就恰好抵消掉了,使得四轴在偏航方向能保持平衡,不至于出现自旋转。四轴飞行器一共有八种比较典型的运动情况,可以概括为:上升、下降、左旋、右旋、左飞、右飞、前飞、后飞。2.1.3姿态解算的意义姿态解算即指控制器读取自身传感器数据,实时进行计算四轴飞行器的姿态角,比如翻滚角roll,俯仰角pitch,偏航角yaw,控制器根据这些信息即可计算4个电机的输出量,使飞行器保持平衡稳定或者保持一定倾斜角度使飞行器朝着某设定方向飞行。姿态解算是飞行器飞行的关键技术之一,解算速度和精度直接关系到飞行器飞行中的稳定性和可靠性。姿态解算的方法有很多,比较典型的方法有扩展型卡尔曼滤波算法EKF、互补滤波算法等。扩展型卡尔曼滤波算法具有高精度的特点,但其计算量大,并要求建立精确的动力学模型,因此并不是实现微型四轴飞行器的最佳选择。而互补滤波算法对传感器的精度要求相对较低,计算量也不大,在微小四轴飞行器的姿态解算中应用最广。2.1.4姿态的表示方法四轴飞行器的姿态表示有很多种方法,最常用的为欧拉角表示方法,即为翻滚角、俯仰角和偏航角。另外还有旋转矩阵表示法和四元数表示法。一、旋转矩阵和欧拉角、转轴-转角表示法旋转矩阵用于表示一个坐标系在另外一个坐标系的姿态。若飞行器姿态用旋转矩阵R表示,则R具有以下性质:两个向量的点积在他们都被同一个旋转矩阵操作(相当于旋转)之后的点积相等,例如a·b=Ra·Rb,其中a和b为两个任意3x1的向量;旋转矩阵的逆即为其转置,即R的负一次方等于R的T次方。欧拉角可以直接从旋转矩阵中直接读出飞行器的姿态,故被广泛接受。从一个坐标系(比如静置的全局坐标系Fw)转到另一个坐标系(比如运动的飞行器自身坐标系Fb)可以有不同的迅速。常用的旋转顺序有Z-X-Y或者Z-Y-X,航空航天上也称之为Tait-Bryan角。以下以Z-Y-X欧拉角举例详细说明。假设全局坐标系Fw固定于地面保持静止,而随飞行器转边的坐标系Fb初始姿态与Fw是重合为F,然后F按以下顺序旋转至最终的姿态Fb:①Fb0绕着Fw0的Z轴按右手坐标系规则转动α角,α角即为偏航角yaw,并假设Fb0转动后的新姿态为Fb0;②Fb1绕着Fb1的Y轴按右手坐标系规则转动β角,β角即为俯仰角pit,并假设Fb1转动后的新姿态为Fb1;③Fb2绕着Fb2的X轴按右手坐标系规则转动θ角,θ角即为翻滚角roll,并假设Fb2转动后的最终坐标系Fb2;需要注意的是,以上三次转动分别都绕自身坐标系的某一个轴,而不是绕固定于地面的全局坐标系的坐标轴。以上三次转动分别对应一个基本旋转矩阵:R(Z,ψ)=R(Y,θ)=R(X,Φ)=以上三次转动的合成矩阵:二、四元数表示法单位四元数与欧拉角、旋转矩阵是等价的,但又不同于欧拉角表示,四元数表示法没有奇异点的问题,正是因为这个优点,单位四元数在姿态估算的核心算法中非常常见。比起三维旋转矩阵,四元数表示法更能方便地给出旋转的转轴和旋转角。四元数一般表示为q=q0+q1i+q2j+q3k。由此可见,四元数的基的乘法是不可交换的。四元数也可以简单表示为q=(q0,q1,q2,q3)。泳衣表示旋转矩阵的四元数必须是单位四元数,即q应满足q02+q12+q22+q32=1。给定两个四元数P=p0,p1,p2,p3,q=q0,q1,q2,q3,它们的乘积演算得出p*q≠q*p(此处*特指四元数乘法),即四元数乘法是不可交换的。可得到使用四元数表示的旋转矩阵:R=第三章方案设计第1节遥控器的构成3.1.1硬件构成无线遥控主要由MCU--STM32F103C8模块、摇杆模块和nRF24L012.4GHz无线模块构成。无线遥控硬件结构图如下图3-1所示。图3-1无线遥控硬件结构图无线遥控硬件整体实物连接图于附录所示。 一、STM32F103C8T6本文遥控设计使用的STM32F103C8T6是ST公司设计研发的STM32F10xx系列中的一款,中等容量增强型,32位基于ARM核心的带64或128K字节闪存的微控制器。STM32F103C8T6芯片如图3-2所示。图3-2STM32F103C8T6芯片STM32F103C8T6是基于ARMCortex-M3内核的处理器,专为人们的要求--高性能、低成本、低功耗的嵌入式应用来设计的,在市场上比较流行,资料多,容易上手,RAM大,时钟频率高,适合用于飞行控制的大量运算。本文设计的遥控需要对摇杆的模拟信号进行AD模数转换,4个方向的模拟信号需要4个模数转换器。STM32F103C8T6拥有12位ADC,是一种逐次逼近型模拟/数字转换器。它有18个通道,各通道的A/D转换可以单次、连续、扫描或间断模式执行。而且STM32的ADC可以使用DMA(datamemoryaccess)方式操作,方便高效。采用的2.4G无线模块的通信接口为SPI接口,可以用硬件SPI,也可以用I/O口模拟SPI,模拟SPI需要用到中断,会占用CPU资源,而硬件SPI不需要CPU参与。STM32F103C8T6有两个硬件SPI接口。被控端四轴飞行器的传感器的通信接口是I2C接口,硬件I2C和模拟I2C的情况类似SPI。STM32F103C8T6有硬件I2C接口。综合考虑以上因素,最终选择STM32F103C8T6。本次设计的STM32F103C8T6接口电路及最小系统如图3-3所示。图3-3STM32F103C8T6接口电路及最小系统2.4GHzNRF24L01无线通信模块本次使用的无线模块为以NRF24L01为核心的2.4GHZ的无线模块。如图3-4所示NRF24L01模块。图3-4NRF24L01模块NRF24L01是由NORDIC生产的工作在2.4~2.5GHz的ISM频段的单片无线收发器芯片。无线收发器包括:频率发生器、增强型SchockBurst模式控制器、功率放大器、晶体振荡器、调制器和解调器。输出功率频道选择和协议的设置可以通过SPI接口进行设置。当工作在发射模式下发射功率为0dBm时的电流消耗为11.3mA,在接收模式下为12.3mA,在掉电模式和待机模式下的电流消耗更低。下图3-5是NRF24L01模块的IO口接口电路。图3-5NRF24L04模块IO口接口电路NRF24L01模块的引脚及功能如下表3-1。表3-1NRF24L01模块的引脚及功能引脚名称引脚功能描述3CE数字输入发射或接收模式选择4CSNSPI片选信号SPI片选信号5SCK数字输入SPI时钟6MOSI数字输入主机输出从机输入数据脚7MISO数字输出主机输入从机输出数据脚8IRQ数字输出可屏蔽中断脚STM32F103C8T6与NRF24L01的连接引脚如下图3-6所示。图3-6STM32F103C8T6与NRF24L01的连接引脚STM32F103C8T6的SPI_CR寄存器的CPOL和CPHA位,可以组成四种时序关系。当CPHA=0时,时序图如图3-7所示。图3-7CPHA=0时序图这时候数据在第一个边沿进行数据位的采样,CPOL=0时为上升沿采样,CPOL=1时为下降沿采样。当CPHA=1时,时序图如图3-8所示。图3-8CPHA=1时序图这时候数据在第二个边沿进行数据位的采样,CPOL=1时为上升沿采样,CPOL=0时为下降沿采样。外设从机的极性一般有严格要求,本次的NRF24L01要求空闲状态SCK=0,CPHA=0;数据在时钟第一个时间边沿采集CPOL=0,如图3-9所示NRF24L01的SPI时序。图3-9NRF24L01的SPI时序图3-9中Cn为SPI命令位,Sn为STATUS寄存器位,Dn为数据位(MSB,多字节输出时,低字节在前)。NRF24L01的工作模式,由CE和CONFIG寄存器的PWR_UO和PRIM_RX位共同控制。如表3-2所示。表3-2NRF24L01的工作模式NRF24L01所处模式PWR_UP位状态PRIM_RX

位状态CE引脚电平

FIFO

寄存器状态接收模式111-发送模式101数据在TX

FIFO

寄存器中发送模式101→0

停留在发送模式,直至发送完待机模式II

101TX

FIFO

为空待机模式I1-0无数据传输掉电模式0-

-

-

其中,收发模式又有:EnhancedShockBurstTM收发模式和ShockBurstTM收发模式,只有EnhancedShockBurstTM收发模式支持自动ACK和自动重发。开启自动ACK,则默认选择Enhanced模式。EnhancedShockBurstTM发送模式初始化:(1)写Tx节点的地址TX_ADDR(2)写Rx节点的地址(主要是为了使能AutoAck)RX_ADDR_P0(3)使能AUTOACKEN_AA(4)使能PIPE0EN_RXADDR(5)配置自动重发次数SETUP_RETR(6)选择通信频率RF_CH(7)配置发射参数(低噪放大器增益、发射功率、无线速率)RF_SETUP(8)配置24L01的基本参数以及切换工作模式CONFIG。EnhancedShockBurstTM发送流程:(1)把地址和要发送的数据按时序送入NRF24L01;(2)配置CONFIG寄存器,使之进入发送模式;(3)微控制器把CE置高(至少10us),激发EnhancedShockBurstTM发射;(4)EnhancedShockBurstTM发射:①给射频前端供电;②射频数据打包(加字头、CRC校验码);③高速发射数据包;④发射完成,NRF24L01进入空闲状态EnhancedShockBurstTM接收流程:(1)配置接收地址和要接收的数据包大小;(2)配置CONFIG寄存器,使之进入接收模式,把CE置高。(3)130us后,NRF24L01进入监视状态,等待数据包的到来;(4)当接收到正确的数据包(正确的地址和CRC校验码),NRF2401自动把字头、地址和CRC校验位移去;(5)NRF24L01通过把STATUS寄存器的RX_DR置位(STATUS一般引起微控制器中断)通知微控制器;(6)微控制器把数据从FIFO读出(0X61指令);(7)所有数据读取完毕后,可以清除STATUS寄存器。NRF2401可以进入四种主要的模式之一。摇杆模块本次遥控设计采用的是两轴XY摇杆模块,而没有使用按键进行操作控制。因为按键只是单一的0和1两个变量,而摇杆使用的电位器设计拥有灵敏的-125至125的行程变量,有较好的操作方便性、可控性和精度。可以输出X、Y两路模拟信号和一路中键确认数字信号。摇杆模块如图3-10所示。图3-10摇杆模块摇杆模块连接电源为3.3V或5V,电源电压不宜太高,否则会导致模块烧毁。X轴、Y轴引脚连接单片机的AD端口。当移动摇杆时,X、Y轴的电压值发生改变,将变量通过AD转换给STM32。当接入3.3V时电压变化范围为0~3.3V。四轴飞行器的遥控油门的位置在左边的是美国手,在右边的是日本手,本次设计使用的是美国手。左右两个摇杆的各个方向功能作用如图3-11所示。图3-11摇杆的各个方向功能作用3.1.2软件实现第一步:对各个模块进行初始化系统时钟初始化和时钟源内部HSI初始化,开启系统tick定时器并初始化其中断,串口初始化,中断初始化,内部flash解锁,加载系统参数配置表,IO初始化,摇杆AD初始化,NRF24L01初始化,设无线模块为接收模式,遥控摇杆校准,定时器初始化。第二步:等待摇杆移动摇杆移动,将变量值AD转换给STM32。第三步:发送数据STM32将数据传给NRF24L01,NRF24L01将数据发送出去。遥控软件流程图如图3-12所示。图3-12遥控软件流程图具体的程序见附录所示。第2节被控端的构成3.2.1硬件构成被控端四轴飞行器的硬件主要由STM32F103C8T6、NRF24L01无线通信模块和MPU6050六轴传感器模块构成,加上适当的稳压、稳流电路。四轴的硬件系统框图如图3-13所示。图3-13四轴的硬件系统框图STM32F103系列单片机和NRF24L01无线通信模块在上一节已经有所介绍,本节不在赘述。一、六轴传感器MPU6050MPU6050为全球首例集成六轴传感器的运动处理组件,它内置一个三轴MEMS陀螺仪、一个三周MEMS加速度计、一个数字运动处理引擎(DMP)以及用于第三方数字传感器接口的辅助I2C端口(常用于拓展磁力计)。当辅助I2C连接到一个三轴磁力计,MPU6050能提供一个完整的九轴融合输出到其主I2C端口。MPU6050拥有16为模/数转换器ADC,将三轴陀螺仪及三轴加速度计的数据转化为数字量输出。为了精确跟踪快速和慢速运动,MPU6050支持用户可编程的陀螺仪满量程范围有:±250、±500、±1000与±2000(单位为°/S或dps),支持用户可编程的加速度计满量程范围有:±2G、±4G、±8G与±16G。MPU6050同时内置了一个可编程的低通滤波器,可用于传感器数据的滤波。MPU6050数据传输可通过最高至400KHz的I2C总线完成,它的封装尺寸为QFN,在业界是革命性的尺寸。其他的特征包括内置的温度传感器以及高达10000GHz的碰撞容忍度的振荡器。MPU6050的供电范围为2.375~3.46V,三轴陀螺仪的正常工作电流为3.6mA,待机电流为5uA,三轴加速度计正常工作电流为500uA,待机电流为10uA。通过片上的数字运动处理引擎DMP可减少复杂的融合运算负荷,同时使用六轴传感器以及DMP仅需3.9mA的工作电流。如下图3-14所示为MPU6050芯片。图3-14MPU6050芯片MPU6050的引脚接线如图3-15所示。图3-15MPU6050的引脚接线SDA和SCL分别接到STM32F103C8T6的PA11和PA12。I2C总线总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。起始信号是当SCL为高期间,SDA由高到低的跳变。停止信号是当SCL为高期间,SDA由低到高的跳变。如图3-16所示起始和停止信号时序图。图3-16起始和停止信号时序图发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。对于反馈有效应答位ACK的要求是,接收器在第9个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。如图3-17所示I2C的响应时序图。图3-17I2C的响应时序图I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。如图3-18所示数据传送有效性时序图。如图3-18所示数据传送有效性时序图。MPU6050初始化过程①初始化IIC接口。②复位MPU6050。由电源管理寄存器1(0X6B)控制。③设置角速度传感器和加速度传感器的满量程范围。由陀螺仪配置寄存器(0X1B)和加速度传感器配置寄存器(0X1C)设置。④设置其他参数。配置中断,由中断使能寄存器(0X38)控制;设置AUXIIC接口,由户控制寄存器(0X6A)控制;设置FIFO,由FIFO使能寄存器(0X23)控制;陀螺仪采样率,由采样率分频寄存器(0X19)控制;设置数字低通滤波器,由配置寄存器(0X1A)控制。⑤设置系统时钟。由电源管理寄存器1(0X6B)控制。一般选择x轴陀螺PLL作为时钟源,以获得更高精度的时钟。⑥使能角速度传感器(陀螺仪)和加速度传感器。由电源管理寄存器2(0X6C)控制。初始化完成,即可读取陀螺仪、加速度传感器和温度传感器的数据了。3.2.2机械构成一、机架由于对重量的要求较高,通常可以直接用自身的PCB电路板充当微型四轴飞行器的机架。使用PCB电路板作为机架时,可以选择0.8mm厚度的PCB板,这样可以兼顾重量和硬度。 二、电池大四轴通常使用2200mAh、3S、25C的电池,小四轴一般是350mAh、1S、25C。电池的C数是指这个电池的最大放电倍率,航模电池通常用S数值来表示电压。 三、电机及驱动在微型四轴飞行器上,由于空间和电流都比较有限,通常采用有刷电机作为动力,具体来说就是空心杯电机和MOS管驱动电路的结合。空心杯电机属于直流、永磁、伺服微特电机,具有突出的节能特性、灵敏方便的控制特性和稳定的运行特性,作为高效率的能量转换装置,代表了电动机的发展方向。空心杯电机在结构上突破了传统电机的转子结构形式,采用的是无铁芯转子。通常采用720空心杯电机。720空心杯大多转速能达到50000r/min左右。工作电压为3.7V。空载时电流为0.08A,堵转为1.8A。输出轴直径1mm,输出轴长度7mm。螺旋桨的尺寸为直径55mm桨配720电机。一般选用最大电流在2A以上的MOS管,比如IRLML2502,或者SI2302。下图3-19为720空心杯电机和螺旋桨。图3-19720空心杯电机和螺旋桨3.2.3软件实现软件大致流程为:系统初始化,无线模块等待接收,接收到数据,将数据和MPU6050模块采集到的姿态数据进行融合解算,通过PID控制输出PWM控制电机调速。四轴飞行器软件流程图如图3-20所示。图3-20四轴飞行器软件流程图第4章数据处理第1节飞行器的姿态解算4.1.1PID算法许多复杂的电子系统中常会包括PID控制,例如磁盘的读写头定位、电源供应器的电源条件甚至是现代地震仪的运动侦查路线。现代电子控制器已大幅被这些利用单芯片或FPGA来实现数字控制器所取代。现代工业使用的PID控制器多半会用PLC或有安装面板的数字控制器来实现。软件实现的好处是价格相对低廉,配合PID实现方法调整的灵敏度很大。在工业锅炉、塑胶射出机械、烫金机及包装行业中都会用到PID控制。PID控制器是一个在工业控制应用中常见的反馈回路部件。这个控制器把收集到的数据和一个参考值进行比较,然后把这个差别用于计算新的输入值,这个新的输入值的目的是让系统的数据达到或者保持在设定的参考值。PID控制器可以根据历史数据和差别的出现率来调整输入值,是系统更加准确且稳定。PID控制器的比例单元P、积分单元I和微分单元D分别对应目前误差、过去累计误差及未来误差。若是不知道受控系统的特性,一般认为PID控制器是最社和用到控制器。借由调整PID控制器的3个参数可以调整控制系统,设法满足设计需求。控制器的响应可以用控制器对误差的反应速度、控制器过冲的程度及系统震荡的程度来表示。不过使用PID控制器不一定能保证可达到系统的最佳控制,也不能保证系统稳定性。经典的单级PID控制器如图4-1所示。图4-1经典的单级PID控制器有些应用只需要PID控制器的部分单元,将不需要单元的参数设为零即可。因此PID控制器可以变成PI控制器、PD控制器、P控制器或I控制器。其中又以PI控制器比较常用,因为D控制器对系统噪声十分敏感,若没有I控制器的话,则系统一般不会回到参考值,而存在一个稳定的误差量。PID回路是要自动实现类似一位操作人员用量具和控制旋钮进行的工作。这个操作人员会用量具测系统输出的结果,然后用控制旋钮来调整这个系统的输入,直到系统的输出在量具上显示稳定的需求结果。在旧的控制文档里,这个过程叫做复位。量具被称为测量,需要的结果被称为设定值,而设定值和测量之间的差别被称为误差。一个控制回路包括以下三个部分:①系统的传感器得到的测量结果;②控制器做出决定;③通过一个输出设备来做出反应。控制器从传感器得到的测量结果,然后用需求结果减去测量结果来得到误差。然后用误差计算出一个对系统的纠正值作为输入结果,这样系统就可以从它的输出结果中消除误差。在一个PID回路中,这个纠正值有三种算法:消除目前的误差,平均过去的误差,透过误差的改变来预测将来的误差。PID控制器可以用来控制任何可被测量及可被控制变量。比如,它可以用来控制温度、压强、流量、化学成分、速度等。汽车上的巡航定速功能就是一个例子。一些控制系统把数个PID控制器串联起来,或是联成网络。这样的话,一个主控制器可能会为其他控制输出结果。一个常见的例子是发动机的控制。控制系统会需要发动机有一个受控的速度,最后停在一个确定的位置。可由一个发动机子控制器用来管理速度,但是这个子控制器的速度是由控制发动机位置的主控制器来管理的。联合和串级控制在化学过程控制系统中也相当常见。标准的直接计算法公式:Pout(t)=Kp*e(t)+Ki*∑e(t)+Kd*(e(t)-e(t-1));上一次计算值:Pout(t-1)=Kp*e(t-1)+Ki*∑e(t-1)+Kd*(e(t-1)-e(t-2));两式相减得到增量法计算公式:Pdlt=Kp*(e(t)-e(t-1))+Ki*e(t)+Kd(e(t)-2*e(t-1)+e(t-2));P比例控制器功能不同比例增益Kp下,受控变量的阶跃响应不同。比例控制考虑当前误差,误差值和一个正值的常数Kp(表示比例)相乘。Kp只是在控制器的输出和系统的误差成比例的时候成立。比如说,一个电热器的控制器的比例尺范围是10-20℃,它的预定值是20℃。注意:在误差是0的时候,控制器的输出也是0。比例控制的输出为:Pout=Kpe(t)。若比例增益打,在相同误差下会有较大的输出,但若比例增益太大,则会使系统不稳定。相反的,若比例增益小,则在相同误差量下,其输出较小,因此控制器会响应较慢。这会导致当有干扰出现时,其控制信号可能不够大,而无法修正干扰的影响。比例控制在误差为0是,其输出也会为0。若要让受控输出为非零的数值,就需要有一个稳态误差或偏移量。稳态误差和比例增益成正比,和受控系统本身的增益成反比。若加入一个偏置,或是加入积分控制,可以消除稳态误差。I积分控制器不同积分增益K1下,受控变量对时间的变化(Kp和KD维持定值)。积分控制考虑过去误差,将误差值在过去一段时间内的总和(误差和)乘以一个正值的常数K1.K1从过去的平均误差值来找到系统的输出结果和预定值的平均误差。一个简单的比例系统会振荡,会在预定值附近来回变化,因为系统无法消除多余的纠正。通过加上负的平均误差值,平均系统误差值就会渐渐减小。所以,最终这个PID回路系统会在设定值处稳定下来。积分控制会加速系统趋近设定值的过程,并且消除纯比例控制器出现的稳态误差。积分增益越大,趋近设定值的速度越快,不过因为积分控制会累计过去所有的误差,可能会使反馈值出现过冲的情形。D微分控制器微分控制考虑将来误差,计算误差的变化率,并和一个正值的常数KD相乘。这个变化率的控制会对系统的改变作出反应。导数的结果越大,那么控制器系统就越能对输出结果做出更快速的反应。这个KD参数也是PID被称为可预测的控制器的原因。KD参数有助于减少控制器短期的改变。实际中一些速度缓慢的系统可以不需要KD参数。微分控制可以提升整定时间及系统稳定性。不过因为纯微分器不是因果系统,因此在PID系统实现是,一般会微分控制加上一个低通滤波器以限制高频增益和噪声。实际应用上较少用到微分控制,估计PID控制器中只有约20%用到了微分控制。4.3.2飞行器PID参数调试PID的参数调试是指透过调整控制参数(比例增益、积分增益/时间、微分增益/时间)让系统达到最佳的控制效果。稳定性(不会有散发性的震荡)是首要条件。此外,不同系统有不同的行为,不同的应用其需求也不同,而且这些需求还可能会互相冲突。PID只有三个参数,在原理上容易说明,但PID参数调试是一项困难的工作,因为要符合一些特别的判据,而且PID控制其限制存在。历史上有许多不同的PID参数调试方式,包括齐格勒-尼克尔斯方法等,其中也有一些已申请专利。PID控制器的设计及调试在概念上很直接,但若有多个(且互相冲突)的目标(例如高稳定性及快速的暂态时间)都要达到的话,在实际上很难完成。PID控制器的参数若仔细调试会有很好的效果,相反的,若调试不当则效果会很差。一般初始设计常需要不断地进行环路模型仿真,并且修改参数,直到达到理想的性能或是可接受的偏差为止。有些系统有非线性的特性,若在无负载条件下调试的参数可能无法再满负载的情况下正常工作。对这样的系统可以利用增益规划的方式进行修正(在不同的条件下选用不同的数值)。稳定性若PID控制器的参数未挑选妥当,则其控制器输出可能就是不稳定的,也就是其输出发散过程中可能有振荡,也可能没有振荡,且其输出只受饱和或是机械损坏等原因所限制。不稳定一般是因为过大增益造成,特别是针对环路延迟时间很长的系统。最佳性能PID控制器两个基本的需求是调整能力(抑制扰动,使系统维持在设定值)及命令追随(设定值变化下,控制器输出追随设定值的反应速度)。有关命令追随的一些判据包括上升时间(risetime)及整定时间。有些应用可能基于安全考虑,不允许输出超过设定值,也有些应用要求在达到设定值过程中的能量消耗可以最小化。人工调试a.位置式PID参数调试首先大概设置一下YAW的参数P和D。P设置为5,D设置为50,以免自转太严重,不方便参加调试。接下来只需要调PITCH和ROLL方向的参数。②然后调节参数D:参数D代表阻尼作用。阻尼太小,四轴就会振荡;阻尼太大,四轴也会振荡。参数D产生的阻尼力,与控制量(角度)的变化率(角速度)有关,变化率(角速度)越大,阻尼力越大。在调试的过程中,我们把PITCH和ROLL的参数D设为一致,从0开始增加。刚开始增加D的时候,四轴剧烈抖动,基本上马上就炸机了,是一种高频率的反复振荡。增加到30左右的时候,发现四轴振动越来越小了,变稳了一些,接着增加,发现到100的时候四轴会有抖动感,于是把D慢慢调小,最后确定在80.③接着调节参数P:参数P代表四轴回复力的大小,即四轴偏离方向水平方向越多,这个回复力就越大。在调试的过程中,我们把PITCH和ROLL的参数P设为一致,从0开始往上增加。刚开始增加P的时候,四轴很快就侧翻了,不像调节参数D的时候处在高频振荡。慢慢增加P到4左右的时候,基本稳定下来了,最后把参数P确定在6.0。④调节参数I:随便给一点点参数,先给力0.005,感觉不太明显,后来加到0.030,感觉即使电池装的偏重心一点,也可以较好地飞行了。为避免参数I过大造成超调振荡,最终确定参数I为0.030。位置PID调试的结果:四轴很容易达到悬停的效果,但是机动性很一般,或者说会中是缓慢的,遥控手感一般。b.串级PID参数调试①所有参数归零,先调PITCH和ROLL的内环P(这个步骤跟调节位置式PID的参数D类似,主要是调节阻尼)。不断增大P,直到四轴能平稳起飞了,记下这个值。然后不断增大到开始轻微振荡,把参数P调小一些,然后加入一点点参数D抑制振荡,内环暂时好累。此时四轴是一个三轴模式,有点类似KK飞控,只有陀螺仪会保持当前角度,但不会自己修正当前角度。把四轴拿在手中摆动,可以明显感觉到抵抗的力(如果此时四轴YAW方向会自旋,就给YAW内环加入参数I,不断增大直到四轴不会自旋了)。②调PITCH和ROLL的外环P,从0开始增大,会感受到四轴回复力越来越大,但是会振荡(P负责回复力度的大小)。加入一点点参数D抑制超调。再加入一点参数I,就能有很好的手感了。如果环内调节得好,外环参数就很容易整定,基本上试几次就可得到较好的效果了。③YAW内环P从0开始增大,调节到转动平稳有力即可。4.3.3基于四元数的姿态解算互补滤波算法有了前面章节的理论基础,本节给出一个具体实例来讲解姿态解算算法。在一个IMU系统中,一般集成有加速度计芯片、陀螺仪芯片、磁传感器(罗盘)芯片;而且目前最常见的飞控系统中只有一个传感器芯片,即这个传感器芯片集成了加速度计、陀螺仪以及磁传感器。读取这些传感器的数据不是本节的重点,这里只关心如何把这些数据解算成飞行器的姿态,并用四元数和欧拉角分别表示出来。MPU6050的DMP输出的是姿态解算后的四元数,采用q30格式。四元数转欧拉角q0=quat[0]/q30;//q30格式转换为浮点数q1=quat[1]/q30;//q30是一个常量,2的30次方即1073741824q2=quat[2]/q30;q3=quat[3]/q30;//计算得到的横滚角/俯仰角/航向角angle->roll=-atan2(2.0f*(q0*q1+q2*q3),q0^2-q1^2-q2^2-q3^2)*180/pi;//俯仰角180/pi=57.3弧度转换为角度angle->pitch=asin(2.0f*(q0*q2-q1*q3))*180/pi;//横滚角Angle->yaw=atan2(2*(q0*q1+q2*q3),q0^2+q1^2-q2^2-q3^2)*180/pi;//航向角把加速度计的三维向量转成单位向量norm=invSqrt(ax*ax+ay*ay+az*az);ax=ax*norm;ay=ay*norm;az=az*norm;估计重力加速度方向在飞行器坐标系中的表示,为四元数表示的旋转矩阵的第三行vx=2*(q1*q3-q0*q2);vy=2*(q0*q1+q2*q3);vz=q0*q0-q1*q1-q2*q2+q3*q3;加速度计读取的方向和重力加速度方向的差值,用向量叉乘计算ex=ay*vz-az*vy;ey=az*vx-ax*vz;ez=ax*vy-ay*vx;误差累计,已与积分常数相乘exInt=exInt+ex*Ki;eyInt=eyInt+ey*Ki;ezInt=ezInt+ez*Ki;用叉积误差来做PI修正陀螺仪零偏,即抵消陀螺仪读书中的偏移量gx=gx+Kp*ex+exInt;gy=gy+Kp*ey+eyInt;gz=gz+Kp*ez+ezInt;一阶近似算法q0=q0_last+(-q1_last*gx-q2_last*gy-q3_last*gz)*halfT;q1=q1_last+(q0_last*gx+q2_last*gz-q3_last*gy)*halfT;q2=q2_last+(q0_last*gy-q1_last*gz+q3_last*gx)*halfT;q3=q3_last+(q0_last*gz+q1_last*gy-q2_last*gx)*halfT;二阶近似算法floatdelta2=(gx*gx+gy*gy+gz*gz)*T*T;q0=q0_last*(1-delta2/8)+(-q1_last*gx-q2_last*gy-q3_last*gz)*halfT;q1=q1_last*(1-delta2/8)+(q0_last*gx+q2_last*gz-q3_last*gy)*halfT;q2=q2_last*(1-delta2/8)+(q0_last*gy-q1_last*gz+q3_last*gx)*halfT;q3=q3_last*(1-delta2/8)+(q0_last*gz+q1_last*gy-q2_last*gx)*halfT;三阶近似算法floatdelta2=(gx*gx+gy*gy+gz*gz)*T*T;q0=q0_last*(1-delta2/8)+(-q1_last*gx-q2_last*gy-q3_last*gz)*T*(0.5-delta2/48);q1=q1_last*(1-delta2/8)+(q0_last*gx+q2_last*gz-q3_last*gy)*T*(0.5-delta2/48);q2=q2_last*(1-delta2/8)+(q0_last*gy-q1_last*gz+q3_last*gx)*T*(0.5-delta2/48);q3=q3_last*(1-delta2/8)+(q0_last*gz+q1_last*gy-q2_last*gx)*T*(0.5-delta2/48);四阶近似算法floatdelta2=(gx*gx+gy*gy+gz*gz)*T*T;q0=q0_last*(1-delta2/8+delta2*delta2/384)+(-q1_last*gx-q2_last*gy-q3_last*gz)*T*(0.5-delta2/48);q1=q1_last*(1-delta2/8+delta2*delta2/384)+(q0_last*gx+q2_last*gz-q3_last*gy)*T*(0.5-delta2/48);q2=q2_last*(1-delta2/8+delta2*delta2/384)+(q0_last*gy-q1_last*gz+q3_last*gx)*T*(0.5-delta2/48);q3=q3_last*(1-delta2/8+delta2*delta2/384)+(q0_last*gz+q1_last*gy-q2_last*gx)*T*(0.5-delta2/48); 四元数规范化norm=invSqrt(q0*q0+q1*q1+q2*q2+q3*q3);q0=q0*norm;q1=q1*norm;q2=q2*norm;q3=q3*norm;结束语由于本人时间仓促,水平有限,本次设计主要是制作遥控控制电机的装置,无法制作出完美的四轴飞行器的设计。由于本人经验不够丰富,论文和设计之中出现的错误在所难免,敬请各位读者批评、指正。四轴飞行器是最近比较火的一种机电类设备,适合作为电子信息、自动控制等学科的研究课题,也适合用作这些专业的教学、科技时间、工程实训设备。目前,从科技竞赛到航拍、侦查,随处可见四轴飞行器的身影。四轴飞行器是机械、通信、电子、自动控制几大学科融汇的具有较高科技含量的一种设备,主要承载了微处理器、惯性导航、自动控制、无线通信、电脑上位机软件、电路设计、PCB制作、外部机械结构设计、空气动力学及基本的航模控制知识。本次设计这套转置,难点之一是硬件方面的设计,更大的难点无疑都指向数据融合和各种算法。网上的资料对此都是泛泛而谈,很少有一些更为具体的应用。本人对多旋翼飞行器的兴趣浓厚,以后依然会继续对此方面进行进一步的研究。致谢首先非常感谢学校的教育和栽培,是学校培养了我现在的思维和学识,我才可以对深层次的科学知识进行相关的研究,这篇论文才能写出来。感谢老师,在跟老师做毕业设计的过程中,学到了远比学习本身更重要的东西,让我进一步成长。感谢我的父母,他们在物质上对我的大力支持是我进行科学研究的基础,他们的爱是我前进的动力。感谢网上各位一起探讨多旋翼飞行器的网友,他们的经验对我来说非常重要。让我少走了许多弯路,帮助我解决了不少问题。感谢同班同学们,是你们的支持让我充满激情。参考文献[1]刘峰,吕强,王国胜等.四轴飞行器姿态控制系统设计[J].计算机测量与控制,2011,19(3):583-585,616.[2]刘杰.四轴飞行器研究与设计[D].南京邮电大学,2013.[3]王冬来,吕强,刘峰等.小型四轴飞行器动力学参数测定方法设计[J].科技导报,2011,29(36):42-45.DOI:10.3981/j.issn.1000-7857.2011.36.007.[4]王俊,鲁晓天.对四轴飞行器基于姿态算法的分析与实现[J].河南科技,2015,(2):51-53.DOI:10.3969/j.issn.1003-5168.2015.02.019.[5]郝芸,杨奇,佟皓萌等.基于STM32的四轴飞行器设计[J].电子测试,2015,(18):6-8.DOI:10.3969/j.issn.1000-8519.2015.18.004.[6]梁延德,程敏,何福本等.基于互补滤波器的四旋翼飞行器姿态解算[J].传感器与微系统,2011,30(11):56-58,61.DOI:10.3969/j.issn.1000-9787.2011.11.017.[7]姜山,祝丽.小型四轴飞行器控制器设计的研究[J].电子世界,2014,(22):260-260,261.[8]

郭天祥.新概念51单片机C语言教程[M].北京:电子工业出版社,2009.1

[9]

刘军,张洋,严汉宇.例说STM32[第二版][M].北京:北京航空航天大学出版社,2011.4

[10]

张毅刚,彭喜元,彭宇.单片机原理及应用[第二版][M].高等教育出版社,2010.5

[11]

张义和.例说51单片机[第三版][M].人民邮电出版社,2010.6.1

[12]

童诗白,华成英.模拟电子技术基础[第四版][M].高等教育出版社,2001.1

[13]

唐介.电机与拖动[第二版][M].高等教育出版社,2007.12[14]

阎石.数字电子技术基础[第四版][M].高等教育出版社,1998

[15]

王化祥.自动检测技术[第二版][M].化学工业出版社,2009.8.1

[16]

赵月飞,胡仁喜.AltiumDesigner13电路设计标准教程[M].科学出版社,2014.8

[17]

STM32中文参考手册_V10

,STM32英文参考手册[18]

作者:(英国)JosephYiu.译者:宋岩.ARMCortex-M3权威指南[M].[19]

尹纪新.无线射频基础[M].人民邮电出版社,2008.10[20]

黄和悦.DIY四轴飞行器基于MSP430F5系列单片机与Android[M].电子工业出版社,2015.9[21]

吴勇.四轴飞行器DIY-基于STM32微控制器[M].北京航空航天大学出版社,2016.2附录电路图及PCB1.1四轴总体连接图1.2四轴飞行器PCB实物图2.1遥控器实物图2.2四轴飞行器打样空板图2.3四轴飞行器实物图代码①main.c#include"stm32f10x.h"#include"stm32f10x_conf.h"#include"SysTick.h"#include"TIM3_IT.h"#include"led.h"#include"adc.h"#include"usart.h"#include"SPI_IO.h"#include"NRF24L01.h"intok;//初始化各个模块intmain(void){ SysTick_Init(); Tim3_Init(5000); LED_GPIO_Config(); ADC1_Init(); USART1_Config(); Spi1_Init(); Delay_us(50000); Nrf24l01_Init(MODEL_RX2,100);}②TIME3_IT.C#include"TIM3_IT.h"#include"NRF24L01.h"#include"usart.h"#include"adc.h"#include"SysTick.h"voidTim3_Init(u16period_num){ TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure; NVIC_InitTypeDefNVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); TIM_DeInit(TIM3); TIM_TimeBaseStructure.TIM_Period=period_num;//装载值prescaleris1200,thatis72000000/72/500=2000Hz; TIM_TimeBaseStructure.TIM_Prescaler=72-1;//分频系数 TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;//orTIM_CKD_DIV2orTIM_CKD_DIV4 TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure); TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //中断优先级设置 NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0; NVIC_InitStructure.NVIC_IRQChannelSubPriority=3; NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_Cmd(TIM3,ENABLE); }unsignedintVCC;unsignedintms;unsignedintRX_speed;unsignedintTX_speed;introll;intpitch;intyaw;intX_g;intY_g;intZ_g;intX_w;intY_w;intZ_w;voidRX_TX_Times(void){ ms++; if(ms>=100) { RX_speed=RX_times; RX_times=0; TX_speed=TX_times; TX_times=0; ms=0; }}voidTME_10ms(void){ ADC1_Value();RX_TX_Times(); NRF_TxPacket_AP(TxBuf,10); Nrf_Check_Event(); roll=NRFRX[0]-30000; pitch=NRFRX[1]-30000; yaw=NRFRX[2]-30000; X_g=NRFRX[3]-30000; Y_g=NRFRX[4]-30000; Z_g=NRFRX[5]-30000; X_w=NRFRX[6]-30000; Y_w=NRFRX[7]-30000; Z_w=NRFRX[8]-30000; NRFTX[0]=accelerator; NRFTX[1]=Pitch_ta+30000; NRFTX[2]=Roll_ta+30000; NRFTX[3]=Yaw_ta+30000; NRFTX[4]=1; UART1_ReportIMU(X_g,Y_g,Z_g,X_w,Y_w,Z_w,RX_speed,TX_speed,accelerator,roll,pitch,yaw/10);}voidTIM3_IRQHandler(void) { staticu8ms10=0; if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET) { TIM_ClearITPendingBit(TIM3,TIM_IT_Update); ms10++; TME_5ms(); if(ms10==2) { ms10=0; TME_10ms(); } }}③adc.c#include"adc.h"#defineADC1_DR_Address((u32)0x4001244C)int16_taccelerator;int16_tPitch_ta;int16_tRoll_ta;int16_tYaw_ta;int16_taccelerator_a;int16_tPitch_ta_a;int16_tRoll_ta_a;u16ADC_ConvertedValue[4];staticvoidADC1_GPIO_Config(void){ GPIO_InitTypeDefGPIO_InitStructure;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOC,ENABLE); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;GPIO_Init(GPIOC,&GPIO_InitStructure); }staticvoidADC1_Mode_Config(void){DMA_InitTypeDefDMA_InitStructure;ADC_InitTypeDefADC_InitStructure;DMA_DeInit(DMA1_Channel1);DMA_InitStructure.DMA_PeripheralBaseAddr=ADC1_DR_Address;DMA_InitStructure.DMA_MemoryBaseAddr=(u32)&ADC_ConvertedValue;DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;DMA_InitStructure.DMA_BufferSize=4;DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;DMA_InitStructure.DMA_Mode=DMA_Mode_Circular;DMA_InitStructure.DMA_Priority=DMA_Priority_High;DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;DMA_Init(DMA1_Channel1,&DMA_InitStructure);DMA_Cmd(DMA1_Channel1,ENABLE);ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;ADC_InitStructure.ADC_ScanConvMode=ENABLE; ADC_InitStructure.ADC_ContinuousConvMode=ENABLE; ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel=4; ADC_Init(ADC1,&ADC_InitStructure);ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_55Cycles5); ADC_RegularChannelConfig(ADC1,ADC_Channel_11,2,ADC_SampleTime_55Cycles5); ADC_RegularChannelConfig(ADC1,ADC_Channel_12,3,ADC_SampleTime_55Cycles5); ADC_RegularChannelConfig(ADC1,ADC_Channel_13,4,ADC_SampleTime_55Cycles5); ADC_DMACmd(ADC1,ENABLE);ADC_Cmd(ADC1,ENABLE);ADC_ResetCalibration(ADC1);while(ADC_GetResetCalibrationStatus(ADC1));ADC_StartCalibration(ADC1);while(ADC_GetCalibrationStatus(ADC1));ADC_SoftwareStartConvCmd(ADC1,ENABLE);}voidADC1_Init(void){ ADC1_GPIO_Config(); ADC1_Mode_Config();}#defineN10floatData_accelerator[N];floatData_Pitch_ta[N];floatData_Roll_ta[N];floatGildeAverageValueFilter(floatNewValue,float*Data){ unsignedchari; floatValue; floatsum; sum=0; Data[N]=NewValue; for(i=0;i<N;i++) { Data[i]=Data[i+1]; sum+=Data[i]; } Value=sum/N; return(Value);}voidADC1_Value(void){ accelerator_a=ADC_ConvertedValue[2]; accelerator=GildeAverageValueFilter(accelerator_a,Data_accelerator); Pitch_ta_a=ADC_ConvertedValue[1]; Pitch_ta=GildeAverageValueFilter(Pitch_ta_a,Data_Pitch_ta)-1500; Roll_ta_a=ADC_ConvertedValue[0]; Roll_ta=GildeAverageValueFilter(Roll_ta_a,Data_Roll_ta)-2100; Yaw_ta=0;//ADC_ConvertedValue[3]; }④SPI_IO.C#include"SPI_IO.h"voidSpi1_Init(void){ GPIO_InitTypeDefGPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_Init(GPIOA,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA,&GPIO_InitStructure);}unsignedcharSpi_RW(unsignedcharuchar){ unsignedcharbit_ctr; for(bit_ctr=0;bit_ctr<8;bit_ctr++) { SPI_MOSI(uchar&0x80); uchar=(uchar<<1); SPI_SCK(1); uchar|=SPI_MISO_IN; SPI_SCK(0); }return(uchar); }⑤NRF24L01.C#include"NRF24L01.h"#include"SPI_IO.h"uint8_tTX_ADDRESS[TX_ADR_WIDTH]={0x01,0x23,0x45}; uint8_tRX_ADDRESS[RX_ADR_WIDTH]={0x01,0x23,0x45}; uint8_tNRF_Write_Reg(uint8_treg,uint8_tvalue){ uint8_tstatus; SPI_CSN_L(); status=Spi_RW(reg); Spi_RW(value); SPI_CSN_H(); return status;}uint8_tNRF_Read_Reg(uint8_treg){ uint8_treg_val; SPI_CSN_L(); Spi_RW(reg); reg_val=Spi_RW(0); SPI_CSN_H(); return reg_val;}uint8_tNRF_Write_Buf(uint8_treg,uint8_t*pBuf,uint8_tuchars){ uint8_ti; uint8_tstatus; SPI_CSN_L(); status=Spi_RW(reg); for(i=0;i<uchars;i++) { Spi_RW(pBuf[i]); } SPI_CSN_H(); return status; }uint8_tNRF_Read_Buf(uint8_treg,uint8_t*pBuf,uint8_tuchars){ uint8_ti; uint8_tstatus; SPI_CSN_L(); status=Spi_RW(reg); for(i=0;i<uchars;i++) { pBuf[i]=Spi_RW(0); } SPI_CSN_H(); return status;}voidNRF_TxPacket_AP(uint8_t*tx_buf,uint8_tlen){ SPI_CE_L(); nRF24L01_tx(NRFTX,TxBuf); NRF_Write_Buf(0xa8,tx_buf,len); SPI_CE_H(); }uint8_tNrf24l01_Check(void){ u8buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5}; u8i; NRF_Write_Buf(NRF_WRITE_REG+TX_ADDR,buf,5); NRF_Read_Buf(TX_ADDR,buf,5); for(i=0;i<5;i++)if(buf[i]!=0XA5)break; if(i!=5)return1; return0; }voidNrf24l01_Init(uint8_tmodel,uint8_tch){ SPI_CE_L(); NRF_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH); NRF_Write_Buf(NRF_WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH); NRF_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); NRF_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); NRF_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1f); NRF_Write_Reg(NRF_WRITE_REG+RF_CH,ch); NRF_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f); //NRF_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x07); if(model==1) { NRF_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH); NRF_Write_Reg(NRF_WRITE_REG+CONFIG,0x0f); } elseif(model==2) //TX { NRF_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH); NRF_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e); } elseif(model==3) //RX2 { NRF_Write_Reg(FLUSH_TX,0xff); NRF_Write_Reg(FLUSH_RX,0xff); NRF_Write_Reg(NRF_WRITE_REG+CONFIG,0x0f); Spi_RW(0x50); Spi_RW(0x73); NRF_Write_Reg(NRF_WRITE_REG+0x1c,0x01); NRF_Write_Reg(NRF_WRITE_REG+0x1d,0x07); } else //TX2 { NRF_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e); NRF_Write_Reg(FLUSH_TX,0xff); NRF_Write_Reg(FLUSH_RX,0xff); Spi_RW(0x50); Spi_RW(0x73); NRF_Write_Reg(NRF_WRITE_REG+0x1c,0x01); NRF_Write_Reg(NRF_WRITE_REG+0x1d,0x07); } SPI_CE_H();}unsignedcharTxBuf[24]; unsignedcharRxBuf[24];unsign

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论