|
本科毕设做的zigbee通信和定位,刚接手时一片茫然,什么都不懂啦就是,开发板又买不起,只能从各种文档看起,走了不少弯路。然后自己的zigbee板子终于熬出来了,就是通信啊定位啊这些问题,当时迷惑了好长一段时间,最终找到了飞比论坛,在这里我收获了很多,解决了我的不少问题。几个月前我说过把我做的东西发上来给大家分享分享的,苦于老板这事情太多一直没时间,最近QQ上老有人问我关于定位的问题,我现在把大家问的多的问题整理一下,结合我做的东西发在这里,算是报答吧
我最后做成的zigbee网络系统中有5个点,其中4个点用的是2530和GPS模块,这样可以实现GPS的精确定位和zigbee的通信;还有一个点用的2430(实验室刚好有),负责不停的广播数据,是需要定位的点。
最后在协议栈里面我将1个2530点配置成coordinator其余3个2530点配置成enddevice,2430配置成enddevice。2530的发数功能都关掉,2430专门发数据供几个2530接收。接收函数如下:
void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
uint16 testaddr;
//unsigned char mytemp[2];
switch ( pkt->clusterId )
{
case GENERICAPP_CLUSTERID:
// "the" message
/*#if defined( LCD_SUPPORTED )
HalLcdWriteScreen( (char*)pkt->cmd.Data, "rcvd" );
#elif defined( WIN32 )
WPRINTSTR( pkt->cmd.Data );
#endif*/
#if defined(mytemp)
// EA=0;
get_temp();
//EA=1;
#endif
#if !defined(mytemp)
//mytemp[0]=pkt->cmd.Data[0];
//mytemp[1]=pkt->cmd.Data[1];
gps_data.mytemperature[0]=pkt->cmd.Data[0];
gps_data.mytemperature[1]=pkt->cmd.Data[1];
#endif
#if defined myUART //reclen=NLME_GetShortAddr();
testaddr=pkt->srcAddr.addr.shortAddr;
gps_data.srcaddr[0]=testaddr;
testaddr=testaddr>>8;
gps_data.srcaddr[1]=testaddr;
testaddr=NLME_GetShortAddr();
gps_data.myaddr[0]=testaddr;
testaddr=testaddr>>8;
gps_data.myaddr[1]=testaddr;
gps_data.myRSSI=pkt->rssi;//取得RSSI值,这是你的关键
Init_UART();
//unsigned char *recmsg;
//int reclen;
//recmsg=pkt->cmd.Data;
//reclen=pkt->cmd.DataLength;
UART_SEND_STRING(gps_data.myhead,48);
#endif
break;
}
}
2530取得RSSI值经过串口上传的一块arm板,arm板嵌入linux系统,通过wifi将数据发送到最终汇聚的一块arm板,再传到上位机。上位机上软件用C#编写,其中RSSI值转距离的函数如下:
for (int i = 1; i < 10; i++)
{
int t = rssis;
int j = i;
while ((j > 0) && (rssis[j - 1] > t))
{
rssis[j] = rssis[j-1];
--j;
}
rssis[j] = t;
} //先排序
for (int i =1; i <9; i++)
rssiTen =rssiTen + rssis;
rssiAverages[count] = rssiTen / 8;//去掉最大最小值在求平均值,用平均值来求距离波动小,准确。
RSSI转距离的函数:(a和n的确定是关键)
public double rssitoDistance(double rssi,int a, double n)
{
double ra = Math.Abs(rssi);
double ka = (ra - a) / (10 * n);
double distance = Math.Pow(10, ka);
return distance;
}
定位算法:
namespace Location
{
class Position
{
private double x;
public double X
{
get { return x; }
set { x = value; }
}
private double y;
public double Y
{
get { return y; }
set { y = value; }
}
private double z;
public double Z
{
get { return z; }
set { z = value; }
}
public Position(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
public Position()
{
this.x = 0;
this.y = 0;
this.z = 0;
}
public Position getVector(Position a, Position b)
{
Position c = new Position();
c.X = a.X - b.X;
c.Y = a.Y - b.Y;
c.Z = a.Z - b.Z;
return c;
}
public Boolean isInOnePlane(Position a, Position b, Position c, Position d)
{
Position ab = new Position();
Position ac = new Position();
Position ad = new Position();
ab = this.getVector(a, b);
ac = this.getVector(a,c);
ad = this.getVector(a,d);
//计算向量ab、ac构成的法向量temp 若temp与ad的点击为0,则四点共面
double tempX = ab.Y * ac.Z - ab.Z * ac.Y;
double tempY = ab.Z * ac.X - ab.X * ac.Z;
double temZ = ab.X * ac.Y - ab.Y * ac.X;
if (Math.Abs(tempX * ad.X + tempY * ad.Y + temZ * ad.Z) < 0.00000001)
{
return true;
}
else
{
return false;
}
}
public Position locationPositon(Position a, Position b, Position c, Position d, double da, double db, double dc, double dd)
{
Position ab = new Position();
Position ac = new Position();
Position bc = new Position();
Position ad = new Position();
Position bd = new Position();
Position cd = new Position();
Position result = new Position();
ab = this.getVector(a, b);
ac = this.getVector(a,c);
bc = this.getVector(b,c);
ad = this.getVector(a,d);
bd = this.getVector(b,d);
cd = this.getVector(c,d);
double sqa = (da * da - a.X * a.X - a.Y * a.Y - a.Z * a.Z)/2;
double sqb = (db * db - b.X * b.X - b.Y * b.Y - b.Z * b.Z)/2;
double sqc = (dc * dc - c.X * c.X - c.Y * c.Y - c.Z * c.Z)/2;
double sqd = (dd * dd - d.X * d.X - d.Y * d.Y - d.Z * d.Z)/2;
double f1 = ac.X * ab.Y - ab.X * ac.Y;
double g1 = ac.X * ab.Z - ab.X * ac.Z;
double h1 = (sqb - sqa) * ac.X - (sqc - sqa) * ab.X;
double i1 = ad.X * ab.Y - ab.X * ad.Y;
double j1 = ad.X * ab.Z - ab.X * ad.Z;
double k1 = (sqb - sqa) * ad.X - (sqd - sqa) * ab.X;
double z1 = (i1 * h1 - f1 * k1) / (i1 * g1 - f1 * j1);
double y1 = (j1 * h1 - g1 * k1) / (j1 * f1 - g1 * i1);
double x1 = ((sqb - sqa) - ab.Y * y1 - ab.Z * z1) / ab.X;
result = new Position(x1,y1,z1);
return result;
}
}
大体上有关定位就这么几段材料,详细问题可以再讨论。
|
|