(14)树莓派B+使用L298N驱动控制四驱车并实现一个简单的web控制端

在系列文章第12篇中提到了L298N,它是H桥双路直流电机驱动,可以使双路直流电机实现正转或者反转,并且通过ENDA和ENDB输入PWM信号,还可以实现加减速。本文用2块L298N驱动板成功驱动了4个直流电机,实现了4轮同时向前、向后以及前向左转、前向右转甚至是后向左转和后向右转的功能,最后通过python的BaseHTTPServer模块(python3中是http.server模块)实现了一个控制小车的HTTP接口,另外用lighttpd启动一个网页,通过网页中的ajax调用控制小车的HTTP接口,最终实现通过web的方式来控制智能小车。

首先介绍一下L298N驱动的使用方法:

电源端(12V、GND、5V),输入5V直流电到L298N的5V接口时,直流电机几乎不能正常运转,当我们输入7-12V接到L298N的12V引脚时,该驱动板还可以在5V引脚输入电压供外部使用,所以输入驱动板的电压就接在12V引脚即可,经测试,5V输入到12V引脚可以正常工作,小车的直流电机也可以正常工作。

逻辑输入端(ENDA IN1 IN2 IN3 IN4 ENDB),分别连接树莓派的GPIO接口,控制逻辑如下图,在本人测试过程中,ENDB端是和IN1 IN2配合使用控制M1电机的,还请大家使用时先测试好:

关于加减速的PWM,我们先忽略,在实现了前进、后退和功能后,这个只是锦上添花的功能,而且可有可无。

接下来,我们就可以连接线路了,如果想要小车移动方便,最好使用移动电源来给树莓派、小车供电(用4节1.5V电池也可以),本人使用的是重达1斤的2万毫安时双输出口移动电源,正好可以给树莓派和外接电路供电。如果暂时没有移动电源,可以只做好测试工作,把小车架空,不要让其随意乱走。

树莓派GPIO和L298N连接关系如下(BOARD编号模式下的GPIO引脚-L298N输入引脚,都是高电平使能,其它引脚低电平):

前轮驱动:18-ENDB, 22-ENDA, 11-左前前, 13-左前后, 15-右前前, 29-右前后

后轮驱动:38-ENDB, 40-ENDA, 31-左后前, 33-左后后, 35-右后前, 37-右后后

电源输出:5V 1A- 树莓派,5V 2.1A-外部电路(面包板,2块L298N驱动)

L298N和电机:按照使用方法中的逻辑关系,每块的OUT1 OUT2接一个电机,OUT3 OUT4接另外一个。

最好在连接前,就已经测试好电机的正负极,L298N连接时都保持一定的先后次序,如IN1 IN2 ENDB 控制 OUT1 OUT2从而控制电机1,这样在写程序测试时会方便很多。

手绘电路图如下,其实比较简单,就是线多而已:

L298N控制4驱直流电机的驱动如下(python2/python3):

L298N_car2.py

#!/usr/bin/python2

#coding=utf-8

import RPi.GPIO as GPIO

import time

‘‘‘

使用2块L298N驱动控制4个直流电机

前轮驱动:18-ENDB, 22-ENDA, 11-左前前, 13-左前后, 15-右前前, 29-右前后

后轮驱动:38-ENDB, 40-ENDA, 31-左后前, 33-左后后, 35-右后前, 37-右后后

‘‘‘

# 初始化设置引脚输出

def init():

GPIO.setmode(GPIO.BOARD)

GPIO.setup(18, GPIO.OUT)

GPIO.setup(11, GPIO.OUT)

GPIO.setup(13, GPIO.OUT)

GPIO.setup(22, GPIO.OUT)

GPIO.setup(15, GPIO.OUT)

GPIO.setup(29, GPIO.OUT)

GPIO.setup(38, GPIO.OUT)

GPIO.setup(31, GPIO.OUT)

GPIO.setup(33, GPIO.OUT)

GPIO.setup(40, GPIO.OUT)

GPIO.setup(35, GPIO.OUT)

GPIO.setup(37, GPIO.OUT)

# 所有引脚置低电平,用于复位、停止运行的功能

def reset():

GPIO.output(18, GPIO.LOW)

GPIO.output(11, GPIO.LOW)

GPIO.output(13, GPIO.LOW)

GPIO.output(22, GPIO.LOW)

GPIO.output(15, GPIO.LOW)

GPIO.output(29, GPIO.LOW)

GPIO.output(38, GPIO.LOW)

GPIO.output(31, GPIO.LOW)

GPIO.output(33, GPIO.LOW)

GPIO.output(40, GPIO.LOW)

