之前做的一个练手小项目,做一下整理、总结。
基于树莓派3B的一块DIY扩展板,使用立创EDA绘制,简单的小板子,但还是打了好几次板。
整体功能:
电源部分可以使用外部USB的5V供电或锂电池供电,网上抄了一个电源切换电路,实测也可以使用,但是切换后树莓派会重启,做不到UPS的效果。。
充放电部分
使用英集芯的IP5306,充放电升压5V集成一体,外围电路比较简单。
舵机控制部分
使用树莓派硬件PWM引脚驱动,舵机5v供电即可。刚开始还给舵机控制加了电机驱动芯片L9110s,后面反而导致树莓派启动不了。排查问题过程中发现拆除L9110s也可以驱动芯片,舵机只是需要一个pwm信号,供电给足即可。
USB转串口
使用CH340N实现,加上USB转串口主要是为了方便调试,可以直接usb连接,使用串口登录树莓派,查询树莓派ip。
OLED模块接口
作为预留,方便后续的功能扩展使用。
可优化部分
舵机的电源可以使用mos关经树莓派IO进行控制,避免在开机后导致舵机直接上电导致旋转的问题。
固件代码使用CMake工具构建,第一次接触这个工具,也只是学会基本使用方法,但也足够了。主要设计的部分总结如下:
对于视频监控,已经有很多成熟的方案了。最常见的是mjpg-streamer,但这种方案更适合局域网的视频监控,对于远程查看可能需要内网穿透等手段。本次项目使用的是视频推流方案,涉及到视频传输相关的一些协议,整体由三部分构成:
1、推流端:树莓派Linux作为视频推流端,将每一帧采集、编码后,推送到远程服务器;
2、服务端:服务端使用的是Nignx,安装RTMP模块进行配置后,可以作为视频流服务器;
3、拉流端:拉流端可以有多个,本次使用的是Android app作为拉流端。
Linux下的视频采集使用的是video for linux 2 (V4L2)应用框架,对摄像头的操作基本都是调用ioctl函数。
使用mmap的方式将每一帧视频从内核队列中读出,减少内存拷贝。
相关代码网上也有很多参考,基本都能跑通。
为什么需要视频编码?
因为很多USB摄像头,支持的采集格式,基本都是YUV格式或MJPEG格式的,这里简单介绍以下:
不管是YUV还是MJPEG格式,采集得到的图片大小都是比较大的。MJPEG每一帧即jpeg图片,大小为像素宽x高,YUYV每一帧大小为像素宽x高x2。这只是一帧大小,摄像头帧率基本都能达到10帧~30帧,这样计算,分辨率比较大时,所占用的带宽就非常大。因此,需要将图片进行编码,减小网络传输带宽。
常用的方案是将YUV编码为H264,H264是一种压缩后的视频格式,详细说明可以百度。
这种编码可以使用软件方式实现,例如使用X264编码器,但会占用较高的CPU。
对于树莓派3B或某些SOC,是有相关硬件视频编码支持的,可以使用硬件加速编码,这种方式会大大降低CPU的占用。
我在项目中使用的是FFMPEG的编码器,添加了树莓派的硬件编码库支持,开启了硬件编码。
树莓派开启视频硬件编码的相关资料还是比较少的,做了很多尝试才成功,这里有空再将相关笔记整理上来。
这部分使用srs_rtmp项目的开源代码,编译成了so库,移植到Linux平台调用。
舵机控制是Linux PWM应用相关编程,并不难,只是树莓派的硬件pwm需要配置、开启。
远程控制部分使用TCP长连接方式实现,服务端使用开源的PHP框架GatewayWorker,负责转发app客户端控制指令到树莓派,完成舵机云台的上下左右运动。
使用nginx搭建的rtmp视频流服务器,网上资料相当多,不过支持H264视频推拉流需要做一些配置。
使用安卓app为上位机,很简单的界面,包含2个功能:
1、直播拉流:使用开源拉流播放库;
2、TCP远程控制:Android下的socket编程,注意一下socket的网络操作不能在UI线程中进行。
这边博客只是做个简单的项目总结,很多东西展开会比较多。项目整体不算难,但涉及的东西比较多,后续有空把这些坑补上吧。
树莓派移植FFmepg记录(x264、硬件编码支持)