索引
一、硬件连接
二、树莓派Zero配置
三、mjpg-streamer安装调试
四、远程互联网环境搭建
五、增加舵机云台
六、云台及外壳设计制作
七、其他记录

一、硬件连接
硬件概览:树莓派ZeroW、16G存储卡、USB转接头、USB摄像头、2A电源

二、树莓派Zero配置
见:树莓派基础使用-树莓派ZeroW无屏幕烧录系统及配置方式
三、安装mjpg-streamer
官网下载地址:https://github.com/jacksonliam/mjpg-streamer
①.执行以下命令安装必库:
sudo apt-get update sudo apt-get install cmake sudo apt-get install libjpeg9-dev
②.mjpg-streamer项目代码的获取方式
方式一:百度网盘
链接:https://pan.baidu.com/s/1jCqrzse-UQEVEti8M4Iqfg
提取码:mosx
方式二:
##如果直接可以访问github可以安装git直接克隆 sudo apt-get install git sudo git clone https://github.com/jacksonliam/mjpg-streamer.git
③.编译安装:
cd mjpg-streamer/mjpg-streamer-experimental sudo make all sudo make install
④.启动命令:
./mjpg_streamer -i "./input_uvc.so" -o "./output_http.so -w ./www"
如果使用的是CSI摄像头用如下命令:
./mjpg_streamer -i "input_raspicam.so" -o "output_http.so -w ./www"
上述命令启动后,会在控制台输出信息(端口8080),这样就可以通过局域网IP访问了

四、互联网远程环境配置
关于公网访问家庭网,个人总结了几种方式供参考,前两种我都使用过,对个人来讲够用了。
一、家庭宽带有公网IP,或能索要到公网IP
二、无法取得公网IP
三、使用IPv6,这种方式没尝试过,在此就不讨论了。
如何确定你的网是否有公网IP,进入到路由器管理界面,找到WAN界面,查看WAN口IP。然后到百度搜IP,如果两个IP一样就是公网IP,否则就不是;
当前网络服务商可能给公网IP的比较少,我选择宽带商之前确认有公网IP才装的。
这种只需要配置动态域名解析服务就行了,而且带宽就是你宽带上行带宽,不限流量。
如果没有公网IP,目前有些第三方软件,像花生壳等能做内网访问,只需要在路由器或树莓派安装客户端软件,就能实现外网访问。
不过这种方式免费的限流量,不常用的情况下也足够使用了。
除第三方提供的软件外,如果你有自己的云服务器,还可以自己搭建内网代理,我之前用过java开源版的xtunnel。
五、增加舵机云台
上面4步后实现了网络监控,接下来准备作一个云台,通过远程控制摄像头拍摄方向;
这部分利用树莓派的GPIO口控制两路9G舵机,分别沿着水平和垂直两个维度运动。之所以选择9G舵机一个是价格便宜,再一个电路简单不需要外部供电。
树莓派-舵机接线图如下:

云台支架:

