
raspi-car
折腾·树莓派小车
来源:https://www.valieo.com/archives/36/
怕原网站失效,于是复制一份
小车需求简要介绍
- 采用双轮差速方式移动
双轮方式需要的零件相对较少,省钱即是王道。
- 通过网络远程控制小车
可通过wifi远程控制,或者配置内网穿透实现任意地点控制。
- 能够实时传送图像
安装摄像头模块
- 超声波测距
安装超声波测距模块
材料
- 智能小车x1 ,淘宝买
2WD【包含车子底座、两个电机、两个轮子、电池模块】,20块钱 - 电机驱动x1,
TB6612FNG直流电机驱动模块,30块钱【只能驱动两个轮子】 - 杜邦线若干
- 摄像头x1【可选】20块钱
- 树莓派4B
第一部分安装
小车底座安装
- 将各个模块安装好,并预留好两个电机的四个线出来

- 将智能小车底座安装好

TB6612FNG与树莓派连接
不看原理,直接跳到“具体接线图”
TB6612FNG驱动
TB6612FNG驱动如下图所示

接口说明:
- VM:电机驱动电源输入(2.74-10.8V)
- VCC:逻辑电平输入(5.0V)
- AO1和AO2:接直流电机A
- BO2和BO1:接直流电机B
- PWMA:控制电机A的转速
- AIN1和AIN2:控制电机A(停止、正转、反转)
- STBY:正常工作/待机状态控制端
- PWMB:控制电机B的转速
- BIN1和BIN2:控制电机B(停止、正转、反转)
- GND:接地
AIN1和AIN2用于控制电机A停止、正转、反转,真值表如下
AIN1 | 0 | 0 | 1 |
|---|---|---|---|
AIN2 | 0 | 1 | 0 |
状态 | 停止 | 正转 | 反转 |
BIN1和BIN2的真值表同上
树莓派40PIN引脚对照表··

树莓派GPIO和TB6612FNG的接线情况如下表
树莓派GPIO接口(BCM编码) | TB6612FNG驱动接口 | 说明 |
|---|---|---|
27 | STBY | 设置TB6612FNG驱动模块的状态(工作/待机) |
18 | PWMA | 基于PWM控制电机A转速 |
14 | AIN1 | 控制电机A停止、正转、反转 |
15 | AIN2 | 控制电机A停止、正转、反转 |
19 | PWMB | 基于PWM控制电机B转速 |
23 | BIN1 | 控制电机B停止、正转、反转 |
24 | BIN2 | 控制电机B停止、正转、反转 |
电机驱动和树莓派4B共用一个5V、3A的电源
具体接线图

