像 raspberry pi 这样的单板计算机 (sbc) 只需数小时就能轻松构建复杂的机器,而不必使用一颗裸微控制器从头开始。 为了展示使用现代 sbc 有多简单,此“easy build”课程将引导您完成构建直线平台并进行编码所需的步骤。这里的直线平台是一个能够以直线方向执行来回运动的,由系统工程师或研究人员用来完成重复性任务的平台。
除了引导您完成这些步骤外,我们还将附上用于演示随附视频中直线平台的代码,以及帮助您启动的项目物料清单。
为什么选择直线平台?
我们启动此项目的初衷是,展示设定 raspberry pi 微型计算机来执行稍复杂的任务是如此容易。 尽管我们不会满足于几个闪光灯,但我们也不想尝试并计算轨道力学。 最终我们决定控制步进电机致动的直线平台。 毕竟,驱动步进电机正好介于闪烁的 led 与计算三个天体的多体问题之间。
我们将项目分成三个部分:电子硬件、软件和机械构造。
电子硬件
图 1:显示从 raspberry pi model b 到限位开关的所有硬件元素的完整系统布局(左上角)。 (使用 digi-key scheme-it 绘制的原理图)
目前为止,这些内容还非常简单、直接。 很显然,除了 raspberry pi 2 (rpi) 外,我们还需要步进电机、步进电机驱动器以及上述两个器件的电源。 之后,我们确定了需要的输入。 最后,我们确定了以下项目:
- 左移按钮
- 右移按钮
- 高/低速开关
- 左限位开关
- 右限位开关
我们将电路布置到 b&k precision gs-830 试验板上。 顾名思义,它拥有 830 个连接点以及一个总线条。
图 2:如图所示,滑动架挤靠在限位开关上,其中蓝色盒子就是限位开关,且在丝杠下方还有一个柱塞。 (来源:digi-key electronics)
输入从左,还是从右,完全随意。 我们只需对两个相反方向命名。 请注意,该限位开关使用上拉电阻器接线为“正常高”。 我们这样做是为了给这些输入提供一些抗噪能力。 raspberry pi 具有惊人的灵敏度,我们发现,紧凑型荧光灯等外部噪声源和继电器线圈等电感器有时可以在 pi 上触发输入。
对于步进电机,我们选择了 nmb technologies corporation 的 23km-k2(图 3)。 我们使用的步进驱动器是 geckodrive 的 g210x。 geckodrive 比市场上许多廉价的非品牌驱动器要昂贵一些,但它们可以提供流畅、无故障的步进控制。 同样,我们手头已经有了一个这样的步进驱动器。 大多数类似 g210x 这样的廉价步进电机驱动器是通过 direction 引脚和 step 引脚来控制的。 这很适合简单的项目:我们只需将这些引脚直接连接到 rpi 上未使用的 gpio 引脚即可。
图 3:对于步进电机,我们选择了 nmb technologies corp. 的 23km-k2 标准混合电机。 (来源:nmb technologies corp.)
我们还将 geckodrive 的 enable 引脚接至 rpi。 这样做使得驱动器仅在程序运行时才“开启”并向电机线圈供电。 否则,即使驱动器未收到执行任何操作的任何指令,驱动器仍会在我们向整个电路供电后立即将功率转储至电机。
将功率转储至电机线圈造成两个结果。 首先,它会促使电机产生制动效果。 电机会主动抵制任何旋转其轴的尝试。 这在某些情况下是希望达到的效果;比如当您将滑动架移到某个点并且希望将其锁定到位,使其不会被撞离位置。
第二个结果是我们希望避免的,即电机会在原地不断升温。 此电路在我们编辑和测试代码的过程中一直保持通电状态。 如果我们不停用驱动器,它会不断向我们的电机转储功率。 步进电机通常都会变热,但我们最好不要让其在等待指令的过程中自行加热。
图 4:36 vdc xp power shp350 系列 36 v 开关式电源用于替换 24 v 电源为系统供电,以增加电机转速。 (来源:xp power)
最初,我们为电机连接 24 vdc 电源, 之后我们决定提高转速,于是找到了 36 vdc 电源,即 xp power 的 shp350 单输出、350 w ac-dc 电源。 这将在 24 v 电源的基础上显著提升电机转速。
gecko 驱动器会限制通过电机线圈的最大电流。 您可以在端子 11 和 12 之间使用电阻器来设置电流限制,也可以使用驱动器上的 dip 开关。 顺便提一下,同一组 dip 开关还用于控制驱动器的微步进模式。 我们将在软件部分对此做进一步讨论。
软件
软件程序显示在本页面的底部。 此时我们决定选择使用两个程序:一个程序用于手动控制平台;另一个程序负责让直线平台滑动架在限位开关之间来回穿梭。 所有代码均使用 idle 3.2.1 以 python 语言编写。 我们之所以使用 python,是因为它是 rpi 的默认语言。 idle 是随 raspbian 一起提供的 python 精简版系统开发环境。
为什么使用 python? 不要让新语言吓住了您。 python 与 c 非常相似,即使您不会编写 python 代码,但只要熟悉 c,就几乎肯定能够阅读和理解程序内容。
我们的手动控制程序要执行的操作几乎一目了然,代码也未作任何说明。 具体而言,电机加速的问题。 步进电机必须逐渐提高转速。我知道,许多读者会说,他们以前见过或控制过步进电机,电机转速完全取决于向其输入的脉冲频率。 也许是这样,但我敢打赌,这些情况下的电机负载肯定很小,甚至根本没有任何负载。
而我们的直线平台中的电机肯定带有负载。 承载的步进电机必须达到一定的转速,否则电机将会失速。 将脉冲输入到其驱动器时,步进电机只会在原地断续运转。 这也是我们在软件中置入加速程度的原因。 加速度需要足够快,使观察者不容易观察到从静止到最高转速的过程,但不能太快以至于失速。
加速程序一开始很慢地旋转电机(步进电机在低速下具有最高的扭矩),以向系统施加最大扭矩,从而克服惯性和“静摩擦力”。 之后,此程序会快速缩短步进脉冲之间的时间,直至达到最高转速。 扭矩会随着转速的提高而减小,但到此时,如果调节得当,系统中的机械阻力已被克服。
简单地介绍一下“静摩擦力”一词的含义。 此术语的真正解释远远超出了此项目分析的目的。 但我们可以采用类比的方法加深了解。 想象一下握住机器的旋钮或手轮,并尝试旋转。 通常,在旋转时必须克服一个初始阻力。 一旦克服这个阻力,旋转旋钮或手轮就会变得容易多了,现在需要的扭矩也要小得多。 在本文中,该初始阻力便是静摩擦力。 这种现象在利用滑台执行操作的机床(例如车床或铣床)中特别明显。
我们的确注意到,python 也有一个显著的局限。 我们对为电机驱动器提供输出的步进引脚进行切换的速度存在限制。 到某一点后,我们在 5 µs 步进脉冲之间加入的延迟不论多小都无关紧要,因为 python 代码中的命令执行之间存在固有的延迟。 我们没有完全弄清这一问题的缘由,也不知道如何解决此问题。 最好的办法是采取变通方案,这也是我们将电机驱动器设为 full_step 模式的原因。
如果使用任何类型的微步进,我们需要将最大脉冲率(取决于 python 的具体情况)除以我们将驱动器切换到的微步数。
因此,对于半步进电机,需要将最高转速除以二。 使用 1/10 微步进时,我们需要将最高转速除以 10! 如果您追求更流畅、波动较小的动作,微步进方式是不错的选择,但对此项目而言则不必如此。
关于微步进的说明
我们在此项目中所用的双极步进电机类型几乎总是设计为每转 200 步。 也就是说,200 个“全”步将会旋转电机轴一周。 现在,比方说,我们将电机驱动器设置成 ¼ 微步进。 我们这样做会将电机的每个满步分成 4 个更小的步。 电机驱动器收到的每个 step 脉冲会将电机轴旋转 ¼ 满步。 这意味着,我们现在必须发送 800 个脉冲到驱动器才能将轴旋转一整转。
1/10 微步呢? 现在,您需要发送 2000 个脉冲才能完成一整转。 咋一看,这看起来不错。 这样做增加了电机的位置分辨率。 是的,但不完全如此:您可以采取多小的步幅存在物理限制。 而且,微步越多,您所获得的可用扭矩越小。
手动控制程序分解
首先,我们导入了时间和 gpio 库。 然后,我们为每个变量设置引脚以及这些引脚的输入/输出。
方向按钮和速度开关设置为使用内部下拉电阻。 限位开关设置为使用内部上拉电阻。
转速和加速变量在开始时设置,并可全局更改,以调节运行程序中的电机转速和加速度。
程序仅运行一个“while”循环作为主循环,扫描“左”和“右”按钮。
按其中一个按钮后,rampup() 子程序就会立即执行电机,沿所按按钮的方向加速至最高转速。
只要按下按钮,程序就会留在 rampup() 程序中。 松开按钮后,rampup() 程序将会跳入 rampdown() 程序,将电机减速至停止。 rampdown() 会持续减速,直至用完减速步数。 然后程序会返回到主循环,以检查方向按钮。 转速开关有两个设置,高和低。 此开关会将速度变量更改为对应的速度变量。
在按下左或右方向按钮以及发出步进脉冲时,步进程序还会检查确认是否已启用两个限位开关之一。 当移动平台触及限位开关时,电机就会停止,改变方向,并执行与原始行进方向相反的 50 步 (decelpulsecount) 移动。 这会将滑动架移至足够远离限位开关的位置,以免再次触及限位开关。
来回穿梭程序
从 raspberry pi 运行该程序后,直线平台会立即在一个方向上以固定的速度移动,直至触及其中一个限位开关。 平台随即改变方向,逐步提速,并继续在另一个方向上移动,直至其触及平台行程另一侧的限位开关,周而复始。 移动速度可通过手动控制程序中所用的相同开关,在预设的高速度或低速度之间切换。
机械构造
图 5:直线平台的最终构造使用现货零件组装而成,包括 1.5 英寸铝型材以及一根 8 螺纹/英寸的丝杠(8 头)。 (来源:digi-key electronics)
直线平台完全由现货零件制成:用于框架的 1.5 英寸铝型材、夹具、轴、电机底座,以及 0.5 英寸直径的 8 螺纹/英寸的丝杠(8 头)。 八头表示螺纹具有 8 条平行螺纹,类似于橙汁容器盖。 最终,丝杠每转动一整转,机械系统就会移动 1 英寸。 我们这样做是为了让直线平台操作视频更生动一些。 我们有 10 螺纹/英寸、单螺纹丝杠,但这会导致移动速度非常慢。 步进电机的局限在于其最大转速实际上很慢。
滑动架架在一对 20 mm 直线轴及配对的轴承上。 针对所用的 nema 23 双极步进电机,我们选择了一个通用的 nema 23 安装支架。 问问图片和视频您可以看到,我们使用齿轮和正时皮带将机械动力从电机传递到轴末端,以便在出现振动或机械静摩擦时能够调节齿轮比。 一些实验表明,电机和轴之间的比率为 1:1 效果很好。
对于位于丝杠从动端的轴台,我们必须做一些设计工作和加工(图 6)。 轴台是支撑轴的一个机械元件,在本例中仅传输旋转运动并阻止直线运动(至少在理论上如此)。 我们能否在没有轴台的情况下完成项目? 存在这种可能。 我们本可以将丝杠直接连接到步进电机的输出轴,但如果我们选择这种做法,我们的系统将很不稳定。 因此,我们在直线平台上设计并制造了一个直接连接到 20 mm 直线轴的轴台。
图 6:为延长设计寿命,使用轴台支撑轴并且仅传输旋转运动,同时阻止直线运动(至少在理论上如此)。 (来源:digi-key electronics)
步进电机内的轴承通常仅设置为处理侧向力,而非轴向力。 随着时间的推移,在滑动架来回穿梭的过程中,这些电机轴承将受到不应有的应力。 最终会损坏电机。 我们不清楚多久会发生这种情况。 但我们不希望电机在项目中途出现磨损,因此我们制造轴台时使用一些推力轴承、一个滚针轴承和一根 1/4 英寸的轴。 滚针轴承(红色)在轴台右侧中间位置固定 1/4 英寸轴,止推轴承(蓝色)负责处理从丝杠传输的任何轴向力。
最后,我们对限位开关进行定位,让滑动架在撞上其机械行程极限之前便能触发该开关。 此时,滑动架的撞击不会导致物理损毁,但肯定会开始磨损正时皮带和齿轮,因此我们会尽力避免这种情况。
以下就是运行中的完整项目:
结论
raspberry pi model b 等 sbc 可以让工程师和研究人员更轻松地设计并实现可行且实用的系统。 此 easy build 分步指南通过一个实用的实例,详细指导读者完成直线平台的设计全过程,同时针对过程中的组件选择和设计决策,提供了深入浅出的分析。 除物料清单和相关代码外,您在实现下一个创意时也可借鉴该实例。
物料清单:
seeed raspberry pi 2 model b
xp power:36 v 电源
nmb technologies corporation:步进电机(零件即将缺货。)
b&k precision:试验板
项目电线
bud industries
mikroelektronika
honeywell:限位开关
dte6-2rq9
ngcmb10ax01r
judco manufacturing:表面贴装开关
c&k components:js 系列滑动开关
其它零件:
gecko 210x 步进电机控制器
½ 英寸 8 头丝杠
bass 丝杠螺母
轴台轴承
联轴器
滑轮
电机驱动正时皮带
铝型材
直线轴承
精密连杆
两个定制底座、滑动架和轴台
代码:
代码、按钮控制
发送顺时针 (cw) 和逆时针 (ccw) 脉冲至步进驱动器;对限位开关做出反应;按初始行程方向相反的方向转动电机以“退避”限位开关。
导入模块和/或模块分段
import rpi.gpio as gpio
import time
设置 i/o 引脚掩码
step = 18 # step signal to driver
directionpin = 23 # direction signal to driver
enable = 24 # enable signal to driver
button1 = 13 # direction pin
button2 = 5
output1 = 19
output2 = 12
output3 = 21
speedhilo = 6
limitleft = 12
limitright = 16
设置通用 io
gpio.setmode(gpio.bcm) #configure pin layout
gpio.setwarnings(false)
gpio.setup(step, gpio.out)
gpio.output(step, gpio.low)
gpio.setup(directionpin, gpio.out)
gpio.output(directionpin, gpio.low)
gpio.setup(enable, gpio.out)
gpio.output(enable, gpio.high)
gpio.setup(button1, gpio.in, pull_up_down=gpio.pud_down)
gpio.setup(button2, gpio.in, pull_up_down=gpio.pud_down)
gpio.setup(speedhilo, gpio.in, pull_up_down=gpio.pud_down)
gpio.setup(limitleft, gpio.in, pull_up_down=gpio.pud_up)
gpio.setup(limitright, gpio.in, pull_up_down=gpio.pud_up)
一般配置及声明
global lospeed, hispeed, starttime, endtime, limitflag, timevar, acceltime, deceltime,decelpulsecoun, flag1, highpulse, direction, limitpulsecount
flag1 = 0 # variable for loop control
timevar = 0 # variable for loop control
direction = 0 # variable for storing direction pin value
endtime = 0 # variable for storing wait time between pulses whilst slowing to a stop
limitflag = 0 # signals that limit has been reached and flow must return to main loop
highpulse = 0.0001 # time for pulses to go high to trigger driver
starttime = 0.001 # time between pulses at start of movement
hispeed = 0.0001 # time between pulses at full speed
lospeed = 0.001 # time between pulses
acceltime = 0.000003 # amount of time to decrement between acceleration pulses
deceltime = 0.00005 # amount of time to increment between deceleration pulses
decelpulsecount = 50 # number of pulses sent during deceleration, 1/4 rev for current setup
limitpulsecount = 200 # number of pulses sent to the driver when a limit is tripped, 1/2 rev for current setup
功能定义
def rampup():
gpio.output(enable, 1) # enable driver for movement
timevar = starttime #initialize time variable with starting time between pulses
global flag1
global limitflag
global direction
flag1 = 1 # set flag hi
if(gpio.input(button1)):
direction = 1
gpio.output(directionpin, direction)
# light an led
if(gpio.input(button2)):
direction = 0
gpio.output(directionpin, direction)
# light an led
while((gpio.input(button1) or gpio.input(button2) == 1)):
if(gpio.input(limitleft)== 0): # if a limit input goes low, call the limit function
limit()
if(gpio.input(limitright)== 0): #if a limit input goes low, call the limit function
limit()
if(limitflag == 1):
limitflag = 0
break
gpio.output(step, 1)
time.sleep(highpulse)
gpio.output(step, 0)
time.sleep(abs(timevar))
if(timevar > endtime):
timevar = timevar - acceltime #decrease time between pulses until they reach endtime
def rampdown():
global flag1
flag1 = 0
global timevar
timevar = endtime #initialize time variable with ending time bewteen pulses
x = decelpulsecount
while(x > 0):
x = x - 1
gpio.output(step, 1)
time.sleep(highpulse)
gpio.output(step, 0)
time.sleep(abs(timevar))
if(timevar 0):
x = x - 1
gpio.output(step, 1)
time.sleep(highpulse)
gpio.output(step, 0)
time.sleep(abs(timevar))
if(timevar 0):
x = x - 1
gpio.output(step, 1)
time.sleep(highpulse)
gpio.output(step, 0)
time.sleep(abs(timevar))
if(timevar endtime):
timevar = timevar - acceltime
if(gpio.input(speedhilo) == 0):
endtime = lospeed #if lo-speed selected, initialize endtime with lo-speed wait time
else:
endtime = hispeed
高频集成稳压器缩小PCB面积实现有效的热管理
电容分压器电路计算示例
2021年物联网将迎来前景可期的五个发展趋势
上海微系统所发布面向5G NR与WiFi6的双模SAW滤波器
必达安保系统G456M4-65A门锁简介
Raspberry Pi完成直线平台的设计全过程
Micro LED相比于其他显示技术有什么优势?
51单片机编程开发之C语言基础一
iOS11 beta2推出还隐藏了27个功能更新,苹果没告诉你嘛?
一加3T终于吃到牛轧糖 一加3/3T开始推送氢OS3.0
小米MIX2最新消息汇总:小米MIX2超强配置,屏占比走上巅峰!雷军又一经典之作
电视网上购物消亡史
虚拟仪器技术的汽车CAN节点测试仪设计
极海APM32F411芯片2.1寸OLED屏应用案例
dfrobot单头管式加热器简介
手机市场利润 iPhone遥遥领先
速锐得解码匹配特斯拉电动汽车安全性能检测车架号及BMS电池数据
探究感应电机气隙偏心故障研究综述
鸿海斥资千万美元入股AI创企蓦然认知
广州京写将参展NEPCON South China 2013