TinyOS 2.x 入门教程 - 图文 联系客服

发布时间 : 星期日 文章TinyOS 2.x 入门教程 - 图文更新完毕开始阅读24b7b0a2a1c7aa00b42acb33

TinyOS Programming

{

uses {

interface Boot;

interface SplitControl as RadioControl; interface AMSend; interface Receive;

interface Timer; interface Read; interface Leds; } }

implementation {

message_t sendBuf; bool sendBusy;

oscilloscope_t local;

uint8_t reading; /* 0 to NREADINGS */

bool suppressCountChange;

// Use LEDs to report various status issues.

void report_problem() { call Leds.led0Toggle(); } void report_sent() { call Leds.led1Toggle(); }

void report_received() { call Leds.led2Toggle(); }

event void Boot.booted() {

local.interval = DEFAULT_INTERVAL; local.id = TOS_NODE_ID;

if (call RadioControl.start() != SUCCESS) report_problem(); }

void startTimer() {

call Timer.startPeriodic(local.interval); reading = 0; }

event void RadioControl.startDone(error_t error) { startTimer(); }

event void RadioControl.stopDone(error_t error) { }

event message_t* Receive.receive(message_t* msg, void* payload, uint8_t len) { oscilloscope_t *omsg = payload;

report_received();

if (omsg->version > local.version) {

Page 42 of 94

TinyOS Programming

local.version = omsg->version; local.interval = omsg->interval; startTimer(); }

if (omsg->count > local.count) { local.count = omsg->count; suppressCountChange = TRUE; }

return msg; }

event void Timer.fired() { if (reading == NREADINGS) { if (!sendBusy && sizeof local <= call AMSend.maxPayloadLength()) { memcpy(call AMSend.getPayload(&sendBuf, sizeof(local)), &local, sizeof local); if (call AMSend.send(AM_BROADCAST_ADDR, &sendBuf, sizeof local) == SUCCESS) sendBusy = TRUE; } if (!sendBusy) report_problem(); reading = 0; if (!suppressCountChange) local.count++; suppressCountChange = FALSE; }

if (call Read.read() != SUCCESS) report_problem(); }

event void AMSend.sendDone(message_t* msg, error_t error) { if (error == SUCCESS) report_sent(); else

report_problem();

sendBusy = FALSE; }

event void Read.readDone(error_t result, uint16_t data) { if (result != SUCCESS) { data = 0xffff; report_problem(); }

local.readings[reading++] = data; } }

Page 43 of 94

TinyOS Programming

1)从上面的代码中可以看出,首先要声明使用两个接口RadioControl和AMSend;具体为模块声明中的以下两行:

interface SplitControl as RadioControl; interface AMSend; 2)接着声明了oscilloscope_t local和uint8_t reading两个变量,用来标识串口状态和计数。并通过灯的闪烁来表示接收数据包的状态,即: void report_problem() { call Leds.led0Toggle(); } void report_sent() { call Leds.led1Toggle(); } void report_received() { call Leds.led2Toggle(); } 接着是对端口的标识和初始化, event void Boot.booted() { local.interval = DEFAULT_INTERVAL; local.id = TOS_NODE_ID; if (call RadioControl.start() != SUCCESS) report_problem(); } 注意其对interval和id也进行了初始化。

3)初始化及启动后,再接下来就是对数据的接收和发送操作了。节点需要每采集到10个数据就将其发送出去,因此需要计数和Timer的触发。每当节点采集到了10个数据后,Oscillos-copeC将数据放入一个message_t的标准信息格式的paylode中,并通过AMSend接口将其广播出去。OscilloscopeC通过Receive接口进行同步,使用SplitControl接口控制radio。

4)运行Oscilloscope可能需要用到一些工具。在下载代码的时候若使用make telosb install,1语句,则需要注意,“1”标识了这个节点,也就是之前提到过的local.id,我们需要确定对不同的节点使用不同的id进行标识,以便在对数据进行显示的时候对不同节点收集到的数据进行区别。

5)其配置文件代码如下:

configuration OscilloscopeAppC { } implementation { components OscilloscopeC, MainC, ActiveMessageC, LedsC, new TimerMilliC(), new DemoSensorC() as Sensor, new AMSenderC(AM_OSCILLOSCOPE), new AMReceiverC(AM_OSCILLOSCOPE); OscilloscopeC.Boot -> MainC; OscilloscopeC.RadioControl -> ActiveMessageC; OscilloscopeC.AMSend -> AMSenderC; OscilloscopeC.Receive -> AMReceiverC; OscilloscopeC.Timer -> TimerMilliC; OscilloscopeC.Read -> Sensor; OscilloscopeC.Leds -> LedsC; } SerialActiveMessgaeC是平台独立的活动消息层组件,工作于串口通信栈的顶端的配置文件,它将SerialActiveMessageP配线到带uart_id_t参数的SerialDispatcherC,同时 将SerialPackerInfoActiveMessgaP配线到带参数uart_id_tTOS_SERIAL_ACTIVE_MESSAGE_ID的SerialDispatcherC。SerialActiveMessageP是一个通用组件,因此可用于各种数据包级的通信层 顶端。它不以目的地址或组号过滤数据包,而是假设从串口端口接收的数据包目的地址就是本节点。这样PC端的工具就不用再寻找和考虑节点的ID和组号了。

Page 44 of 94

TinyOS Programming

6)传感器的配置过程由DemoSensorC组件完成,DemoSensorC与平台相关,不包含在

TinyOS的库中。每个DemoSensorC的实现部分都不一样。Telosb的DemoSensorC是VoltageC的实例,micaz系列多使用ConstantSensorC或SineSensorC之类的TinyOS库中提供的组件。统称传感器的配置工作都是在DemoSensorC所实例化的组件中完成的。传感器组件的目录一般为:tinyos-2.X/tos/platforms, tinyos-2.X/tos/sensorboards。

7)Oscilloscope收集到数据后会将其通过radio进行广播,节点上的三个LED的亮灭表示了节点的状态,接收数据、发送数据或是出现错误。在Oscilloscope的java目录下,是对采集到的数据的GUI应用。首先进入tinyos-2.x/apps/Oscilloscope/java目录下输入make,在编译生成了Oscilloscope Java GUI。

cd java make ./run 若是我们需要在PC上对Oscilloscope采集到的数据进行显示,则需要用到另一个应用程序BaseStation和一个串口工具SerialForward。当我们打开了SerialForward,并通过一个下载了 BaseStation代码的节点将从Oscilloscope接收的采集到的数据从GUI显示出来:

图6.4 Oscilloscope Java GUI

6.5 BaseStation应用程序

BaseStation的功能是实现一个中转功能,将从节点接收到的信息发送给计算机,将从计算机接收到的信息广播给其他节点。在上例中,若想要将Oscilloscope节点采集到的数据从计算机上显示出来,则需要一个BaseStation的基站节点,通过它接收Oscilloscope广播的数据并从串口传给计算机,同样能将从串口接收到的计算机的数据通过radio广播出去。换句话说,BaseStation和net.tinyos.tools.Listen是PC和传感器网络通信的桥梁。

对于基站的节点来说,LED0s闪烁:发送一个数据包到其他节点。LED1闪烁:接收到数据包,发送一个数据包到串口。LED2闪烁:丢失一个数据包(接收的速度大于发送的速度)。

Page 45 of 94