GPIO.output(35, GPIO.LOW)

GPIO.output(37, GPIO.LOW)

# 左前轮向前转

def front_left_forward():

GPIO.output(18, GPIO.HIGH)

GPIO.output(11, GPIO.HIGH)

GPIO.output(13, GPIO.LOW)

# 右前轮向前转

def front_right_forward():

GPIO.output(22, GPIO.HIGH)

GPIO.output(15, GPIO.HIGH)

GPIO.output(29, GPIO.LOW)

# 左后轮向前转

def rear_left_forward():

GPIO.output(38, GPIO.HIGH)

GPIO.output(31, GPIO.HIGH)

GPIO.output(33, GPIO.LOW)

# 右后轮向前转

def rear_right_forward():

GPIO.output(40, GPIO.HIGH)

GPIO.output(35, GPIO.HIGH)

GPIO.output(37, GPIO.LOW)

def front_left_back():

GPIO.output(18, GPIO.HIGH)

GPIO.output(11, GPIO.LOW)

GPIO.output(13, GPIO.HIGH)

def front_right_back():

GPIO.output(22, GPIO.HIGH)

GPIO.output(15, GPIO.LOW)

GPIO.output(29, GPIO.HIGH)

def rear_left_back():

GPIO.output(38, GPIO.HIGH)

GPIO.output(31, GPIO.LOW)

GPIO.output(33, GPIO.HIGH)

def rear_right_back():

GPIO.output(40, GPIO.HIGH)

GPIO.output(35, GPIO.LOW)

GPIO.output(37, GPIO.HIGH)

# 前进,4轮全部向前转

def forward():

reset()

front_left_forward()

front_right_forward()

rear_left_forward()

rear_right_forward()

# 后退,4轮全部向后转

def back():

reset()

front_left_back()

front_right_back()

rear_left_back()

rear_right_back()

# 前向左转,右边两个轮子向前转

def front_left_turn():

reset()

front_right_forward()

rear_right_forward()

time.sleep(0.3)

reset()

# 前向右转

def front_right_turn():

reset()

front_left_forward()

rear_left_forward()

time.sleep(0.3)

reset()

# 后向左转

def rear_left_turn():

reset()

rear_left_back()

front_left_back()

time.sleep(0.3)

reset()

# 后向右转

def rear_right_turn():

reset()

rear_right_back()

front_right_back()

time.sleep(0.3)

reset()

# 停止

def stop():

reset()

# 测试各个功能点

if __name__ == "__main__":

init()

reset()

#front_left_forward()

#front_right_forward()

#rear_left_forward()

#rear_right_forward()

forward()

time.sleep(2)

back()

time.sleep(2)

front_left_turn()

time.sleep(1)

front_right_turn()

time.sleep(1)

rear_left_turn()

time.sleep(1)

rear_right_turn()

stop()

GPIO.cleanup()

驱动程序测试完毕以后,我们就可以写一个HTTP server来提供通过HTTP的方式调用驱动接口。python实现HTTP Server不做详细介绍,我们直接使用最简单的方式即可,毕竟不会涉及多线程、并发。

参考程序如下:

rasphttp2.py

#!/usr/bin/python2

#coding=utf-8

from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler

import urllib

import L298N_car2 as car

from abc import ABCMeta, abstractmethod

class DispatcherHandler(BaseHTTPRequestHandler):

def do_GET(self):

print ‘client:‘, self.client_address, ‘reuest path:‘, self.path, \

‘command:‘, self.command

#query = urllib.splitquery(self.path)

query= self.path.split(‘?‘, 1)

action = query[0]

params = {}

if len(query) == 2:

for key_value in query[1].split(‘&‘):

kv = key_value.split(‘=‘)

if len(kv) == 2:

params[kv[0]] = urllib.unquote(kv[1]).decode("utf-8", "ignore")

runCar = RunCar()

buf = {}

if self.path.startswith("/car?"):

buf["return"] = runCar.action(params)

else:

buf["return"] = -1

self.protocal_version = "HTTP/1.1"

self.send_response(200)

self.send_header("Content-type", "application/json; charset=UTF-8")

#self.send_header("Content-type", "test/html; charset=UTF-8")

self.send_header("Pragma", "no-cache")

self.send_header("Cache-Control", "no-cache")

self.end_headers()

self.wfile.write(buf)

def do_POST(self):

self.send_error(404)

class Job():

__metaclass__ = ABCMeta

@abstractmethod

def action(self, params):

pass

class RunCar(Job):

def __init__(self):

car.init()

#子类必须实现父类的抽象方法,否则实例化时会报错

def action(self, params):

print params