树莓派测试控制电机
安装好后,树莓派测试电机是否可以被正常控制,前进后退左转右转是否正常
先安装RPi.GPIO模块,命令如下:
sudo apt-get install python3-rpi.gpio安装好后,将下面的代码保存到test.py中,运行测试脚本python3 test.py,如果电机可以运转则正常!!!
代码如下:
#motorTest.py
#导入 GPIO库
import RPi.GPIO as GPIO
import time
#设置 GPIO 模式为 BCM
GPIO.setmode(GPIO.BCM)
#定义引脚
STBY = 27
PWMA = 18
AIN1 = 14
AIN2 = 15
PWMB = 19
BIN1 = 23
BIN2 = 24
#设置 GPIO 的工作方式
GPIO.setup(STBY, GPIO.OUT)
GPIO.setup(PWMA, GPIO.OUT)
GPIO.setup(AIN1, GPIO.OUT)
GPIO.setup(AIN2, GPIO.OUT)
GPIO.setup(PWMB, GPIO.OUT)
GPIO.setup(BIN1, GPIO.OUT)
GPIO.setup(BIN2, GPIO.OUT)
pwma = GPIO.PWM(PWMA,300)
pwmb = GPIO.PWM(PWMB,300)
# 前进或后退(大于零前进,小于零后退)
def goForward(speed):
if(speed>=0):
GPIO.output(AIN1,GPIO.LOW)
GPIO.output(AIN2,GPIO.HIGH)
GPIO.output(BIN1,GPIO.LOW)
GPIO.output(BIN2,GPIO.HIGH)
pwma.start(speed)
pwmb.start(speed)
time.sleep(0.02)
else:
GPIO.output(AIN2,GPIO.LOW)
GPIO.output(AIN1,GPIO.HIGH)
GPIO.output(BIN2,GPIO.LOW)
GPIO.output(BIN1,GPIO.HIGH)
pwma.start(-speed)
pwmb.start(-speed)
time.sleep(0.02)
# 左转或右转(大于零左转,小于零右转)
def turnLeft(speed):
if(speed>=0):
GPIO.output(AIN2,GPIO.LOW)
GPIO.output(AIN1,GPIO.HIGH)
GPIO.output(BIN1,GPIO.LOW)
GPIO.output(BIN2,GPIO.HIGH)
pwma.start(speed)
pwmb.start(speed)
time.sleep(0.02)
else:
GPIO.output(AIN1,GPIO.LOW)
GPIO.output(AIN2,GPIO.HIGH)
GPIO.output(BIN2,GPIO.LOW)
GPIO.output(BIN1,GPIO.HIGH)
pwma.start(-speed)
pwmb.start(-speed)
time.sleep(0.02)
def motorStop():
GPIO.output(AIN1,GPIO.LOW)
GPIO.output(AIN2,GPIO.LOW)
GPIO.output(STBY,GPIO.HIGH)
#以60%的速度前进
goForward(60)
time.sleep(1)
#以60%的速度后退
goForward(-60)
time.sleep(1)
#左转
turnLeft(60)
time.sleep(2)
#右转
turnLeft(-60)
time.sleep(2)
#停止
motorStop()
pwma.stop()
pwmb.stop()
GPIO.cleanup()摄像头安装
我使用的是CSI视频接口的摄像头,500万像素【淘宝上买只要20块,不过后面有官方推出的V2摄像头800万像素,要120块以上】
关机、断电、给摄像头安装摄像头。安装好后启动树莓派,输入命令:
vcgencmd get_camera检测摄像头
- 如果输出以下内容,则可以直接到“测试摄像头”
supported=1 detected=1, libcamera interfaces=0- 如果输出以下内容,则需要一些设置后,才能使用
supported=0 detected=0, libcamera interfaces=0无法使用摄像头时方法一:
先打开树莓派的配置:
sudo raspi-config
选择Interface Options:
再选择Legacy Camera:

在这个页面回答Yes。
系统会显示如下信息:

回到主菜单,点击Finish:

重启树莓派。
sudo reboot
无法使用摄像头时方法二
- 将方法一中,
Legacy Camera再关闭掉,先别重启 - 再编辑
/boot/config.txt,找到gpu_men,设置成128或者更高,我的原来就是128,所以改成了256,然后重启树莓派,可能是显存过低导致的。 start_x=1,并重启树莓派

