Arduino案例实操 -- 磁悬浮套件(上推式)_上推式磁悬浮电路图-程序员宅基地

技术标签: arduino磁悬浮  arduino小项目  磁悬浮项目  从Arduino开始起飞  

磁悬浮装置,是由转子、传感器、控制器和执行器4部分组成,其中执行器包括电磁铁和功率放大器两部分。假设在参考位置上,转子受到一个向下的扰动,就会偏离其参考位置,这时传感器检测出转子偏离参考点的位移,作为控制器的微处理器将检测的位移变换成控制信号,然后功率放大器将这一控制信号转换成控制电流,控制电流在执行磁铁中产生磁力,从而驱动转子返回到原来平衡位置。因此,不论转子受到向下或向上的扰动,转子始终能处于稳定的平衡状态。


一、工作原理

ok,长话短说,在arduino上实现磁悬浮的现象,依靠悬浮底座的霍尔传感器收集的磁场变化,控制底座的线圈的电流流动,以此来稳定悬浮转子的在x、y轴的悬浮居中状态。
磁悬浮原理
在控制程序中涉及到PID的控制,可以调整底座对转子的牵引灵敏度,及牵引力度等;但这不是我们做磁悬浮要研究的重点,运用默认的PID设置已经足够控制转子的稳定性了,有兴趣且不懂PID的小伙伴不用因此望而却步。


二、套件组成

在上面大致说明了磁悬浮装置的硬件组成, 在制作过程中,主要分两个方面:

1、控制组件
  • 控制组件位于套件底部,是磁悬浮套件的核心组成部分
  • 通过基础的两组(4个)磁铁或多组磁铁摆放成一个圆形磁场,以及能控制磁场稳定性的电磁铁(线圈)
  • 磁铁分南北极两级,同级相斥,异级相吸的道理大家都懂,以相同磁极的朝向摆放即形成了一个向上推的圆形磁场
  • 电磁铁以四方形对角方式摆放,用于控制磁场以改变磁场位置,对角的电磁铁磁场朝向彼此相反
  • 控制组件板载霍尔传感器负责监控磁场变化,信号经电路放大后(程序)调整输出到电机驱动板,驱动板则是控制电磁铁改变磁场位置来保证磁场的稳定
2、悬浮组件
  • 转子一般由磁铁构成,可浮起的磁铁数量重量由控制组件板载磁铁相斥力的大小决定,转子磁场朝向与控制组件朝上磁场相同

三、材料清单

这一步比较考动手能力,提供一个套件材料清单,准备好各种材料工具再动手,加油!

1、模块/元器件
  • LM324N * 1
  • 电磁铁(悬浮线圈) * 4
  • AH3503线性霍尔传感器 * 3
  • M3沉孔环形磁铁 D12 x 3mm * 16
  • 圆形磁铁(转子) D25 x 3mm * 3
  • 圆形磁铁(转子) D20 x 3mm * 1
  • M3平头螺丝15mm * 4
  • M3螺母 * 4
  • 洞洞板/面包板 * 1
  • L298N电机驱动模块 * 1
  • 7.5V/12V DC电源适配器 * 1
  • DC电源插座 * 1
  • 贴片/直插 电阻 5.6k * 2
  • 贴片/直插 电阻 47k * 2
  • 贴片/直插 电阻 180k * 2
  • 10k电位器 * 2
  • 圆规 * 1
  • 常见2.54排针若干
  • 常见2.54母对母杜邦线若干
  • 红/黑导线若干

LM324N为运算放大器,负责对霍尔输入信号进行放大
悬浮线圈可以直接在某宝买现成的,有专门卖磁悬浮线圈的
洞洞板和面包板主要用于接插霍尔传感器和放大电路的,看个人条件选择其一即可
杜邦线和排针为接线必备的,杜邦线母对母、公对母、公对公都准备些备用
案例中所用到的磁铁都是强磁,小心操作,很容易给夹淤血甚至夹出血

2、焊接工具
  • 电烙铁
  • 焊锡
  • 示波器/万用表
  • 热熔胶/胶枪
  • 螺丝刀
  • 剪线钳
  • 锯子

示波器用于测霍尔传感器波形,也可用万用表代替
胶枪固定布线及固定电磁铁摆放之类的
磁铁固定和电位器调教,电机驱动板接线都需要用到螺丝刀(一字和十字螺丝刀)
如果用洞洞板焊接元器件需要用到锯子来裁剪洞洞板的大小


四、DIY安排上
1、设计磁场组件板

磁场组件板即安放电磁铁、悬浮磁铁,霍尔传感器的平台,基本不需要去做PCB板,DIY只要将引出几个几口,包括霍尔传感器的供电(5V,GND),3个霍尔传感器的模拟输出(Hx,Hy,Hz),以及控制4个电磁铁磁场变化的接口

  • 有条件的娃建议设计PCB来做,接口以杜邦线引出,可以省去很多接线的烦恼
  • 不会画板的娃可以做建模软件设计组件板,然后转成切片软件去做3D打印,也是蛮方便的,不过接口牵线焊接做固定
  • 最后,考虑到你可能不会画板也不会建模,更不想花钱去找别人帮忙做,那么就来做手工吧,找个硬纸板来自己DIY吧,计算好孔位做裁剪,有钻子的可以考虑用薄木板做,还是多少要点硬度的
  • 分享一个博主自己建模打印的组件板(想用白色料做的,哪知打印机装的黑色料,但是不影响效果),电磁铁位置设计了围边来固定电磁铁位置,中间带螺丝孔可以用螺丝固定电磁铁,因为可能跟你们现实采购的磁铁及电磁铁直径存在差异,所以这里不分享板上的螺丝孔位数据,避免误导
    在这里插入图片描述
    在这里插入图片描述
    组件板说到画板及建模是考虑摆放位置的设计和孔位的距离,手工划线的话记得使用直尺圆规等工具辅助
    板上预留孔位为固定磁铁的正方形螺丝孔位(4组磁铁为正方形摆放,孔位直径比螺丝直径稍大即可)
    电磁铁安装位置与磁铁孔位相间,对角两个电磁铁之间距离控制再2cm以内(非电磁铁圆心距离),避免电磁铁距离过远影响磁场控制效果
