树莓派4B-Python-控制L298N
- L298N(迷你版)模块
- 参数介绍
- 工作原理
- 与树莓派4B连接
- 代码
- 1.PWM控制方式:
- 2.无线控制 / 远程控制方式:
- 3.另一种无线控制 / 远程控制的方式:
- 4.网页控制(局域网):
本篇文章是用Python语言编写的程序通过树莓派4B控制L298N模块,最终实现让两个电机任意的正反转。
L298N(迷你版)模块
本人使用的是这款L298N迷你型,虽然少了许多东西(如巨大的散热片等),但是功能还是一样的。
参数介绍
工作电压:2V~10V
工作电流:单路工作电流为1.5A,峰值电流可达2.5A,待机电流小于0.1uA
双H桥,可控制两个或四个电机(四个电机为两两并联)
该模块的原理图大概如下:
工作原理
L298N电机驱动模块搭载两个H桥集成电路,供电电压范围较大,范围在2V~10V之间,供电电压越高,给予控制的直流电机电压也越高,随之直流电机转动的速度也会越快;输入端分别是IN1、IN2、IN3、IN4,用于接收控制器发出的电信号;当输入端发出信号后,输出端就可以控制两组直流电机正反转。
以下为L298N的逻辑控制表和控制流程图。
与树莓派4B连接
红色:5V---- +
蓝色:GND---- -
黄色:GPIO19----IN1
绿色:GPIO16----IN2
橙色:GPIO26----IN3
紫色:GPIO20----IN4
代码
1.PWM控制方式:
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
IN1_PIN1 = 19
IN2_PIN1 = 16
IN1_PIN2 = 26
IN2_PIN2 = 20
GPIO.setup(IN1_PIN1, GPIO.OUT)
p1 = GPIO.PWM(IN1_PIN1, 50) # 这里的50是频率为50Hz
p1.start(0)
GPIO.setup(IN2_PIN1, GPIO.OUT)
p2 = GPIO.PWM(IN2_PIN1, 50)
p2.start(0)
GPIO.setup(IN1_PIN2, GPIO.OUT)
p3 = GPIO.PWM(IN1_PIN2, 50)
p3.start(0)
GPIO.setup(IN2_PIN2, GPIO.OUT)
p4 = GPIO.PWM(IN2_PIN2, 50)
p4.start(0)
# 可以通过更改括号内的数值改变电机转动的速度,数值范围0~100
def forward(time_sleep):
p1.start(50)
p2.start(0)
p3.start(50)
p4.start(0)
time.sleep(time_sleep)
def reverse(time_sleep):
p1.start(0)
p2.start(50)
p3.start(0)
p4.start(50)
time.sleep(time_sleep)
def left(time_sleep):
p1.start(50)
p2.start(0)
p3.start(0)
p4.start(0)
time.sleep(time_sleep)
def right(time_sleep):
p1.start(0)
p2.start(0)
p3.start(50)
p4.start(0)
time.sleep(time_sleep)
def left_0(time_sleep):
p1.start(50)
p2.start(0)
p3.start(0)
p4.start(50)
time.sleep(time_sleep)
def right_0(time_sleep):
p1.start(0)
p2.start(50)
p3.start(50)
p4.start(0)
time.sleep(time_sleep)
def stop(time_sleep):
p1.start(0)
p2.start(0)
p3.start(0)
p4.start(0)
time.sleep(time_sleep)
while True:
cmd = str(input("按以下键后回车(w,前进;x,后退;s,停止):"))
direction = cmd
if direction == "w" or "s" or "a" or "d" or "q" or "e":
if direction == "w": # 前进
forward(1)
stop(0.1)
elif direction == "s": # 后退
reverse(1)
stop(0.1)
elif direction == "a": # 单轮左转
left(1)
stop(0.1)
elif direction == "d": # 单轮右转
right(1)
stop(0.1)
elif direction == "q": # 双轮左转
left_0(1)
stop(0.1)
elif direction == "e": # 双轮右转
right_0(1)
stop(0.1)
elif direction == "x": # 停止移动
stop(0.1)
else:
print("命令无法识别")
break
2.无线控制 / 远程控制方式:
'''
功能为使用键盘控制小车移动,并不用按回车键
此程序必须在IDE上使用,并且要把有线/无线键盘接在树莓派上才可以使用,否则会出现列表索引超出范围的错误
'''
from gpiozero import Robot
from evdev import InputDevice, list_devices, ecodes
robot = Robot(left=(19, 16), right=(26, 20))
#获取可用的输入设备的列表
devices = [InputDevice(device) for device in list_devices()]
#过滤掉所有不是键盘的东西。键盘被定义为任意键盘
#键盘被被定义为任何具有密钥的设备,
#并且专门具有密钥1..31(大概是esc,数字键,QWERTY的第一行加上一些),哪个没有键0(保留)
must_have = {i for i in range(1, 32)}
must_not_have = {0}
devices = [
dev
for dev in devices
for keys in (set(dev.capabilities().get(ecodes.EV_KEY, [])),)
if must_have.issubset(keys)
and must_not_have.isdisjoint(keys)
]
#选择第一个键盘
keyboard = devices[0] #发生Error:列表索引超出范围
#原因:必须将键盘(有线或无线)连接到树莓派上,不能够用VNC和ssh连接的键盘
#问题的解决:需要将有线/无线键盘的USB直接插在树莓派的USB接口上,并且使用命令行输入
keypress_actions = {
ecodes.KEY_UP: robot.forward, # 键盘上的方向键:上
ecodes.KEY_DOWN: robot.backward, # 键盘上的方向键:下
ecodes.KEY_LEFT: robot.left, # 键盘上的方向键:左
ecodes.KEY_RIGHT: robot.right, # 键盘上的方向键:右
}
"""
此处进行扩展:
若想继续增加按键,可以添加:
ecodes.KEY_HOME:
ecodes.KEY_END:
ecodes.KEY_F1:
ecodes.KEY_F2:
...
ecodes.KEY_F12:
但是F1~F12按键中有一两个按键会触发其他功能,好像是F8和F10吧,可以不使用这两个按键,以免触发其他功能(是指软件本身的功能,不是自己程序的功能)
"""
for event in keyboard.read_loop():
if event.type == ecodes.EV_KEY and event.code in keypress_actions:
if event.value == 1: #按键响应
keypress_actions[event.code]()
if event.value == 0: #按键释放
robot.stop()
3.另一种无线控制 / 远程控制的方式:
比上一种更为方便
'''
KEY_UP 键盘方向键:上 0403 ↑
KEY_DOWN 键盘方向键:下 0402 ↓
KEY_LEFT 键盘方向键:右 0404 ←
KEY_RIGHT 键盘方向键:左 0405 →
KEY_F1 键盘F1键:F1 0410 Function keys.
KEY_F(n) 键盘Fn键:F(n) (KEY_F0 (n)) formula for f
L298N必须接5V,不然电机力度不够,转弯时不正常
使用命令行才能运行,且可以使用vnc的键盘,连接到树莓派上的键盘也可以用,在ssh中可以控制,退出控制小车的程序按 Ctrl+C
'''
import curses
from gpiozero import Robot
robot = Robot(left=(19, 16), right=(26, 20))
actions = {
curses.KEY_UP: robot.forward,
curses.KEY_DOWN: robot.backward,
curses.KEY_LEFT: robot.right,
curses.KEY_RIGHT: robot.left,
# 以下为按键的扩展
#curses.KEY_HOME:
#curses.KEY_END:
#curses.KEY_F1:
#curses.KEY_F2:
# ...
#curses.KEY_F12:
}
# 以下程序不明白也没关系,简单的说就是检测按键是否按下,会进行两次检测,按下后
def main(window):
next_key = None
while True:
curses.halfdelay(1)
if next_key is None:
key = window.getch()
else:
key = next_key
next_key = None
if key != -1:
curses.halfdelay(3)
action = actions.get(key)
if action is not None:
action()
next_key = key
while next_key == key:
next_key = window.getch()
robot.stop()
curses.wrapper(main)
##2020.8.20
4.网页控制(局域网):
1.以下是控制小车的程序,将程序文件命名为index.py:
#!/usr/bin/env python3
from bottle import get,post,run,request,template
import RPi.GPIO as GPIO
import time
# L298N引脚接GPIO
IN1 = 19
IN2 = 16
IN3 = 26
IN4 = 20
def init():
GPIO.setmode(GPIO.BCM)
GPIO.setup(IN1,GPIO.OUT)
GPIO.setup(IN2,GPIO.OUT)
GPIO.setup(IN3,GPIO.OUT)
GPIO.setup(IN4,GPIO.OUT)
# 前进
def forward(tf):
GPIO.output(IN1,GPIO.HIGH)
GPIO.output(IN2,GPIO.LOW)
GPIO.output(IN3,GPIO.HIGH)
GPIO.output(IN4,GPIO.LOW)
time.sleep(tf)
GPIO.cleanup()
# 后退
def down(tf):
GPIO.output(IN1,GPIO.LOW)
GPIO.output(IN2,GPIO.HIGH)
GPIO.output(IN3,GPIO.LOW)
GPIO.output(IN4,GPIO.HIGH)
time.sleep(tf)
GPIO.cleanup()
# 左转弯
def left(tf):
GPIO.output(IN1,GPIO.LOW)
GPIO.output(IN2,GPIO.HIGH)
GPIO.output(IN3,GPIO.HIGH)
GPIO.output(IN4,GPIO.LOW)
time.sleep(tf)
GPIO.cleanup()
# 右转弯
def right(tf):
GPIO.output(IN1,GPIO.HIGH)
GPIO.output(IN2,GPIO.LOW)
GPIO.output(IN3,GPIO.LOW)
GPIO.output(IN4,GPIO.HIGH)
time.sleep(tf)
GPIO.cleanup()
# 停止
def stop():
GPIO.output(IN1,False)
GPIO.output(IN2,False)
GPIO.output(IN3,False)
GPIO.output(IN4,False)
GPIO.cleanup()
@get("/")
def index():
return template("index")
@post("/cmd")
def cmd():
print("按下了按钮: "+request.body.read().decode())
init()
sleep_time = 1
arg = request.body.read().decode()
if(arg=='up'):
forward(sleep_time)
elif(arg=='down'):
down(sleep_time)
elif(arg=='left'):
left(sleep_time)
elif(arg=='right'):
right(sleep_time)
elif(arg=='stop'):
stop()
else:
return False
#return "OK"
run(host="0.0.0.0",port="8080")
2.以下为连接web的程序,命名为main.py:
#!/usr/bin/env python3
from bottle import get,post,run,request,template
@get("/")
def index():
return template("index")
@post("/cmd")
def cmd():
print("按下了按钮: "+request.body.read().decode())
#return "OK"
run(host="0.0.0.0",port="8080")
3.接下来就是html文件了,命名为index.html:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>树莓派遥控小车</title>
<link href="http://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" media="screen">
<script src="http://code.jquery.com/jquery.js"></script>
<style type="text/css">
#up {
margin-left: 55px;
margin-bottom: 3px;
}
#down {
margin-top: 3px;
margin-left: 55px;
}
</style>
<script>
$(function(){
$("button").click(function(){
$.post("/cmd",this.id,function(data,status){});
});
});
</script>
</head>
<body>
<div id="container" class="container">
<div>
<button id="up" class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-up"></button>
</div>
<div>
<button id='left' class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-left"></button>
<button id='stop' class="btn btn-lg btn-primary glyphicon glyphicon-stop"></button>
<button id='right' class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-right"></button>
</div>
<div>
<button id='down' class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-down"></button>
</div>
</div>
<script src="http://cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</body>
</html>
说明一下,先将树莓派与电脑 / 手机连接在同一个局域网内(比如同一个WiFi下,或者用手机开热点让电脑和树莓派连接上),树莓派上需要先运行index.py程序(本人是用Thonny软件打开的),底下就会显示接收或发出的控制动作命令。然后再用电脑 / 手机输入类似的网址就可以控制小车移动了:
http://192.168.43.165:8080/
192.168.43.165------这是你树莓派连接网络用的地址
8080--------------------这是在index.py和main.py中设置的
在第一次连接时会非常慢,多试几次会成功的(应该也是可以直接双击打开index.html进入的),就会得到如下图所示网页界面(这是在树莓派内直接双击打开index.html得到的)。
##2020.8.28
希望以上代码对大家有所帮助!
已经加入网页(局域网)控制小车的代码