您的位置:首页 > 其它

用树莓派制作智能小车

2015-12-17 23:10 609 查看


用树莓派制作智能小车

DarkBull's Blog 2014-06-02 4164 阅读



难得周末有空,折腾了一下智能不车。

道具:树莓派,usb无线网卡,L298N电机驱动板,usb移动电源一个,两块手机电板(串联组成7.2v的电源供小车驱动),智能小车底盘,杜邦线若干,橡皮筋若干,电脑一台

原理:通过树莓派的gpio接口,控制电机驱动及速度,实现小车的前进后退,变向。

电机通过L298N驱动,其中电路图为:



小车的电机驱动需要外接电源,不可从树莓派的gpio口取电,gpio口只提供5v的电压,驱动电机够吃力的,轻者造成树莓派死机,重者直接把树莓派烧掉~~ 手头上刚好有几前买过的一只山寨机的两块电板,刚好拿来,串联成一个7.2v的电源。

车轮的速度可以通过pmw控制,随便找两个gpio口,连接到驱动电板的ena、enb,控制,非常方便。

小车的控制,我走的是http,在树莓派上运行一个tornado进程,在手机上通过触控控制。如果左轮的速度>右轮,则右转,反之左转。web界面很简单,如下图,点到哪里,得到一个相对于圆心的点,根据点到圆心的x,y轴距离,算出小车左右轮的速度,从而通过pwm控制小车。界面使用了html5的canvas。本来在小车上装了个摄像头,通过mjpg-stream把图像实时显示在网页上,无奈摄像头太差,就不加了。下次要买个nb点的摄像头。



越来越赖了,直接贴源码,作个标记,下次继续完善:加个机械臂,装一大堆传感器。

前台代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>智能小车控制平台</title>
<script type="text/javascript" src=""/static/jquery.min.js"></script>
</head>

<body>
<canvas id="cav_dir" width="400" height="400" style="background-color: #eeeeee">
您的浏览器不支持。
</canvas>
<span id="spn">hello</span>
<img src="http://192.168.1.20:8090/?action=stream" />

<script type="text/javascript">
$(function() {
var c=document.getElementById("cav_dir");
var cxt=c.getContext("2d");

var r = 200

cxt.beginPath();
cxt.fillStyle="rgba(0, 255, 0, 0.5)";
cxt.arc(r, r, r, 0, Math.PI*2, false);
cxt.closePath();

cxt.lineWidth = 2
cxt.strokeStyle = "'rgba(255,0,0,0.5)';
cxt.moveTo(0, r - 1)
cxt.lineTo(2 * r, r - 1)
cxt.moveTo(r - 1, 0)
cxt.lineTo(r - 1, 2 * r)
cxt.stroke()

cxt.fill();

function run(event) {
event = event || window.event
event.preventDefault()
var x = event.touches[0].clientX - r
var y = event.touches[0].clientY - r
var oInp = document.getElementById("spn");
oInp.innerHTML = '(' + x + ',' + y + ')'
if (x * x + y * y < r * r) {
$.post('/?x=' + x + '&y=' + y + '&r=' + r)
}
}

function stop(event) {
event = event || window.event
event.preventDefault()
$.post('?x=0&y=0&r=' + r)
}

c.addEventListener('touchstart',run, false);
c.addEventListener('touchmove',run, false);
c.addEventListener('touchend',stop, false);

})

</script>
</body>
</html>


后台代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author: darkbull
# @Date:   2014-05-31 10:02:21
# @Last Modified by:   darkbull
# @Last Modified time: 2014-06-02 15:29:20

"""Web控制树莓派小车
"""

import tornado.web
import tornado.ioloop
import codecs
import RPi.GPIO as GPIO
import time
import atexit
import math
atexit.register(GPIO.cleanup)

GPIO.setmode(GPIO.BCM)

IN1 = 17
IN2 = 22
IN3 = 23
IN4 = 24

# 左边轮速度控制
PWM_L = 8
PWM_R = 7

GPIO.setup(IN1, GPIO.OUT, initial=False)
GPIO.setup(IN2, GPIO.OUT, initial=False)
GPIO.setup(IN3, GPIO.OUT, initial=False)
GPIO.setup(IN4, GPIO.OUT, initial=False)

GPIO.setup(PWM_L, GPIO.OUT, initial=False)
GPIO.setup(PWM_R, GPIO.OUT, initial=False)
pwm_l = GPIO.PWM(PWM_L, 50)
pwm_l.start(0)
pwm_r = GPIO.PWM(PWM_R, 50)
pwm_r.start(0)

def front():
GPIO.output(IN1, True)
GPIO.output(IN2, False)
GPIO.output(IN3, True)
GPIO.output(IN4, False)

def back():
GPIO.output(IN1, False)
GPIO.output(IN2, True)
GPIO.output(IN3, False)
GPIO.output(IN4, True)

# def left():
#     # GPIO.output(IN1, False)
#     # GPIO.output(IN2, True)
#     GPIO.output(IN1, False)
#     GPIO.output(IN2, False)
#     GPIO.output(IN3, True)
#     GPIO.output(IN4, False)

# def right():
#     # GPIO.output(IN1, True)
#     # GPIO.output(IN2, False)
#     GPIO.output(IN1, False)
#     GPIO.output(IN2, False)
#     GPIO.output(IN3, False)
#     GPIO.output(IN4, True)

def stop():
GPIO.output(IN1, False)
GPIO.output(IN2, False)
GPIO.output(IN3, False)
GPIO.output(IN4, False)

def run(x, y, r):
"""小车运行
"""
if x * x + y * y > r * r:
return

speed_min = 15
speed_max = 100
speed_delta = speed_max - speed_min
# y轴为小车的运行方向,速度以y轴的值为基准
if y < 0:
back()
elif y > 0:
front()
else:
stop()
return

t = abs(y) * 100.0 / r
if t < 20:  # 电压太小,驱动不起来
t = 20
d = math.atan2(x, y) * 180 / math.pi

if x < 0: # 往左边偏, 右轮的速度比左轮快
t2 = t * (abs(90 + d) / 90)
pwm_r.ChangeDutyCycle(t)
pwm_l.ChangeDutyCycle(t2)
elif x > 0: # 往右边偏, 左边的速度比右轮快
t2 = t * (abs(90 - d) / 90)
pwm_l.ChangeDutyCycle(t)
pwm_r.ChangeDutyCycle(t2)
print x, y, t, t2

class CarController(tornado.web.RequestHandler):
def get(self):
with codecs.open('webcar.html', 'r', encoding='utf-8') as fp:
self.write(fp.read())

def post(self):
r = int(self.get_argument('r'))
x = int(self.get_argument('x'))
y = int(self.get_argument('y'))
run(x, y, r)
self.write('ok')

if __name__ == '__main__':
app = tornado.web.Application([('/', CarController)], static_path='static', debug=True)
app.listen(18080)
tornado.ioloop.IOLoop.instance().start()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: