TinyOS、NesC程序开发经验谈
时间:2008-03-22 来源:zcwuwei
    TinyOS、NesC程序开发经验谈 
    <作者:Enoch Wang  引用自:http://chinawangquan.spaces.live.com>
  
  
    自己当初不知到为什么,导师让我选做图像(在硕士一年级下学期时开发了人脸与指纹融合识别系统),还是无线传感器网络(WSN)时,我从导师偏向的介绍中坚定做WSN,之后虽然还有别的与WSN无关的项目去做,但知道自己主要研究方向是WSN。
05年11月和06年6月,两次参加Crossbow的培训,第一次是什么不懂,第二次是带着项目问题过去的,自然收获也不一样了。1年半的编程,让我从刚开始的摸索到可以应付项目程序的需要,也算有所得了。离开实验室时,还给实验室留下一套实验系统,也是个系统框架,可以扩展,听说实验室用我的那个框架还在开发新系统,很是高兴。
我之前有一些语言的开发经验,从刚开始的Basic,到C,VB,C++,VC和ASP,这些给我学习TinyOS和NesC有很好的帮助,不然我就不是花上一个月熟悉它了。所以C的基础是必要的,熟悉NesC和tinyos比较好的方法是按照 ..\tinyos\cygwin\opt\tinyos-1.x\doc\tutorial 中的几个lesson进行操作。以下是TinyOS、NesC程序开发经验谈。
一、 nesC的语法
NesC是标准C的扩展,应用背景是传感器网络这样的嵌入式系统,这类系统的特点是内存有限,存在任务和中断两类操作。NesC的语法和标准C基本没有区别(NesC应该不能动态分配内存)。NesC程序的基本组成是Component,一个Component是一个*.nc文件。每个Component可以完成一定的工作,一个app一般有一个称为“Main”的Component作为程序的执行体(类似于C的main函数),“Main”调用其他的component以实现程序的功能。“Main”调用其他Component,以及一个Component调用其他的Component的方式是“interface”的连接,Component “uses”的interface连接到其他component “provides”的interface。Interface可以看作函数声明的一种封装,一个interface的内容是几个函数的声明(没有函数的定义),TinyOS系统提供了一系列interface(interface应该是由系统提供,不用自己写的)。可以理解为Interface是Component的属性,函数是interface的属性。Component分为两类,“configuration”用来完成component之间的连接,“module”用来完成该Component的功能(内容是“provides”的interface中函数的定义)。NesC定义了两类特殊的函数,“command”和“event”。函数调用时,Command用“call”,event用“signal”,在一个component中,provides的interface中的command函数必须被实现(在implementation中定义),uses的interface中的event函数必须被实现。“async”指出这个command或者event可以在有中断时使用。为了协调任务和中断的执行,nesC使用“atomic”指出该段代码“不可被打断”。另外定义了“task”封装一些代码来完成一个任务,系统有FIFO的task队列。不同的Task之间没有优先级,但task可以被interrupt handler打断。为防止全局变量等公用数据被非正常修改,nesC规定只在task中进入公共的数据部分。
二、 学习nesC比较有效的过程
在系统附带的文档里..\tinyos\cygwin\opt\tinyos-1.x\doc\tutorial 提供了8个lesson,是用来熟悉nesC语法用的。把lesson1(Blink)和lesson2(sense)看懂,并且按照后面练习中的要求修改程序。做完之后,对于nesC的语法就比较熟悉了。之后看别的程序差不多就可以直接看源代码了。
三、 生成程序的结构图
很有用的功能,在程序的文件夹里,键入“make micaz docs”命令,可以在../doc/nesdoc/micaz目录下生成这个程序的结构图。通过看结构图来了解程序比较直观。另外,在编写程序的时候,有一个问题,就是调试程序很困难。因此在编写完程序并且编译通过之后,可以先生成它的结构图,检查是否正确,作为调试程序的一个步骤。
四、 调试方法
在程序中尽量多得使用三个指示灯,是比较有效的调试方法。程序写完之后可以生成程序的结构图以及用listen命令读取消息包的类型。
五、 有用的链接
TinyOS tutorial: http://www.tinyos.net/tinyos-1.x/doc/tutorial/
TinyOS FAQ: http://www.tinyos.net/faq.html#SEC-43
TinyOS Programming, NesC Tutorial(这些网上可以下载到,没有找到的话,留下Email我给你发,对了我这也有TinyOS中文版和NesC中文版,但我建议还是英文原版的好,翻译过来的实在是...)
六、 一个程序示例
(实现RSSI信号的16个Node节点采集,请注意对应的文件名,烧制时注意节点ID号。以下是完整的Node节点程序,PC程序为以前说的SNICI软件系统,这个程序加以修改可以得到声音定位程序,实验室现在在做视频无线传感器网络的是在starget上实现的。)
      ********************************************************************
              Copyright (C), 2006-2007, by Enoch.
              FileName:       Rssi.h 
              Description:    Hardware specific definitions for the MTS300/310.
      *********************************************************************/
    
    
      enum
      {
          INITIAL_TIMER_RATE      = 1000,
          INITIAL_TIMER_REAE_STEP = 8,
          INITIAL_TIMER_DELAY     = 1500
      };
    
      enum
      {
          BASE_NODE = 0,
          MOVE_NODE = 100,
      };
    
       /********************************************************************
              Copyright (C), 2006-2007, by Enoch.
              FileName:        Rssi.nc  
              Description:    RSSI tracking system.
      *********************************************************************/
    
      includes RssiMsg;
      includes Rssi;
    
      configuration Rssi
      {
      }
    
      implementation
      {
        components Main, RssiM, TimerC, GenericComm as Comm, LedsC;
    
        Main.StdControl -> RssiM;
        Main.StdControl -> Comm;
    
        RssiM.TimerSend -> TimerC.Timer[unique("timer")];
        RssiM.Sendtest -> Comm.SendMsg[RSSI];
        RssiM.Receivetest -> Comm.ReceiveMsg[RSSI];
        RssiM.UARTSend -> Comm.SendMsg[RSSI+2];
        RssiM.Leds -> LedsC;
      }
    
      /********************************************************************
              Copyright (C), 2006-2007, by Enoch.
              FileName:       RssiMsg.h 
              Description:    RSSI tracking system.
      *********************************************************************/
    
      enum
      {
          TOTAL_NODE = 16
      };
    
      typedef struct RssiMsg
      {
          uint8_t addr;
          uint16_t seq;
      }RssiMsg;
    
      typedef struct NodeUARTMsg
      {   
          uint8_t fromaddr;
          uint8_t rssi;
          uint16_t seq;
      }NodeUARTMsg;
    
      typedef struct UARTMsg
      {   
          uint8_t rssi[TOTAL_NODE];
          uint16_t seq;
      }UARTMsg;
    
      enum
      {
          RSSI = 44,
      };
    
      /********************************************************************
              Copyright (C), 2006-2007, by Enoch.
              FileName:       RssiM.nc 
              Description:    RSSI tracking system.
      *********************************************************************/
    
      includes RssiMsg;
      includes Rssi;
    
      module RssiM
      {
           provides interface StdControl;
           uses
           {
               interface Timer as TimerSend;
               interface SendMsg as Sendtest;
               interface ReceiveMsg as Receivetest;
               interface SendMsg as UARTSend;
               interface Leds;
           }
      }
    
      implementation
      {
          TOS_Msg MoveData, UARTSendData, MoteSendData;
          uint8_t rssi_value[TOTAL_NODE];
          uint16_t seq = 0;
          uint32_t i = 0;
          task void SendData()
          {
              call UARTSend.send(TOS_UART_ADDR, sizeof(UARTMsg), &UARTSendData);
          }
          task void SendNodeData()
          {
              call Sendtest.send(TOS_BCAST_ADDR, sizeof(RssiMsg), &MoveData);
          }
           command result_t StdControl.init()
           {
               call Leds.init();
               call Leds.greenOn();
               for (i = 0; i < TOTAL_NODE; i++)
              {
                  rssi_value[i] = 255;
              }
               seq = 0;
               return SUCCESS;
           }
    
           command result_t StdControl.start()
           {   
               /* Moving node start the timer */
               if (TOS_LOCAL_ADDRESS == MOVE_NODE)
               {
                   call TimerSend.start(TIMER_REPEAT, INITIAL_TIMER_RATE);
                   call Leds.greenToggle();
                   call Leds.redToggle();
               }
               else if (TOS_LOCAL_ADDRESS == BASE_NODE)
               {
                   seq = 1;
               }
               return SUCCESS;
           }
    
           command result_t StdControl.stop()
           {
               if (TOS_LOCAL_ADDRESS == MOVE_NODE)
               {
                   call TimerSend.stop();
               }
               return SUCCESS;
           }
           event result_t TimerSend.fired()
           {
               /* Moving node send message */
               if (TOS_LOCAL_ADDRESS == MOVE_NODE)
               {
                   RssiMsg* snd_msg = (RssiMsg*)MoveData.data;
                  // Data
                   snd_msg->addr = TOS_LOCAL_ADDRESS;
                   snd_msg->seq  = ++seq;
                   call Sendtest.send(TOS_BCAST_ADDR, sizeof(RssiMsg), &MoveData);
                   call Leds.yellowToggle();
               }
               return SUCCESS;
           }
    
           event result_t Sendtest.sendDone(TOS_MsgPtr msg, result_t success)
           {
                call Leds.yellowToggle();
                return SUCCESS;
           }
          /* Motes Reciece Message */
           event TOS_MsgPtr Receivetest.receive(TOS_MsgPtr msgptr)
           {
               /* BASE mote recieve message to UART */
               if (TOS_LOCAL_ADDRESS == BASE_NODE)
               {
                   NodeUARTMsg* node_uart_msg = (NodeUARTMsg*)msgptr->data;
                   UARTMsg* uart_msg = (UARTMsg*)UARTSendData.data;
                   RssiMsg* snd_msg = (RssiMsg*)MoveData.data;
                   uint8_t node_addr  = node_uart_msg->fromaddr;
                   uint16_t node_seq  = node_uart_msg->seq;
                   uint8_t max_rssi = 255;
                   uint16_t max_node = 0;
                   if (((RssiMsg*)msgptr->data)->addr == MOVE_NODE)
                   {
                       if (((RssiMsg*)msgptr->data)->seq > 0)
                       {
                           /* Select the max rssi value node */
                           for (i = 0; i < TOTAL_NODE; i++)
                           {
                               uart_msg->rssi[i] = rssi_value[i];
                           }
                          // Data
                           uart_msg->seq = node_seq;
                           /* Upstream the data */    
                           //call UARTSend.send(TOS_UART_ADDR, sizeof(RssiMsg), &MoveData);
                           //call UARTSend.send(TOS_UART_ADDR, sizeof(UARTMsg), &UARTSendData);
                           post SendData();
                           //post SendNodeData();
                           //call Sendtest.send(TOS_BCAST_ADDR, sizeof(RssiMsg), &MoveData);
                           for (i = 0; i < TOTAL_NODE; i++)
                           {
                               rssi_value[i] = 255;
                           }
                           rssi_value[node_addr-1] = node_uart_msg->rssi;
                           //call Leds.redToggle();
                       }
                       return msgptr;
                   }
                   else
                   {
                       /* data is recieved for saving */
                       rssi_value[node_addr-1] = node_uart_msg->rssi;
                       //call Leds.greenToggle();
                   }   
               }
               /* Node proccess */
               else if (TOS_LOCAL_ADDRESS > BASE_NODE && TOS_LOCAL_ADDRESS != MOVE_NODE)
               {
                   RssiMsg* recv_rssi_msg = (RssiMsg*)msgptr->data;
                   NodeUARTMsg* send_mote_msg = (NodeUARTMsg*)MoteSendData.data;
                   if (recv_rssi_msg->addr == MOVE_NODE)
                   {
                       send_mote_msg->fromaddr = TOS_LOCAL_ADDRESS;
                        send_mote_msg->rssi = (int8_t)msgptr->strength;
                        send_mote_msg->seq  = recv_rssi_msg->seq;
                        /* Delay send to base mote */
                        for (i = 0; i < TOS_LOCAL_ADDRESS * INITIAL_TIMER_DELAY; i++)
                       call Sendtest.send(BASE_NODE, sizeof(NodeUARTMsg), &MoteSendData);
                    }
                    else if (recv_rssi_msg->addr == BASE_NODE)
                    {
                        if (recv_rssi_msg->seq == TOS_LOCAL_ADDRESS)
                        {
                            call Leds.redOn();
                        }
                        else
                        {
                            call Leds.redOff();
                        }
                    }   
               }
               return msgptr;
           }
          // UART Send Message
             event result_t UARTSend.sendDone(TOS_MsgPtr msg, result_t success)
           {
               //call Leds.yellowToggle();
                return SUCCESS;
           }
      }
    
      /********************************************************************
              Copyright (C), 2006-2007, by Enoch.
              FileName:       Makefile 
              Description:    RSSI tracking system.
    
*********************************************************************/
COMPONENT = Rssi
XBOWROOT=%T/../contrib/xbow/tos
PFLAGS= -I$(XBOWROOT)/platform/micaz
      # For MICA2 and MICA2DOT
      #PFLAGS+= -I../../tos/platform/mica2 -I../../tos/CC1000RadioAck -I../../tos/lib/ReliableRoute -I%T/lib/Queue -I%T/lib/Broadcast -I%T/lib/Attributes
    
      # For MICAZ
      PFLAGS+= -I../../beta/tos/lib/CC2420Radio -I%T/lib/Broadcast -I%T/lib/Attributes
    
      include ../MakeXbowlocal
      include ${TOSROOT}/tools/make/Makerules
    
| 
             | 
        
Related to Wireless Sensor Networks:
- TinyOS、NesC程序开发经验谈
 - Location in Wireless Sensor Networks_06-07Year(无线传感器网络定位06-07年)
 - Survey on Wireless Sensor Networks(无线传感器网络综述)
 - Hardware on Wireless Sensor Networks(无线传感器网络硬件)
 - Security in Wireless Sensor Networks(无线传感器网络安全)
 - Time Synchronization in Wireless Sensor Networks(无线传感器网络时间同步)
 - Target Tracking in Wireless Sensor Networks(无线传感器网络目标跟踪)
 - Location in Wireless Sensor Networks_1/3(无线传感器网络定位1/3)
 - Location in Wireless Sensor Networks_2/3(无线传感器网络定位2/3)
 - Location on Wireless Sensor Networks_3/3(无线传感器网络定位3/3)
 










