BetaFlight模块设计之十五:RunCam设备任务分析
Posted lida2003
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BetaFlight模块设计之十五:RunCam设备任务分析相关的知识,希望对你有一定的参考价值。
BetaFlight模块设计之十五:RunCam设备任务分析
基于BetaFlight开源代码框架简介的框架设计,逐步分析内部模块功能设计。
RunCam设备任务
描述:主要用于处理遥控器、飞控、摄像头之间的事务处理(此过程中也形成了RunCam设备标准协议)。
├──> 初始化
│ ├──> [v]硬件初始化runcamDeviceInit
│ └──> [v]业务初始化rcdeviceInit
├──> 任务
│ ├──> [x]实时任务
│ ├──> [x]事件任务
│ └──> [v]时间任务[TASK_RCDEVICE] = DEFINE_TASK("RCDEVICE", NULL, NULL, rcdeviceUpdate, TASK_PERIOD_HZ(20), TASK_PRIORITY_MEDIUM),
├──> 驱动
│ ├──> [v]查询runcamDeviceGetDeviceInfo/rcdeviceReceive/runcamDeviceParseV1DeviceInfo/runcamDeviceParseV2DeviceInfo
│ └──> [x]中断
└──> 接口
├──> Support RunCam Device Protocol (FW v1.1.0/FW above v1.1.0)
└──> OMNIBUSF4 机型支持该协议
注:RunCam Device Protocol is the serial communication protocol (Latest V1.1.0) initially developed for the RunCam Split and analog cameras.
机型配置
从代码角度分析,目前官网上4.3代码,只有OMNIBUSF4机型是配置了这个串口(也许配置工具也能调整),不过总体来说现在摄像头的VideoOut接FC_VideoIn,然后FC_VideoOut接图传VideoIn,更多OSDlayer上的内容在飞控上完成,这个协议的作用后续可能会越来越淡出视线。
/src/main/target/OMNIBUSF4/config.c
SERIAL_PORT_UART4, FUNCTION_RCDEVICE ,
rcdeviceUpdate任务分析
任务总体上表述四部分:1)从设备端接受串口数据;2)摄像头控制过程;3)遥控器5按键模拟;4)设备请求数据处理
rcdeviceUpdate
├──> rcdeviceReceive
├──> rcdeviceCameraControlProcess
├──> rcdevice5KeySimulationProcess
└──> <isFeatureSupported(RCDEVICE_PROTOCOL_FEATURE_FC_ATTITUDE)>
├──> runcamDeviceRequest_t *request = rcdeviceGetRequest();
└──> <request>
└──> rcdeviceProcessDeviceRequest(request);
1. rcdeviceReceive函数分析
这个rcdeviceReceive函数主要分为两部分:1)处理FC发出,且需要反馈的串口报文事务;2)接受设备端主动发起的事务请求。
rcdeviceReceive
├──> <(respCtx = getWaitingResponse(millis())) != NULL> //判断存在需要反馈的事务,发送事务报文;失败尝试三次
│ ├──> <!serialRxBytesWaiting(respCtx->device->serialPort> //等待设备端事务反馈
│ │ └──> break //等待超时
│ ├──> const uint8_t c = serialRead(respCtx->device->serialPort);
│ ├──> <判断报文满足协议格式>
│ │ └──> break //不满足协议头定义
│ ├──> respCtx->recvBuf[respCtx->recvRespLen] = c;
│ ├──> respCtx->recvRespLen += 1;
│ ├──> <respCtx->recvRespLen == respCtx->expectedRespLen>
│ ├──> [不同协议报文格式解析] ==> RCDEVICE_RESP_INCORRECT_CRC or RCDEVICE_RESP_SUCCESS
│ ├──> <respCtx->parserFunc != NULL>
│ │ └──> respCtx->parserFunc(respCtx); //执行事务反馈函数
│ └──> <respCtx->result == RCDEVICE_RESP_SUCCESS>
│ └──> rcdeviceRespCtxQueueShift(&waitingResponseQueue); //移除已经获得反馈的事务
└──> <currentDevice != NULL> //处理设备端请求事务
├──> <!serialRxBytesWaiting(currentDevice->serialPort)>
│ └──> break //没有设备请求
├──> <requestParserContext.isParseDone>
│ └──> break //最近一次设备请求尚未处理,已经有后续事务,先放在缓存中
├──> <requestParserContext.state != RCDEVICE_STATE_WAITING_HEADER && millis() - requestParserContext.lastRecvDataTimestamp > 200> // 200ms超时检查
│ └──> requestParserContext.state = RCDEVICE_STATE_WAITING_COMMAND; // reset state to waiting header,这里代码有问题,逻辑和批注都描述状态机恢复到判断SOF状态(RCDEVICE_STATE_WAITING_HEADER)
├──> [RCDEVICE_STATE_WAITING_HEADER/RCDEVICE_STATE_WAITING_COMMAND/RCDEVICE_STATE_WAITING_DATA_LENGTH/RCDEVICE_STATE_WAITING_DATA/RCDEVICE_STATE_WAITING_CRC过程收包]
└──> requestParserContext.lastRecvDataTimestamp = millis();
2. rcdeviceCameraControlProcess函数分析
这里主要摄像头的可用功能Enable/Disable控制。
rcdeviceCameraControlProcess
└──> 遍历BOXCAMERA1/BOXCAMERA2/BOXCAMERA3模式
├──> <IS_RC_MODE_ACTIVE(i)> //模式激活
│ ├──> <switchStates[switchIndex].isActivated> //已经激活的模式,无需重复激活
│ │ └──> continue
│ ├──> uint8_t behavior = RCDEVICE_PROTOCOL_CAM_CTRL_UNKNOWN_CAMERA_OPERATION;
│ ├──> <isFeatureSupported(RCDEVICE_PROTOCOL_FEATURE_SIMULATE_WIFI_BUTTON)><!ARMING_FLAG(ARMED) && !(getArmingDisableFlags() & (ARMING_DISABLED_RUNAWAY_TAKEOFF | ARMING_DISABLED_CRASH_DETECTED))>
│ │ └──> behavior = RCDEVICE_PROTOCOL_CAM_CTRL_SIMULATE_WIFI_BTN;
│ ├──> <isFeatureSupported(RCDEVICE_PROTOCOL_FEATURE_SIMULATE_POWER_BUTTON)>
│ │ └──> behavior = RCDEVICE_PROTOCOL_CAM_CTRL_SIMULATE_POWER_BTN;
│ ├──> <isFeatureSupported(RCDEVICE_PROTOCOL_FEATURE_CHANGE_MODE)><!ARMING_FLAG(ARMED) && !(getArmingDisableFlags() & (ARMING_DISABLED_RUNAWAY_TAKEOFF | ARMING_DISABLED_CRASH_DETECTED))>
│ │ └──> behavior = RCDEVICE_PROTOCOL_CAM_CTRL_CHANGE_MODE;
│ └──> <behavior != RCDEVICE_PROTOCOL_CAM_CTRL_UNKNOWN_CAMERA_OPERATION>
│ ├──> runcamDeviceSimulateCameraButton(camDevice, behavior); //直接串口命令下发
│ └──> switchStates[switchIndex].isActivated = true;
└──> <!IS_RC_MODE_ACTIVE(i)>//模式不激活
└──> switchStates[switchIndex].isActivated = false;
3. rcdevice5KeySimulationProcess函数分析
这里是一个遥控器的模拟5按键操作:
- IS_MID(THROTTLE) && IS_MID(ROLL) && IS_MID(PITCH) && IS_LO(YAW): 退出Cam菜单
- IS_MID(THROTTLE) && IS_MID(ROLL) && IS_MID(PITCH) && IS_HI(YAW):进入Cam菜单
- IS_LO(ROLL) :KEY_LEFT
- IS_HI(PITCH):KEY_UP
- IS_HI(ROLL) :KEY_RIGHT
- IS_LO(PITCH):KEY_DOWN
- IS_MID(THROTTLE) && IS_MID(ROLL) && IS_MID(PITCH) && IS_HI(YAW):KEY_ENTER
rcdevice5KeySimulationProcess
├──> <USE_CMS><cmsInMenu>
│ └──> return
├──> <ARMING_FLAG(ARMED) || IS_RC_MODE_ACTIVE(BOXSTICKCOMMANDDISABLE) || (getArmingDisableFlags() & (ARMING_DISABLED_RUNAWAY_TAKEOFF | ARMING_DISABLED_CRASH_DETECTED))>
│ └──> return
├──> <isButtonPressed>
│ └──> <IS_MID(YAW) && IS_MID(PITCH) && IS_MID(ROLL)>
│ ├──> rcdeviceSend5KeyOSDCableSimualtionEvent(RCDEVICE_CAM_KEY_RELEASE);
│ └──> waitingDeviceResponse = true;
└──> <!isButtonPressed>
├──> <waitingDeviceResponse>
│ └──> return
├──> <IS_MID(THROTTLE) && IS_MID(ROLL) && IS_MID(PITCH) && IS_LO(YAW)> // Disconnect Lo YAW
│ └──> <rcdeviceInMenu>
│ └──> key = RCDEVICE_CAM_KEY_CONNECTION_CLOSE;
├──> <!(IS_MID(THROTTLE) && IS_MID(ROLL) && IS_MID(PITCH) && IS_LO(YAW))>
│ ├──> <!rcdeviceInMenu>
│ │ └──> <IS_MID(THROTTLE) && IS_MID(ROLL) && IS_MID(PITCH) && IS_HI(YAW)> // Enter HI YAW
│ │ └──> key = RCDEVICE_CAM_KEY_CONNECTION_OPEN;
│ └──> <rcdeviceInMenu>
│ ├──> <IS_LO(ROLL)> // Left LO ROLL
│ │ └──> key = RCDEVICE_CAM_KEY_LEFT;
│ ├──> <IS_HI(PITCH)> // Up HI PITCH
│ │ └──> key = RCDEVICE_CAM_KEY_UP;
│ ├──> <IS_HI(ROLL)> // Right HI ROLL
│ │ └──> key = RCDEVICE_CAM_KEY_RIGHT;
│ ├──> <IS_LO(PITCH)> // Down LO PITCH
│ │ └──> key = RCDEVICE_CAM_KEY_DOWN;
│ └──> <IS_MID(THROTTLE) && IS_MID(ROLL) && IS_MID(PITCH) && IS_HI(YAW)> // Enter HI YAW
│ └──> key = RCDEVICE_CAM_KEY_ENTER;
└──> <key != RCDEVICE_CAM_KEY_NONE>
├──> rcdeviceSend5KeyOSDCableSimualtionEvent(key);
├──> isButtonPressed = true;
└──> waitingDeviceResponse = true;
4. rcdeviceProcessDeviceRequest函数分析
这里是设备从FC出请求获取yaw,roll,pitch方面的信息,以便显示在OSD layer上。
rcdeviceProcessDeviceRequest
└──> <request->command == RCDEVICE_PROTOCOL_COMMAND_REQUEST_FC_ATTITUDE>
└──> runcamDeviceSendAttitude(camDevice); // send yaw, roll, pitch info to device for OSD layer display
以上是关于BetaFlight模块设计之十五:RunCam设备任务分析的主要内容,如果未能解决你的问题,请参考以下文章