act = int(params[‘a‘])

if act == 1:

car.forward()

return 1

if act == 2:

car.back()

return 1

if act == 3:

car.front_left_turn()

return 1

if act == 4:

car.front_right_turn()

return 1

if act == 5:

car.rear_left_turn()

return 1

if act == 6:

car.rear_right_turn()

return 1

if act == 0:

car.stop()

return 1

else:

return -1

if __name__ == "__main__":

PORT_NUM = 8899

serverAddress = ("", PORT_NUM)

server = HTTPServer(serverAddress, DispatcherHandler)

print ‘Started httpserver on port: ‘, PORT_NUM

try:

server.serve_forever()

except KeyboardInterrupt, e:

pass

finally:

server.socket.close()

print ‘Exit...‘

运行rasphttp2.py程序(python2 rasphttp2.py或者chmod a+x rasphttp2.py && ./rasphttp2.py),成功启动一个HTTP server以后,就可以在浏览器中测试接口了,比如:http://raspberryIP:8899/car?a=1 表示测试小车向前进的接口。可以通过HTTP
server的后台输出观察控制信息。

最后,为了更加方便的操作小车,我们可以提供一个简单的网页,点击网页上的按钮就可以操作我们的小车了。

参考代码:

car.html

<html>

<head>

<meta http-equiv="content-type" content="test/html; charset=UTF-8" />

<title>智能小车控制端</title>

<script type="text/javascript" src="/jquery.js"></script>

<script type="text/javascript">

$(document).ready(function(){

$("#forward").click(function(){

$.ajax({

type: "GET",

url: "http://192.168.1.111:8899/car",

data: {"a": 1},

dataType: "json",

cache: "false",

success: function(data){},

error: function(data){}

});

});

$("#stop").click(function(){

$.ajax({

type: "GET",

url: "http://192.168.1.111:8899/car",

data: {"a": 0},

dataType: "json",

cache: "false",

success: function(data){},

error: function(data){}

});

});

$("#back").click(function(){

$.ajax({

type: "GET",

url: "http://192.168.1.111:8899/car",

data: {"a": 2},

dataType: "json",

cache: "false",

success: function(data){},

error: function(data){}

});

});

$("#front_left_turn").click(function(){

$.ajax({

type: "GET",

url: "http://192.168.1.111:8899/car",

data: {"a": 3},

dataType: "json",

cache: "false",

success: function(data){},

error: function(data){}

});

});

$("#front_right_turn").click(function(){

$.ajax({

type: "GET",

url: "http://192.168.1.111:8899/car",

data: {"a": 4},

dataType: "json",

cache: "false",

success: function(data){},

error: function(data){}

});

});

});

</script>

</head>

<body>

<button id="forward" name="forward">前进</button>

<button id="back" name="back">后退</button>

<button id="front_left_turn" name="front_left_turn">左前拐</button>

<button id="front_right_turn" name="front_right_turn">右前拐</button>

<button id="stop" name="stop">停止</button>

</body>

</html>

如果你的树莓派上安装了HTTP服务器,则配置一下服务器根目录,正确访问car.hrml即可。我的是lighttpd,参考我的系列文章第6篇,配置好lighttpd.conf文件以及car.html的权限(文件所属比如是www:www,放在服务器根目录等等),通过lighttpd -f /path/lighttpd.conf即可。

另外,需要注意的是树莓派的防火墙中要允许使用的端口的网络连接;直接Ctrl+C 终止掉lighttpd在控制台的运行后,发现它的进程还在,可能是配置文件中没有相关的配置;树莓派每次启动后,在没有对GPIO进行设置前,如果接通L198N驱动的电源,小车有2个轮子会直接运行,可能和默认的GPIO输出有关系;我的PI现在还连的是网线,结合前面的建立无线AP的文章,现在可以用无线网卡发射AP,手机连上后访问控制页面来进行控制小车了,有点像遥控车,如果无线网卡不发射AP而连的是家里的路由器,则可以通过路由器转发,远程控制小车。

最后还是上一张实物图:

时间: 2024-10-11 23:08:27

(14)树莓派B+使用L298N驱动控制四驱车并实现一个简单的web控制端的相关文章

(14)树莓派B+使用L298N驱动控制四驱车

在系列文章第12篇中提到了L298N,它是H桥双路直流电机驱动,可以使双路直流电机实现正转或者反转,并且通过ENDA和ENDB输入PWM信号,还可以实现加减速.本文用2块L298N驱动板成功驱动了4个直流电机,实现了4轮同时向前.向后以及前向左转.前向右转甚至是后向左转和后向右转的功能,最后通过python的BaseHTTPServer模块(python3中是http.server模块)实现了一个控制小车的HTTP接口,另外用lighttpd启动一个网页,通过网页中的ajax调用控制小车的HTT