2、电磁铁布置

组件板准备好后,可以开始放置电磁铁了,所谓电磁铁,也就是我们买回来的4个线圈,当铜线绕成圆柱状的线圈通上电流之后,自然就成了一个电磁铁了(不懂的去复习一下初中物理)
将线圈固定好在组件板上预留的位置,用螺丝螺母把线圈固定住,记得将线圈引出来的两根铜线头朝向组件板圆心部位,通过组件板圆心孔对应的线槽位牵引至组件板底部,方便后续的接线,固定好的电磁铁实物图可以参照下面图片(电磁铁外圈逆时针朝上放置固定(见图)
在这里插入图片描述

3、霍尔元件焊接

这一步,准备好你们手头的霍尔传感器,要开始练练焊接了
找个万用板裁剪成组件板中间孔位大小,并确保你裁剪好的万用板上的铜片为够你焊接3个霍尔传感器,即至少要有9个铜片孔位。
首先,先来认识一下霍尔传感器

在磁性传感器中,利用霍尔效应的传感器称为霍尔传感器。霍尔传感器包括几个部分。首先,它包含一个霍尔元件,该霍尔元件输出通过霍尔效应产生的霍尔电压(HV)。其次,它包含一个霍尔IC,该霍尔IC使霍尔输出通过IC工艺变为高/低数字输出。第三,它包含一个线性霍尔IC,可放大并线性化霍尔输出。

霍尔传感器多为一个扁平状直插式元器件,以带丝印一面的引脚功能分别是VCC、GND、H-OUT,切记不要接错线了
在这里插入图片描述
霍尔传感器用于测试磁场时焊接应将传感器检测面垂直于磁场方向,即当我们把4个电磁铁的摆放位置分为X轴和Y轴时,我们需要在X、Y轴的原点处放置2个霍尔传感器来分别检测X轴及Y轴的磁场变化,示意图如下,将4个电磁铁标记为X+、X-、Y+、Y-,并将X轴及Y轴磁场用蓝线标记出来,霍尔传感器的焊接如图中X、Y交叉点红色小框框的摆放,竖放的霍尔传感器检测X轴磁场,横放的霍尔传感器检测Y轴磁场,两个霍尔传感器尽可能的往XY原点处凑,并且检测面尽量与磁场方向垂直(X轴/Y轴),确保良好的磁场检测效果
在这里插入图片描述
实际的传感器布置图如下
在这里插入图片描述
霍尔传感器除了检测面位置跟所检测的磁场线垂直外,还要注意一下传感器焊接的高度,传感器检测面高度尽量保持在电磁铁高度的中心,且靠近磁场中心,这样可以提高磁场检测的效率
在这里插入图片描述
在这里插入图片描述
眼尖的小伙伴可能注意到了传感器检测板上还有一个检测面朝上的霍尔传感器,这个霍尔传感器的作用是检测上方是否放置了转子的,我们把它定义为Z轴的霍尔磁场检测;同样的,Z轴传感器的摆放也有要求,需要折弯引脚将检测面水平放置,避免X、Y轴磁场对其检测有干扰,检测面高度为电磁铁高度的一半,且尽量靠近磁场中心点,保障磁场有效检测
传感器检测板背面的跳线焊接尽量美观,引出5V、GND引脚,和X、Y、Z轴输出脚到排针上,可在接线口附近贴上标签做线序标识,方便后面用杜邦线接线
在这里插入图片描述
有洞洞板的可以直接将霍尔传感器插洞洞板上, 省去焊接烦恼,这个我没试过,应该可行,但对于供电或者输出读取的貌似比较难布线,各尽其才吧,高度也需要根据电磁铁高度进行调整

4、放大电路焊接

在组件板上引出X、Y轴的霍尔磁场输出后(Z轴输出不需要放大),焊接放大电路,准备好你的LM324N和必要的电阻、10k电位器和排针,重新找个万用板,按照下面的电路接线图焊接,好消息是,这次的板子不需要裁剪,找个能满足放大电路布线的板子就行,基本5 * 5 左右就欧了
在这里插入图片描述
尽量找到相应的电阻来焊接电路,没找到一样阻值的用比较接近的电阻也可,直插式电阻会更方便焊接,贴片电阻就有点靠技术了
需要注意LM324N是12V供电,10k电位器额外的5V供电,需要共地
图中 OUTPUT 引脚接入UNO板的模拟输入,INPUT 引脚接霍尔传感器的输入引脚

下面是个人的放大电路焊接板,找个万用板插上芯片电阻电位器就欧了,稍微考验个人焊接能力,对自己焊接能力没信心的可以用洞洞板插直插式引出供电跟X、Y轴输入输出引脚也可,引脚都在图片上有标明,也可贴小标签注明引脚免得接错,注意区分开5V及12V
在这里插入图片描述
接着是背面展示,可以采用焊盘连锡的方式代替部分接线
在这里插入图片描述

5、驱动电路连接
a - L298N模块接口说明

关于驱动电路,不需要焊接,上面提到了L298N电机驱动模块,希望你已经在某宝上买到了,记得不要买成芯片了,L298N电机驱动模块如下,接口都给标记了
在这里插入图片描述

  • 电源/地:不用多说吧,两路电压输入(12V和5V),5V 可以直接在UNO上牵线过来,12V从电源适配器处获得,地线要注意了,电机驱动板的电源地需要跟放大电路和UNO共地
  • 板载5V输出使能:控制板载的5V输出,保持跳帽连接
  • 马达A输出:out1、out2接电磁铁X轴或Y轴(实验中用于X轴控制)
  • 马达B输出:out3、out4接电磁铁X轴或Y轴(实验中用于Y轴控制)
  • A通道使能:用于使能马达A口输出的引脚,到货默认接跳帽(实验中需要拔掉跳帽,连接UNO I/O口,由UNO控制X轴电磁铁输出)
  • B通道使能:用于使能马达B口输出的引脚,到货默认接跳帽(实验中需要拔掉跳帽,连接UNO I/O口,由UNO控制Y轴电磁铁输出)
  • 单片机IO控制输入:4个输入引脚,分别由UNO的4个I/O来控制out1、out2、out3、out4引脚的输出电压大小,即电机驱动模块接的马达的话是控制马达的转速快慢(实验中由UNO4个I/O来控制X轴、Y轴两对电磁铁对转子的拉扯力度大小)
b - 电磁铁同轴串连

不管你是自己杠出来的线圈还是买来的,必定都会将电磁铁线圈两端引出来,譬如下图,能清晰的看到线圈一端由内圈引出,另一端则是最外圈引出(记住这两根线,后面要考)
在这里插入图片描述
当把电磁铁固定在组件板上时,X轴Y轴两组线圈两端都从中间的万用板处引到了组件板底部,附上组件板正面图一张,要特别注意一点,每个电磁铁两端引到底部后,要区分好哪根是电磁铁内圈哪根是电磁铁外圈的(可以外圈靠左,内圈靠右加强辨识,如霍尔元件焊接步骤的最后一张图)
在这里插入图片描述
到了组件板底部,上一步区分好的电磁铁内外圈的端头,这时候要开搞了,将对角的电磁铁内圈的引出端头焊接到一起,即X轴的两电磁铁内圈焊一起,Y轴两电磁铁内圈焊一起,焊好就像一个交叉十字路口一样,注意XY两轴的焊接点不要触碰到一起去(emmm垫个纸巾方便看,有漆皮的话需要刮掉线圈漆皮才能上到锡)
在这里插入图片描述
接着,每个电磁铁就剩外圈的端头空着了,用8pin 2.54单排针剪成4段2pin排针(或8pin的双排针剪成4段2pin双排也可),以侧躺的方式用热熔胶固定在4段电磁铁外圈端头附近(需要确保外圈端头可碰到排针短针头一侧),将电磁铁外圈端头焊接在各自对应的排针上,确定没虚焊后把焊接点也上胶,上图参考(emmm博主好像摆成了“卍”字了,可根据个人需要改变排针朝向,但焊接线路部分不变)
在这里插入图片描述
到这电磁铁的焊接也都顺利完成了,电磁铁外圈预留的排针接口,用于L298N电机模块来驱动每个电磁铁

c - 综合接线

花了些时间画了实物连接线,没有专门的连线工具可真头疼,电磁铁 + 驱动板 + 放大电路 + UNO控制器都安排上了(此处该有掌声!!!)
在这里插入图片描述

  • 电磁铁同轴内圈相连,外圈同轴接驱动板同侧(即X轴两外圈接驱动板out1,out2,Y轴两外圈接驱动板out3,out4)
  • 霍尔传感器,X轴检测霍尔的输出接放大电路X输入引脚(Y轴同),Z轴检测霍尔的输出直接接UNO模拟引脚(具体见程序部分)
  • 驱动板5V引脚可为UNO,放大电路电位器部分供电,L298N与LM324放大芯片同为12V供电,三部分电路(驱动板、放大电路与UNO需共地)
  • 放大电路XY轴霍尔输出引脚接UNO模拟引脚

套件中的供电线(5V、12V)及地线可以采用杜邦线来改造,或其他适当的电线都可,不要用过于细小的导线当供电线,粗细可跟杜邦线做对比,或直接使用杜邦线
图中驱动板引脚(IN1~IN4,ENA,ENB)与UNO连接部分以程序中指定引脚为准,图中连线只做连接部位示意,切勿踩坑

在这里插入图片描述
接线后稍微有点犯尴尬癌,等后期做成产品包装了再对接线做优化。

6、控制程序上传
a - Z轴霍尔读取

先不着急烧写完整程序,在上一步的套件接线可以发现组件板上的三个霍尔传感器,XY轴霍尔传感器输出都接到放大电路中,只有Z轴霍尔输出直接接UNO模拟输入引脚,先写小段程序读取Z轴霍尔传感器的输入值

void setup()
{
    
	pinMode(A0, INPUT);		//配置A0(Z轴霍尔传感器)为输入
	Serial.begin(115200);	//配置串口波特率115200
}

void loop()
{
    
	//间隔读取Z轴霍尔读数
	Serial.println(analogRead(A0));		
	delay(1000);
}

Z轴霍尔传感器在套件中的作用为检测磁悬浮套件上方是否放置了转子,从而切换磁悬浮套件为工作状态或是休眠状态
磁悬浮套件工作时,需要控制L298N电机驱动模块来改变XY轴电磁铁的磁场强弱,长时间工作会造成驱动芯片及电磁铁发烫严重,如果你的电磁铁不是螺丝固定,用的热熔胶固定的话电磁铁产生的热量足以融化热熔胶造成电磁铁移位磁场不稳定,所以想想Z轴霍尔的存在还是有点道理的
下面看一下Z轴霍尔的串口输出数据
在这里插入图片描述
当组件板上方不放置转子时,Z轴霍尔的输入数值在550附近,将转子从高处慢慢放置到组件板上方,可观察到霍尔数值开始变小,最后是处在低于300的数值,这时我们可以通过判断Z轴霍尔输入值来断定磁悬浮套件是否有放置转子

b - 转子

有必要介绍一下转子,转子即磁悬浮套件上方悬浮的磁铁组合,一般由3个D25磁铁跟1个D20磁铁组成,在某宝上都能买到
在这里插入图片描述
D20即磁铁直径20毫米(D25同理),后方 * n为磁铁厚度n毫米
D20磁铁厚度3毫米的也可,emmm博主本来买的3毫米的然后是缺货才用的2mm
在实际转子放置中,D20磁铁的一面朝下

套件中所用磁铁都为强磁,磁性高吸附性强,因此在将磁铁组拆分及组合时要格外小心,避免磁铁之间因磁性相吸造成强烈碰撞,可造成磁铁的破裂及缺损
另外拆分磁铁时也需多注意,强磁的力度足以将手指肉夹出血(…博主亲身经历)

c - 磁悬浮简化代码

在确定接线无误跟转子准备好过后,可以开始为UNO烧写程序进行套件测试,代码中穿插了PID调节

#include <PID_v1.h>		//PID库

#define IN1 6
#define IN2 5
#define IN3 4
#define IN4 3
#define ENA 10
#define ENB 9
#define BL 13			//转子指示灯

//PID基本参数定义
double Setpoint_X, Input_X, Output_X,X_plus;
double p_X = 1,i_X = 0,d_X = 0.01;
double Setpoint_Y, Input_Y, Output_Y,Y_plus;
double p_Y = 1,i_Y = 0,d_Y = 0.01;

//转子状态flag
int on_put;

/**************************************************
*				PID初始化函数
*PID(&Input,&Output,&Setpoint,Kp,Ki,Kd,Directiion)
*参数:		(double)
*Input:		输入参数,待控制的量
*Output:	输出参数,经过PID控制系统的输出量
*Setpoint:	目标值
*Kp,Ki,Kd:	PID控制的比例、积分、微分系数
*Direction:	DIRECT或REVERSE,指的是当输入与目标值出现偏差时,向哪个方向控制
**************************************************/
PID PID_X(&Input_X, &Output_X, &Setpoint_X,p_X,i_X,d_X, DIRECT);
PID PID_Y(&Input_Y, &Output_Y, &Setpoint_Y,p_Y,i_Y,d_Y, DIRECT);

//X轴电磁铁调节函数
void turn_X(int a)
{
    
	if(a>=0)
	{
    
		digitalWrite(IN1,1);
		digitalWrite(IN2,0);
		analogWrite(ENA,a);
	}
	else
	{
    
		a=-a;
		digitalWrite(IN1,0);
		digitalWrite(IN2,1);
		analogWrite(ENA,a);
	}
}

//Y轴电磁铁调节函数
void turn_Y(int a)
{
    
	if(a>=0)
	{
    
		digitalWrite(IN3,0);
		digitalWrite(IN4,1);
		analogWrite(ENB,a);
	}
	else
	{
    
		a=-a;
		digitalWrite(IN3,1);
		digitalWrite(IN4,0);
		analogWrite(ENB,a);
	}
}

//setup function
void setup()
{
    
	//IN1 - IN4,ENA,ENB,BL均为OUTPUT模式
	pinMode(IN1,OUTPUT);
	pinMode(IN2,OUTPUT);
	pinMode(IN3,OUTPUT);
	pinMode(IN4,OUTPUT);
	pinMode(ENA,OUTPUT);
	pinMode(ENB,OUTPUT);
	pinMode(BL,OUTPUT);

	//初始化引脚电平
	digitalWrite(IN1,0);
	digitalWrite(IN2,0);
	digitalWrite(IN3,0);
	digitalWrite(IN4,0);
	analogWrite(ENA,0);
	analogWrite(ENB,0);

	Serial.begin(115200);				//串口波特率115200,用于套件状态打印

	Setpoint_X = 560;					//560 设定霍尔传感器的指定模拟值560 
	Setpoint_Y = 560;					//约等于2.5V,上电后由电位器微调

	PID_X.SetTunings(p_X,i_X,d_X);		//设定P、I、D参数,在运行周期内做调整
	PID_Y.SetTunings(p_Y,i_Y,d_Y);
	PID_X.SetOutputLimits(-255,255);	//指定输出范围,最大值、最小值都为double型
	PID_Y.SetOutputLimits(-255,255);
	PID_X.SetSampleTime(5);				//PID采样周期,单位毫秒,默认为5
	PID_Y.SetSampleTime(5);
	PID_X.SetMode(AUTOMATIC);			//设置PID运算为自动模式
	PID_Y.SetMode(AUTOMATIC);

	Serial.println("CXF Ready");		//套件初始化完成
}

void loop()
{
    
	//获取经放大电路后的XY轴霍尔数值
	Input_X = analogRead(A1);
	Input_Y = analogRead(A2);

	//读取Z轴霍尔数值判断是否放置了转子
	if(analogRead(A0)<500)
	{
    
		digitalWrite(BL,1);
		on_put=1;
	}
	else
	{
    
		digitalWrite(BL,0);
		on_put=0;
	}

	//切换套件为工作状态或休眠状态
	if(on_put)
	{
    
		//调用PID控制
		PID_X.Compute();
		PID_Y.Compute();

		//调整XY轴
		turn_X(Output_X+X_plus);
		turn_Y(Output_Y+Y_plus);

	}
	else
	{
    
		turn_X(0);
		turn_Y(0);
	}
}

代码中使用到PID库,XY轴PID参数默认为1,0,0.01使套件控制处于比较稳定的状态,不用修改PID参数(别给自己挖坑)
IN1 - IN4可接普通数字IO,ENA,ENB必须接PWM引脚,按这个要求选择引脚即可,不必跟着代码中的引脚
代码中有个地方需要根据实际测试做修改,即UNO模拟引脚A0的霍尔读取数值,如果不放置转子时读数在500以上,可与代码中判断条件相同 if(analogRead(A0)<500) ,判断条件为放置转子后的数值区间,在第8-b步骤磁场转子磁极调试时可能还需要进行判断条件调整,可以先看8-b步骤做了解避免踩坑,这里就不啰嗦了

把程序烧写进UNO后可以做简单的测试,即将转子移到组件板霍尔传感器上方,观察UNO板载灯L是否亮起,正常状态为放置转子灯亮,拿走转子灯灭,如果测试结果不符合的各自检查代码中A0引脚的数值判断部分
测试正常的小伙伴可以进入下一步了

7、电磁铁综合调试

还没讲到电磁铁与驱动板的实际接线,就先别自己瞎搞了,现在跟着博主来动手。相信你已经将自己的两组电磁铁分好了X轴和Y轴了,继续附个综合接线图瞅瞅
在这里插入图片描述

a - X轴电磁铁调试

可见X轴两电磁铁分别接驱动板的out1和out2口,先不纠结哪个电磁铁接哪个out口,用杜邦线随机一个X轴电磁铁接out1/out2任意一个口,然后把另一根线也接上,如下图粉色线,把两根线连上
在这里插入图片描述
切记,只接X轴电磁铁,Y轴不接,针对X轴独立调试
这会儿接上你的12V电源,电流需要有2A以上,这里还是要全部接线没问题的前提下,拿着转子(放置转子时L灯亮)在组件板中间(霍尔传感器上方),朝着X轴两个电磁铁的方向移动,去感觉电磁铁对转子存在着拉力还是斥力
如果X轴两个电磁铁对转子存在斥力将转子推到组件板中间位置,那么接线是正确的不用改动
如果X轴两个磁铁都将转子吸附过去,那么交换两个电磁铁连接的杜邦线,注意驱动板out1,out2的杜邦线连接保持不变!!!再测试会发现原先的电磁铁吸引转子变成了电磁铁对转子的斥力,这时候接线为正确的
在这里插入图片描述

b - Y轴电磁铁调试

Y轴电磁铁调试方式如同X轴调试,需注意地方如下

  • Y轴也是独立调试(先标记X轴电磁铁接线颜色,再拔掉X轴接线测试Y轴)
  • Y轴电磁铁接驱动板out3,out4口
  • 同样的用转子测试Y轴电磁铁的拉力或者斥力,为拉力的话交换电磁铁接线,为斥力的话固定Y轴电磁铁接线
8、完善悬浮磁场

注意了,离套件完成就差最后一步了,hold住!!!
如果说第7步电磁铁是将转子往套件中心位置推的话,那么M3沉孔环形磁铁,就是将转子顶起来实现“悬浮”的

a - 环形磁铁组装

环形磁铁一般是12片,分四组即每组是3片,参数见上面材料清单
在这里插入图片描述
正常来说环形磁铁组的高度需跟电磁铁相同高度,但因为环形磁铁为强磁,4组环形磁铁组每组3片便能撑起转子,并使转子处于电磁铁能驱动的高度范围(每组增加到4片环形磁铁将会把转子高度“悬浮”的更高,使转子脱离电磁铁的控制范围,无法实现磁悬浮功能
在这里插入图片描述
以同样的方式将4组环形磁铁用长螺丝固定在组件板上,10cm的沉头螺丝长度就够用了,在背面也不会因为螺丝太长影响布线
在这里插入图片描述

b - 转子磁极调试

好了,苦逼的调试工作正式开始,磁悬浮套件的组件板器件组装已经全部完成,上面的电磁铁或环形磁铁组就不要再做挪动操作了
在套件上电之前将转子(D20朝下)在拿到任意一个环形磁铁组正上方,测试转子朝向磁极朝向是否正确,有以下两种情况

1.转子与环形磁铁组相斥
这时候就要对3个地方做调整了(emmm很不幸博主踩雷了):

  • 反转转子朝下的磁极,同样的将D20磁铁放转子磁铁组的最底下
  • 交换X轴两电磁铁接线,交换Y轴两电磁铁接线(参考第7步电磁铁调试)
  • 容易忽略的地方,重新检测A0的霍尔读取值,并将放置转子时的读取区间同步到代码中

2.转子与环形磁铁组相吸
如果转子与磁铁组相吸,那么很幸运可以直接进行下一步调试

c - XY轴电磁铁磁场校准

保持现有配置进行套件上电,拿着转子到组件板正中间感受是否有环形磁铁组向上的斥力(转子在组件板正中间可感受到环形磁铁组的斥力,无法将转子放到环形磁铁组高度以下的地方,所以转子被“悬浮”起来;转子与环形磁铁组横向的力为吸引力,“浮起来”的转子容易被4个环形磁铁组吸过去),及XY轴电磁铁将转子往组件板中心推动的斥力,与描述不符的可照前面步骤检查是否配置出错或接线松动
这时候的转子为浮空状态,但还需要对XY轴电磁铁进行磁场校准(例如X轴电磁铁,虽然都是将转子往中间推,但是未经校准的两个电磁铁推力一大一小,即转子不在X轴正中位置,Y轴同理),转子稍微偏离一点组件板正中心就很容易被环形磁铁给吸走
分以下几步校准电磁铁磁场

  • 准备螺丝刀,咱需要转动放大电路板上的XY轴电位器来校准磁场
  • 用左手食指及拇指在组件板中心位置围个圈,随后将转子放置在组件板上方,可直接松开转子(此操作为了避免转子与环形磁铁组相吸发生碰撞造成磁铁破裂),也可用一些刚好大小的圆圈制品来挡住转子与环形磁铁相吸,但切记不要用金属制品,咱可是在调试磁场呢(博主用3D打印了适当大小的空心圆柱,用热熔胶固定在电磁铁上,来圈住躁动的转子)
    在这里插入图片描述
  • 老方法,单轴独立调试,先校准X轴电磁铁,用螺丝刀慢慢转动X轴的电位器,观察转子在X轴上的移动方向,注意一定要慢,如果转子在X轴上越来越偏离中心位置,那么X轴电位器往另一方向转动,直到目测转子稳定在X轴中心位置就欧了
  • Y轴同理,将转子在Y轴上校准至中心位置

这会儿可以把围着转子的手拿开了,磁悬浮套件校准完毕,没错你已经顺利毕业了

注意!
关于你们需要的PID_v1头文件,资源链接在这,带完整代码,头文件,以及磁悬浮控制板原理图
博文磁悬浮资料包下载


五、相关知识补充及调试拓展
1.电磁铁便携调试手段

博文中电磁铁的磁场调节主要通过微调XY轴的电位器来实现转子的磁场平衡,也可在代码中加入串口处理,通过串口输入指令对XY轴霍尔参考值进行微调的形式来平衡XY轴电磁铁磁场(与上述第8步骤为同样的磁场调试手段)
代码在网上大部分地方都能下载到,下面为完整磁悬浮+串口调节代码,读者按各自磁悬浮套件情况可做修改调整

#include <PID_v1.h>

#define IN1 6
#define IN2 5
#define IN3 4
#define IN4 3
#define ENA 10
#define ENB 9
#define BL 13

// extern uint8_t SmallFont[];
// extern uint8_t MediumNumbers[];
// extern uint8_t BigNumbers[];

double Setpoint_X, Input_X, Output_X,X_plus;
double p_X = 1,i_X = 0,d_X = 0.01;
double Setpoint_Y, Input_Y, Output_Y,Y_plus;
double p_Y = 1,i_Y = 0,d_Y = 0.01;

int on_put;

// unsigned long time;

/**************************************************
*				PID初始化函数
*PID(&Input,&Output,&Setpoint,Kp,Ki,Kd,Directiion)
*参数:		(double)
*Input:		输入参数,待控制的量
*Output:	输出参数,经过PID控制系统的输出量
*Setpoint:	目标值
*Kp,Ki,Kd:	PID控制的比例、积分、微分系数
*Direction:	DIRECT或REVERSE,指的是当输入与目标值出现偏差时,向哪个方向控制
**************************************************/
PID PID_X(&Input_X, &Output_X, &Setpoint_X,p_X,i_X,d_X, DIRECT);
PID PID_Y(&Input_Y, &Output_Y, &Setpoint_Y,p_Y,i_Y,d_Y, DIRECT);

// char inByte='9',nullByte,run_flag,run_dirict;
// float go_step;

void turn_X(int a)
{
    
	if(a>=0)
	{
    

		digitalWrite(IN1,1);
		digitalWrite(IN2,0);
		analogWrite(ENA,a);
	}
	else
	{
    
		a=-a;

		digitalWrite(IN1,0);
		digitalWrite(IN2,1);
		analogWrite(ENA,a);
	}
}

void turn_Y(int a)
{
    
	if(a>=0)
	{
    
		digitalWrite(IN3,0);
		digitalWrite(IN4,1);
		analogWrite(ENB,a);
	}
	else
	{
    
		a=-a;
		digitalWrite(IN3,1);
		digitalWrite(IN4,0);
		analogWrite(ENB,a);
	}
}


void setup()
{
    
	pinMode(IN1,OUTPUT);
	pinMode(IN2,OUTPUT);
	pinMode(IN3,OUTPUT);
	pinMode(IN4,OUTPUT);
	pinMode(ENA,OUTPUT);
	pinMode(ENB,OUTPUT);
	pinMode(BL,OUTPUT);

	digitalWrite(IN1,0);
	digitalWrite(IN2,0);
	digitalWrite(IN3,0);
	digitalWrite(IN4,0);
	analogWrite(ENA,0);
	analogWrite(ENB,0);

	Serial.begin(115200);

	Setpoint_X = 560;					//560 设定霍尔传感器的指定模拟值 560 约等于 2.5V
	Setpoint_Y = 560;					//560;

	PID_X.SetTunings(p_X,i_X,d_X);		//设定P、I、D参数,在运行周期内做调整
	PID_Y.SetTunings(p_Y,i_Y,d_Y);
	PID_X.SetOutputLimits(-255,255);	//指定输出范围,最大值、最小值都为double型
	PID_Y.SetOutputLimits(-255,255);
	PID_X.SetSampleTime(5);				//PID采样周期,单位毫秒,默认为10
	PID_Y.SetSampleTime(5);
	PID_X.SetMode(AUTOMATIC);			//设置PID运算为自动模式
	PID_Y.SetMode(AUTOMATIC);

	Serial.println("CXF Ready");
}

void loop()
{
    
	// while (Serial.available() > 0)
	// {
    
	// 	nullByte= char(Serial.read());

	// 	if(nullByte == 'w')
	// 	{
    
	// 		Setpoint_X+=10;
	// 		//inByte =Serial.read();
	// 	}
	// 	else if(nullByte == 'q')
	// 	{
    
	// 		Setpoint_X-=10;
	// 	}
	// 	else if(nullByte == 's')
	// 	{
    
	// 		Setpoint_Y+=10;
	// 	}
	// 	else if(nullByte == 'a')
	// 	{
    
	// 		Setpoint_Y-=10;
	// 	}
	// 	else if(nullByte == 'o')
	// 	{
    
	// 		run_flag=!run_flag;
	// 		run_dirict = 1;
	// 		Setpoint_X=560;
	// 		Setpoint_Y=560;
	// 	}
	// 	else if(nullByte =='p')
	// 	{
    
	// 		run_flag=!run_flag;
	// 		run_dirict = 0;
	// 		Setpoint_X=560;
	// 		Setpoint_Y=560;
	// 	}
	// 	else if(nullByte =='x')
	// 	{
    
	// 		nullByte=char(Serial.read());

	// 		if(nullByte>20)
	// 		{
    
	// 			inByte=nullByte;
	// 			Setpoint_X = 10*(inByte-'0')+480;
	// 		}

	// 		nullByte=char(Serial.read());

	// 		if(nullByte>20)
	// 		{
    
	// 			inByte=nullByte;
	// 			Setpoint_Y = 10*(inByte-'0')+480;
	// 		}
	// 	}

	// 	if(Setpoint_X>575)
	// 		Setpoint_X=575;

	// 	if(Setpoint_Y>575)
	// 		Setpoint_Y=575;

	// 	if(Setpoint_X<480)
	// 		Setpoint_X=480;

	// 	if(Setpoint_Y<480)
	// 	Setpoint_Y=480;

	// 	nullByte ='?';

	// }

	Input_X = analogRead(A1);
	Input_Y = analogRead(A2);

	if(analogRead(A0)>520)
	{
    
		digitalWrite(BL,1);
		on_put=1;
	}
	else
	{
    
		digitalWrite(BL,0);
		on_put=0;
	}

	// i++;

	// if(i==1000)
	// {
    
	// 	i=0;
	// }

	if(on_put)
	{
    
		//调用PID控制
		PID_X.Compute();
		PID_Y.Compute();

		//调整XY轴
		turn_X(Output_X+X_plus);
		turn_Y(Output_Y+Y_plus);

		// if(run_flag)
		// {
    
		// 	if(millis()-time>2)
		// 	{
    
		// 		time = millis();
		// 		if(run_dirict)
		// 		{
    
		// 			X_plus = 25*cos(go_step);
		// 			Y_plus = 25*sin(go_step);
		// 		}
		// 		else
		// 		{
    
		// 			X_plus = 25*sin(go_step);
		// 			Y_plus = 25*cos(go_step);
		// 		}
		// 		go_step+=0.07;

		// 		if(go_step>6.3)
		// 			go_step=0;
		// 	}
		// }
	}
	else
	{
    
		turn_X(0);
		turn_Y(0);
	}
}

之前为了以最简洁的代码实现磁悬浮功能,博主将串口调节部分都注释了,如以上代码注释部分,也可让读者有所区分功能代码跟调节代码(代码资料包在上面的资源链接中课自行下载),剩下的交给你们自己了,加油鸭
在这博主有个idea给安利下,串口指令调节可能还有些繁琐(每次微调都要字符输入跟发送),有条件的可扩展4个按键出来,正好对应4个电磁铁,只要控制好每次按键按下时的霍尔调节值,磁场调节还是很方便的

2.关于PID

什么是PID?
源自维基百科:“比例-积分-微分控制器(PID控制器或三项控制器)是一种控制回路反馈机制,它广泛应用于工业控制系统以及其它各种需要连续调制控制的应用中。PID控制器能够持续计算误差值{\通过字母e(t)表示},误差值表示期望设定值(SP)和测量过程变量(PV)之间的差异,并应用基于比例、积分和微分项(分别通过P、I和D进行表示)的校正过程,这三个字母构成了控制器的名字。”
简而言之:“PID控制器计算‘误差’值,并将其作为测量[输入]和所需设定值之间的差值。控制器试图通过调节[输出]来实现误差的最小化。”
因此,您告诉PID控制器需要测量哪些内容(“输入”)、待测量的位置(“设定点”),以及待调整的变量(“输出”)。
通过Youtube网站轻松理解PID:https://www.youtube.com/watch?v=UR0hOmjaHp0
在这里插入图片描述
在这里插入图片描述
随后PID将调整输出结果,试图使输入等于设定值。作为参考,在汽车领域,输入、设定点和输出分别为速度、期望速度和油门角度。
剩下的你们自行找度娘啦,博主领进门修行靠个人,博主对PID的理解运用也是不太深呢
完结 ~~ 撒花 ❀❀❀ ~~~

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_36955622/article/details/102726212

智能推荐

栈——后进先出(LIFO:last in first out)_栈的后进先出例题-程序员宅基地

文章浏览阅读2.9k次,点赞2次,收藏2次。栈:后进先出(LIFO:last in first out)例如:自助餐中的自取餐盘面试题目:有六个元素6 5 4 3 2 1 的顺序进栈,哪一个不是合法的出栈序列:A. 5 4 3 6 1 2 B.4 5 3 2 1 6 C.3 4 6 5 2 1 D.2 3 4 1 5 6解析:进入栈的顺序保持6 5 4 3 2 1 ,3出栈所以栈中现在是从栈底-->栈顶依次为6..._栈的后进先出例题

java实现post请求(PostMethod)-程序员宅基地

文章浏览阅读3.9k次。项目要求:实现post请求,且请求格式是json格式。maven依赖包<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.3</version></dependency><dependency> ..._postmethod

N皇后问题-n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。_在n×n的方格棋盘放置3个皇后,任意两个皇后不能相邻,否则她们会相互攻击(也就是说-程序员宅基地

文章浏览阅读4.4k次。n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。相互攻击就是说:在同一行、同一列或者在同一斜线方向时,不能同时存在两个皇后。示例:输入: 4输出: [ [".Q..", // 解法 1 "...Q", "Q...", "..Q."], ["..Q.", // 解法 2 "Q...", "...Q", ".Q..._在n×n的方格棋盘放置3个皇后,任意两个皇后不能相邻,否则她们会相互攻击(也就是说

使用Docker安装达梦数据库_docker pull安装达梦8-程序员宅基地

文章浏览阅读1.8k次。前言最近公司要求对老项目进行维护,需要安装达梦数据库,我采用了centos7.8的docker进行安装,这里做个记录。一、docker的安装查看当前centos系统内核版本,高于3.10才能安装docker#uname -r下载和安装docker#yum -y install docker安装完成后,查看docker版本#docker version启动docker服务#systemctl start docker设置docker开机启动#systemctl enable _docker pull安装达梦8

Springboot集成高低版本kafka_spring-kafka版本-程序员宅基地

文章浏览阅读3.7k次。springboot整合kafka的时候一定要根据自己springboot版本选择对应版本的kafka,两者版本对应关系可以直接查看官网。_spring-kafka版本

Java性能优化:数据传输优化_java数据推送方案优化-程序员宅基地

文章浏览阅读1.2k次。数据传输优化一、前言客户端与服务端经常进行着频繁的数据传输,数据传输又影响着用户体验,本小节就传输速率的优化,整理了部分注意事项。二、数据传输优化2.1 减少数据字节数:在开始的时候,采用的是xml传输,这就要使用到Serializable/Parcelable序列化以及反序列化,其传输速度之慢,基本已经被遗弃,后来又出现了JSON序列化传输,其常用工具就是GSON和fastjson,但随着时代的进步,json也体现出了局限性json的局限性主要体现在其是基于字符串的传输,在_java数据推送方案优化

随便推点

QT常见错误:"multiple definition of xxx"_e:\34[c++]\11[20230323qt_test]\example\contach.cpp-程序员宅基地

文章浏览阅读904次。错误原因重复定义解决方法打开QT工程文件*.pro查看SOURCES += \ 以及 HEADERS += \下方是否有重复的源文件名或头文件名,删掉重复的即可_e:\34[c++]\11[20230323qt_test]\example\contach.cpp:3: error: multiple defini

ajax jsonp跨域_ajax 什么时候 jsonp跨域-程序员宅基地

文章浏览阅读1.6k次。js跨域问题是指:js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据。只要协议、域名、端口有任何一个不同,都被当作是不同的域。js跨域参考:http://www.cnblogs.com/2050/p/3191744.html可以通过jsonp实现js跨域,但是获取的数据必须是脚本文件,例如json。下面_ajax 什么时候 jsonp跨域

自然语言处理(NLP)学习路线总结_nlp自然语言处理流程-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏29次。文章目录1、自然语言处理概述2、自然语言处理入门基础2.1 数学基础2.2 语言学基础2.3 Python基础2.4 机器学习基础2.5 深度学习基础2.6 自然语言处理的理论基础3、自然语言处理的主要技术范畴3.1 语义文本相似度分析3.2 信息检索(Information Retrieval, IR)3.3 信息抽取(Information Extraction)3.4 文本分类(Text Categorization)3.5 文本挖掘(Text Mining)3.6 文本情感分析(Textual Af_nlp自然语言处理流程

【转载】梦断计院--一个计算机学院学生大学学习生活的回顾与反省-程序员宅基地

文章浏览阅读272次。作为正值大学毕业的我,无意中看到这篇博文,只看了点开头,就决定给他转载。此刻的我没有工作,时不时的还得为感情事而发愁,一天天的吵架,合好,吵架。我也不像以前的我啦,学习没激情,目标不坚定,生活挺颓废,工作也不找,整天待在寝室进行所谓的“学习”,其实是为工作做准备,把这大学以来丢的东西补上,然后再去找工作,学到现在,也没发觉学得怎么样,离成为一个合格的计算机科学与技术专业的学生相差甚远。

洛谷P4180 严格次小生成树-程序员宅基地

文章浏览阅读360次。题意就是求严格次小生成树。其实思路挺明确的,跟非严格次小生成树差不多。那么先回忆一下非严格次小生成树:先求出最小生成树,再利用Kruskal的贪心思路,对每一条非树边求它连成的环上最大的一条边,用这条非树边替换掉,对于替换掉每一条边后的树权值取min就是答案。严格与非严格的区别:不能相等了。所以好像只求最大值会出问题,如果一个环上有两条一样长的边,得到的结果就是非严格的。所以改进算法,倍增..._p4180

java的cp命令_"java -cp \"./bin"-程序员宅基地

文章浏览阅读9.6k次。-cp 参数后面是类路径,是指定给解释器到哪里找到你的.class文件, 写法: java -cp .;myClass.jar packname.mainclassname classpath中的jar文件能使用通配符,如果是多个jar文件,要一个一个地罗列出来,从某种意义上说jar文件也就是路径。要指定各个JAR文件具体的存放路径,相同路径有多个可使用通配符 java -cp .;c:/classes/myClass.jar;d:_"java -cp \"./bin"