简单的Web控制树莓派小车

说在前面:大四第一学期没课,决定做一个智能小车。从最初的一无所有,到小车可实现远程控制,虽然在这期间遇到了不少问题,但同时也让我学到了许多新知识。当然,小车的完成并非是我一个人的力量,各位大佬的教程给了我很大的帮助,在此表示感谢。在文末我会给出我所参考过的教程链接。

一、所需材料:

必需

  1. 树莓派(我的是4 B,其它代的也行)
  2. 小车车轮、电机、底盘。(*宝大概20块左右)
  3. L298N(电机驱动模块。*宝10块左右)
  4. 杜邦线若干(建议买长一点的,公公和公母都买一些)
  5. 18650充电锂电池。(至少4节,*宝40左右)
  6. 降压模块,5 A。(树莓派4 B的最大电流要求为3 A,我用充电宝输出的2.1 A给树莓派供电,树莓派开不了机。建议买那种不带示数的,便宜,不过就需要你有一个万用表了。)

可需

  1. 开关2个。(个人建议,开关会让你方便很多。*宝一个1块,包邮。)
  2. 电线。(杜邦线也可以给树莓派供电,不过我看有人用杜邦线给树莓派供电,树莓派运行不是很稳定。为了树莓派安全,建议用较粗的线给树莓派供电,*宝2 M 5块 包邮)
  3. 万用表。(建议买一个,因为它的用处真的很大。*宝15左右,挺准的。)
  4. 电烙铁。(不太贵,接头用锡焊一下不容易掉。)
  5. 树莓派摄像头。(可以让小车变成一个移动监控。)
  6. 超声波模块。(可实现避障功能,让小车更加智能。*宝10块左右)
  7. 舵机一个。(可以让小车实现自动避障)
  8. 470欧和300欧的电阻各一个。(用于超声波模块返回脉冲信号的分压。树莓派的GPIO口最大输入电压为3.3 V,超声波发送给树莓派的脉冲电压为5 V,为防止树莓派被烧,所以需要分压。
  9. 面包板一个。(串联电阻用)

之前还没做小车的时候,觉得挺简单的,需要的东西也不多,当真的做起来时,发现自己啥也没有。想和做确实不一样啊 ^ ^!

嗯~看看我的车啥样

简单的Web控制树莓派小车_第1张图片

俯视

简单的Web控制树莓派小车_第2张图片

侧视

二、接线

接线部分比较简单,我简要说一下我的接线方式,供大家参考。

1.树莓派供电

我看别人有用充电宝给树莓派供电的,不过我用充电宝2.1 A输出给树莓派供电,树莓派的黄灯一直闪。
我的供电方式:
简单的Web控制树莓派小车_第3张图片
如果你的小车上还要搭载别的传感器,你可以直接从降压模块的输出端给其供电。

2.电机供电

简单的Web控制树莓派小车_第4张图片

三、代码

  1. 小车控制界面

<html lang="en">
	<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">
  			#front {
				margin-left: 55px;
				margin-bottom: 3px;
					}
			#rear	{
				margin-top: 3px;
				margin-left: 55px;
					}
			.btn{
				background: #62559f;
				}
			/*嵌入视频页面大小*/
			#stream {
				width:360px;
				height:300px;
				margin-top:5px;
					}
			/*嵌入超声波测距页面大小*/
			#distance{
				width:200px;
				height:50px;
		style>
		
		<script> //鼠标事件脚本。
			function mouseDown(obj)
				{
				$.post("/cmd",obj.id,function(data,status){});
				}

			function mouseUp(obj)
				{
				$.post("/cmd","stop",function(data,status){});	
				}
		script>
	head>
	<body>
		
		<div> 
			<iframe id=stream  src="http://192.168.43.38:8082">iframe>
		div>
		
		<div id="container" class="container">
			<div>
				<button id="front" onmousedown="mouseDown(this)" onmouseup="mouseUp(this)" class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-up">button>
			div>
			<div>
 
				<button id='leftFront' onmousedown="mouseDown(this)" onmouseup="mouseUp(this)" 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='rightFront' onmousedown="mouseDown(this)" onmouseup="mouseUp(this)" class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-right">button>
			div>
			<div>
				<button id='rear' onmousedown="mouseDown(this)" onmouseup="mouseUp(this)" class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-down">button>
			div>
			<div>
				<button id='leftRear' onmousedown="mouseDown(this)" onmouseup="mouseUp(this)" class="btn btn-lg btn-primary glyphicon">左后转button>
				<button id='rightRear' onmousedown="mouseDown(this)" onmouseup="mouseUp(this)" class="btn btn-lg btn-primary glyphicon">右后转button>
			div>
		div>
		<script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js">script>
		
		<div> 
			<iframe id=distance src="http://192.168.43.38:8081">iframe>  
		div>
	body>
html>
  1. 小车方向控制代码
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
from bottle import get, post, run, request, route, template
import RPi.GPIO as GPIO
import time
import sys