测试摄像头
打开VNC桌面,将下面代码保存为testcamera.py,并在VNC桌面运行python3 testcamera.py,如果跳出来一个摄像头窗口,则正常!!!
测试摄像头代码:
# 该程序打开摄像头,显示视频,按q拍摄一张照片并储存下来
import cv2
cap = cv2.VideoCapture(0)
while(1):
# 获得图片
ret, frame = cap.read()
# 展示图片
cv2.imshow("capture", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
# 存储图片
cv2.imwrite("camera.jpg", frame)
break
cap.release()
cv2.destroyAllWindows()注意:
- cv2看之前一篇安装opencv文章
完整代码
下载:https://wwd.lanzouy.com/iJp5207kqd9g 密码:7qp0
代码下载好后,安装motion【一个将摄像头运行在后台的web服务】
安装motion
sudo apt install motion -y- 编辑/etc/default/motion文件,开启守护进程
sudo nano /etc/default/motion- 设置
start_motion_daemon=yes - 编辑/etc/motion/motion.conf文件
sudo nano /etc/motion/motion.conf以下仅列出部分配置,详细的配置文档见Motion - Config File Options
#将deamon off 改成 deamon on
deamon on
#设置视频分辨率
width 800
height 600
#视频帧率
framerate 24
stream_maxrate 30
#允许非本机访问总控制页面
webcontrol_localhost off
#允许非本机查看视频监控
stream_localhost off启动motion
sudo systemctl start motion
sudo motion安装gpac
sudo apt install gpac -y安装bottle
pip3 install bottle先运行一遍上面步骤中的test.py,命令
python3 test.py再安装Start.py,命令
python3 Start.py在浏览器中访问树莓派地址:8088
结束motion进程
sudo killall -TERM motionHC-SR04超声波模块
【此模块我没有做,直接抄的】
HC-SR04实图如下,其有四个引脚,分别为Vcc、Trig、Echo、End

HC-SR04模块具体参数如下图(淘宝)

HC-SR04模块的工作原理
(1)树莓派向 Trig 脚发送一个 10us 的脉冲信号。
(2) HC-SR04 接收到信号,开始发送超声波,并把 Echo置为高电平,然后准备接收返回的超声波。
(3) HC-SR04 接收到返回的超声波,把 Echo 置为低电平。
(4)Echo 高电平持续的时间就是超声波从发射到返回的时间间隔。
(5)计算距离:
距离(单位:m) = (startTime - endTime) * 声波速度 / 2
声波速度取 343m/s 。
接线
HC-SR04只有4个引脚,接线比较简单,具体见下表
HC-SR04引脚 | 树莓派GPIO(BCM编码) | 说明 |
|---|---|---|
Vcc | - | 5V电源,可直接用树莓派供电 |
Gnd | - | 接地 |
Trig | 任意GPIO,我使用的是GPIO5 | 接收树莓派控制信号 |
Echo | 任意GPIO,我使用的是GPIO6 | 返回测距信息 |
代码
#导入 GPIO库
import RPi.GPIO as GPIO
import time
#设置 GPIO 模式为 BCM
GPIO.setmode(GPIO.BCM)
#定义 GPIO 引脚使用BCM编码
TRIG = 5
ECHO = 6
#设置 GPIO 的工作方式 (IN / OUT)
GPIO.setup(TRIG, GPIO.OUT)
GPIO.setup(ECHO, GPIO.IN)
# 获取距离信息
def getDistance():
# 向Trig引脚发送10us的脉冲信号
GPIO.output(TRIG, GPIO.HIGH)
time.sleep(0.00001)
GPIO.output(TRIG, GPIO.LOW)
# 开始发送超声波的时刻
while GPIO.input(ECHO)==0:
pass
startTime=time.time()
# 收到返回超声波的时刻
while GPIO.input(ECHO)==1:
pass
endTime=time.time()
# 计算距离 距离=(声波的往返时间*声速)/2
timeDelta = endTime - startTime
distance = (timeDelta * 34300) / 2
return distance
if __name__ == '__main__':
try:
while True:
dist = getDistance()
print("Distance = {:.2f} cm".format(dist))
time.sleep(1) # 每间隔1秒测量一次
except KeyboardInterrupt:
print("Stopped")
GPIO.cleanup()第二部分web控制
Web控制
以下所有代码均已上传至github
安装bottle库
- 安装pip
pip是特定于Python的软件包管理器,没有安装pip的按照下述方式安装,安装了跳过此步
安装pip
sudo apt install python2-pip -y或者安装pip3
sudo apt install python3-pip -y- 如果系统中只安装了Python2,那么就只能使用pip。
- 如果系统中只安装了Python3,那么既可以使用pip也可以使用pip3,二者是等价的。
- 如果系统中同时安装了Python2和Python3,则pip默认给Python2用,pip3指定给Python3用。
我在这里安装的是pip3,以下代码也仅在python3下测试通过
- 安装bottle
pip3 install bottle代码
1. 超声波测距模块
# 超声波测距模块 HC-SR04
import RPi.GPIO as GPIO
import time
class Measure(object):
def __init__(self, GPIO_TRIG, GPIO_ECHO) -> None:
super().__init__()
self.GPIO_TRIG = GPIO_TRIG
self.GPIO_ECHO = GPIO_ECHO
GPIO.setmode(GPIO.BCM)
#设置 GPIO 的工作方式 (IN / OUT)
GPIO.setup(GPIO_TRIG, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)
def getDistance(self):
# 向Trig引脚发送10us的脉冲信号
GPIO.output(self.GPIO_TRIG, True)
time.sleep(0.00001)
GPIO.output(self.GPIO_TRIG, False)
# 开始发送超声波的时刻
while GPIO.input(self.GPIO_ECHO)==0:
pass
startTime=time.time()
# 收到返回超声波的时刻
while GPIO.input(self.GPIO_ECHO)==1:
pass
endTime=time.time()
# 计算距离 距离=(声波的往返时间*声速)/2
timeDelta = endTime - startTime
distance = (timeDelta * 34300) / 2
return round(distance,2)2. 电机驱动模块
# MotorControl.py
# TB6612FNG电机驱动
# 电机控制
import RPi.GPIO as GPIO
'''
self.GPIO_PWM
self.GPIO_IN1
self.GPIO_IN2
self.freq
self.last_pwm
self.pwm
'''
class Motor(object):
def __init__(self, GPIO_PWM, GPIO_IN1, GPIO_IN2, freq=300) -> None:
super().__init__()
self.GPIO_PWM = GPIO_PWM
self.GPIO_IN1 = GPIO_IN1
self.GPIO_IN2 = GPIO_IN2
self.freq = freq
GPIO.setmode(GPIO.BCM)
#GPIO.setwarnings(False)
GPIO.setup(self.GPIO_PWM, GPIO.OUT)
GPIO.setup(self.GPIO_IN1, GPIO.OUT)
GPIO.setup(self.GPIO_IN2, GPIO.OUT)
self.pwm = GPIO.PWM(self.GPIO_PWM, self.freq)
self.last_pwm = 0
self.pwm.start(self.last_pwm)
''' 静态方法 TB6612FNG的STBY引脚
1. GPIO_STBY int BCM编码号
2. status bool 为true则TB6612FNG工作,反之待机 默认为false
'''
@staticmethod
def standby(GPIO_STBY,status=False):
GPIO.setmode(GPIO.BCM)
#GPIO.setwarnings(False)
if status:
GPIO.setup(status, GPIO.OUT)
GPIO.output(status, True)
else:
GPIO.output(status, False)
''' 设置PWM占空比
1. dc 占空比 [0,100]
'''
def __setPWM(self, dc):
if dc != self.last_pwm:
self.pwm.ChangeDutyCycle(dc)
self.last_pwm = dc
''' 启动
1. speed int 范围[-100,100] 正数则正转,负数则反转
'''
def run(self, speed):
if(speed>=0):
GPIO.output(self.GPIO_IN1, False)
GPIO.output(self.GPIO_IN2, True)
self.__setPWM(speed)
else:
GPIO.output(self.GPIO_IN1, True)
GPIO.output(self.GPIO_IN2, False)
self.__setPWM(-speed)
'''停止'''
def stop(self):
GPIO.output(self.GPIO_IN1, False)
GPIO.output(self.GPIO_IN2, False)
self.__setPWM(0)
def cleanup(self):
self.stop()
self.pwm.stop()3. 小车控制
考虑到两个电机的转速可能不完全一致,所以需要一个微调功能。
摄像头模块在DIY树莓派小车(二)树莓派4B安装并使用摄像头和超声波模块中使用motion在8081端口开启了视频输出,可以直接调用,这里不再写有关摄像头模块的代码
# CarControl.py
# 控制小车移动 (前进 后退 左转 右转)
# 驱动:TB6612FNG
import RPi.GPIO as GPIO
from MotorControl import Motor
from Distance import Measure
'''
TB6612FNG 接口
# STBY
GPIO_STBY = 27
# 左边电机
GPIO_PWMA = 18
GPIO_AIN1 = 14
GPIO_AIN2 = 15
# 右边电机
GPIO_PWMB = 19
GPIO_BIN1 = 23
GPIO_BIN2 = 24
HC-SR04 接口
GPIO_TRIG = 5
GPIO_ECHO = 6
小车功能
1. 微调
2. 变速
3. 前进
4. 后退
5. 左转
6. 右转
7. 停车
8. 测距
'''
class Car(object):
def __init__(self) -> None:
super().__init__()
'''电机模块'''
# STBY引脚定义
self.GPIO_STBY = 27
GPIO.setmode(GPIO.BCM)
#GPIO.setwarnings(False)
GPIO.setup(self.GPIO_STBY, GPIO.OUT)
# 左右两个电机
self.motor_left = Motor(18,14,15)
self.motor_right = Motor(19,23,24)
# STBY = True TB6612FNG开始工作
Motor.standby(self.GPIO_STBY,True)
# 速度 占空比
self.motor_speed = 60
self.motor_left_speed = 60
self.motor_right_speed = 60
# 速度系数 用于微调
self.motor_left_coefficient = 1.0
self.motor_right_coefficient = 1.0
'''超声波测距模块'''
self.measure = Measure(5, 6)
# 微调 使两个电机转速一致 left=True向左微调 反之向右
def fineTuning(self, left):
if left:
# 向左微调 左边的电机减速 右边的电机加速
self.motor_left_coefficient -= 0.05
self.motor_right_coefficient += 0.05
else:
# 向右边微调 左边的电机加速 右边的电机减速
self.motor_left_coefficient += 0.05
self.motor_right_coefficient -= 0.05
# 更改速度 [0,100]
def setSpeed(self, speed):
if speed>100:
speed = 100
if speed<0:
speed = 0
self.motor_speed = speed
self.motor_left_speed = self.motor_left_coefficient * speed
self.motor_right_speed = self.motor_right_coefficient * speed
# 前进
def forward(self):
self.motor_left.run(self.motor_left_speed)
self.motor_right.run(self.motor_right_speed)
# 后退
def backward(self):
self.motor_left.run(-self.motor_left_speed)
self.motor_right.run(-self.motor_right_speed)
# 左转
def turnLeft(self):
self.motor_left.run(-self.motor_left_speed)
self.motor_right.run(self.motor_right_speed)
# 右转
def turnRight(self):
self.motor_left.run(self.motor_left_speed)
self.motor_right.run(-self.motor_right_speed)
# 停止
def stop(self):
self.motor_left.stop()
self.motor_right.stop()
# 测距
def getDistance(self):
return self.measure.getDistance()
def getSpeed(self):
return self.motor_speed
# 释放资源
def cleanup(self):
self.motor_left.cleanup()
self.motor_right.cleanup()
GPIO.cleanup()4. 获取树莓派信息
以下代码用于获取树莓派CPU温度、CPU使用率、RAM使用率
# RaspberryInfo.py
# 获取树莓派 CPU温度 内存使用率 CPU使用率
import os
# CPU温度
def getCpuTemp():
res = os.popen('vcgencmd measure_temp').readline()
return(res.replace("temp=","").replace("'C\n",""))
# CPU使用率
def getCpuUsage():
return(str(os.popen("top -n1 | awk '/Cpu\(s\):/ {print $2}'").readline().strip()))
# RAM信息
def getRAMinfo():
p = os.popen('free')
i = 0
while 1:
i = i + 1
line = p.readline()
if i==2:
return(line.split()[1:4])
# 内存使用率
def getRamUsage():
RAM_stats = getRAMinfo()
return round(int(RAM_stats[1]) / int(RAM_stats[0])*100,1)5. 小车Web控制面板
通过按钮或者键盘来控制小车移动
键盘操作方法见下表
按键 | W | S | A | D | Q | E | Z | C |
|---|---|---|---|---|---|---|---|---|
功能 | 前进 | 后退 | 左转 | 右转 | 加速 | 减速 | 左微调 | 右微调 |
<!-- index.html -->
<!-- 树莓派小车控制面板 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Raspberry Car Control Panel</title>
<link href="http://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" media="screen">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<style type="text/css">
#front {
margin-left: 55px;
margin-bottom: 3px;
}
#rear{
margin-top: 3px;
margin-left: 55px;
}
.btn{
background: #62559f;
}
</style>
<script>
$(function(){
$("button").mousedown(function(){
console.log(this.id + "mouse down");
$.post("/cmd",this.id,function(data,status){});
});
// 鼠标弹起则停止移动
$("button").mouseup(function(){
console.log(this.id + "mouse up");
$.post("/cmd","stop",function(data,status){});
})
// 键盘控制小车移动
$(document).keydown(function(event){
switch(event.keyCode){
case 87://w
console.log("press W");
$.post("/cmd","forward",function(data,status){});
break;
case 83://s
console.log("press S");
$.post("/cmd","backward",function(data,status){});
break;
case 65://a
console.log("press A");
$.post("/cmd","turnLeft",function(data,status){});
break;
case 68://d
console.log("press D");
$.post("/cmd","turnRight",function(data,status){});
break;
case 81://q
console.log("press Q");
$.post("/cmd","speedUp",function(data,status){});
break;
case 69://e
console.log("press E");
$.post("/cmd","slowDown",function(data,status){});
break;
case 90://z
console.log("press Z");
$.post("/cmd","leftFineTuning",function(data,status){});
break;
case 67://c
console.log("press C");
$.post("/cmd","rightFineTuning",function(data,status){});
break;
}
});
$(document).keyup(function(event){
switch(event.keyCode){
case 87://w
case 83://s
case 65://a
case 68://d
case 81://q
console.log("key up");
$.post("/cmd","stop",function(data,status){});
break;
}
});
});
</script>
</head>
<body>
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-7">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">实时画面</h3>
</div>
<div class="panel-body">
<iframe src="http://192.168.0.100:8081/" width="820" height="620" frameborder="1" name="name" scrolling="auto"></iframe>
</div>
</div>
</div>
<div class="col-xs-6 col-md-4">
<div class="panel panel-default">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">信息</h3>
</div>
<div class="panel-body" >
<iframe id="car-info" width="320" height="195" src="http://192.168.0.100:8088/info"></iframe>
</div>
</div>
<div class="panel-heading">
<h3 class="panel-title">控制</h3>
</div>
<div class="panel-body" style="margin: 30px;margin-left: 40px">
<div class="row" >
<div class="col-md-2"></div>
<div class="col-md-2"><button id="forward" class="btn btn-large btn-primary" type="button"><span class="glyphicon glyphicon-triangle-top" aria-hidden="true"></span><br/>前进</button></div>
<div class="col-md-2"></div>
</div>
<br/>
<div class="row">
<div class="col-md-2"><button id="turnLeft" class="btn btn-large btn-primary" type="button"><span class="glyphicon glyphicon-triangle-left" aria-hidden="true"></span><br/>左转</button></div>
<div class="col-md-2"><button id="backward" class="btn btn-large btn-primary" type="button"><span class="glyphicon glyphicon-triangle-bottom" aria-hidden="true"></span><br/>后退</button></div>
<div class="col-md-2"><button id="turnRight" class="btn btn-large btn-primary" type="button"><span class="glyphicon glyphicon-triangle-right" aria-hidden="true"></span><br/>右转</button></div>
</div>
<br/>
<div class="row">
<div class="col-md-2"><button id="speedUp" class="btn btn-large btn-primary" type="button"><span class="glyphicon glyphicon glyphicon-plus-sign" aria-hidden="true"></span><br/>加速</button></div>
<div class="col-md-2"></div>
<div class="col-md-2"><button id="slowDown" class="btn btn-large btn-primary" type="button"><span class="glyphicon glyphicon glyphicon-minus-sign" aria-hidden="true"></span><br/>减速</button></div>
</div>
<br>
<div class="row">
<div class="col-md-2"><button id="leftFineTuning" class="btn btn-large btn-primary" type="button"><span class="glyphicon glyphicon-triangle-left" aria-hidden="true"></span><br/>左微调</button></div>
<div class="col-md-2"></div>
<div class="col-md-2"><button id="rightFineTuning" class="btn btn-large btn-primary" type="button"><span class="glyphicon glyphicon-triangle-right" aria-hidden="true"></span><br/>右微调</button></div>
</div>
</div>
</div>
</div>
</body>
</html>6. 树莓派小车信息页面
此页面嵌入到小车Web控制面板页面中,显示小车速度(PWM占空比)、距离、CPU温度、CPU使用率、内存使用率
此页面1秒刷新一次
<!-- info.html -->
<!-- 树莓派小车信息面板 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--每1秒刷新一次-->
<meta http-equiv="refresh" content="1">
<title>信息</title>
</head>
<body>
<p>Speed: {{speed}}</p>
<p>Distance: {{distance}}cm</p>
<p>CPU Temp: {{cpuTemp}}℃</p>
<p>CPU Uasge: {{cpuUsage}}%</p>
<p>RAM Uasge: {{ramUsage}}%</p>
</body>
</html>7. 启动
# Start.py
from bottle import get,post,run,request,template
from CarControl import Car
from RaspberryInfo import *
car = Car()
def main(status):
print("Event: "+status)
if status == "forward":
car.forward()
elif status == "backward":
car.backward()
elif status == "turnLeft":
car.turnLeft()
elif status == "turnRight":
car.turnRight()
elif status == "speedUp":
car.setSpeed(car.getSpeed() + 5)
elif status == "slowDown":
car.setSpeed(car.getSpeed() - 5)
elif status == "leftFineTuning":
car.fineTuning(True)
elif status == "rightFineTuning":
car.fineTuning(False)
elif status == "stop":
car.stop()
# 控制台
@get("/")
def index():
print("request index.html")
return template("index.html")
# 控制小车
@post("/cmd")
def cmd():
adss=request.body.read().decode()
main(adss)
return "OK"
# 小车信息
@get("/info")
def info():
print("Update status Information")
return template("info.html", speed=car.getSpeed(), distance=car.getDistance(), cpuTemp=getCpuTemp(), cpuUsage=getCpuUsage(), ramUsage=getRamUsage())
run(host='0.0.0.0', port=8088, debug=False)
car.cleanup()实测
启动
sudo motion # 打开摄像头
python3 Start.py在浏览器中输入如下Url进入树莓派小车控制页面
http://树莓派ip:8088Web页面如下,可以通过网页上的按钮或者键盘控制小车(局域网内网络延迟很低,画面几乎实时显示)
控制面板右侧显示的是树莓派小车信息,其中Speed是PWM占空比,范围是[0,100],Distance是超声波测距的结果
- 文章作者:
- Lthero博客
- 版权声明:
- 本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0许可协议。转载请注明来自 Lthero博客!





