手动写一个电机模块

一个python模块就是一个.py文件。我们通过一个简单的easyDriver步进电机模块,来讲解一下如何手动地编写一个step_motor.py

注意:此内容需要的知识稍多,如果网上可以找到别人写好的模块文件,建议不需要自己编写代码,不需要重复造轮子。

但是写一个python模块,比在一些单片机用C语言写一个可调用的驱动,要方便多了。

知识:

  • 了解步进电机的驱动原理
  • 了解easyDriver的使用方式
  • 了解编写Python的类

了解控制原理

首先,要知道步进电机:

我们的硬件是一个easyDriver驱动模块。

首先我们要搞清楚它的工作原理。

通过查找datasheet,和网上的资料。我们得知:

引脚DIR的高低决定电机的方向(正转/反转),STEP引脚给一个脉冲,步进电机就运行一步。

有关步进电机的原理,请看这篇文章:http://singtown.cc/?p=67

所以编程思路就是通过控制IO口的高低电平,来抽象出一个Stepper的类:

第一步:框架

class Stepper:
    def __init__(self, step_pin, dir_pin):
       #初始化

    def steps(self, step_count):
        #驱动电机走几步

    def rel_angle(self, angle):
        #驱动电机旋转相应的角度(相对角度控制)
    def abs_angle(self, angle):
        #驱动电机旋转到相应的位置(绝对角度控制)

这就是一个类了,只不过还没有添加实质的功能。

第二步:添加构造函数

构造函数在实例化对象的时候会调用,可以看成是初始化的功能。

比如s = Stepper(xxx)的时候,会执行init(xxx)里的程序。

参数里,我们传入两个引脚对象,还有一个step_time默认为200。因为步进电机是一步一步运动的,每一步之间需要有延时,这里默认是200us。

class Stepper:
    def __init__(self, step_pin, dir_pin, step_time=200):
        #初始化
        self.stp = step_pin
        self.dir = dir_pin

        self.stp.init(Pin.OUT_PP)
        self.dir.init(Pin.OUT_PP)

        self.step_time = step_time # us
        self.steps_per_rev = 1600
        self.current_position = 0

    def steps(self, step_count):
        #驱动电机走几步

    def rel_angle(self, angle):
        #驱动电机旋转相应的角度(相对角度控制)
    def abs_angle(self, angle):
        #驱动电机旋转到相应的位置(绝对角度控制)

添加硬件实现

udelay是延时us的函数,在第一句import进来。
在steps(xxx)中实现让步进电机运动的功能。
首先设置dir引脚的电平(控制方向),然后stp引脚发送高低脉冲就可以。

from pyb import udelay
class Stepper:
    def __init__(self, step_pin, dir_pin, step_time=200):
        #初始化
        self.stp = step_pin
        self.dir = dir_pin

        self.stp.init(Pin.OUT_PP)
        self.dir.init(Pin.OUT_PP)

        self.step_time = step_time # us
        self.steps_per_rev = 1600
        self.current_position = 0

    def steps(self, step_count=1):
        #驱动电机走几步
        self.dir.value(0 if step_count > 0 else 1)#当step_count为正数的时候,设置dir引脚为低电平。否则为高电平。
        for i in range(abs(step_count)):#发送step_count数量的脉冲
            self.stp.value(1)
            udelay(self.step_time)
            self.stp.value(0)
            udelay(self.step_time)
        self.current_position += step_count#记录现在的角度

    def rel_angle(self, angle):
        #驱动电机旋转相应的角度(相对角度控制)
    def abs_angle(self, angle):
        #驱动电机旋转到相应的位置(绝对角度控制)

测试steps

把这个类的代码保存成stepper.py文件,放到OpenMV的根目录中。
在main.py中调用Stepper,测试steps会不会使步进电机转动:
别忘了正确给电机供电。

from stepper import Stepper
from pyb import Pin
dir_pin = Pin(‘P0’)
stp_pin = Pin(‘P1’)

s = Stepper(step_pin=stp_pin, dir_pin=dir_pin)

s.steps()#电机动一步

s.steps(100)#电机动100步

s.steps(-100)#电机反转100步

添加旋转角度函数

init(xxx)中,写了一个steps_per_rev变量,这个的1600代表每圈1600个脉冲,为什么呢。。。因为电机的型号是200个脉冲(步进角为1.8度),easyDriver又进行了8细分,不知道细分的,看一下步进电机的资料。

既然一圈是1600脉冲,那么一步就是360/1600度啦。根据这个关系,角度转换成脉冲的公式就是:角度/360*1600。

那么在绝对角度控制中,因为把当前位置记录下来了,所以做一个差,然后旋转就可以了。

from pyb import udelay
class Stepper:
    def __init__(self, step_pin, dir_pin, step_time=200):
        #初始化
        self.stp = step_pin
        self.dir = dir_pin

        self.stp.init(Pin.OUT_PP)
        self.dir.init(Pin.OUT_PP)

        self.step_time = step_time # us
        self.steps_per_rev = 1600
        self.current_position = 0

    def steps(self, step_count=1):
        #驱动电机走几步
        self.dir.value(0 if step_count > 0 else 1)
        for i in range(abs(step_count)):
            self.stp.value(1)
            udelay(self.step_time)
            self.stp.value(0)
            udelay(self.step_time)
        self.current_position += step_count

    def rel_angle(self, angle):
        #驱动电机旋转相应的角度(相对角度控制)
        steps = int(angle / 360 * self.steps_per_rev)
        self.steps(steps)
    def abs_angle(self, angle):
        #驱动电机旋转到相应的位置(绝对角度控制)
        steps = int(angle / 360 * self.steps_per_rev)
        steps -= self.current_position % self.steps_per_rev
        self.steps(steps)

完成

至此,一个Stepper模块已经完成!还有一些额外的功能可以添加。比如读角度,旋转xx转。

在main.py中测试一下代码:

from pyb import Pin
from stepper import Stepper
import time

step_pin = Pin('P0')
dir_pin = Pin('P1')

my_stepper = Stepper(step_pin,dir_pin)

print("relative angle move test begin:", my_stepper.read_pos())
my_stepper.rel_angle(180)#相对角度控制
print("relative angle move test end:", my_stepper.read_pos())

time.sleep(1000)

print("steps angle move test end:", my_stepper.read_pos())
my_stepper.steps(-400)#步进脉冲控制
print("steps angle move test end:", my_stepper.read_pos())

time.sleep(1000)

print("absolute angle move test begin:", my_stepper.read_pos())
my_stepper.abs_angle(0)#绝对角度控制
print("absolute angle move test end:", my_stepper.read_pos())

time.sleep(1000)

results matching ""

    No results matching ""