1、安装pigpio官方推荐的驱动(
pigpio文档:23. API - Pins — GPIO Zero 1.6.2 Documentation
文档地址:14. API - Output Devices — GPIO Zero 1.6.2 Documentation)
git clone https://github.com/joan2937/pigpio cd pigpio make #编译 sudo make install #安装 sudo ./x_pigpio # 检查完整性 sudo pigpiod # 运行
2、舵机控制程序:
import asyncio
import websockets
import pigpio
import time
## GPIO端口号BCM编码,根据接线修改
PIN_H_SERVO = 17 # 垂直舵机
PIN_V_SERVO = 18 # 水平舵机
PWM_frequency = 50 # Hz
# 初始化函数
def init():
# 对舵机控制相关初始化
global pwm_horizontal,pwm_vertical
pwm_horizontal = pigpio.pi()
pwm_horizontal.set_PWM_range(PIN_H_SERVO, 20000)
pwm_horizontal.set_PWM_frequency(PIN_H_SERVO, PWM_frequency)
pwm_vertical = pigpio.pi()
pwm_vertical.set_PWM_range(PIN_V_SERVO, 20000)
pwm_vertical.set_PWM_frequency(PIN_V_SERVO, PWM_frequency)
# 水平方向舵机控制
def setHorizontal(x):
# 将角度参数转换成pigpio占空比参数
duty = 500 + 11*x
pwm_horizontal.set_PWM_dutycycle(PIN_H_SERVO,duty)
print("x =", x, "-> duty =", duty)
time.sleep(1)
# 垂直方向舵机控制
def setVertical(y):
# 占空比参数
duty = 500 + 11 * y
pwm_vertical.set_PWM_dutycycle(PIN_V_SERVO,duty)
print("y =", y, "-> duty =", duty)
time.sleep(1)
async def handle(websocket, path):
async for message in websocket:
print("got a command:{}".format(message))
temp = message.split("=")
if temp[0] == 'x':
setHorizontal(int(temp[1]))
if temp[0] == 'y':
setVertical(int(temp[1]))
print("Done")
async def main():
# start a websocket server
async with websockets.serve(handle, "0.0.0.0", 8765):
await asyncio.Future() # run forever
print("starting...")
init()
asyncio.run(main())3、修改mjpg-streamer的页面程序,增加控制按钮,通过websockets向树莓派发送舵机指令,实现控制(websockets文档:GitHub - aaugustin/websockets: Library for building WebSocket servers and clients in Python)
Webscoket:是Web浏览器和服务器之间的一种全双工通信协议。
页面中增加一组按钮,代码如下:
<button id="servo_up"><div class="btnface" style="background-image: url('f-up.png');background-size:100% 100%;"></div></button>
<button id="servo_down"><div class="btnface" style="background-image: url('f-down.png');background-size:100% 100%;"></div></button>
<button id="servo_left"><div class="btnface" style="background-image: url('f-left.png');background-size:100% 100%;"></div></button>
<button id="servo_right"><div class="btnface" style="background-image: url('f-right.png');background-size:100% 100%;"></div></button>
<button id="servo_auto"><div class="btnface" style="background-image: url('f-auto.png');background-size:100% 100%;"></div></button>JS写websockets客户端代码:
var x = 90, y = 90;
//判断浏览器是否支持WebSocket
var supportsWebSockets = 'WebSocket' in window || 'MozWebSocket' in window;
if (supportsWebSockets) {
var ws = new WebSocket("ws://10.0.0.10:8765"); //连接WebSocket服务端
ws.onopen = function(){
console.log("websocket connect success!");
ws.send("x=90"); // 首次连接后,发送初始化角度命令,水平和垂直舵机都设置成90度
ws.send("y=90");
}
ws.onmessage = function(e){
console.log("receive message:" + e.data);
}
ws.onclose = function(e){
console.log("websocket close!");
}
ws.onerror = function(e){
console.log("websocket error:" + e);
}
//舵机控制函数
$('#servo_up').click(function() { // 垂直 上
y = y + 10;
if(y >= 180){
y = 180;
}
ws.send("y=" + y);
});
$('#servo_down').click(function() { // 垂直 下
y = y - 10;
if(y <= 0){
y = 0;
}
ws.send("y=" + y);
});
$('#servo_left').click(function() { // 水平 左
x = x + 10;
if(x >= 180){
x = 180;
}
ws.send("x=" + x);
});
$('#servo_right').click(function() { // 水平 右
x = x - 10;
if(x <= 0){
x = 0;
}
ws.send("x=" + x);
});
}else{
layer.alert("浏览器不支持WebSocket!");
}六、外壳及支架设计
一共四个部分的3D打印件

七、其他记录
1、舵机抖动问题(发生在启动后,调用sleep过程中或停止时)
一开始我们使用的GPIO库是gpiozero,相关介绍如下:
gpiozero GitHub地址:gpiozero · GitHub
gpiozero 文档地址:gpiozero — GPIO Zero 1.6.2 Documentation
在调试过程中发现,云台在启动后会不停抖动。查询官网文档发现了一个Note提示:

出自地址:14. API - Output Devices — GPIO Zero 1.6.2 Documentation
“为了减少舵机抖动,尽量使用pigpio驱动而不是默认驱动” 原因是:pigpio使用DMA取样使得事件边缘更精确
于是替换了默认库,舵机停止时没有出现抖动现象
2、报错信息如下:sudo: pigpiod: command not found

需要先执行:sudo pigpiod
实测发现,如果通过pip install安装,没有pigpiod命令
==
Copyright © 2015 - 2016 DISPACE.NET | 使用帮助 | 关于我们 | 投诉建议