CC2431 是一款可以基于RSSI 定位的 芯片。
定位原理,通过RSSI 强度换算距离。
可以打个类似的比方,一个人站在群山之间,每个山头都有一个地理坐标,然后大喊一声,各个方向会返回回声,通过回声强度换算成离各个山头的距离,最后通过数学几何计算出自己站立的坐标。
在CC2431 中实现方法是,CC2431 喊一嗓子,其他参考节点收到这个信息后,又向CC2431 喊了一嗓子。参考节点的位置是已知的,CC2431 把参考节点“喊话声音”RSSI 换算成距离,然后根据其它参考节点的位置信息通过数学几何算出自己的位置。
CC2431 内置了硬件计算器计算数学几何,无需软件算法所以比较简单。当然可以通过软件在CC2430 上实现最后这个数学几何问题。
其实原理很简单,实现方法也非常明了!
具体代码
代码直接看CC2431“喊话”
初始化代码先不看,直接看Event相关。
case ZDO_STATE_CHANGE: #if defined( RTR_NWK ) NLME_PermitJoiningRequest( 0 ); #endif /* Broadcast the X,Y location for any passive listeners in order to * register this node. */ osal_start_timerEx( BlindNode_TaskID, BLINDNODE_FIND_EVT, BLINDNODE_FIND_DELAY ); break; default: break;
当设备启动成功加入网络后都会触发时间ZDO_STATE_CHANGE,上面宏里面的code是没有执行(可以从工程中发现没有定义RTR_NWK),后面是定时执行时间BLNDNODE_FIND_EVT,而且从上面的英文可以看出CC2431 准备向any passive listensers 发信息了,也就是喊一嗓子!
接着看BLNDNODE_FIND_EVT 这个事件是如何处理的。
if ( events & BLINDNODE_FIND_EVT ) { BlindNode_FindRequest(); return ( events ^ BLINDNODE_FIND_EVT ); }
处理方法直接了当,调用了函数 BlindNode_FindRequest();
接着往下追代码
/********************************************************************* * @fn BlindNode_FindRequest * * @brief Start a sequence of blasts and calculate position. * * @param none * * @return none */ void BlindNode_FindRequest( void ) { if ( state == eBnIdle ) { startBlast(); } }
从上面的code可以看到首先需要判断目前的状态state是否是idle(空闲状态),这个state是个全局变量,在初始化函数中首先被设置为idle状态。
void BlindNode_Init( uint8 task_id ) { BlindNode_TaskID = task_id; state = eBnIdle; config.loc.param_a = LOC_DEFAULT_A; config.loc.param_n = LOC_DEFAULT_N;
这个全局变量会伴随我们分析code的很大一部分时间。
既然满足eBnIdle那么就会调用Startblast();也就是正在开始“喊一嗓子了”
/********************************************************************* * @fn startBlast * * @brief Start a sequence of blasts and calculate position. * * @param none * * @return none */ static void startBlast( void ) { uint8 idx; afAddrType_t dstAddr; dstAddr.addrMode = afAddrBroadcast; dstAddr.addr.shortAddr = NWK_BROADCAST_SHORTADDR_DEVALL; dstAddr.endPoint = LOCATION_REFNODE_ENDPOINT; if ((ZDO_Config_Node_Descriptor.CapabilityFlags & CAPINFO_RCVR_ON_IDLE) == 0) { // Turn the receiver on while idle - temporarily. idx = true; ZMacSetReq( ZMacRxOnIdle, &idx ); } SampleApp_Sleep( FALSE ); for ( idx = 0; idx < BLINDNODE_MAX_REF_NODES; idx++ ) { refNodes[idx].addr = INVALID_NODE_ADDR; } (void)AF_DataRequest( &dstAddr, (endPointDesc_t *)&epDesc, LOCATION_RSSI_BLAST, 0, NULL, &transId, AF_SKIP_ROUTING, 1 ); rspCnt = 0; blastCnt = BLINDNODE_BLAST_COUNT; state = eBnBlastOut; osal_start_timerEx( BlindNode_TaskID, BLINDNODE_BLAST_EVT, BLINDNODE_BLAST_DELAY ); }
CC2431 (盲节点)调用StartBlast()喊出第一声,这也只是个开始!
第一步先分析到这里,欲知后事,请听下回分解!
CC2431定位套餐推荐:https://item.taobao.com/item.htm?id=527836022363