查看: 60436|回复: 45

关于ZIGBEE定位,RSSI转距离的问题

[复制链接]
sunke1988 发表于 2012-11-13 11:17:42 | 显示全部楼层 |阅读模式
       本科毕设做的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;

        }
    }

大体上有关定位就这么几段材料,详细问题可以再讨论。




 楼主| sunke1988 发表于 2012-11-13 11:19:40 | 显示全部楼层
QQ273889196,加的时候可以注明飞比论坛,建议有问题就在飞比上提问。
outman 发表于 2012-11-13 11:31:40 | 显示全部楼层
感谢楼主对飞比的支持,资料很给力,相信又有不少人可以从中受益了{:soso_e182:}
已经为楼主转为了我们的vip会员,并赠送了飞币,期待楼主的下一个大作
 楼主| sunke1988 发表于 2012-11-13 12:55:51 | 显示全部楼层
outman 发表于 2012-11-13 11:31
感谢楼主对飞比的支持,资料很给力,相信又有不少人可以从中受益了
已经为楼主转为了我们的v ...

谢谢奥特曼大神的鼓励,飞比论坛帮助了我太多了,分享分享是应该的
龚水朋 发表于 2012-11-13 15:03:41 | 显示全部楼层
正好赶上今天看RSSI,真是巧啊。谢谢。
 楼主| sunke1988 发表于 2012-11-13 15:40:05 | 显示全部楼层
补充一点:用2430时,通过寄存器读出的值有问题,我试过从寄存器读出的值,然后与通过smartRF软件读出的值比较,发现软件读出的值变化明显而2430里寄存器的值不怎么变化。不知道是什么问题。2530从收到的数据包里取RSSI值肯定没问题的。
雪影无痕 发表于 2012-11-19 19:54:24 | 显示全部楼层
非常感谢!我也正弄着,和我一起做的一个伙伴负责上位机,我主要负责ZIgBee这一块的,但是现在他不弄了,我的上位机就没了,我自己又不会写,不知道楼主能不能分享一个!非常感谢……{:soso_e100:}
雪影无痕 发表于 2012-11-19 20:01:11 | 显示全部楼层
我以前只会用Vb写简单的!这个写不来…………方便的话发一个到我邮箱liu_xueneng@163.com……Thankyou!
 楼主| sunke1988 发表于 2012-11-19 20:59:03 | 显示全部楼层
雪影无痕 发表于 2012-11-19 20:01
我以前只会用Vb写简单的!这个写不来…………方便的话发一个到我邮箱……Thankyou!

关于定位的代码全在这了。其余的代码是视频通信什么的,给你你也没耐心看,3万多行呢。定位的就这么多,你自己加点东西,显示显示就行了。我只能帮你到这了。
雪影无痕 发表于 2012-11-19 22:23:06 | 显示全部楼层
恩恩 谢谢!我自己弄弄!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表