智能巡防小车做到第四篇的程度基本把需要的功能都完成了,还可以另外扩展一个控制小车的APP出来,小车与APP交互的数据包括小车当前行走状态、火源勘测状态,舵机角度(小车转向角和风扇转向角)、风扇开关状态等,同时通过APP可以控制小车的运动状态。
5.1 通讯模块
小车与APP之间采用ESP8266模块进行数据透传,透传模式设置较为简单,这里不做阐述
5.2 APP功能简介
5.2.1 功能界面
app图标是一个卡通的消防车图案,对于小车的功能而言这个图案很形象了hahaha
APP主界面极狐包揽了所有功能,状态显示包括火焰警报显示,风扇状态显示,巡防车当前运行模式;控制方面的包括小车运行模式控制(自动、手动),小车前进、后退、停止及小车转向控制,风扇的打开、关闭及风扇转动角度,还有巡防车状态复位等,如图
复位选项中,可选择小车某个部位单独复位或者全复位操作,风扇复位及车轮复位都是将风扇、车轮的朝向设置为正前方,全复位除了包含风扇复位和车轮复位外,还会将在运行中的小车停止下来
在切换巡防车运行模式时会进行切换提示,自动模式为巡防小车依靠自身传感器进行巡线和火源检测操作,切换手动模式后会先向小车发送一次全复位的指令,然后小车完全由APP接管
当手机连接上小车WiFi时,会先进行一次交互,小车将当前运行模式发送给APP(自动或手动模式),APP收到数据后在界面上显示
5.2.2 自动模式
(WiFi连接后)自动模式下,小车实时将数据发送到APP上, 可在APP界面居中位置中看到
风扇的开关状态,小车运行模式,在没检测到小车附近存在火源时,APP显示无火源警报,右侧用一棵绿色的树表示当前无险情
小车检测到附近火源时,向APP发送火焰警报,APP界面提示火焰警报,绿树图案也会变成有险情的灭火图案,小车则在发现火源时自动执行风扇灭火
5.2.3 手动模式
(WiFi连接后)在APP界面切换手动模式,除了上面说到的可以设置小车复位之外,模拟的摇杆界面可以控制小车转向和前后行进,右侧控制风扇的开关及舵机的转向
5.3 APP交互协议
小车与APP交互时自定义一套的指令协议还是比较方便的,主要以字符串指令进行数据交互,下面分享部分协议内容
APP指令 | 数据范围 | 数据反馈格式 | 数据反馈指令 | 指令备注 |
---|---|---|---|---|
CONTROL_CarRun*** | 0 - 150 | RECEIVE_*** | 小车前进 | |
CONTROL_CarRun*** | -150 - 0 | RECEIVE_*** | 小车后退 | |
CONTROL_ServoC*** | 45 - 135 | RECEIVE_*** | 车头转向(角度方向为小车朝向) | |
CONTROL_ServoF*** | 160 - 20 | RECEIVE_*** | 风扇舵机转向(角度方向为小车朝向) | |
CONTROL_FANOpen | RECEIVE_*** | RECEIVE_OpenRuning | 风扇打开 | |
… | … | … | … | … |
CONTROL_***Mode | CONTROL_ManualMode | RECEIVE_*** | RECEIVE_ManualModeReady | 切换运行模式为手动模式(APP控制) |
… | … | … | … | … |
5.4 部分代码
代码展示主要处理部分,loop函数中,使用硬件串口(WiFi)进行字符串接收
//app指令接收,while+延时保证字符串完整接收
if(Serial.available()){
while(Serial.available()){
AppOrder += (char)Serial.read();
delay(2);
}
//判断字符串开头部分
if(AppOrder.startsWith("CONTROL_"))
{
if(AppOrder.indexOf("GetCarState") == 8)
{
CarStateSend();
AppOrder = "";
}
// 判断是否为手动模式指令
if(AppOrder.indexOf("ManualMode") == 8)
{
digitalWrite(BuzzerPin, LOW);
delay(500);
digitalWrite(BuzzerPin, HIGH);
State_Reset(0);
RunMode = ManualMode;
AppReady = true;
Serial.println("RECEIVE_ManualModeReady");
AppOrder = "";
//判断是否为自动模式指令
}else if(AppOrder.indexOf("AutoMode") == 8)
{
RunMode = AutoMode;
AppReady = false;
Serial.println("RECEIVE_AutoModeReady");
AppOrder = "";
}
if(AppReady != true) AppOrder = "";
}
else AppOrder = "";
}
手动模式控制
//手动模式控制
if((RunMode == ManualMode) && (AppReady == true)){
//火焰检测状态发送
if((FireStateGet() == true) && (FireFlag == false))
{
...
}else
if((FireStateGet() == false) && (FireFlag == true))
{
...
}
//处理app的复位指令
if(AppOrder.startsWith("CONTROL_Reset")){
String ResetState = "";
...
AppOrder = "";
}
//处理app的舵机控制指令
if(AppOrder.startsWith("CONTROL_Servo")){
if(AppOrder.charAt(13) == 'C'){
...
AppOrder = "";
}else
if(AppOrder.charAt(13) == 'F'){
String Servo_Angle = "";
...
AppOrder = "";
}
}
//小车前进指令
if(AppOrder.startsWith("CONTROL_CarRun")){
String CarSpeed = "";
...
AppOrder = "";
}
//小车停止指令
if(AppOrder.startsWith("CONTROL_CarStop")){
CarStop();
AppOrder = "";
}
//风扇状态控制
if(AppOrder.startsWith("CONTROL_FAN")){
String FANState = "";
...
AppOrder = "";
}
}
自动模式运行
//自动模式下巡线/火焰检测
else if((RunMode == AutoMode)&&(AppReady == false)){
if(FireStateGet() == false) OpenMV_LinePatrol();
else if(FireStateGet() == true) FireFighting();
}
5.5 结语
智能巡防小车案例到这里就结束了,APP部分不开源,所分享的案例内容只作为案例记录和案例分享,希望这能为读者提供帮助或参考,做出更好的电子产品 ~~~溜了溜了