由声网 Agora 举办的首届AI in RTC 大赛,已在10 月 24 日圆满落幕。其中,参与创意编程赛道的 100 多支参赛队伍在 3 个多月里挥洒创意与热情,带来了许多用心的项目。咱们邀请了获奖的参赛队伍们,逐一分享了他们的开发实践。html
buggy 团队基于 Android 手机、开发板、传感组件等,开发了一个可经过手机远程控制,支持视频的小车。android
如下内容由 buggy 团队撰写:编程
在消费电子设备的迅猛发展趋势下,智能手机的价格变低、配置却变高,愈来愈多的人选择更换配置更高的智能手机。旧手机若是没有被回收利用,其中的重金属和塑料将会对环境形成不可逆转的严重污染,使人可惜的是绝大部分的旧智能手机还能正常使用。目前,对旧手机的主流处理办法是回收提炼贵金属,但提炼过程当中仍是会产生有毒有害气体。数组
智能手机的摄像头已经知足通常的图像采集要求。将旧智能手机摄像头利用起来,开发视频监控应用,成为旧手机从新利用的一大趋势[1],能够节省大量的视频采集设备成本,还能减小环境污染和资源浪费。bash
印度Mindhelix初创团队开发的智能安防产品Rico将旧智能手机利用起来,作出了一种有创意的安防产品。Rico主要由旧智能手机、智能插座,Rico内置的各类环境传感器及手机应用程序等软硬件组成。将旧智能手机装上应用程序,插入Rico中,本来要报废的智能手机就承担起视频摄像、人脸识别、语音控制、麦克风通话、行程提醒和音乐播放等功能。Rico内置的各类环境传感器能够监测一氧化碳、煤气、烟雾浓度、温度、湿度、灯光强度和运动;智能插座能够链接到家里的各类家用电器和电灯,控制其开启和闭合;全部监测到的数据经过API接口上传至云端,在手机应用程序上能够查看家庭环境的各项指标。例如温度、湿度等。若是出门忘记关灯,能够经过手机远程控制电灯关闭[2]。网络
在北美比较受欢迎的阿福管家(Alfred),是由台北初创团队研发的一款把旧手机变为监控摄影机的APP,提供动态侦测、推播通知、即时录影、夜视功能。用户只须要在两个智能手机上安装APP,一个设定为相机端,另外一个为监控端,两端登入同一个Google账号,即可以经过WIFI或3G/4G实现远程监控[3][4]。并发
当今在安防监控领域,大多数民用监控设备有几大弊端:app
此设计要求实现一个手机能够远程经过WIFI查看小车上的手机摄像头拍摄的画面并控制小车移动。利用淘汰的智能手机的摄像头,实时采集视频图像信号并经过无线WIFI网络将视频信号实时传输到手机端观看,再经过小车上的手机的红外遥控功能对小车进行移动方向、速度的控制。使用C语言开发单片机程序,用Java语言开发安卓程序。ide
此小节围绕安卓端视频传输方案的选择、单片机的选择、车身的选择、马达驱动的选择和遥控控制模块的选择展开讨论。函数
安卓端视频传输方案的选择
查阅相关文献和资料后对Android的实时图像传输的图像数据处理方式进行了汇总,总结出下表中的五套Android实时图像网络传输方案[5]。
在因特网环境下,方案1不可取。方案2中MediaRecorder有很强的硬件依赖性,所以不一样的手机表现是不同的,有的手机数据传输的时候会出现阻塞现象,实时性就下降了。方案3和方案4实时性低。方案5平均流量消耗高,也不可取。
这里采用另外一种方案,使用声网Agora的视频通话 SDK进行二次开发。既保证了实时性,又下降了开发难度。
单片机的选择:单片机用于接收红外信号并控制马达驱动,根据在网上教程比较多的单片机是STC89CXX系列,STC89C52RC单片机是STC89C52的升级版,不断发展的半导体工艺也让该单片机的功耗不断下降。不只仅是作到了能耗上的升级,也进一步增强了单片机的处理性能。因此选择STC89C52RC型号。
车身的选择:第一种方案,淘宝上购买用于此设计的车身。小车底盘和顶面采用3mm厚亚克力板经激光切割总体成形,并预留了多组安装孔,扩展能力强。利用小车的圆形底盘特性,在底面左右两边直流马达和橡胶防滑车轮,先后两个万向轮起平衡小车做用。直流马达更是容易控制及调速,并且这种玩具车架通常都价格便宜;第二种方案,本身作一个车身。采用铝合金板制做,须要切割板钻孔。此过程很是耗时,应该将时间用在程序开发上。因此采用第一种方案从淘宝上购买车身。
马达驱动的选择:方案1,经过继电器控制马达的运动状态。好处是结构简单,但工做原理为机械结构,因此坏处是反应慢,并且占用的空间大;方案2,采用TI公司的马达专业驱动芯片L293D。电压最大36V,峰值电流最大1.2A,0.6A连续额定电流。采用TTL电平信号控制。具备两个使能控制器,可作PWM信号输入端,用来调整马达速度[5]。综上选择方案2。
遥控控制模块的选择:方案1,使用红外遥控。虽然红外的遥控的控制距离只有10m左右,没法绕过障碍物进行遥控。但发射红外遥控信号的手机就架在小车上,能够将手机的红外发射器和红外接收器放在一块固定住。虽然并非全部的安卓手机都有红外发射器,但都有3.5mm的耳机接口,红外信号的38kHz频率在音频范围内,能够用耳机接口外接的红外发光二极管发射红外遥控信号[6];方案2,能够用蓝牙来完成对小车的控制,小车上须要配备蓝牙模块与手机进行配对通讯。但并非全部的手机都支持蓝牙,早期的一些安卓智能手机就不支持蓝牙。相比蓝牙模块,红外模块成本更低。因此采用方案1。
本设计是以安卓手机为控制核心,在手机控制端实时查看小车上的手机摄像头采集到的图像,并发送控制命令发给小车上的手机,再经过手机被控制端红外发送动做指令。VS1838B为红外接收模块,接收手机端的红外遥控信号,再交给STC89C52RC单片机判断红外遥控的码值,对应控制L293D马达驱动,从而实现小车的先后左右移动。电源采用2节18650锂电池串联供电。
3.4系统框图 本系统的系统框图如图所示。
整个小车的硬件设计能够分为四个模块:电源电路、单片机最小系统、马达驱动模块、红外接收模块。电源电路为单片机最小系统、红外接收模块、马达驱动和两个车轮马达供电。
单片机最小系统
单片机的最小系统就是让单片机能正常工做并发挥其功能时所必须的组成部分,也可理解为是用最少的元件组成的单片机能够工做的系统[7]。单片机最小系统的系统框图和电路原理图如图所示。
STC89C52RC单片机可谓是国产单片机发展历程上的一块里程碑,初步作到了国内量产。而52单片机则是51的升级版,不断发展的半导体工艺也让该单片机的功耗不断下降。不只仅是作到了能耗上的升级,也进一步增强了单片机的处理性能。在保持原有的8位处理器不变的大方针下,采用了CMOS的生产工艺STC89S52RC单片机片内集成512字节RAM、8K字节ROM。在烧写次数方面达到了1000次左右的优良性能,低功耗模式状况下时钟系统虽然会中止工做,可是内部的寄存器仍是可以进行正常的处理。为了适应不一样的使用场合,这款单片机提供了多种封装,本次设计根据最小系统有时须要更换单片机的具体状况,使用双列直插DIP-40的封装,配合缩紧底座。
马达驱动模块
L293D是TI公司的产品,比较常见的是16脚PDIP封装。L293D经过TTL电平信号控制,由OUTPUT1,OUTPUT2和OUTPUT3,OUTPUT4驱动2个马达。INPUT一、INPUT二、INPUT三、INPUT4脚链接STC89C52RC的P0. 0、P0. 一、P0. 二、P0. 3口,控制马达的运动状态。ENABLE1,ENABLE2为控制使能端,对应与单片机的P0. 四、P0. 5口相连,控制马达的停转和PWM调速[8]。P0. 四、P0. 5口经过输出不一样占空比的PWM波形来改变马达的快慢。占空比是指高电平持续时间在一个周期时间内的百分比。单片机输出PWM信号可采用软件延时或定时器两种方法,在此用的是软件延时的方法。当高电平延时时间到时,电平取反变成低电平,而后再延时;当低电平延时时间到时,电平取反变高电平,一直这样反复就能获得PWM波形[9]。VSS可接4.5~7V电压,给芯片的逻辑电路提供电压。VS电压范围为4.5~36 V,给输出端提供电压。L293D的真值逻辑和功能的对应如表4-1所示。 表L293D真值逻辑和功能对应表
红外遥控模块
红外遥控模块主要由遥控发射器、红外接收头、接口电路组成。红外遥控器用来产生遥控编码脉冲,驱动红外发射管输出红外遥控信号,这里使用的使手机自带的红外发射功能。遥控接收头完成对遥控信号的放大、检波、整形、解调出遥控编码脉冲,这里使用一体化红外接收头来完成这一系列操做。遥控编码脉冲是一组串行二进制码,此串行码输入到单片机,由其内部CPU完成对遥控指令解码,并执行相应的遥控功能[9]。
红外遥控的实现原理
本次红外遥控采用的是NEC协议,调制方式为PPM脉冲位置调制,载波38kHz。位0和位1所不一样之处就是在高电平脉冲后的低电平脉宽不同,逻辑1为2.25ms,脉冲时间560us;逻辑0为1.125ms,脉冲时间560us。其波形如图所示。
下图是NEC的协议格式。首先是引导码,9ms的高电平脉冲和4.5ms的低电平,接下来是8位的地址码和8位的地址反码,用于校验地址码, 而后是8位的命令码和8位的命令反码,用于校验码[10]。
红外接收模块
本次采用的是VS1838B 一体化红外接收头有三个引脚,其外观和引脚排列如图4-6所示。OUT端即解调信号的输出端,链接单片机的P3. 2口。
此次设计能够用C语言编程序,也能够用汇编语言编程序,如今的单片机内部容量已经比较大了,可使用C语言编写程序,没必要使用晦涩难懂的汇编语言[11]。因此本次设计中系统程序用C语言编写程序,用软件Keil C51编译。
主程序设计
在本设计中,单片机主要是在主程序的控制下,定时对红外一体化接收头VS1838B接收的红外信号进行识别分析,读出的数据若是为0x十二、0x1八、0x1四、0x16则分别对应控制小车的前进、后退、左转、右转。小车硬件系统软件设计的流程图如图4-7所示。
主要代码以下。
void main(){
IrInit();//初始化
ENA=0;
ENB=0;
T=2048;
speed=400;//数字越大速度越快
ENA=1;
ENB=1;
while(1){
detectorIR();//判断红外信号
motorRun();//控制电机状态
if(speed!=T){
ENA=0;
ENB=0;
delay(T-speed);
ENA=1;
ENB=1;
delay(speed);
}
}
}
复制代码
红外遥控接收程序设计
红外遥控接收程序的重心在于解码的方式,解码方法以下:
主要代码以下。
void ReadIr() interrupt 0
{
u8 j,k;
u16 err;
Time=0;
delay(700); //7ms
if(IRIN==0) //确认是否真的接收到正确的信号
{
err=1000; //1000*10us=10ms,超过说明接收到错误的信号
/*当两个条件都为真是循环,若是有一个条件为假的时候跳出循环,省得程序出错的时
侯,程序死在这里*/
while((IRIN==0)&&(err>0)) //等待前面9ms的低电平过去
{
delay(1);
err--;
}
if(IRIN==1) //若是正确等到9ms低电平
{
err=500;
while((IRIN==1)&&(err>0)) //等待4.5ms的起始高电平过去
{
delay(1);
err--;
}
for(k=0;k<4;k++) //共有4组数据
{
for(j=0;j<8;j++) //接收一组数据
{
err=60;
while((IRIN==0)&&(err>0))//等待信号前面的560us低电平过去
{
delay(1);
err--;
}
err=500;
while((IRIN==1)&&(err>0)) //计算高电平的时间长度。
{
delay(10); //0.1ms
Time++;
err--;
if(Time>30)
{
return;
}
}
IrValue[k]>>=1; //k表示第几组数据
if(Time>=8) //若是高电平出现大于565us,那么是1
{
IrValue[k]|=0x80;
}
Time=0; //用完时间要从新赋值
}
}
}
if(IrValue[2]!=~IrValue[3])
{
return;
}
}
}
复制代码
本设计的安卓程序可以使用手机摄像头实时地将手机拍到的图像传送到手机端或电脑端,同时接收手机端或电脑端发出的指令。根据指令小车上的手机再发送相应的红外遥控信号给小车,手机安卓程序是小车端和控制端二合一的,在初始界面进行选择,主要是实现接收和发送信令、实时音视频传输和红外信号传输等功能。
Android开发包及其工具的安装和配置 本次开发使用声网(Agora)的视频通话和信令的SDK进行二次开发。下面介绍在正式使用 Agora SDK for Android进行通话/直播和信令控制前,须要准备的开发环境,包含前提条件及SDK集成方法等内容[12]。 请确保知足如下开发环境要求:
在编译和启动实例程序前,须要首先获取一个可用的App ID:
集成Agora视频SDK:
完成以上步骤后,用Android Studio打开该项目,连上设备,就能够编译并运行程序了。
手机端程序的设计
由于Android4.4及以上才有ConsumerIrManager类用来操控红外设备,因此本程序是基于Android 5.1系统的OPPO A51手机开发和测试的。用Android Studio开发,在此开发环境下完成Android手机终端的相关应用开发很是的方便[13]。 手机控制端实时视频功能的程序流程图如图所示。
具体使用方法见声网官网文档中心的参考[12],这里就不进行详尽描述了。下面来对主要步骤进行简单介绍。
(1)初始化
进入频道以前,调用create建立一个实例。
import io.agora.rtc.Constants;
import io.agora.rtc.IRtcEngineEventHandler;
import io.agora.rtc.RtcEngine;
import io.agora.rtc.video.VideoCanvas;//初始化前先导入这4个包
...
private void initializeAgoraEngine() {
try {
mRtcEngine = RtcEngine.create(getBaseContext(),
getString(R.string.agora_app_id),
mRtcEventHandler);
} catch (Exception e) {
Log.e(LOG_TAG, Log.getStackTraceString(e));
throw new RuntimeException("NEED TO check rtc sdk init fatal error\n" + Log.getStackTraceString(e));
}
}
复制代码
(2)加入频道
App在加入频道前,须要先设置频道模式,再加入频道。 建立实例后,调用setChannelProfile方法设置频道模式。
mRtcEngine.setChannelProfile(Constants.CHANNEL_PROFILE_COMMUNICATION);
复制代码
以后调用joinChannel方法加入频道。
private void joinChannel() {
mRtcEngine.joinChannel("token", "demoChannel1", "Extra Optional Data", 0);
}
复制代码
(3)离开频道
调用leaveChannel方法离开频道,结束或退出通话或直播。
private void leaveChannel() {
mRtcEngine.leaveChannel();
}
复制代码
(4)信令的实现
信令的具体使用方法见声网官网文档中心的参考[14],这里就不进行详尽描述了。主要使用的函数以下:
// 初始化信令 SDK
m_agoraAPI = AgoraAPIOnlySignal.getInstance(context, appID);
// 登陆 Agora 信令系统
m_agoraAPI.login2(appId, account, token, uid, deviceID, retry_time_in_s, retry_count)
/////////////频道测试///////////////
// 加入频道
m_agoraAPI.channelJoin(channelName)
// 发送频道消息
m_agoraAPI.messageChannelSend(channelName, msg, msgID)
// 设置对端接收到频道消息回调
m_agoraAPI.onMessageChannelReceive(channelID, account, uid, msg) {
// code there
}
// 退出 Agora 信令系统
m_agoraAPI.logout()
复制代码
小车上的手机实时视频功能的程序流程图如图所示。
手机端红外线发射功能的程序流程图如图所示。
由于Android4.4及以上才有ConsumerIrManager类用来操控红外设备,因此如下程序是基于Android 5.1系统的OPPO A51手机开发和测试的。
首先从系统服务中获取到ConsumerIrManager服务。
IR=(ConsumerIrManager)getSystemService(CONSUMER_IR_SERVICE);
复制代码
而后将要发送的红外码存入数组中。
//0x73
int[] pattern2 = { 9000, 4500,
560, 560, 560, 560, 560, 560, 560, 560, 560,560, 560, 560, 560, 560, 560, 560,
560, 1690, 560, 1690, 560, 1690, 560, 1690, 560, 1690, 560, 1690, 560, 1690, 560, 1690,
560, 560, 560, 560, 560, 560, 560, 1690, 560, 1690, 560, 560, 560, 560, 560, 560,
560, 1690, 560, 1690, 560, 1690, 560, 560, 560, 560, 560, 1690, 560, 1690,560, 1690,
560, 42020, 9000, 2250, 560, 98190 };
复制代码
数组中存放的是数值表明的是一种交替的载波序列模式,经过毫秒测量。这6行数据依次表示引导码,地址码,地址码,数据码,数据反码,连续码,具体原理详见4.1.3节红外遥控原理。
第三行数据码反置,好比0x12=0001 0010反置为 0100 1000,只有反置了以后才能接收正常。最后经过以下方法最终发送红外信号。
mCIR.transmit(hz, pattern2);//后退
复制代码
transmit(int carrierFrequency, int[] pattern) :此方法控制手机产生 carrierFrequency为频率的,以pattern为红外开关的时间数组,发送红外信号。(例如:transmit(38000,{100,200,300,400}) 将会产生一个频率为38KHz的红外信号,信号的电平高低为 100us高电平,200us低电平,300us高电平,400us低电平。注意pattern的数据个数要为偶数个,否则报错。)[15]。
你们能够访问buggy 团队的博客,与他们交流。同时,欢迎访问 RTC 开发者社区。