用STM32与PID算法做一个磁悬浮装置

发布者:jingyun最新更新时间:2024-04-07 来源: elecfans关键字:STM32  PID算法 手机看文章 扫描二维码
随时随地手机看文章

今天教大家来做一个磁悬浮玩具

1)磁悬浮的基本原理


磁悬浮有下推式和上拉式两种基本形式。

所谓下推式,就是控制部分在底座上,悬浮的磁铁在上面,依靠底座从下往上的排斥磁力推动磁铁悬浮;而上拉式,是控制部分在上面,悬浮的磁铁在下面,依靠控制部分从上方的吸引力吸住磁铁不会落下去。

本文实现的是下推式,仅讲解下推式磁悬浮的原理和实现方法。

如下图,是一个环形磁铁的磁力线:

poYBAGPtjHqAcfHiAAB607ay9y4472.jpg

如果在它上方放置另一个小磁铁,N极向下S极向上,那么它会受到下面的环形磁铁的斥力。越靠近下方的环形磁铁,斥力就越大。当距离合适时,斥力与上方磁铁的重力相等时,就能实现悬浮:

pYYBAGPtjIyARhtRAACXv5KbjBo653.jpg

但是,仅仅依靠两个磁铁的相互作用是不能保持稳定的,因为两个磁铁的斥力只要与重力的方向不在同一直线上,就不能保持平衡,上方的小磁铁就会向旁边飞出去。

而下推式磁悬浮的实现方法,就是在上述的系统里,再增加一个控制上方小磁铁保持在中轴线位置的装置。这样,小磁铁即不能往旁边移动,垂直方向的重力又和磁铁斥力相抵消,就 能实现稳定的悬浮了。

具体实现时,如果没有大环形磁铁,可以使用一圈小磁铁代替,效果是一样,如本文效果图里用的4个、8个都行,但是一定要排布在对称位置。

控制小磁铁位置的装置,一般由霍尔元件和电磁铁组成。用两个霍尔元器件来检测磁场,两个霍尔元件安装在环形磁铁的中心处,且互相垂直,检测面都与铅垂线平行。如果上方的小磁铁在中轴线上,那么系统的磁力线也是铅垂线方向的,两个霍尔元件都无输出;如果小磁铁偏离了中轴线,那么系统的磁力线方向会偏离铅垂线方向,霍尔元件就能检测出往某个方向偏移了。此时,由MCU采集霍尔元件的输出,控制电磁铁,产生一个水平方向相反的磁力,将小磁铁拉回中轴线上就行了。

由于该系统是一个动态平衡的系统,需要不断地采集、判断、调整,最好使用PID控制。

了解了原理,下面就一起实现吧。

2)硬件电路图及调试

由上述的原理讲解,我们的硬件只需要处理好两件事情就行了:一是采集两个相互垂直安装的霍尔元件的输出,以获取小磁铁的偏移位置;二是控制两组相互垂直的电磁铁,产生水平的磁力。

霍尔元件及其信号放大部分,UGN3503是霍尔元器件,电位器提供一个初始的零位电压,霍尔的输出信号通过反向放大后,输出到STM32的AD口采集:

poYBAGPtjLiAUICQAAGuDq4VlL0034.jpg

电磁铁驱动部分,使用L293D电机驱动芯片来驱动电磁铁,L293D由STM32输出的PWM波来驱动:

pYYBAGPtjQaAEAKHAAFjjohISaA560.jpg

电源部分,驱动电磁铁用9~12V的电压比较合适,霍尔供电用5V:

pYYBAGPtjReAAX1UAAEAtnbjWJI801.jpg

因为小白白在DIY的时候STM32是外接的最小系统,所以原理图里没画STM32,只留了几个接点。

注意布局时,霍尔元件和电磁铁的放置位置,有特殊要求。最终的PCB图如下:

poYBAGPtjT-AamelAAMR818IHc8174.jpg

U3和U4是两个检测磁铁位置的霍尔元件,需要安装在环形磁铁中心附近,并且互相垂直;而且霍尔的平面要在相对角电磁铁的连线上。

注意两个霍尔U3和U4的位置:(U5也是个霍尔,本来是预留来检测是否有磁铁放在上面的,暂时没有用上)

LL1~LL4是四个电磁铁,LL1和LL2一组,LL3和LL4一组,安装时,同组的需要对角放置;而且要注意安装时同名端相连,通电后,同组的两个电磁铁磁力线能相互连接产生闭合磁力线(也就是一个上方为N极时同组另一个上方为S极)。这样才能保证同组的电磁铁产生的磁力在水平方向是相同的。

在电路图焊接完成后,与STM32F103C8T6最小系统相连,霍尔的输出AD1、AD2连接到STM32的PA0和PA1;PWM1~4依次连接到STM32的PA15、PB4、PB3、PB5。其他供电部分的连接就不说了。

安装好环形磁铁,上电后,在空载状态下调整U3、U4连接的电位器,使得AD1和AD2都在1.65V左右(也即AD采集时3.3V的中间值)。

