手动写一个电机模块
一个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)