步进电机定位问题解决尝试

    有关步进电机前面我们已经做过实验,主要是执行给定的步数;然后步进电机按照设置的频率执行;这部分可见文章:步进电机驱动实验;但是有时候我们会遇到一些场景,比如我们希望步进电机在指定的旋转位置停止;这时候如果只是计算设置频率的步数会容易出现不精确的现象;因此我们想到一个方案,在需要停止的地方加上一个传感器作为检测反馈;就像我们常用的倒车雷达当有障碍物时变会及时提醒我们,然后我们做出减速设置刹车的决定。
    在本实验,这个充当检测反馈的传感器就是U型光电传感器;关于U型光电传感器的使用方法可以见前面的实验:U型光电传感器实验,以及U型光电传感器测速实验;实验用到的3D打印件,以及接线示例见下图:
组装效果
组装效果
接线示例
    具体的接线部分可分别查看文章:步进电机驱动实验以及U型光电传感器实验;其中供电部分我们采用的是家用的6节5号电池;这部分可自由搭配,大于5V即可;同时接线的时候如果有GND,建议先接GND,防止带电操作损坏传感器;
#实验效果
    由第一张图注解可以看到,转盘我们定义了4个点,4个点不是固定的可以随意定义多个点;但是需要注意每个点后面需要有一个触发板,用于U型光电传感器的感知;我们默认A点位初试点,然后定义比如从A点到B点为一个步长,A点到C点为两个步长,然后以此类推;最后达到我们输入指定的步长然后步进电机能够精准停止在指定的点上的效果。先看效果图:
执行效果
    由于视频压缩厉害,可能看不清输入的信息;第一个输入是2,就是执行2个步长;可见步进电机开始转动,每经过一个位置点就能看到背面光亮从亮到灭的过程,这就是U型光电传感器被触发了一次,我们记做一个步长;当步长等于我们录入的指令时,步进电机停止准确停止在C点;待停顿一秒后,然后又恢复到初试位置A点;等待下次执行。接下来看一下代码实现;

#coding:utf-8

'''
from JiuJiang
树莓酱的操作实例
https:://www.shumeijiang.com
'''
import sys
import RPi.GPIO as GPIO ##引入GPIO模块
import time    ##引入time库
from classes.motorAct import motorAct  #引入动作类
GPIO.setwarnings(False)

#u型光电传感器
uPin = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(uPin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) #初始化u型光电低电压

#动作实例化
motor = motorAct()

#定义多步操作
def walk(step, direction):
    if not step:
        return ;
    if not direction:
        direction = 'forward'

    run = 0
    roundStep = 600 #圈长 大于一圈的长度
    for i in range(0, roundStep):
        tect = GPIO.event_detected(uPin)
        status = GPIO.input(uPin)

        #发现事件且处于高电平
        if tect == 1 and status == GPIO.HIGH:
            run += 1
        if direction == 'backward':
            motor.oneStepBack(0.003)
        elif direction == 'forward':
            motor.oneStep(0.003)

        #检测停止条件
        if run >= step:
            motor.stopMoving()
            break

        time.sleep(0.005)  ##每步间的间隔
        #print("第%d步" % i)
    return run

#执行步进
if __name__ == '__main__':
    try:
        step = raw_input("走几步")
        step = int(step)

        #最大步长
        max_step = 4
        if step > max_step:
            print('bad step')
            sys.exit()

        #注册一个电平RISING事件 设置防抖时间
        GPIO.add_event_detect(uPin, GPIO.RISING, bouncetime=1000)

        #动作执行
        ret = walk(step, 'forward')  ##正向走对应步数
        time.sleep(1)
        walk(step, 'backward') ##反向走对应的步数
    except KeyboardInterrupt:
        pass

    GPIO.cleanup()
    其中U型光电检测涉及到传感器抖动问题的解决,这部分可以参考文章:树莓派之传感器防抖GPIO边缘检测函数等;由上面的代码可以看到,我们先注册一个U型光电传感器的RISING事件,即电压升高事件,然后接收要执行的步长进行执行,当检测U型光电被触发的次数等于步长时则停止;停止1秒后,再恢复原点;当然也可以不恢复原点,但是需要记录执行后的原点位置,这样下次执行时才知道要执行到某一点是从哪里开始。
3D打印件stl文件,可以通过发送邮件lee.chuke@foxmail.com获取。