####  定义Car类
class Car(object):
    def __init__(self):
        self.enab_pin = [36, 37]
        ####  self.enab_pin是使能端的pin
        self.inx_pin = [33, 35, 38, 40]
        ####  self.inx_pin是控制端in的pin
        self.RightAhead_pin = self.inx_pin[0]
        self.RightBack_pin = self.inx_pin[1]
        self.LeftAhead_pin = self.inx_pin[2]
        self.LeftBack_pin = self.inx_pin[3]
        ####  分别是右轮前进,右轮退后,左轮前进,左轮退后的pin
        self.setup()

    ####  setup函数初始化端口
    def setup(self):
        print("begin setup ena enb pin")
        GPIO.setmode(GPIO.BOARD)
        GPIO.setwarnings(False)
        for pin in self.enab_pin:
            GPIO.setup(pin, GPIO.OUT)
            GPIO.output(pin, GPIO.HIGH)
        ####  初始化使能端pin,设置成高电平
        pin = None
        for pin in self.inx_pin:
            GPIO.setup(pin, GPIO.OUT)
            GPIO.output(pin, GPIO.LOW)
        ####  初始化控制端pin,设置成低电平
        print("setup ena enb pin over")

    ####  front函数,小车前进
    def front(self):
        self.setup()
        GPIO.output(self.RightAhead_pin, GPIO.HIGH)
        GPIO.output(self.LeftAhead_pin, GPIO.HIGH)

    ####  leftFront函数,小车左拐弯
    def leftFront(self):
        self.setup()
        GPIO.output(self.RightAhead_pin, GPIO.HIGH)
        GPIO.output(self.LeftBack_pin, GPIO.HIGH)

    ####  rightFront函数,小车右拐弯
    def rightFront(self):
        self.setup()
        GPIO.output(self.LeftAhead_pin, GPIO.HIGH)
        GPIO.output(self.RightBack_pin, GPIO.HIGH)

    ####  rear函数,小车后退
    def rear(self):
        self.setup()
        GPIO.output(self.RightBack_pin, GPIO.HIGH)
        GPIO.output(self.LeftBack_pin, GPIO.HIGH)

    ####  leftRear函数,小车左退
    def leftRear(self):
        self.setup()
        GPIO.output(self.RightBack_pin, GPIO.HIGH)
        GPIO.output(self.LeftAhead_pin, GPIO.HIGH)

    ####  rightRear函数,小车右退
    def rightRear(self):
        self.setup()
        GPIO.output(self.LeftBack_pin, GPIO.HIGH)
        GPIO.output(self.RightAhead_pin, GPIO.HIGH)


####  定义main主函数
def main(status):
    car = Car()

    if status == "front":
        car.front()
    elif status == "leftFront":
        car.leftFront()
    elif status == "rightFront":
        car.rightFront()
    elif status == "rear":
        car.rear()
    elif status == "leftRear":
        car.leftRear()
    elif status == "rightRear":
        car.rightRear()
    elif status == "stop":
        car.setup()

#### 收到浏览器请求,返回一个HTML文件。
@get('/')
def login():
    return template("/home/pi/Desktop/Car Master/login.html") #### 此处输入html文件的具体目录。

#### 收到浏览器发来的指令。
@post("/cmd")
def cmd():
    adss = request.body.read().decode()
    print("按下了按钮:" + adss)
    main(adss)
    return "OK"

#### 开启服务器,端口默认8080。
run(host="0.0.0.0")
  1. 超声波测距界面

<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta http-equiv="refresh" content="3"> 
  <title>超声波测距title>
 head>
 <body>
  <p>Distance:{{dist}}p>
 body>
html>
  1. 超声波测距代码
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import RPi.GPIO as GPIO
import time
from bottle import run, request, route, template
class Ranger(object):
    def setup(self): # 确定输入输出 GPIO 口。
        # 初始化gpio口。
        GPIO.setmode(GPIO.BOARD)
        GPIO.setup(29, GPIO.OUT)
        GPIO.setup(31, GPIO.IN)


    # trigger_pin 脚发送开始测量信号。
    def send_trigger_pulse(self):
        self.setup()
        GPIO.output(29,True)
        time.sleep(0.00001)
        GPIO.output(29,False)


    def wait_for_echo(self,value,timeout):
        count = timeout
        while GPIO.input(31) != value and count > 0:
            count = count - 1

    # 根据返回高电平时间计算距离,声速取340m/s。
    def get_distance(self):
        self.send_trigger_pulse()
        self.wait_for_echo(True, 10000)
        start = time.time()
        self.wait_for_echo(False, 10000)
        finish = time.time()
        pulse_len = finish - start
        distance_cm = pulse_len / 0.000058
        return distance_cm

# 将测得的距离返回给html模板。
@route("/")  #如果没有规定方式,默认get。
def distance():
    ranger = Ranger()
    dis = ranger.get_distance()
    return template("distance", dist=dis)


run(host="0.0.0.0", port=8081, debug=True) 
  1. 视频的代码下载地址:https://github.com/waveform80/pistreaming

然后,我的控制界面是这样

简单的Web控制树莓派小车_第5张图片
参考链接:
https://blog.csdn.net/qq_41923622/article/details/85850780
https://blog.csdn.net/xia0_ba1/article/details/79680748
https://blog.csdn.net/qq_36958104/article/details/83447224

如果有问题,欢迎评论区讨论啊!

你可能感兴趣的:(简单的Web控制树莓派小车)