到这里,硬件的设计工作就基本完成了。

3)软件编程实现

软件的实现也是大致分为两大功能:一是通过AD采集,获取磁铁再水平方向X、Y轴的位置;二是通过两个方向位置偏移的大小来计算驱动两个方向电磁铁的PWM输出值,这个计算过程使用了PID算法

程序架构是:在主循环里不断地采集霍尔元件的电压,也就是AD1、AD2的值;在中断里计算PID控制算法,设置PWM的输出。

首先在cubemx里配置ADC,打开AD0、AD1和AD4(实际只用了AD0和AD1,AD4是预留的,采集了但是没有用于计算),分别配置到图中的rank1、rank2、rank3下:

poYBAGPtjWWAVh04AAGzqBawSL8696.jpg

使能定时器TIM2中断:

poYBAGPtjXiAVbr4AAIpsa8OZuU356.jpg

到这里,cubemx里的硬件主要配置就完成了。接下来可以生成keil工程,编写软件代码。

在keil工程里,adc部分,使用如下函数进行AD采集,采集了三个通道,即AD0、AD1、AD4:

poYBAGPtjdKABtgDAADOs7SIQqs041.jpg

然后进行滑动平均滤波,这里最终只保留了AD0和AD1两路,10bit的精度,存放到了xPos和yPos中,作为两个方向的位置值。

poYBAGPtjbWALB4qAAFsBYuNV1U755.jpg

filter_adc()函数需要放在主循环中循环调用,不断更新位置值:

pYYBAGPtjaWAeWO6AAB24vbCLig230.jpg

PID部分主要的实现代码如下:
pYYBAGPtjguAdSOTAABkUdyGOuM853.jpg
poYBAGPtjhKAQF0zAAGWhyTbxJI809.jpg

注意这里PID实现时对积分项的处理,当误差的累加值非常大时(也即积分项很大时)不会再累加误差项,而是限制到一个最大值MAX_INTEGRATION_ERROR,这是一种避免积分饱和的方法。(关于PID的积分饱和,可以参见小白白以前发的文章《PID控制的深入探讨(位置式PID、增量式PID、PID的积分饱和)》)

接下来,讲一下如何设置PWM输出值,以及怎么控制电磁铁磁场的正负向。

由于我们使用了L293D芯片来驱动电磁铁,以LL1和LL2这一路为例,当PWM2设置为低电平,则PWM1输出为高时就能驱动电磁铁;当PWM2设置为高电平,则PWM1输出为低时,电流与前述状态相反,就能反向驱动电磁铁。如下图所示:

pYYBAGPtjiSAGvyyAABKVbw9LUU977.jpg

同时,我们只需要改变PWM1的脉宽,就能实现电磁铁的磁场强度控制。

另一路LL3和LL4电磁铁也是一样的原理,可以通过PWM3控制磁场强度,通过PWM4来控制磁场方向。

这部分的实现代码如下,其中PWM1和PWM3的输出值(也就是代码中的xPWM和yPWM),是先通过调用PID计算函数得出值,再依据正负向设置到定时器的PWM输出的,整个函数放在定时器中断中调用。

pYYBAGPtjk6ATeV7AAFzJiRs1ek961.jpg
pYYBAGPtjlSAZOf0AAIYOSEGI_o785.jpg

最后提醒一下,PID的参数值,是需要调整的,这些值与磁铁大小、定时器的控制周期长短都是相关的,本文中的取值如下:

#define P_value 4

#define I_value 1

#define D_value 30

4)一些补充内容

在调试时,可以先拿住小磁铁从上往下移动,当感觉重力被磁力抵消时,再向水平的X、Y方向移动,如果感觉有水平的阻力,那么就成功了一大半了,后面只需要微调参数即可。要注意保护强磁铁,如果两个磁铁不加保护直接吸到一起很可能会被撞碎。

到这里,磁悬浮最基本的功能就做好了,但是还有很多可以优化的地方。

比如现在计算周期用的是2KHz,正好在人的听觉范围内,这在使用时,电磁铁可能会产生一些噪音,可以考虑把控制周期改到20KHz以上,但是要注意PID的参数需要调整。

再比如,多利用一个霍尔元件,可以增加检测载荷的功能,如果没有载荷,可以关闭PWM省电。


关键字:STM32  PID算法 引用地址:用STM32与PID算法做一个磁悬浮装置

上一篇:STM32入门学习笔记之TFTLCD显示实验1
下一篇:STM32代码远程升级之IAP编程

推荐阅读最新更新时间:2024-11-06 11:27

