从汽车制造业的装配线到太空远程手术机器人,随处可见机械臂。这些机器人的机制类似于人类,可以对其进行编程以实现相似的功能和增强的功能。它们可以比人类更快,更准确地执行重复动作,也可以在恶劣的环境中使用而不会冒生命危险。我们已经使用Arduino构建了一个记录和播放机械臂,可以对其进行训练以完成特定任务,并使其永远重复。
在本教程中,我们将使用行业标准的PIC16F877A 8位单片机来控制带电位器的同一机械手。该项目面临的挑战是PIC16F877A仅具有两个PWN功能引脚,但是我们需要为机器人控制约5个伺服电机,这需要5个单独的PWM引脚。因此,我们必须利用GPIO引脚,并使用定时器中断在PIC GPIO引脚上生成PWM信号。现在,我们当然可以升级到更好的微控制器或使用解复用器IC,使这里的工作变得简单得多。但是,仍然值得尝试这个项目以获得学习经验。
我在本项目中使用的机械手臂的机械结构完全是3D打印的,这是我先前的项目;您可以在此处找到完整的设计文件和组装过程。另外,如果您没有3D打印机,也可以使用纸板制作简单的机械臂,如链接中所示。假设您已经掌握了机械臂,那么请继续进行该项目。
电路原理图
该基于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。
由于该程序涉及大量调试,因此16x2 LCD显示屏也连接到PIC的portB。这将显示被控制的伺服电机的占空比。除此之外,我还扩展了所有GPIO和模拟引脚的连接,以防万一将来需要连接任何传感器。最后,我还连接了编程器引脚H1,以使用ICSP编程选项通过pickit3直接对PIC进行编程。
在GPIO引脚上生成PWM信号以进行伺服电机控制
电路准备就绪后,我们必须弄清楚如何在PIC的GPIO引脚上生成PWN信号,以控制伺服电机。我们已经厌倦了使用Timer中断方法的类似操作,并且成功了。在这里,我们只是在此基础上进行构建,因此,如果您是此处的新手,我强烈建议您在继续之前阅读本教程。
所有业余伺服电机的工作频率均为50Hz。表示伺服电机的一个完整脉冲周期为1/50(F = 1 / T),即20ms。在这完整的20毫秒中,控制信号仅从0到2毫秒,而其余信号始终处于关闭状态。下图显示了接通时间仅在0到2ms之间变化,以使电动机在整个20ms持续时间中从0度旋转到180度。
考虑到这一点,我们必须以如下方式编写程序:PIC从电位计读取0到1204并将其映射到0到100,这将是伺服电机的占空比。使用该占空比,我们可以计算出伺服电机的接通时间。然后,我们可以初始化计时器中断以定期间隔溢出,使其行为类似于Arduino中的millis()函数。这样,我们可以将状态GPIO引脚切换为高电平一段所需的时间,然后在20ms(一个完整的周期)后将其关闭,然后重复相同的过程。现在,我们已经了解了让我们进入程序的逻辑。
编程PIC16F8771A用于机械臂
像通常在本页末找到带有视频的完整程序一样,也可以从此处下载代码以及所有必要的文件。在本节中,我们将讨论程序背后的逻辑。该程序使用ADC模块,计时器模块和LCD模块来控制机械臂。如果您不知道如何使用ADC功能或定时器功能或如何将LCD与PIC接口,则可以退回到相应的链接来学习它们。在假定读者熟悉这些概念的情况下给出以下说明。
定时器0端口配置
代码中最重要的部分是将计时器0设置为每个特定延迟溢出。可以通过以下公式计算此延迟:
延迟=((256-REG_val)*(Prescal * 4))/ Fosc
通过使用OPTION_REG和TMR0寄存器,我们将定时器0设置为以32的预分频值运行,并且REG val设置为248。我们的硬件中使用的晶振频率(Fosc)为20Mhz。使用这些值,可以将延迟计算为
延迟=((256-248)*(32 * 4))/(20000000) = 0.0000512秒(或) = 0.05毫秒
因此,现在我们将计时器设置为每0.05ms溢出一次。下面是执行相同操作的代码
/ *****定时器的端口配置****** / OPTION_REG = 0b00000100; //具有外部频率和32作为预分频器的Timer0 //也使能PULL UP TMR0 = 248; //加载时间值0.0001s;delayValue只能在0-256之间,只有 TMR0IE = 1;//使能PIE1寄存器 GIE = 1的 定时器中断位;//启用全局中断PEIE = 1; //启用外围中断 / *********** ______ *********** /
在伺服电机的总0ms到2ms控制窗口中,我们可以以0.05毫秒的分辨率对其进行控制,这使我们可以在0度到180度之间为电机设置(2 / 0.05)40个不同位置。如果您的MCU支持该值以获得更多位置和精确控制,则可以进一步减小该值。
中断服务程序(ISR)
现在,我们将定时器0设置为每0.05ms溢出一次,我们将把TMR0IF中断标志设置为0.05ms。因此在ISR函数中,我们可以重新设置该标志,并增加一个变量称为计数 由一个。因此,现在此变量将每0.05ms增加1。
无效中断timer_isr() { if(TMR0IF == 1)//由于定时器溢出触发了定时器标志->设置为每0.05ms溢出 { TMR0 = 248; //加载定时器值 TMR0IF = 0; //清除计时器中断标志 计数++; //每0.05ms递增1 }
计算占空比和准时
接下来,我们必须计算所有五个伺服电动机的占空比和接通时间。我们有五个伺服电机,每个伺服电机用于控制手臂的各个部分。因此,我们必须读取所有五个ADC的ADC值,并计算每个占空比和占空比。
ADC值将在0到1024的范围内,只需将所得值乘以0.0976(100/1024 = 0.0976),即可将其转换为0%到100%的占空比。然后必须将此0至100%占空比转换为ON时间。我们知道,在100%占空比下,导通时间必须为2ms(对于180度),因此乘以0.02(2/100 = 0.02)会将0到100占空比转换为0到2ms。但是,然后将我们的计时器变量计数设置为每0.05ms增加一次。这意味着每1毫秒计数值将为20(1 / 0.05 = 20)。因此,我们必须将20与0.02相乘以计算程序的准确准时,这将使我们得到值0.4(0.02 * 20 = 0.4)。相同的代码如下所示,您可以使用for循环将其对所有5个锅重复5次。结果值存储在T_ON数组中。
for(int pot_num = 0; pot_num <= 3; pot_num ++) { int Pev_val = T_ON; POT_val =(ADC_Read(pot_num)); //使用ADC Duty_cycle =(POT_val * 0.0976) 读取POT的值 //将0到1024映射到0到100 T_ON = Duty_cycle * 0.4; // 20 * 0.02
选择要旋转的电动机
我们无法同时控制所有五个电机,因为这会使ISR代码沉重,从而降低整个微控制器的速度。因此,我们一次只能旋转一台伺服电机。要选择旋转哪个伺服器,微控制器会监视所有五个伺服电机的开启时间,并将其与之前的开启时间进行比较。如果接通时间发生变化,那么我们可以得出结论,必须移动特定的伺服器。相同的代码如下所示。
如果(T_ON!= Pev_val) { Lcd_Clear(); 伺服= pot_num; Lcd_Set_Cursor(2,11); Lcd_Print_String(“ S:”); Lcd_Print_Char(servo +'0'); 如果(pot_num == 0) {Lcd_Set_Cursor(1,1); Lcd_Print_String(“ A:”);} 否则,如果(pot_num == 1) {Lcd_Set_Cursor(1,6); Lcd_Print_String(“ B:”);} 否则,如果(pot_num == 2) {Lcd_Set_Cursor(1,11); Lcd_Print_String(“ C:”);} 否则,如果(pot_num == 3) {Lcd_Set_Cursor(2,1); Lcd_Print_String(“ D:”);} 否则,如果(pot_num == 4) {Lcd_Set_Cursor(2,6); Lcd_Print_String(“ E:”);} char d2 =(Duty_cycle)%10; 字符d1 =(Duty_cycle / 10)%10; Lcd_Print_Char(d1 +'0'); Lcd_Print_Char(d2 +'0');
我们还将在液晶显示屏上打印伺服占空比,以便用户知道其当前位置。根据接通时间的变化,可变伺服系统将更新为0到4之间的数字,每个数字代表单个电动机。
在ISR内部控制伺服电机
在ISR内部,变量计数每0.05ms递增一次,这意味着变量每1ms递增20。使用此方法,我们必须控制引脚以产生PWM信号。如果count的值小于接通时间,则使用下面的行打开该电动机的GPIO
PORTD = PORTD-伺服代码;
在这里,伺服阵列代码包含所有五个伺服电动机的引脚详细信息,并基于可变伺服电动机中的值,将使用该特定伺服电动机的代码。然后将其与现有PORTD位进行逻辑或(-),以便我们不会干扰其他电动机的值,而仅更新该特定电动机。同样地,关闭销钉
PORTD = PORTD&〜(伺服代码);
我们使用逻辑逆运算符(〜)反转了位值,然后在PORTD上执行了AND(&)操作以仅关闭所需的引脚,而使其他引脚保持先前的状态。完整的代码段如下所示。
无效中断timer_isr() { if(TMR0IF == 1)//由于定时器溢出触发了定时器标志->设置为每0.05ms溢出 { TMR0 = 248; //加载定时器值 TMR0IF = 0; //清除定时器中断标志 计数++; //计数由1递增每0.05ms - >计为20对每1ms(0.05 / 1 = 20)) } INT servo_code = {0b01000000,0b00100000,0b00010000,0b00001000,0b00000100}; 如果(count> = 20 * 20) count = 0; 如果(count <=(T_ON)) PORTD = PORTD-伺服代码; 否则 PORTD = PORTD&〜(servo_code); }
我们知道,在GPIO引脚再次打开之前,整个周期必须持续20ms。因此,我们通过将count的值与400进行比较来检查该count是否超过20ms(与上面讨论的计算方法相同),如果是,我们必须再次将count初始化为零。
PIC机械臂代码的仿真
在将代码带入实际硬件之前,最好先对其进行仿真。因此,我使用Proteus来模拟我的代码,并验证了它可以正常工作。用于仿真的电路如下图所示。我们使用示波器检查是否根据需要生成了PWM信号。我们还可以验证LCD和伺服电机是否按预期旋转。
如您所见,LCD根据第三个电动机的电位器值将电动机D的占空比显示为07 。类似地,如果移动另一个电位计,则该电位计的占空比及其电机编号将显示在LCD上。示波器上显示的PWM信号如下所示。
使用示波器上的光标选项将总周期测量为22.2ms,这非常接近所需的20ms。最后,我们确定代码可以正常工作,因此要继续进行电路工作,我们可以将其焊接在穿孔板上或使用PCB。它在面包板上不容易工作,因为由于连接不良,POT总是会带来一些问题。
使用EasyEDA进行PCB设计
为了设计该 PIC机械臂,我们选择了称为EasyEDA的在线EDA工具。我已经使用了很长时间了,由于它的覆盖范围广且易于使用,因此发现它非常方便。设计完PCB之后,我们可以通过低成本的PCB制造服务订购PCB样品。他们还提供元件采购服务,其中有大量的电子元件库存,用户可以与PCB订单一起订购所需的元件。
在设计电路和PCB时,您还可以公开您的电路和PCB设计,以便其他用户可以复制或编辑它们并从您的工作中受益,我们还对该电路公开了整个电路和PCB布局,请检查下面的链接:
easyeda.com/circuitdigest/pic-development-board-for-robotic-arm
使用此链接,您可以直接订购和使用我们在该项目中使用的同一块PCB。设计完成后,可以将电路板视为3D模型,这将有助于可视化电路板在制造后的外观。我们正在使用的电路板的3D模型如下所示。除此之外,您还可以查看电路板的顶层和底层,以检查平滑的屏幕是否符合预期。
在线计算和订购样品
完成此PIC Robot PCB的设计后 ,您可以通过JLCPCB.com订购PCB。要从JLCPCB订购PCB,您需要Gerber File。要下载PCB的Gerber文件,只需单击 EasyEDA编辑器页面上的 Generate Fabrication File 按钮,然后从那里下载Gerber文件,或者您可以单击 JLCPCB 上的 订购, 如下图所示。这会将您重定向到JLCPCB.com,您可以在其中选择要订购的PCB数量,所需的铜层数,PCB厚度,铜重量以及甚至是PCB颜色,如下图所示:
选择所有选项后,单击“保存到购物车”,然后您将转到上载您从EasyEDA下载的Gerber文件的页面。上传您的Gerber文件,然后单击“保存到购物车”。最后,单击“安全地结帐”以完成您的订单,然后几天后您将得到PCB。他们以极低的成本(2美元)制造PCB。他们的构建时间也非常短,DHL交付3-5天的时间为48小时,基本上,您将在订购一周后获得PCB。
订购PCB后,您可以 查看 日期和时间以显示 PCB的 生产进度 。您可以通过在“帐户”页面上进行检查,然后单击“生产进度”。
订购几天的PCB后,我得到了包装良好的PCB样品,如下图所示。
在获得这些零件之后,我将所有必需的组件焊接到了PCB上。我还直接焊接了POT,而不是使用连接线,因为我最初使用的母对母线可能是由于接触不良而产生了奇怪的模拟输出电压。组装完所有组件后,我的PCB看起来像这样。
您可能已经注意到,该板上只有一个7805。那是因为起初我以为我可以摆脱只为PIC和伺服电机供电的稳压器,后来又意识到我需要两个。因此,我已使用外部电路通过您在此处看到的绿色电线为伺服电机供电。
但是,您不必为此担心很多;我现在对PCB进行了更改。您可以使用修改后的PCB,并将两个稳压器焊接在板上。
PIC机械臂的工作
在完成所有累人的工作之后,该是时候还清了。将所有组件焊接在板上,然后将程序上传到PIC控制器。完整的代码在下面给出,或者可以从此处下载。板上提供的编程连接器应该可以帮助您直接使用Pickit 3轻松上传程序。程序上传后,您应该会看到LCD显示当前正在控制的伺服器。要了解有关对PIC单片机进行编程的更多信息,只需遵循上一教程。
从那里您可以简单地转动电位器,并检查伺服电机如何响应每个电位计。了解格式后,您就可以控制机械臂执行需要执行的任何动作并获得乐趣。您可以在下面的视频中找到 该项目的完整工作。
那就是人们希望您理解该项目并从中学习到一些新东西。如果您有任何疑问,请将其留在评论部分,或使用论坛进行其他技术讨论。