树莓派4B-Python-控制L298N

  • L298N(迷你版)模块
  • 参数介绍
  • 工作原理
  • 与树莓派4B连接
  • 代码
  • 1.PWM控制方式:
  • 2.无线控制 / 远程控制方式:
  • 3.另一种无线控制 / 远程控制的方式:
  • 4.网页控制(局域网):



本篇文章是用Python语言编写的程序通过树莓派4B控制L298N模块,最终实现让两个电机任意的正反转。

L298N(迷你版)模块

本人使用的是这款L298N迷你型,虽然少了许多东西(如巨大的散热片等),但是功能还是一样的。

通过树莓派控制PWM直流电机的无级变速调速器 Python代码 树莓派能控制电机吗_方向键

参数介绍

工作电压:2V~10V
工作电流:单路工作电流为1.5A,峰值电流可达2.5A,待机电流小于0.1uA
双H桥,可控制两个或四个电机(四个电机为两两并联)

该模块的原理图大概如下:

通过树莓派控制PWM直流电机的无级变速调速器 Python代码 树莓派能控制电机吗_python_02

工作原理

L298N电机驱动模块搭载两个H桥集成电路,供电电压范围较大,范围在2V~10V之间,供电电压越高,给予控制的直流电机电压也越高,随之直流电机转动的速度也会越快;输入端分别是IN1、IN2、IN3、IN4,用于接收控制器发出的电信号;当输入端发出信号后,输出端就可以控制两组直流电机正反转。

以下为L298N的逻辑控制表和控制流程图。

通过树莓派控制PWM直流电机的无级变速调速器 Python代码 树莓派能控制电机吗_方向键_03


通过树莓派控制PWM直流电机的无级变速调速器 Python代码 树莓派能控制电机吗_ico_04

与树莓派4B连接

通过树莓派控制PWM直流电机的无级变速调速器 Python代码 树莓派能控制电机吗_树莓派_05


红色:5V---- +

蓝色:GND---- -

黄色:GPIO19----IN1

绿色:GPIO16----IN2

橙色:GPIO26----IN3

紫色:GPIO20----IN4

通过树莓派控制PWM直流电机的无级变速调速器 Python代码 树莓派能控制电机吗_python_06

代码

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得到的)。

通过树莓派控制PWM直流电机的无级变速调速器 Python代码 树莓派能控制电机吗_树莓派_07


程序参考出处

##2020.8.28
希望以上代码对大家有所帮助!
已经加入网页(局域网)控制小车的代码