硬件简介
采用Telesky 5v步进电机+ULN2003驱动板,在某宝上面一般为十元左右。
ULN2003是大电流驱动阵列,多用于一些设备的控制和驱动,可以直接驱动电机等设备。
步进电机转子每次都转动固定的角度,可以通过代码控制每次旋转的角度大小和准转动的次数,并按照预先设定的旋转方向进行转动,从而实现准确按照预设的方向进行旋转一定的角度。依靠步进电机我们可以实现开关门、摄像头的转向等操作。
转动控制
通过按照顺序把驱动板的四个gpio接口轮着置为高电平,便可以让步进电机进行转动一定的角度,要把树莓派的4个GPIO输出口依次置为高电平。正转时,GPIO1-4分次传入:[1,0,0,0],[sleep],[0,1,0,0],[sleep],[0,0,1,0],[sleep],[0,0,0,1]。逆转时,GPIO1-4分次传入:[0,0,0,1],[sleep],[0,0,1,0],[sleep],[0,1,0,0],[sleep],[1,0,0,0]。停止时,GPIO1-4一次传入:[0,0,0,0]。知道这些数据后我们便可以开始专注写应用程序了。
异步任务
由于整个系统需要一个较快的反馈,而步进电机的转动时间又比较长,因此采用异步任务的方式,这里使用到python的Celery异步任务模块,Celery是一个python开发的异步分布式任务调度模块。Celery本身并不提供消息服务,使用第三方服务,也就是borker来传递任务,一般使用rabbitMQ或者Redis,这里使用了redis,在树莓派上面直接apt便可以下载redis。
redis和相关python包安装
下载安装redis和python celery包:
sudo apt-get install redis-server
pip install Celery
默认redis安装完毕便自动启动服务,可执行sudo service redis-server status
查看redis状态:
● redis-server.service - Advanced key-value store
Loaded: loaded (/lib/systemd/system/redis-server.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2019-06-06 10:55:18 CST; 2 days ago
..............
代码
创建tasks.py
文件并增加以下内容:
# coding:utf-8
#!/usr/bin/env python
import RPi.GPIO as GPIO
import time
import sys
from celery import Celery
app = Celery('tasks', backend='redis://localhost:6379/0', broker='redis://localhost:6379/1') # 配置好celery的backend和broker
def setStep(w1, w2, w3, w4):
IN1 = 11 # pin11
IN2 = 12
IN3 = 13
IN4 = 15
GPIO.output(IN1, w1)
GPIO.output(IN2, w2)
GPIO.output(IN3, w3)
GPIO.output(IN4, w4)
def stop():
setStep(0, 0, 0, 0)
@app.task
def forward(delay, steps):
setup()
for i in range(0, steps):
setStep(1, 0, 0, 0)
time.sleep(delay)
setStep(0, 1, 0, 0)
time.sleep(delay)
setStep(0, 0, 1, 0)
time.sleep(delay)
setStep(0, 0, 0, 1)
time.sleep(delay)
destroy()
@app.task
def backward(delay, steps):
setup()
for i in range(0, steps):
setStep(0, 0, 0, 1)
time.sleep(delay)
setStep(0, 0, 1, 0)
time.sleep(delay)
setStep(0, 1, 0, 0)
time.sleep(delay)
setStep(1, 0, 0, 0)
time.sleep(delay)
destroy()
def setup():
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
IN1 = 11
IN2 = 12
IN3 = 13
IN4 = 15
GPIO.setup(IN1, GPIO.OUT)
GPIO.setup(IN2, GPIO.OUT)
GPIO.setup(IN3, GPIO.OUT)
GPIO.setup(IN4, GPIO.OUT)
def destroy():
GPIO.cleanup()
if __name__ == '__main__':
action = sys.argv[1].strip()
if action == 'on':
backward.delay(0.003, 512)
print('步进电机正转')
else:
forward.delay(0.005, 512)
print('反转')
开启worker执行任务
使用celery -A tasks worker --loglevel=info
命令启动,执行效果如下:
celery -A tasks worker --loglevel=info
-------------- celery@raspberrypi v4.3.0 (rhubarb)
---- **** -----
--- * *** * -- Linux-4.14.79-v7+-armv7l-with-debian-9.4 2019-06-08 19:46:28
-- * - **** ---
- ** ---------- [config]
- ** ---------- .> app: tasks:0x760bdeb0
- ** ---------- .> transport: redis://localhost:6379/1
- ** ---------- .> results: redis://localhost:6379/0
- *** --- * --- .> concurrency: 4 (prefork)
-- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
--- ***** -----
-------------- [queues]
.> celery exchange=celery(direct) key=celery
[tasks]
. tasks.add
. tasks.backward
. tasks.forward
[2019-06-08 19:46:28,459: INFO/MainProcess] Connected to redis://localhost:6379/1
[2019-06-08 19:46:28,505: INFO/MainProcess] mingle: searching for neighbors
[2019-06-08 19:46:29,605: INFO/MainProcess] mingle: all alone
[2019-06-08 19:46:29,672: INFO/MainProcess] celery@raspberrypi ready.
测试步进电机正反转
另外打开一个窗口执行python tasks.py on
命令,直接返回步进电机正转
的结果,查看worker任务执行窗口,会有一下信息显示:
[2019-06-08 19:48:48,129: INFO/MainProcess] Received task: tasks.backward[35446816-4f10-4af7-9199-849397972439]
[2019-06-08 19:48:54,483: INFO/ForkPoolWorker-3] Task tasks.backward[35446816-4f10-4af7-9199-849397972439] succeeded in 6.348048455s: None