上篇文章已经介绍了四驱小车如何组装,这篇文章我们将继续介绍如何驱动小车前进后退以及左转右转;因为小车循迹的过程中,会遇到左转线、直线、右转线以及停顿标示;这个时候就需要小车能实现左转、右转、直行、停车、后退等动作。
#直流电机驱动板L298N驱动原理:
直流电机 | 转动效果 | IN1 | IN2 | IN3 | IN4 |
MOTOR-A | 正向(调速) | 高电平/PWM | 低电平 | | |
| 反向(调速) | 低电平 | 高电平/PWM | | |
| 停止 | 低电平 | 低电平 | | |
| 刹车 | 高电平 | 高电平 | | |
MOTOR-B | 正向(调速) | | | 高电平/PWM | 低电平 |
| 反向(调速) | | | 低电平 | 高电平/PWM |
| 停止 | | | 低电平 | 低电平 |
| 刹车 | | | 高电平 | 高电平 |
从上面表格可见,motorA连接引脚IN1和IN2,当IN1高电平IN2低电平的时候,电机正向转动,其中IN1输入PWM进行调速和扭矩变化;反之IN1低电平和IN2高电平的时候电机反向转动,从而实现倒车;其他电机以此类推。
#其中PWM控制转速和扭矩,示例如下:
1、创建PWM实例:p = GPIO.PWM(channel, frequency);
2、开始PWM:p.start(duty_cycle) #duty_cycle为占空比;
3、更改频率,更改扭矩:p.ChangeFrequency(frequency);
4、更改占空比,更改转速:p.ChangeDutyCycle(duty_cycle);
5、PWM停止:p.stop()
#代码示例
#!/usr/bin/env python
#coding:utf-8
'''
from JiuJiang
树莓酱的操作实例
https:://www.shumeijiang.com
'''
import RPi.GPIO as GPIO ##引入GPIO模块
import time ##引入time库
GPIO.setmode(GPIO.BCM)
#驱动类
class baseAct:
def __init__(self, ain1, ain2, ain3, ain4, bin1, bin2, bin3, bin4):
self.ain1 = ain1
self.ain2 = ain2
self.ain3 = ain3
self.ain4 = ain4
self.bin1 = bin1
self.bin2 = bin2
self.bin3 = bin3
self.bin4 = bin4
GPIO.setup(self.ain1, GPIO.OUT)
GPIO.setup(self.ain2, GPIO.OUT)
GPIO.setup(self.ain3, GPIO.OUT)
GPIO.setup(self.ain4, GPIO.OUT)
GPIO.setup(self.bin1, GPIO.OUT)
GPIO.setup(self.bin2, GPIO.OUT)
GPIO.setup(self.bin3, GPIO.OUT)
GPIO.setup(self.bin4, GPIO.OUT)
#结束动作
def act_stop(self, duration, slow_time=0.15):
#执行时间
duration = float(duration)-slow_time
time.sleep(duration)
#self.init_move('forward', duration, 50, 50)
if slow_time:
#执行缓冲慢行
self.apwm1.ChangeDutyCycle(20)
self.apwm3.ChangeDutyCycle(20)
self.bpwm1.ChangeDutyCycle(20)
self.bpwm3.ChangeDutyCycle(20)
time.sleep(slow_time)
#结束动作
self.apwm1.stop()
self.apwm3.stop()
self.bpwm1.stop()
self.bpwm3.stop()
GPIO.output(self.ain2, GPIO.LOW)
GPIO.output(self.ain4, GPIO.LOW)
GPIO.output(self.bin2, GPIO.LOW)
GPIO.output(self.bin4, GPIO.LOW)
##PWM初始化
def init_move(self, act_type, duration, duty_ratio, hz_num):
if act_type == 'forward':
hpin1 = self.ain1
lpin1 = self.ain2
hpin2 = self.ain3
lpin2 = self.ain4
hpin3 = self.bin1
lpin3 = self.bin2
hpin4 = self.bin3
lpin4 = self.bin4
elif act_type == 'backward':
hpin1 = self.ain2
lpin1 = self.ain1
hpin2 = self.ain4
lpin2 = self.ain3
hpin3 = self.bin2
lpin3 = self.bin1
hpin4 = self.bin4
lpin4 = self.bin3
elif act_type == 'turn_left':
hpin1 = self.ain1
lpin1 = self.ain2 #右前电机前进 pin2低电平则前进
hpin2 = self.ain3
lpin2 = self.ain4 #右后电机前进
hpin3 = self.bin2
lpin3 = self.bin1 #左前电机后退 pin2高电平则后退
hpin4 = self.bin4
lpin4 = self.bin3 #左后电机后退
elif act_type == 'turn_right':
hpin1 = self.ain2
lpin1 = self.ain1 #右前电机后退 pin2高电平则后退
hpin2 = self.ain4
lpin2 = self.ain3 #右后电机后退
hpin3 = self.bin1
lpin3 = self.bin2 #左前电机前进 pin2高电平则前进
hpin4 = self.bin3
lpin4 = self.bin4 #左后电机前进
else:
print "不支持的类型"
pass
#挨个实例化每个电机的PWM实例
self.apwm1 = GPIO.PWM(hpin1, hz_num) #实例PWM 并可自定义hz
self.apwm1.start(0) #初始占空比为0
GPIO.output(hpin1, GPIO.HIGH) #设置单个电机一个高电压
GPIO.output(lpin1, GPIO.LOW) #另一个低电压
self.apwm1.ChangeDutyCycle(duty_ratio) #设置用户自定义占空比
#驱动第二个电机
self.apwm3 = GPIO.PWM(hpin2, hz_num)
self.apwm3.start(0)
GPIO.output(hpin2, GPIO.HIGH)
GPIO.output(lpin2, GPIO.LOW)
self.apwm3.ChangeDutyCycle(duty_ratio)
#驱动第三个电机
self.bpwm1 = GPIO.PWM(hpin3, hz_num)
self.bpwm1.start(0)
GPIO.output(hpin3, GPIO.HIGH)
GPIO.output(lpin3, GPIO.LOW)
self.bpwm1.ChangeDutyCycle(duty_ratio)
#驱动第四个电机
self.bpwm3 = GPIO.PWM(hpin4, hz_num)
self.bpwm3.start(0)
GPIO.output(hpin4, GPIO.HIGH)
GPIO.output(lpin4, GPIO.LOW)
self.bpwm3.ChangeDutyCycle(duty_ratio)
##前进
def act_forward(self, duration, duty_ratio, hz_num=50, close_slow=False):
self.init_move('forward', duration, duty_ratio, hz_num)
if close_slow:
slow_time = 0
else:
slow_time = 0.15
#停止动作 并执行缓冲
self.act_stop(duration, slow_time)
##后退
def act_backward(self, duration, duty_ratio, hz_num):
self.init_move('backward', duration, duty_ratio, hz_num)
#停止动作 并缓冲执行
self.act_stop(duration)
##向左转
def turn_left(self, duration, duty_ratio, hz_num, serial=False):
self.init_move('turn_left', duration, duty_ratio, hz_num) #左转执行
slow_time = 0.05 #减速时间
if serial==True:
slow_time = 0
self.act_stop(duration, slow_time) #动作停止
##向右转
def turn_right(self, duration, duty_ratio, hz_num, serial=False):
self.init_move('turn_right', duration, duty_ratio, hz_num) #右转执行
slow_time = 0.05 #减速时间
if serial==True:
slow_time = 0 #连续不减速
self.act_stop(duration, slow_time) #动作停止
##刹车
def act_break(self):
GPIO.output(self.ain1, GPIO.HIGH)
GPIO.output(self.ain2, GPIO.HIGH)
GPIO.output(self.ain3, GPIO.HIGH)
GPIO.output(self.ain4, GPIO.HIGH)
GPIO.output(self.bin1, GPIO.HIGH)
GPIO.output(self.bin2, GPIO.HIGH)
GPIO.output(self.bin3, GPIO.HIGH)
GPIO.output(self.bin4, GPIO.HIGH)
如上代码可见,封装了直流电机驱动类baseAct,以及直行、后退、左转、右转和刹车等方法;实例化类后便可直接调用,其中ain1、ain2、ain3、ain4为左侧电机驱动板引脚,bin1、bin2、bin3、bin4为右侧电机驱动板引脚,分别对应即可。
#参考文章:https://www.shumeijiang.com/2020/05/04/直流电机驱动变速实验/