选择:

基于PIC单片机的机器臂

0.00¥

基于PIC单片机的机器臂

0.00¥

该项目由用户Swilder提供。

从汽车制造业的装配线到太空中的远程手术机器人,机器人手臂随处可见。这些机器人的机制类似于人类,其可以被编程用于类似功能和增强的能力。它们可以用于比人类更快更准确地执行重复操作,或者可以在恶劣环境中使用而不会危及人的生命。我们已经使用Arduino建立了一个记录和游戏机器人手臂,可以训练他们完成特定的任务,并让他们永远重复。

在本教程中,我们将使用行业标准PIC16F877A 8位微控制器来控制带电位计的同一机械臂。该项目面临的挑战是PIC16F877A只有两个PWN引脚,但我们需要为我们的机器人控制大约5个伺服电机,这需要5个独立的PWM引脚。因此,我们必须利用GPIO引脚并使用定时器中断在PIC GPIO引脚上产生PWM信号。当然,现在我们可以升级到更好的微控制器或使用解复用器IC来简化这里的工作。但是,值得为这个项目尝试学习体验。

我在这个项目中使用的机械臂的机械结构完全是3D打印的,用于我之前的项目; 你可以在这里找到完整的设计文件和组装程序。或者,如果您没有3D打印机,您还可以使用纸板构建一个简单的机械臂,如链接中所示。假设你已经以某种方式抓住你的机器人手臂让我们进入项目。

版权声明:本站所有设计均源于网友上传或网上搜集,供学习和研究使用,其版权归原作者所有,对可以提供充分证据的侵权信息,本站将在确认后24小时内删除。

添加到愿望单
添加到愿望单
分类: 标签:

描述

第1步:电路图

电路图的图片

该PIC单片机机械臂的完整电路图如下所示。原理图使用EasyEDA绘制。

电路图非常简单; 整个项目由12V适配器供电。然后使用两个7805电压调节器将此12V转换为+ 5V。一个标记为+ 5V,另一个标记为+ 5V(2)。具有两个调节器的原因是当伺服旋转时,它会吸入大量电流,从而产生电压降。这种电压降迫使PIC重新启动,因此我们无法 在同一+ 5V电压轨上同时运行PIC和伺服电机。因此,标有+ 5V的电源用于为PIC微控制器,LCD和电位计供电,标有+ 5V(2)的独立稳压器输出用于为伺服电机供电。

提供0V至5V可变电压的电位器的五个输出引脚连接到PIC的模拟引脚An0至AN4。由于我们计划使用定时器来产生PWM,因此伺服电机可以连接到任何GPIO引脚。我为伺服电机选择了RD2到RD6的引脚,但它可以是您选择的任何GPIO。

由于该程序涉及大量调试,因此16×2 LCD显示器也连接到PIC的端口B. 这将显示正在控制的伺服电机的占空比。除此之外,我还扩展了所有GPIO和模拟引脚的连接,以防将来需要连接任何传感器。最后,我还连接了编程器引脚H1,使用ICSP编程选项直接使用pickit3对PIC进行编程。

步骤2:在GPIO引脚上生成PWM信号,用于伺服电机控制

用于伺服电机控制的GPIO引脚上生成PWM信号的图片

电路准备就绪后,我们必须弄清楚如何在PIC​​的GPIO引脚上产生PWN信号来控制伺服电机。我们已经使用Timer中断方法累了类似的东西并且成功了。在这里,我们将建立在它之上。

所有业余爱好伺服电机的工作频率均为50Hz。这意味着伺服电机的一个完整脉冲周期为1/50(F = 1 / T),即20ms。在这20ms内,控制信号仅为0到2ms,而其余信号总是关闭。下图显示了ON时间如何仅在0到2ms之间变化,将电机从0度旋转到180度持续20ms。

考虑到这一点,我们必须以这样的方式编写程序:PIC从电位计读取0到1204并将其映射到0到100,这将是伺服电机的占空比。使用此占空比,我们可以计算伺服电机的ON时间。然后我们可以定期中断初始化定时器中断,使其与Arduino中的millis()函数类似。这样,我们可以将状态GPIO引脚切换为高电平达到所需的持续时间,并在20ms(一个完整周期)后将其关闭,然后重复相同的过程。现在,我们已经了解了逻辑,让我们进入该计划。