一个简单的行为控制管理方法

代码很简单 实现的方式很多,用cookies 用static 变量 file文件缓存 等等 比如 function behavior_function($function=__FUNCTION__, $class=__CLASS__) { $name = 'behavior_' . $class . '_' . $function; setcookie($name, $_COOKIE[$name]+1, time() + 3000, "/"); return $_COOKIE[$nam

asp.net 一个简单的登录控制

如果说一个网站需要用户登录后才能浏览,那么用户登录控制就不可避免.但是对于几百个以上的页面,不可能每个页面都做一次登录验证.因此,这需要在母版页中进行登录控制,这样就可以使得每一个使用这个母版页的子页面在加载的时候都会自动的进行一次登录验证.首先是创建一个网站项目,添加母版页和子页面,子页面引用母版页,同时还要创建一个登录页面.然后中母版页的Page_Load方法中调用验证登录的函数IsLogin protected void IsLogin() { try { if (Session["use

U3D 一个简单的角色控制脚本

之所以写这个脚本,是因为我想起了我还是新手的时候,那时为了一个角色控制脚本百度了半天还是一无所获,因为看不懂啊,都写的太高级了 希望这个脚本能够帮助那些 像曾经的我一样迷失于代码中的新手们能够清晰的理解这个角色控制的含义 ///角色控制脚本 public class Player : MonoBehaviour { public float m_speed=1;   //这个是定义的玩家的移动速度  之所以Public是因为为了方便对其进行调节  (public的属性和对象会在Unity中物体的

简单的web控制shell脚本方法

1)查看php运行用户: <?php system('id -a'); ?> 一般php运行用户是apache 2)给apache用户做密钥信任: 2.1) 先看看apache用户的信息: # su - apache This account is currently not available. # cat /etc/passwd|grep apache apache:x:48:48:Apache:/var/www:/sbin/nologin 改为: apache:x:48:48:Apach

【Espruino】NO.18 使用L298N驱动直流电机

http://blog.csdn.net/qwert1213131/article/details/38584743 本文属于个人理解,能力有限,纰漏在所难免,还望指正! [小鱼有点电] [Espruino中文社区] 小学时代玩过玩具四驱车,各种奇葩霸气的车型,疾驰的速度,令人神往,已经那个年代的回忆了,记得车子的转弯只能靠车轮旁边的转向轮,而且得碰到障碍才会转弯,有时候会因为高速而撞坏,想想如果能遥控该多爽,让他往哪就得往哪.废话不多说,开始正文. 需要准备一块基于L298N的电机驱动板(L2

dell optiplex ubuntu 14.04 安装 NVIDIA 显卡驱动

公司配置的 dell optiplex使用核显带起双屏幕,玩dota2无法特效全开.so,在京东上买了一块750Ti.安装驱动的时候需要切换到ubuntu的全命令行模式,关掉桌面系统才能安装.这时候这个坑出现了,要想安装驱动,就必须进入全命令行模式,要想进入命令行模式必须有驱动.反复尝试后,发现只能用DP口带单屏幕才能成功.在这里特别记录下.嘎嘎dell optiplex ubuntu 14.04 安装 NVIDIA 显卡驱动,布布扣,bubuko.com

Laptop Ubuntu16.04/14.04 安装Nvidia显卡驱动

笔记本型号 机械革命(MECHREVO)深海泰坦X6Ti-S(黑曜金)15.6英寸 CPU型号 i5-7300HQ 内存 8G 硬盘容量 128SSD+1T机械硬盘 显卡 GeForce GTX 1050 显存容量 4G 怎样选购用于Linux的笔记本电脑? 在笔记本上安装linux驱动问题主要发生在 GPU 和网卡上.网卡选 Intel 或者 Broadcom 就基本不会有问题了. 显卡推荐N卡,并且是 MUXed 的连接方式. 这里需要解释一个概念,MUXed vs MUXless 大家都知

【STM32H7教程】第41章 STM32H7的BDMA应用之控制任意IO做PWM和脉冲数控制

完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第41章       STM32H7的BDMA应用之控制任意IO做PWM和脉冲数控制 本章教程为大家讲解定时器触发DMAMUX,控制BDMA让GPIO输出PWM以及脉冲数的控制,实际项目中有一定的使用价值. 41.1 初学者重要提示 41.2 定时器触发BDMA驱动设计 41.3 BDMA板级支持包(bsp_tim_dma.c) 41.4 BDMA驱动移植和使用 41