轻松使用阿里云完成智能小车
前言
智能小车,自娱自乐,希望通过该分享帮助更多爱好者们化繁为简,待我完成到第三季,我将会把程序放出来拱大家使用,我准备分三季来实现,APP后台部署在阿里小程序云,通过阿里云MQTT消息队列服务,来完成指令控制,并实现事件日志机制。
第一季实现小车的控制目标
1、实现小车4驱控制
2、实现摄像头实时查看,借助反向代理来完成内外网的通信
3、实现指令通过阿里云微消息队列MQTT来交互
4、设计APP端的控制界面实现
第二季实现目标
1、实现摄头云端控制
2、人脸检测
3、打包容器
4、热体红外+超声波测距+湿度温度
第三季实现目标
1、思考中
2、第一季开发准备
3、硬件
开发准备
硬件
- 树莓派3b+
- 小车底座
- L298N电机驱动模块
- 杜邦线
- 充电宝
- 6v~50V电源
- 树莓派专用摄像头 Raspberry Pi Camera
软件
- 阿里小程序云应用
- MJPG-Streamer
- frp
- 阿里云微消息队列MQTT
- 支付宝小程序开发者工具
硬件连接
整体效果
1.树莓派上电,将充电宝用usb线将树莓派于其连接,可看到树莓派红色指示灯常亮,绿色指示灯闪烁。如果发现红色指示灯忽然熄灭或者亮点很低,请检查充电宝输出电压以及电流是否太低
2.插入树莓派摄像头,注意不要插反,排线金属侧正对插排口金属侧,插入后扣紧排口
3.gpio与电机驱动模块in口连接。这边我们选择GPIO5、GPIO6、GPIO12、GPIO13、GPIO19、GPIO16、GPIO26、GPIO20 (GIPIO与针脚值不一致,对应针脚位置请参考下图,针脚39,40的位置在USB口旁边) 与驱动模块的IN1~IN8连接 (连接顺序请自行调整,驱动模块IN1的数字量输入控制OUT1输出,OUT1-OUT2如果连接同一个电机的输入和输出端,那么IN1-IN2对应输入数字信号[1,0]则代表前进,[0,1]代表后退,[0,0]或者[1,1]代表停止,以此类推IN1~IN8,OUT1~OUT8)
环境部署
云应用是面向小程序应用场景,为开发者提供的一键构建后端应用运行环境、后端服务部署、运维监控等能力的一站式小程序部署服务。
我们需要申请一个云应用充当小程序的服务器以及fpc服务器。现在阿里推出繁星计划,可以免费申请2个月的测试环境以及一个月的生产环境,无需申请,直接在应用界面新建新运用,创建详情请参考文档
在控制台获取服务器ip、用户名(默认root)、密码(需要修改默认密码,然后重启服务器),通过SSH工具连接,用于部署下面步骤
MJPG-Streamer是一个命令行应用程序,它将JPEG帧从一个或多个输入插件复制到多个输出插件。它可用于通过基于IP的网络将JPEG文件从网络摄像头流式传输到各种类型的查看器,如Chrome,Firefox,Cambozola,VLC,mplayer和其他能够接收MJPG流的软件。
- 开启树莓派摄像头
树莓派摄像头总线是默认没开启的,请在命令行中开启,进入后,选择camera
项,再选择enable
,然后重启
sudo raspi-config
2.安装必要的库
sudo apt-get update
sudo apt-get install subversion
sudo apt-get install libjpeg8-dev
sudo apt-get install imagemagick
sudo apt-get install libv4l-dev
sudo apt-get install cmake
sudo apt-get install git
3.git开源的project到本地,编译
sudo git clone https://github.com/jacksonliam/mjpg-streamer.git
cd mjpg-streamer/mjpg-streamer-experimental
make all
sudo make install
4.解决V4L driver不支持的问题
sudo wget http://www.linux-projects.org/listing/uv4l_repo/lrkey.asc &&
sudo apt-key add ./lrkey.asc
5.修改sources.list,在末尾添加源,并安装uv4l uv4l-raspicam,然后重启
sudo nano /etc/apt/sources.list
#末尾添加,保存
deb http://www.linux-projects.org/listing/uv4l_repo/raspbian/ wheezy main
sudo apt-get update
sudo apt-get install uv4l uv4l-raspicam
sudo reboot
6.重启之后:
sudo pkill uv4l
sudo apt-get update
sudo apt-get install uv4l-uvc
sudo apt-get install uv4l-xscreen
sudo apt-get install uv4l-mjpegstream
sudo reboot
7.再一次重启之后开启视频流服务
sudo modprobe bcm2835-v4l2
./mjpg_streamer -i "./input_uvc.so -d /dev/video0 -n -y -f 25 -r 640x480" -o "./output_http.so -n -w /usr/local/www"
8.然后打开浏览器输入:http://raspberry-ip-address:8080/?action=stream
应该就可以看到Raspberry Pi Camera采集的动态视频了,延迟大概不超过0.8秒吧。
frp是一个快速反向代理,可帮助您将NAT或防火墙后面的本地服务器暴露给Internet。截至目前,它支持tcp&udp以及http和https协议,其中请求可以通过域名转发到内部服务。
- 服务端部署 frps
在购买的服务端(有公网IP)部署frps,用于穿透树莓派本地的视频流
wget --no-check-certificate https://raw.githubusercontent.com/clangcn/onekey-install-shell/master/frps/install-frps.sh -O ./install-frps.sh
chmod 700
./install-frps.sh
./install-frps.sh install
然后一直回车(默认配置),知道全部安装完成。安装成功截图
2.启动frps
frps start
查看frps版本号
frps -v
我这边安装的是version 0.20.0
,客户端也要安装对应版本
3.树莓派部署frpc
由于我们服务器部署frps的版本是version 0.20.0
,所以我们本地也要部署相同的版本
wget https://github.com/fatedier/frp/releases/download/v0.20.0/frp_0.20.0_linux_arm.tar.gz
tar zxvf frp_0.20.1_linux_arm.tar.gz
cd frp_0.14.1_linux_arm
vi frpc.ini
修改 frpc.ini 文件
# frpc.ini
[common]
#服务器IP
server_addr = x.x.x.x
#服务器fpcs服务对应端口Bind port
server_port = 5443
#服务端token
oken = 你的服务端token
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6000
#[]内名称不能重复,标签作用
[web_raspberry_web]
type = http
#端口号 对应本机视频web服务器的端口
local_port = 8080
#配置穿透外网访问域名,可设置多个
custom_domains = raspberry.你的域名.com
修改好frpc.ini后,启动frpc客户端。如果想在后台运行,可在命令后加 &
./frpc -c frpc.ini
申请域名解析
将你的的域名主机记录 raspberry
A 记录解析到你的服务器IP x.x.x.x
服务器部署 Nginx
Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。
Ubuntu16.04安装及配置nginx
- 安装gcc g++的依赖库
apt-get install build-essential
apt-get install libtool
- 安装pcre依赖库
sudo apt-get update
sudo apt-get install libpcre3 libpcre3-dev
- 安装zlib依赖库
apt-get install zlib1g-dev
4.安装ssl依赖库
apt-get install openssl
安装nginx
#下载最新版本:
wget http://nginx.org/download/nginx-1.16.0.tar.gz
#解压:
tar -zxvf nginx-1.11.3.tar.gz
#进入解压目录:
cd nginx-1.11.3
#配置:
./configure --prefix=/usr/local/nginx
#编辑nginx:
make
注意:这里可能会报错,提示“pcre.h No such file or directory”,具体详见:http://*.com/questions/22555561/error-building-fatal-error-pcre-h-no-such-file-or-directory
需要安装 libpcre3-dev,命令为:sudo apt-get install libpcre3-dev
#安装nginx:
sudo make install
#启动nginx:
sudo /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
注意:-c 指定配置文件的路径,不加的话,nginx会自动加载默认路径的配置文件,可以通过 -h查看帮助命令。
#查看nginx进程:
ps -ef|grep nginx
在浏览器输入 http://raspberry.你的域名.com:8080
出现页面则nginx部署成功
配置测试页面
新建一个index.html
文件,用于测试页面,内容如下
<html>
<head>
<meta name="generator"
content="HTML Tidy for HTML5 (experimental) for Windows https://github.com/w3c/tidy-html5/tree/c63cc39" />
<meta http-equiv="Content-Type" content="text/html;" charset="UTF-8" />
<meta name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" />
<meta http-equiv="refresh" content="3" />
<title>树莓派实时监控站</title>
</head>
<body>
<center>
<font size="20" face="微软雅黑" color="#0074CD">
<b>树莓派<br>
实时监控站</b>
</font>
<hr />
frameLabelStart--frameLabelEnd <!--修改此处-->
<br />
<p>
<font size="5" color="#269C5D">
<b>Design by James</b>
</font>
</p>
<p>
<font size="5" color="#269C5D">
<i>a Web Monitoring Based on Raspberry Pi</i>
</font>
</p>
</center>
</body>
</html>
将该文件替换在nginx配置的web路径的index.html文件,例如/var/www/index.html
在浏览器输入 http://raspberry.你的域名.com:8080
尝试一下能否访问,如果成功出现树莓派实时监控页面,则web页面部署成功
阿里云微消息队列MQTT
微消息队列 MQTT 是阿里云推出的一款面向移动互联网以及物联网领域的轻量级消息中间件,针对移动互联网以及物联网 IoT 场景的消息传输特点,支持了包括 MQTT、STOMP、GB-808、新能源国标等主流通信协议
- 创建服务
打开MQTT控制台,需要登录阿里云账号,若没账号请自行申请。登录后请根据阿里云mqtt说明书创建mqtt服务。创建完毕后如下图,主要用到参数有 实例id、公网接入点、消息存储实例、Topic、Group
海创物联开发平台部署
海创开发平台是海创科技有限公司开发的一款快速编程平台,该平台开发的组件能快速与PLC、GPIO、各式设备进行通讯,有丰富的API支持,基本你们想到的事情它都能干,非常适合做物联网的网关控制中心
- 导入程序
打开海创物联开发平台的控制页 http://树莓派ip:1880/#flow/fd2b8cdb.5b63b
复制以下代码,打开开发平台,点击右上角菜单,选择导入-剪切板,然后粘贴保存,即可看到工作区新增了一个新的流程,该流程用于接受MQTT命令控制小车
[{"id":"9e9c968e.24e348","type":"rpi-gpio out","z":"d99269c6.a2d0b8","name":"","pin":"29","set":true,"level":"0","freq":"","out":"out","x":720,"y":140,"wires":[]},{"id":"37f46ac8.666436","type":"rpi-gpio out","z":"d99269c6.a2d0b8","name":"","pin":"31","set":true,"level":"0","freq":"","out":"out","x":720,"y":180,"wires":[]},{"id":"5f130d8f.f55d84","type":"function","z":"d99269c6.a2d0b8","name":"控制","func":"switch(msg.payload)\n{\n case '0':return [{payload:0},{payload:0},{payload:0},{payload:0},{payload:0},{payload:0},{payload:0},{payload:0}];\n case '1':return [{payload:0},{payload:1},{payload:0},{payload:1},{payload:0},{payload:1},{payload:0},{payload:1}];\n case '2':return [{payload:1},{payload:0},{payload:1},{payload:0},{payload:1},{payload:0},{payload:1},{payload:0}];\n case '4':return [{payload:0},{payload:0},{payload:0},{payload:0},{payload:1},{payload:0},{payload:1},{payload:0}];\n case '3':return [{payload:1},{payload:0},{payload:1},{payload:0},{payload:0},{payload:0},{payload:0},{payload:0}];\n}\n","outputs":8,"noerr":0,"x":510,"y":320,"wires":[["9e9c968e.24e348","676a7be6.b97e14"],["37f46ac8.666436","676a7be6.b97e14"],["2e8cc1ec.6369ce","676a7be6.b97e14"],["c7700a0b.47b378","676a7be6.b97e14"],["676a7be6.b97e14","482e8885.76d548"],["676a7be6.b97e14","62b4d0fc.a93f3"],["676a7be6.b97e14","fd3c406.31fc4c"],["676a7be6.b97e14","6ac88490.ba21bc"]]},{"id":"2e8cc1ec.6369ce","type":"rpi-gpio out","z":"d99269c6.a2d0b8","name":"","pin":"32","set":true,"level":"0","freq":"","out":"out","x":720,"y":240,"wires":[]},{"id":"c7700a0b.47b378","type":"rpi-gpio out","z":"d99269c6.a2d0b8","name":"","pin":"33","set":true,"level":"0","freq":"","out":"out","x":720,"y":280,"wires":[]},{"id":"8e757771.a599e8","type":"inject","z":"d99269c6.a2d0b8","name":"","topic":"停止","payload":"0","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":260,"wires":[["5f130d8f.f55d84"]]},{"id":"89e33a84.467878","type":"inject","z":"d99269c6.a2d0b8","name":"","topic":"前进","payload":"1","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":320,"wires":[["5f130d8f.f55d84"]]},{"id":"e521ba16.452cc8","type":"inject","z":"d99269c6.a2d0b8","name":"","topic":"后退","payload":"2","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":380,"wires":[["5f130d8f.f55d84"]]},{"id":"676a7be6.b97e14","type":"debug","z":"d99269c6.a2d0b8","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":750,"y":580,"wires":[]},{"id":"482e8885.76d548","type":"rpi-gpio out","z":"d99269c6.a2d0b8","name":"","pin":"35","set":true,"level":"0","freq":"","out":"out","x":720,"y":340,"wires":[]},{"id":"62b4d0fc.a93f3","type":"rpi-gpio out","z":"d99269c6.a2d0b8","name":"","pin":"36","set":true,"level":"0","freq":"","out":"out","x":720,"y":380,"wires":[]},{"id":"fd3c406.31fc4c","type":"rpi-gpio out","z":"d99269c6.a2d0b8","name":"","pin":"37","set":true,"level":"0","freq":"","out":"out","x":720,"y":440,"wires":[]},{"id":"6ac88490.ba21bc","type":"rpi-gpio out","z":"d99269c6.a2d0b8","name":"","pin":"38","set":true,"level":"0","freq":"","out":"out","x":720,"y":480,"wires":[]},{"id":"6473261a.673168","type":"inject","z":"d99269c6.a2d0b8","name":"","topic":"左转","payload":"3","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":440,"wires":[["5f130d8f.f55d84"]]},{"id":"73eb851c.b88ddc","type":"inject","z":"d99269c6.a2d0b8","name":"","topic":"右转","payload":"4","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":250,"y":480,"wires":[["5f130d8f.f55d84"]]},{"id":"bf85c267.64f96","type":"mqtt in","z":"d99269c6.a2d0b8","name":"","topic":"","qos":"2","broker":"bf40108b.620c2","x":235,"y":160,"wires":[["5f130d8f.f55d84","8a1c007d.34912"]]},{"id":"8a1c007d.34912","type":"debug","z":"d99269c6.a2d0b8","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":435,"y":180,"wires":[]},{"id":"c1f327d8.b01818","type":"inject","z":"d99269c6.a2d0b8","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":240,"y":40,"wires":[["c4d9812a.7b54b"]]},{"id":"c4d9812a.7b54b","type":"mqtt out","z":"d99269c6.a2d0b8","name":"","topic":"","qos":"","retain":"","x":415,"y":40,"wires":[]},{"id":"bf40108b.620c2","type":"mqtt-broker","z":"","name":"","broker":"","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]
导入后效果如下
- 修改节点属性
导入的流程不能直接使用,需要修改一些节点属性配置。
双击mqtt out节点,在属性窗点击服务器右侧的那个小标签按钮进入mqtt服务配置。填好服务器(阿里mqtt实例的外网http接入点)、端口号(默认1883)、客户端id("Group ID@@@任意id"
客户端ID在每个实例每个主题中只能唯一,重复情况下后面连接的自动被阿里断开)、用户名(这边我们使用的是签名鉴权模式,Token鉴权模式参考文档"Signature|Access Key
|实例 ID
")、密码(参考阿里的签名机制,快捷生成签名请点击签名校验),点击保存返回mqtt属性配置页,填写主题(阿里的Topic ID),QOS选择1
(至少上传一次)。mqtt in节点类似,由于接受消息是用于控制小车,所以QOS选择2
(仅分发一次),以下是配置详情
PIN控制着电机驱动模块从而控制小车的动作,前进(四个*前进)、后退(四个*后退)、左转(右侧*转)、右转(左侧*转)。假设相邻的两个OUT口连接一个电机,那么驱动模块的控制逻辑为
IN1 | IN2 | ~ |
---|---|---|
数字信号 | 1 | 0 |
电机 | 前进 | |
数字信号 | 0 | 1 |
电机 | 后退 | |
数字信号 | 0 | 0 |
电机 | 停止 | |
数字信号 | 1 | 1 |
电机 | 停止 |
根据该逻辑配置function节点(示例已包含,请根据自己的接法设置GPIO口的信号输出)
- 部署调试
点击菜单栏的部署按钮对程序部署,程序正式运行
单击定时器后mqtt out节点会将测试使用的时间戳上传到阿里的mqtt服务器,然后mqtt in会订阅接受到该消息,并在右侧调试窗口输出。正式使用数据请输入0
、1
、2
、3
使用mqtt发送正式消息,操作结果