第3步:为机械臂编程PIC16F8771A

像往常一样,可以在本页末尾找到带有视频的完整程序,也可以从这里下载所有必要文件的代码。在本节中,我们将讨论该程序背后的逻辑。该程序采用ADC模块,定时器模块和LCD模块来控制机械臂。如果您不了解如何使用ADC功能或定时器功能或将LCD与PIC连接,则可以回退到相应的链接以了解它们。假设读者熟悉这些概念,给出以下解释。

定时器0端口配置

代码中最重要的部分是将Timer 0设置为每个特定延迟的溢出流。计算此延迟的公式可以表示为

Delay = ((256-REG_val)*(Prescal*4))/Fosc

通过使用OPTION_REG和TMR0寄存器,我们将定时器0设置为以预分频值32运行,REG val设置为248.我们硬件中使用的晶振频率(Fosc)为20Mhz。使用这些值,延迟可以计算为

Delay = ((256-248)*(32*4)) / (20000000)
= 0.0000512 seconds (or)
 = 0.05 msec

所以现在我们已经将定时器设置为每0.05ms溢出一次。下面给出了执行相同操作的代码

/*****Port Configuration for Timer ******/ 
OPTION_REG = 0b00000100; // Timer0 with external freq and 32 as prescalar // Also Enables PULL UPs 
TMR0=248; // Load the time value for 0.0001s; delayValue can be between 0-256 only 
TMR0IE=1; //Enable timer interrupt bit in PIE1 register 
GIE=1; //Enable Global Interrupt
PEIE=1; //Enable the Peripheral Interrupt
/***********______***********/

在伺服电机的总控制窗口0ms到2ms之间,我们可以用0.05msec的分辨率控制它,这使得我们可以在0度到180度之间为电机提供(2 / 0.05)40个不同的位置。如果您的MCU可以支持它以获得更多位置和精确控制,您可以进一步降低此值。

中断服务例程(ISR)

现在我们将Timer 0设置为每0.05ms溢出一次,我们将TMR0IF中断标志设置为0.05ms。因此,在ISR函数中,我们可以重置该标志并将名为count的变量递增1。所以现在这个变量每0.05ms增加1。

void interrupt timer_isr() { 
if(TMR0IF==1) // Timer flag has been triggered due to timer overflow -> set to overflow for every 0.05ms { 
TMR0 = 248; //Load the timer Value 
TMR0IF=0; // Clear timer interrupt flag 
count++; //Count increments by 1 for every 0.05ms }

计算占空比和导通时间

接下来我们要计算所有五个伺服电机的占空比和导通时间。我们有五个伺服电机,每个伺服电机用于控制臂的各个部分。因此,我们必须读取所有五个的ADC值,并计算每个的占空比和导通时间。

ADC值将在0到1024的范围内,只需将0.0976(100/1024 = 0.0976)乘以获得的值即可转换为0%至100%占空比。然后必须将此0到100%的占空比转换为ON时间。我们知道,在100%占空比时,ON时间必须为2ms(180度),因此乘以0.02(2/100 = 0.02)将0到100占空比转换为0到2ms。但是我们的定时器变量计数设置为每0.05ms增加一次。这意味着每1ms计数值将为20(1 / 0.05 = 20)。所以我们必须将20乘以0.02来计算我们程序的准确时间,这将给出0.4(0.02 * 20 = 0.4)的值。相同的代码如下所示,你可以看到它使用for循环重复5次。结果值存储在T_ON数组中。

for (int pot_num=0; pot_num<=3; pot_num++) 
{ int Pev_val = T_ON[pot_num];
POT_val = (ADC_Read(pot_num)); //Read the value of POT using ADC 
Duty_cycle = (POT_val * 0.0976); //Map 0 to 1024 to 0 to 100 
T_ON[pot_num] = Duty_cycle* 0.4;//20*0.02

选择要旋转的电机

我们不能将所有五个电机控制在一起,因为它会使ISR代码大大减慢整个微控制器的速度。所以我们一次只能旋转一个伺服电机。要选择旋转哪个伺服,微控制器会监控所有五个伺服电机的开启时间,并将其与之前的准时进行比较。如果ON时间发生变化,我们可以得出结论,必须移动特定的伺服。相同的代码如下所示。

if (T_ON[pot_num] != Pev_val) { 
Lcd_Clear(); 
servo = pot_num; 

Lcd_Set_Cursor(2,11); Lcd_Print_String("S:");
Lcd_Print_Char(servo+'0'); 
if (pot_num==0) 
{Lcd_Set_Cursor(1,1); 
Lcd_Print_String("A:");} 
else if (pot_num==1) 
{Lcd_Set_Cursor(1,6); 
Lcd_Print_String("B:");} 
else if (pot_num==2) 
{Lcd_Set_Cursor(1,11); 
Lcd_Print_String("C:");} 
else if (pot_num==3) 
{Lcd_Set_Cursor(2,1); 
Lcd_Print_String("D:");} 
else if (pot_num==4) 
{Lcd_Set_Cursor(2,6); 
Lcd_Print_String("E:");}
char d2 = (Duty_cycle) %10; 
char d1 = (Duty_cycle/10) %10; 
Lcd_Print_Char(d1+'0');Lcd_Print_Char(d2+'0');

我们还在LCD屏幕上打印伺服占空比,以便用户可以知道其当前位置。基于接通时间的变化,可变伺服系统用0到4的数字更新,每个数字代表各个电动机。

控制ISR内的伺服电机

在ISR内部,变量计数每0.05ms增加一次,这意味着每1ms变量将增加20个。使用这个,我们必须控制引脚产生PWM信号。如果count的值小于导通时间,则使用以下线路打开该电机的GPIO

PORTD = PORTD | servo_code[servo];

这里的数组servo_code []具有所有五个伺服电机的引脚细节,并根据可变伺服中的值,将使用该特定伺服电机的代码。然后逻辑OR(|)与现有的PORTD位,这样我们就不会干扰其他电机的值,只更新这个特定的电机。同样用于关闭引脚

PORTD = PORTD&〜(servo_code [servo]);

 

我们使用逻辑反(〜)运算符反转了位值,然后在PORTD上执行了AND(&)操作,仅关闭所需的引脚,同时使其他引脚保持其先前的状态。完整的代码段如下所示。

void interrupt timer_isr() { 

if(TMR0IF==1) // Timer flag has been triggered due to timer overflow -> set to overflow for every 0.05ms { 
TMR0 = 248; //Load the timer Value 
TMR0IF=0; // Clear timer interrupt flag 
count++; //Count increments by 1 for every 0.05ms -> count will be 20 for every 1ms (0.05/1 = 20)) }

int servo_code[] = {0b01000000, 0b00100000, 0b00010000, 0b00001000, 0b00000100 }; 
if (count >= 20*20) 
count=0;
if (count <= (T_ON[servo]) ) 
PORTD = PORTD | servo_code[servo]; 
else 
PORTD = PORTD & ~(servo_code[servo]); }

我们知道在GPIO引脚再次打开之前,总周期必须持续20ms。因此,我们通过将count的值与400(上面讨论的相同计算)进行比较来检查计数是否超过20ms,如果是,我们必须再次将计数初始化为零。

步骤4:PIC机器人臂代码的仿真

PIC机器人臂代码仿真图PIC机器人臂代码仿真图

在将代码带到真实硬件之前模拟代码总是更好。所以我使用Proteus来模拟我的代码并验证它是否正常工作。用于仿真的电路如下所示。我们使用示波器检查是否按要求生成PWM信号。我们还可以验证LCD和伺服电机是否按预期旋转。

如您所见,LCD根据作为第3电机的锅值显示电机D的占空比为07。类似的,如果移动另一个电位器,则该电位器的占空比及其电机编号将显示在LCD上。示波器上显示的PWM信号

使用示波器上的光标选项测量总循环周期为22.2ms,非常接近所需的20ms。最后,我们确信代码有效,因此要继续使用电路,我们可以将其焊接在穿孔板上或使用PCB。它不会在面包板上轻松工作,因为POT总是会因连接不良而产生一些问题。

第5步:使用EasyEDA进行PCB设计

使用EasyEDA的PCB设计图片

为了设计这个PIC机器人手臂,我们选择了名为EasyEDA在线EDA工具。我已经使用它很长一段时间了,因为它占地面积大,易于使用,所以非常方便。在设计PCB之后,我们可以通过其低成本PCB制造服务订购PCB样品。他们还提供组件采购服务 ,他们拥有大量电子元件,用户可以订购他们所需的组件以及PCB订单。

在设计电路和PCB时,您还可以公开您的电路和PCB设计,以便其他用户可以复制或编辑它们并从您的工作中受益,我们还将此电路的整个电路和PCB布局公开,检查以下链接:

HTTPS://easyeda.com/circuitdigest/pic-development -…

使用此链接,您可以直接订购我们在此项目中使用的相同PCB并使用它。一旦设计完成,电路板可以被视为3D模型,这将非常有助于可视化电路板在制造后如何出现。我们正在使用的电路板的3D模型如下所示。除此之外,您还可以查看电路板的顶层和底层,以检查光滑的屏幕是否符合预期。

在线计算和订购样品

完成PIC机器人PCB的设计后,您可以通过JLCPCB.com订购PCB 。要从JLCPCB订购PCB,您需要Gerber File。要下载PCB的Gerber文件,只需单击EasyEDA编辑器页面上的Generate Fabrication File按钮,然后从那里下载Gerber文件,或者您可以单击JLCPCB上的Order,如下图所示。这会将您重定向到JLCPCB.com,您可以在其中选择要订购的PCB数量,所需的铜层数,PCB厚度,铜重量,甚至PCB颜色,如下图所示:

选择所有选项后,单击“保存到购物车”,然后您将进入可以上传我们从EasyEDA下载的Gerber文件的页面。上传您的Gerber文件,然后单击“保存到购物车”。最后安全地点击Checkout以完成您的订单,然后您将在几天后获得PCB。他们以非常低的速率制造PCB,价格为2美元。他们的建造时间也非常少,这是48小时DHL交付3-5天,基本上你会在订购后一周内获得你的PCB。

订购PCB后,您可以查看PCB的生产进度以及日期和时间。您可以通过进入“帐户”页面进行检查,然后单击“生产进度”。

在订购PCB的几天后,我得到了漂亮包装的PCB样品,如下图所示。

在获得这些部件之后,我已经在PCB上焊接了所有必需的元件。我也直接焊接POT,而不是使用连接线,因为我最初使用的母线到母线可能会因为接触松动而产生奇怪的模拟输出电压。组装好所有组件后,我的PCB看起来像这样。

您可能已经注意到此板上只有一个7805。那是因为最初我认为我可以通过调节器为PIC和伺服电机供电,后来我意识到我需要两个。所以我使用外部电路通过你在这里看到的绿线为伺服电机供电。

然而,你不必担心它,因为; 我现在已对PCB进行了更改。您可以使用修改过的PCB并焊接板上的稳压器。

PIC机械臂的工作原理

在经历了所有疲惫的工作后,是时候付清了。焊接电路板上的所有组件并将程序上载到PIC控制器。完整代码如下,或者可以从这里下载。电路板上提供的编程连接器可以帮助您直接使用Pickit 3上传程序,而不会有太多麻烦。程序上传后,您应该看到LCD显示当前正在控制的伺服。要了解有关PIC单片机编程的更多信息,请按照上一个教程进行操作。

从那里你可以简单地转动锅,检查伺服电机如何响应每个电位器。一旦您了解了格式,您就可以控制机器人手臂执行您需要执行的任何操作并获得乐趣。您可以在下面链接的视频中找到项目的完整工作。那就是人们希望你理解这个项目并从中学到新东西。如果您有任何问题,请将其留在评论部分或使用论坛 进行其他技术讨论。

第6步:代码和演示视频

评论

目前还没有评论

成为第一个评论 “基于PIC单片机的机器臂” 的人

电子邮件地址不会被公开。 必填项已用*标注

关闭菜单
×
×

产品入口: 产品添加到购物车