STM32之独立看门狗实验
实验现象: 开始LED1亮,LED2熄灭,若不隔时间按KEY1则发现LED2因独立看门狗的作用使系统复位而不断闪烁,若间断的按KEY1则发现LED2不会闪烁,表明没有复位。 实验平台: 基于STM32F103C8T6的彩屏开发板 操作步骤: 1)向IWDG_KR 写入0X5555。 通过这步,我们取消IWDG_PR 和IWDG_RLR 的写保护,使后面可以操作这两个寄存器。 设置 IWDG_PR 和IWDG_RLR 的值。 这两步设置看门狗的分频系数,和重装载的值。由此,就可以知道看门狗的喂狗时间(也 就是看门狗溢出时间),该时间的计算方式为: Tout=((4×2^prer) ×rlr) /40 其中Tout 为看门狗溢
[单片机]
用于stm32Discovery的图像转代码取模小工具
最近拿着st的官方板子在开发图形界面,看了下代码是直接把整个像素32bit拷贝到控制器中Graphic RAM(就是一块SDRAM)中的,所以以往遇到的生成器都不能用,在内部则又是转换费时费力,占用内存 所以针对stm32的discovery lcd显示写了个图像代码生成的程序,可以直接生成32bit的ARGB格式代码 等后面发一个成熟点的版本,目前还是有些容易遇到的bug
[单片机]
用于stm32Discovery的图像转代码取模小工具
stm32对编码器计数
图和程序(部分)都是前辈留下的,我看了了半天也试了很多次,现在越来越混了,不知道前辈到底是用什么方法在测脉冲,感觉图和程序都有问题,有大神帮忙解释下给点建议吗。我现在脑子全是乱的。
[单片机]
<font color='red'>stm32</font>对编码器计数
STM32的ADC实测
  测试芯片:STM32F103R8T6 (双AD)   编译平台:IAR5.40   测试概述:使用片内振荡器时钟HSI,双ADC同步采样,ADC1采用DMA1存放,ADC2采用直接读取。        每读取十个采样值计数一次,定时一秒钟,通过串口将采样次数送出,测试ADC采样速率。 一、主频设为:56MHz   使用HSI,STM32F103最高频率可达72MHz,主频在56MHz时AD速率最大。   RCC_PLLConfig(RCC_PLLSource_HSI_Div2,RCC_PLLMul_14);   // 8 2 14 = 56MHz 二、ADC工作频率:14MHz   RCC_ADCCLKConfig(RC
[单片机]
<font color='red'>STM32</font>的ADC实测
STM32—FMSC详解
这个是从网上找到的,内容如下: STM32 FMSC LCD难点解析: 以下是网上和自己整理的:感觉应该可以把STM32 ----FSMC LCD中的关键RS说清楚~ ---------------------------------------------------------------------------------------------------------------------- 第一个角度理解STM32有FSMC(其实其他芯片基本都有类似的总线功能),FSMC的好处就是你一旦设置好之后,WR(写)、RD(读)、DB0-DB15这些控制线和数据线, 都是FSMC自动控制的。打个比方,当你在程序中写到:
[单片机]
stm32 IAP 实现
在对STM32存储器结构及相关知识了解后,我们就可以进行IAP的设计了。 在上一篇笔记中,进行了一个简单的IAP程序结构,以及和User App程序的相互联系的系统设计。 本篇对IAP实现的细节进行了较为详细的论述,包括源码结构的设计;我们从上位机(PC C#)和下位机(MCU C)共同描述IAP功能的实现过程。 1 STM32的IAP实现平台 IAP功能的实现需要两个方面(上位机和STM32上的IAP程序)的密切合作。因此,我们除了需要知道STM32芯片上的IAP程序结构,我们还需要了解上位机的程序结构,这样才能使上位机和STM32很好的相互工作。 下位机(指的是STM32构成的单片机系统): 本下位机系统使用C语言
[单片机]
<font color='red'>stm32</font> IAP 实现
STM32自学笔记(一)GPIO配置与使用
由于是stm32学习的第一个章节,会啰嗦一些,旨在帮助和我一样刚接触stm32时一头雾水的朋友,更好地理解、学会它。 很多学过51,刚开始学stm32的朋友可能会和我一样十分不适应,在我看来,stm32与51代码最大的区别在于,stm32几乎所有外设都要进行配置过后才能使用,比如说你想操作一个IO口,那么首先要对这个IO口所挂载的时钟进行使能,再对此IO口进行配置、使能。这也是为什么51点亮一个LED只需要一行代码,你找到的stm32的代码却看着都让人头大的原因。 为什么要进行初始化(配置)?就GPIO来说,51的IO口很简单,能且只能实现高低电平的输入输出;而stm32可以在此基础上,指定GPIO输入输出的类型,速率
[单片机]
STM32之三通过串口想PC机打印信息
作为基本的通信手段,串口通信操作简单,使用方便,在几乎各种单片机芯片上都具备,我们今天就是要学着操作下stm32的串口,使之能与pc简单的通信,我们实现向PC机发送字符程序 像往常一样,我们首先要建立两个文件,即uart.c和uart.h文件,下面来看下我们来看看串口配置,直接上程序 void uart_init(u32 bound) { // NVIC_InitTypeDef NVIC_InitStructure;//建立各自的对象,然后对各自进行初始化 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; //串口使能USAR
[单片机]
<font color='red'>STM32</font>之三通过串口想PC机打印信息
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved