Towards Out-of-the-Box Wireless Sensor Networks
Full text
Towards Out-of-the-Box Wireless Sensor Networks Gil de Castro Ferro Mestrado Integrado em Engenharia de Redes e Sistemas Informáticos Departamento de Ciência de Computadores 2015 Orientador Luís Lopes, Professor Associado, Faculdade de Ciências da Universidade do Porto
Todas as correções determinadas pelo júri, e só essas, foram efetuadas. O Presidente do Júri, Porto, ______/______/_________
This thesis is dedicated to my beloved ones, for all the support and patience in all the most important moments of my life. Gil de Castro Ferro June 2015 I
Acknowledgments I would like to thank my mentor, Professor Lu´ıs Lopes, for the opportunity of working with him in this project, giving me the opportunity to do research on one of my favorite fields of study. A special thanks to my colleague Carlos Machado, for all the advice and expertise in some hardware issues. To my family, for all the patience and support, and specially for the unconditional love. Last but not least, to my friends, who shared most of my growth and happiness in this journey. This work was supported by “Project RTS - Real Time Languages and Tools for Critical Real-Time Systems” (contract NORTE-07-0124-FEDER-000062) II
Resumo Programar Redes de Sensores-Atuadores Sem Fios (WSN) n˜ao ´e uma tarefa trivial, dada a variedade de configura¸c˜oes de hardware que s˜ao altamente dependentes da aplica¸c˜ao final. Al´em disso, os sistemas operativos e m´aquinas virtuais existentes, na maioria dos casos muito pr´oximos do hardware, tornam esta tecnologia pouco apelativa e, por consequˆencia, impedem a sua mais ampla dissemina¸c˜ao . Nesta tese apresentamos uma nova vers˜ao da arquitetura SONAR, que tem como objetivo minimizar o esfor¸co necess´ario para configurar, programar e implantar uma WSN. Esta arquitetura fornece um servi¸co de publish/subscribe que pode ser utilizado pelos clientes para facilmente acederem `as streams de dados geradas nos n´os da rede, permitindo, ao mesmo tempo, a gest˜ao da rede, incluindo a sua reprograma¸c˜ao dinˆamica e debug. A arquitetura SONAR ´e composta por trˆes camadas, que implementam uma interface de cliente ao estilo shell, um servi¸co de broker e um sistema operativo e m´aquina virtual que vˆem pr´e-instalados nos n´os da WSN. Realizamos ainda um conjunto de testes que medem o impacto da nossa solu¸c˜ao em termos de tempo, consumo de energia e mem´oria nos n´os da rede. Os resultados obtidos mostram que o impacto associado `a utiliza¸c˜ao do nosso sistema operativo e m´aquina virtual ´e relativamente pequeno, para os parˆametros medidos. Para testar a portabilidade da nossa camada de dados, portamos a nossa implementa¸c˜ao de uma WSN baseada em Arduinos Mega2560 para outra baseada em Arduinos Uno. Estes ´ultimos s˜ao significativamente mais restritos em termos de recursos e configura¸c˜oes de hardware. Esta experiˆencia mostra que a quantidade de c´odigo que necessita de ser reescrito ´e muito pequena (apenas algumas linhas), sendo ainda de referir que essas altera¸c˜oes foram feitas em bibliotecas espec´ıficas para componentes de hardware, tendo-se mantido inalterado o c´odigo referente ao sistema operativo e `a m´aquina virtual com exce¸c˜ao de algumas defini¸c˜oes b´asicas de parˆametros. III
Abstract Programming Wireless Sensor-Actuator Networks (WSN) is a non-trivial task, given the multitude of hardware configurations that are highly dependent on the final application. Moreover, the existing operating systems and programming languages, mostly very close to the hardware, make the technology unappealing to the masses and therefore preclude its wider dissemination. In this thesis we present a new version of the SONAR architecture, which aims to minimize the effort needed to configure, program and deploy a WSN. The architecture also provides a publish/subscribe service that can be used by clients to seamlessly access the data-streams generated by the sensing nodes while allowing, at the same time, the management of the network, including its dynamic reprogramming and debugging. SONAR is a three-layer architecture composed by a shell-like client interface, a broker service, and an operating system and virtual machine installed in the nodes of the WSN. We perform a set of tests that measure the impact of our solution in terms of time, energy consumption and memory footprint on the devices. The results show that the resource footprint associated with our operating system and virtual machine is small in all the given parameters. To test the portability of our data layer, we port the implementation from an Arduino Mega2560 based WSN to another one based on Arduino Uno devices. The latter are significantly more constrained in terms of resources and hardware configuration. This experiment shows that the amount of code re-write is very small (just a few lines) and these changes are done in libraries specific of hardware components. The operating system and virtual machine are untouched, except for the definition of basic constant parameters. IV
Acronyms AJAX Asynchronous JavaScript and XML. 23 API Application Programming Interface. 9 DOM Document Object Model. 24 FRP Functional Reactive Programming. 8 GUI Graphical User Interface. 3 HTML HyperText Markup Language. 24 HTTP Hypertext Transfer Protocol. 14, 24, 25 IoT Internet of Things. 2, 11, 12 MQTT Message Queue Telemetry Transport. 13 MQTT-SN Message Queue Telemetry Transport for Sensor Networks. 13, 14 OS Operating System. 6, 9–13 QoS Quality of Service. 14 REST Representational State Transfer. 14 SONAR Sensor Observation aNd Actuation aRchitecture. 3–6, 19, 23, 24 STL SONAR Task Language. 4 STMP Spatio-Temporal Macroprogramming. 8 V
VM Virtual Machine. 6, 9, 10, 12, 13 WSN Wireless Sensor Network. X, 1–7, 9–14, 23 XSS Cross-Site Scripting. 24 VI
Contents Resumo III Abstract IV List of Tables XI List of Figures XIII 1 Introduction 1 1.1 Context ..................................... 2 1.2 Motivation.................................... 3 1.3 Problem Statement and Proposed Solution . . . . . . . . . . . . . . . . . . 4 1.4 Outline...................................... 5 2 Related Work 6 2.1 Programming Languages . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 2.1.1 Programming Languages Overview . . . . . . . . . . . . . . . . . . 7 2.2 Operating Systems and Virtual Machines . . . . . . . . . . . . . . . . . . 9 2.2.1 Operating Systems Overview . . . . . . . . . . . . . . . . . . . . . . 10 2.2.2 Virtual Machines Overview . . . . . . . . . . . . . . . . . . . . . . 12 VII
Chapter 1 Introduction In the past 25 years, advances in hardware manufacture and wireless communications provided the means to develop a new class of embedded devices, capable of interconnecting, sensing physical conditions and of interacting with the environment. In this context WSN arise as a new paradigm of networks. A WSN can be defined as a distributed system composed of a varying number of embedded devices, usually called nodes, provided with a processing unit, a wireless communication interface, and a set of sensors/actuators, making these devices capable of sensing real physical environment or interacting with it [1]. Figure 1.1 depicts an example of a typical WSN scenario. A set of nodes with different sensors/actuators communicate via a radio interface, transmitting the sensed data to a gateway (data collection node), which is directly connected to computing resources. A set of clients can then access this data via a traditional network. Given the characteristics of WSN nodes, the basic mode of operation of these networks differs significantly from traditional ones. In [2], the authors present three main differences: 1. Nodes are highly restricted in terms of energy, computational power and memory; 2. The design of a WSN is strongly driven by each particular application; 3. The deployment of WSN applications requires self-configuration of nodes and software updates in the network without human intervention. 1
CHAPTER 1. INTRODUCTION 2 Figure 1.1: WSN typical scenario example. The application areas of WSN goes from medical diagnosis, wildlife monitoring, traffic control, military systems, precision agriculture, among others [3]. Currently, there is a trend to increase the usage of WSN into new areas, alongside with development of the so-called Internet of Things (IoT) [4]. 1.1 Context Despite their wide range of applications, WSN are still rather cumbersome to use, especially by non-specialists. A few reasons can be identified for why this is so: •The user needs a high level of expertise in configuring sensor devices, as well as low level programming; •The wide offer of hardware platforms that can be used to deploy WSN contribute to a lack of portability of the applications; •In most of the cases, the dynamic reprogramming or debugging of the deployment is a difficult task to do, impossible in some cases; •The integration of a WSN with a traditional network is not trivial.
CHAPTER 1. INTRODUCTION 3 1.2 Motivation Project Sensor Observation aNd Actuation aRchitecture (SONAR) [5, 6] purposes a three layer framework that allows a seamless deployment of a WSN. Figure 1.2 depicts the architecture used. Figure 1.2: Previous architecture of SONAR The Client Layer provides thin-clients implemented with a user-friendly Java Graphical User Interface (GUI) that provide hooks to access the Processing Layer to manage the deployments or to receive data streams. The management actions include: add/remove a periodic task to a deployment, change the period of a running task and view the data generated in a running task. The Processing Layer is responsible for the reception and storage of the data generated in the Data Layer, as well as providing remote methods so the client can access this data. This layer also propagates management actions originating in the Client Layer to the underlying Data Layer. The Data Layer is composed of a set of nodes and a single gateway (the initial implementation uses nodes based on Arduino Mega 2560 [7]). The nodes run a small operating system and virtual machine that schedule and run byte-code for tasks written in a domain-specific programming language, the SONAR Task Language (STL).
CHAPTER 1. INTRODUCTION 4 The initial SONAR architecture presented several limitations, first identified in [6]. These include: •non-scalable storage of data generated by WSN deployments; •complex management of pre-compiled modules required for different platforms; a hardware independent format is desirable; •non-scalable, centralized processing of data in the Processing layer; Some proposed solutions are forwarded in [6] but an implementation is lacking, together with an evaluation of performance in the time/energy axes. 1.3 Problem Statement and Proposed Solution The development and integration of systems that make use of WSN is still a hard task to do, given the significant differences with traditional networks. In this thesis we build on the work initiated in [6] and propose to answer the following relevant research questions: 1. Is it possible to develop a framework for programming, configuring and deploying WSN in a seamless way, providing clients with the corresponding data-streams? 2. What is the impact of this approach on hardware/energy resources? 3. Can we do this in such a way that it is portable across WSN and allows dynamic reprogramming and debugging? To answer these questions, we divide the work done in this thesis in three main phases: 1. Rewrite the Client and Processing Layer of SONAR, implementing command-linebased thin-clients and a publish/subscribe broker; 2. Evaluate the impact of our approach in terms of computation overhead, energy consumption, memory usage, and code size, with respect to a native Arduino, C++- based solution;
CHAPTER 1. INTRODUCTION 5 3. Test the effort of porting our architecture to different hardware nodes. With respect to the former implementation of SONAR, the work presented in this dissertation involved: 1. the redesign and implementation of the client and processing layers, namely publish/subscribe broker and clients, and an administration client; 2. rewriting part of the virtual machine installed in the nodes (data layer), and extensive testing; 3. significant changes to the SONAR Task Language (STL) compiler; 4. performance and resources usage evaluation of a prototype ported to a Arduino 2560 based WSN; 5. port the prototype to the Arduino Uno microcontroller. 1.4 Outline The remainder of this thesis is organized as follows: Chapter 2 presents the state-of-theart in software systems for WSN relevant for this work. Chapter 3 presents a high-level overview of the current SONAR architecture, detailing each layer and its components. Chapter 4 presents the technical aspects related to the modification of the architecture. Chapter 5 presents a formal description of the SONAR software that comes pre-installed in the nodes, depicting the programming language used to write new tasks, the operating system and virtual machine of these nodes, and the compiler we created to generate the byte-code representation of the written tasks. Chapter 6 presents the evaluation of the impact associated with our prototype, in terms of time, energy consumption, memory usage, and code size comparing to the same implementations using the Arduino native language. In Chapter 7 we describe the process of porting our prototype to Arduino Uno based nodes with greater memory constraints, focusing on the changes made, which we try to quantify. Finally, Chapter 8, presents a summary of the conclusions obtained in with this work, as well as a set of changes to be implemented as future work.
Chapter 2 Related Work In this chapter we present a survey on the state-of-the-art relevant for this thesis. Section 2.1 starts by analyzing the relevant work done in the field of Programming Languages for WSN. Section 2.2 describes projects that developed operating systems and virtual machines for WSN. Finally, Section 2.3 ends the chapter with existing publish/- subscribe systems for WSN. Along the chapter we try to establish a parallelism between our work and other approaches. 2.1 Programming Languages Despite the advances observed in the last years, programming WSN applications still remains a hard task to do, given the wide range of existing programming languages, aside with the high heterogeneity of platforms. Most of the available languages work at low level and focus on the development of specific types of applications. With respect to the platforms, the configuration of the hardware is not a trivial task. Both these aspects introduce the need for expert users. Currently, there is a considerable range of programming languages for WSN, each with a set of advantages/disadvantages in what concerns to the development of a specific application. Next, we present a brief description of three different languages, each one belonging to a different programming paradigm. To simplify the analysis, we define some taxonomy on the programming languages for WSN. 6
CHAPTER 2. RELATED WORK 7 In [8], Gummadi et al. present a taxonomy that divides the programming languages in two main groups, according to the network perception: macroprogramming and node-centric programming. The former corresponds to an approach where application development is done without defining the behavior of each node individually, the latter corresponds to an approach where there is the need for the definition, and deployment of the behavior of each node. A different taxonomy was purposed by Mottola et al. in [1]. They present an extensive survey on a set of different aspects related to programming WSN. In this article, they purposed a taxonomy related with the language aspects, divided in four categories: Communication, Computation Scope, Data Access Model, and Programming Paradigm. In the current context, we only analyze the Programming Paradigm dimension as it is the most relevant for this thesis when analyzing the following set of programming languages. According to Motolla’s taxonomy, there are three main types of programming languages: Imperative, Declarative, and Hybrid. The first type corresponds to the languages where programs are described in terms of statements that change the program state, which can be divided in Sequential and Event-Driven languages; the second type corresponds to the the languages that expresses the logic of a program without describing the control flow, which can be divided in Functional, Rule-Based, SQL-Like and Special-Purpose; the third type corresponds to the programming languages that adopt a mixture of the two previous ones. Figure 2.1 presents a scheme describing the two taxonomies previously presented. Next, we describe and categorize the set of programming languages that may be relevant in the current context of WSN, analyzing the network perception and the programming paradigm of each. 2.1.1 Programming Languages Overview TinyDB [9] is a query processing system focused in the optimization of energy consumption, running in the top of TinyOS. It incorporates acquisitional techniques along with traditional query techniques, taking advantage from the fact that sensors possess control over when, where and how periodically the data is sensed and delivered to query processors. Madden et al. detail in [9] all the aspects related to the query language implemented in TinyDB, as well as the optimizations made in order to minimize the energy consumption, the query dissemination in the system and, finally, the model created for query execution and result collection.
CHAPTER 2. RELATED WORK 8 (a) Network Perception (b) Programming Paradigms Figure 2.1: Network Perception and Programming Paradigms nesC [10] is an event-driven programming language that extends the C language, built atop of TinyOS. It is based in components that are assembled to form programs, as well as bidirectional interfaces, which specify the components behavior in terms of their interfaces. The interfaces specify the functions to be implemented by the interface’s provider (commands) and by the user of the interface (events). nesC static links the components via their interfaces, increasing their runtime efficiency and robustness [11]. Gay el al. detail in [10] the design of nesC, as well as summary of their experience with it. Regiment [12] is spatial macroprogramming language and runtime environment, with a compiler compiler that targets a lightweight intermediate representation called the Token Machine Language. It is based in the concept of Functional Reactive Programming, a programming paradigm that uses some building blocks of functional programming languages, like map, reduce, or filter. It was designed to support Spatio-Temporal Macroprogramming applications. In Regiment, the network is seen by the programmer as a set of spatialdistributed and time-varying signals, which represents the state of an individual node or region aggregate. Given this fact, the development of an application using Regiment is based in the usage of three main language concepts: 1. Signals, which are principal object the developer control;
CHAPTER 2. RELATED WORK 9 2. Regions, which represent a collection of signals; 3. Nodes, which allows the developer to access the state of an individual node. A Regiment program is translated to a node-level program using the language compiler. In this process, the program code is first reduced to an intermediate language called RQuery, which is finally translated to node-level code. In the process, the compiler performs many stages of node normalization, analysis and optimizations. Newton et al. present in [12] an overview of the Regiment language, describing in detail the respective compiler and deglobalization techniques, as well as an evaluation of performance of some event-detection in simulation. Table 2.1 summarizes the information for the three programming languages presented that are representative of the state-of-the-art. Prog. Language Network Perception Prog. Paradigm TinyDB Macroprogramming Declarative, SQL-Like nesC Sensor-Based Imperative, Sequential Regiment Macroprogramming Declarative, Functional Table 2.1: Programming Languages classification 2.2 Operating Systems and Virtual Machines The restricted resources that characterizes WSN makes the usage of a traditional Operating System (OS) impracticable, given the fact that tradition OS are designed for devices with significantly more resources. These differences should be taken into account when developing a OS for nodes in a WSN. There are a set of functionalities that an OS should provide and that include: resource abstractions for different hardware devices, interrupt management, task scheduling, concurrency control and networking support. Moreover, the OS should provide the application programmers high-level Application Programming Interface (API), independent of the underlying hardware [13]. Concurrently, virtual machines presented another important approach in developing WSN. Despite the great advantages of using OS, like performance optimization and the reduction
CHAPTER 2. RELATED WORK 10 of energy consumption, the lack of interoperability and reprogramming of the network makes them not totally satisfactory. In this context, Virtual Machine (VM) allow a more flexible model for application development, eventually with some performance and energy efficiency penalties. In the next two subsections we describe the most important works done in these areas, focusing in the main characteristics of each one. This part of the study will help understanding the current approaches that are being used when developing OS and VM for WSN. 2.2.1 Operating Systems Overview TinyOS is one of the most used OS for WSN, which can nowadays be thought as a standard. It is a tiny multithreaded OS whose implementation tries to guarantee concurrent data flow among hardware devices, providing modularized components with a small processing and storage overhead. It follows an Event-based model designed to support high levels of concurrent applications in a small amount of memory, using a simple FIFO mechanism for task scheduling. Levis et al. [14] presents a complete description about the system where they analyze the system components, execution models and support for concurrency. Contiki [15] is an open-source OS designed for networked embedded devices, implemented in the C language. A running instance of Contiki is composed for a kernel, a set of libraries, program loader and a set of processes. In Contiki all the communication between processes goes through the kernel, given the fact that it does not provide a hardware abstraction layer. However, it allows devices and applications to access the hardware directly. This OS allows preemptive multi-threading, implemented as a library on top of the event-based kernel, which can be optionally linked when implementing applications that require a multi-threading model of operation. Contiki’s kernel is a lightweight event scheduler that dispatches events to running processes, with a periodical call to process polling handlers. One particularity of Contiki is the implementation of a lightweight uIP TCP/IP stack, allowing IPv4 and IPv6 addressing with a small footprint. Application development in Contiki is made using the C language and it allows an over-the-air programming of the entire network. Dunkel et al. [15] presents a full description of the Contiki, analyzing in detail the construction of the kernel and the preemptive multi-threading. The authors also analyze how Contiki handles the libraries and how it support communication, finishing the article presenting some bedtests using this OS.
CHAPTER 3. SONAR ARCHITECTURE 17 To manage the WSN the owner uses a simple shell interface that is also supplied with the software. He can now list all the running tasks, set the period of a task, and add or remove a task in the network. These tasks are written using a very simple specific domain programming language, STL, which we address later in this thesis. To monitor the data produced at his WSN, the owner simply connects to the Broker of the publish/subscribe system. It then selects the data streams it is interested in from the WSN. This can be done for multiple WSN (e.g., more greenhouses, the garden, the house), and for many tasks running on the nodes of a WSN (e.g., temperature and humidity, movement detection, luminosity), providing a multiplicity of data streams that can be subscribed by users. This is the level of seamlessness that we aim to address with our architecture, SONAR. In the following sections we describe the components of each layer of the architecture. 3.2 Architecture Overview SONAR follows a typical 3 layer architecture, depicted in figure 3.1. It is based on a publish/subscribe architecture where a set of clients, connected to the Internet, access the data generated at each SONAR deployment through the SONAR Broker. The data layer is composed by a set of nodes that come with a pre-installed operating system and virtual machine, and a gateway, that collects the data produced in the nodes. Each node can schedule and run multiple tasks. A task can be described as a program that periodically runs in the nodes, with no interruptions, and that generally produces a data-stream. The gateway acts as a simple forwarder, exchanging data from the nodes with the other layers. A client, when connected to the Broker, can access a list containing information about the registered deployments. For each deployment, it is presented the set of running tasks, with the following parameters: task description, task period, and type of generated data. The client can subscribe the desired data streams and receives the respective data produced in the data layer. The management of the each deployment is made using an administration client that connects directly to a deployment adapter. With this client, a user is able to manage his deployment, adding or removing tasks, or changing the period of a running task.
CHAPTER 3. SONAR ARCHITECTURE 18 Figure 3.1: SONAR architecture. 3.3 Client Layer The Client layer is composed by two different modules included in the software the user must install in his computer: •a Publish/Subscribe Client, used to connect to a SONAR Broker (middle layer), allowing the user to list and subscribe the available deployments, receiving the data produced after the subscription; •an Administration Client that allows authenticated users to access a deployment, through a component called Adapter, and to manage it, sending control messages.
CHAPTER 3. SONAR ARCHITECTURE 19 3.3.1 Publish/Subscribe Client The Publish/Subscribe Client is a shell-based interface where a user can access the methods to list and subscribe a data stream, available in a SONAR Broker. Using this module, a user can send data messages, allowing him to list all the available deployments and respectively running tasks, subscribe and unsubscribe, tasks and query the Broker for a specific type of data being produced in all the available deployments. Figures 3.2a and 3.2b depict, respectively, the data flow of listing or subscribing a task and the data flow of publishing data generated at the Data layer to a client. To subscribe a data stream, the user sends a request to the broker indicating the ID of the desired data stream. The Broker parses that request and then responds to the client with a message confirming a successful subscription. When new data is available in the data layer, the respective adapter forwards that data to the Broker, who checks the clients subscribing these data-streams. It then sends the received data to each subscriber. 3.3.2 Administration Client The Administration Client is the component used by the users to administer deployments, namely, to register and unregister it own deployment in a Broker, as well as to manage it, allowing him to add, remove or change the period of a running task. Figures 3.3a and 3.3b depict, respectively, the data flow in the process of register/unregister the deployment and the data flow when adding, removing, or changing the period of a task. To register a deployment, the user sends a control message to the Adapter, who sends a register request to the Broker containing the MAC Address of the gateway. The Broker processes the request and response with a confirmation that the deployment had been registered. To manage his own deployment, the user sends a message control message to the Adapter containing the management command, which is then forwarded to the deployment gateway node. After receiving the command, the gateway radio the command to all the nodes in the deployment.
CHAPTER 3. SONAR ARCHITECTURE 20 (a) Data flow of listing and subscribing a task (b) Data flow of publish mechanism Figure 3.2: Data flow in the Publish/Subscribe Client
CHAPTER 3. SONAR ARCHITECTURE 21 (a) Data flow in a deployment register (b) Data flow in tasks management Figure 3.3: Data flow in the Administration Client
CHAPTER 3. SONAR ARCHITECTURE 22 3.4 Broker Layer The Broker is the middle layer of our architecture, which maintains a connection with one (or more) SONAR Adapters, as well as with a set of SONAR Clients. This component is responsible for the three main tasks: registering deployments, publishing data provided by the data layer, and handling subscription requests from clients. To allow these functionalities, the Broker stores three main structures: •atasks structure that stores all the parameters of one data streams registered in the Broker. Each task representation is composed by four parameters: an ID that identifies inequivoquely the task; a period that indicates the periodicity of the task; a values description that presents the data produced in that task; the units description that presents the units of each value produced; and, the task info, an optional field used to store some extra information about the task. •adeployments table that stores all the registered deployments. For each deployment, this table maps a pair of parameters: an general information field (optional), containing some generalist information about the deployment and a list of tasks, containing the ID of each task running in that deployment. •asubscribers table that, for each available data stream, maps a list of subscribers IDs, identifying the clients subscribing that data stream. 3.4.1 Data Flow in SONAR Broker There are two types of data flows related with the Broker: the first is related with the messages sent by the SONAR Clients, when listing, subscribing or unsubscribing a data stream; the second is related with the data produced at the data layer, which is received from the Adapter to be forwarded to the respective subscribers. Client layer ↔Broker messages Figures 3.4 and 3.5 describe the messages flow exchanged between the Client and the Broker when the Client is subscribing a data stream. The Client starts by listing all the available data stream. Figure 3.4 depicts the data flow involved
CHAPTER 3. SONAR ARCHITECTURE 23 1. the client send a message to the Broker asking for all the available data streams; 2. the Broker receives the message, queries its deployments table and produces a message containing a summary with the available deployments and the respective data streams. 3. The Broker responds to the client with the message containing the parameters needed so that the Client can subscribe the desired tasks; Figure 3.4: Available data streams After receiving a list of the available data streams, the client is able to subscribe them (Figure 3.5): 1. The Client sends a message to the Broker containing the IDs of the data streams to be subscribed; 2. the Broker receives that message and add the client ID to the entry of the subscribers table; 3. the Broker responds to the Client, confirming that he is now subscribing that data streams.
CHAPTER 3. SONAR ARCHITECTURE 24 Figure 3.5: Subscribing/Unsubcribing a data stream Data layer ↔Broker messages Figure 3.6 describes the mechanism for publishing a message. When the Broker receives a message containing Data from one Adapter, it parses the message and retrieves two parameters: the identifier of the deployment where the data was generated and the identifier of the task who generated the data. Using that information, it queries its Subscribers Table and retrieve the identifiers of the Clients who are subscribing that task. Using these identifiers, the Broker forwards the messages to the respective clients. Figure 3.6: Data delivery to subscriber of a given task.
CHAPTER 3. SONAR ARCHITECTURE 25 3.5 Data Layer The Data layer abstract all the sensors and actuators present in each deployment. It is composed by three different components: •SONAR Adapter; •gateway nodes; •a mesh of Nodes. 3.5.1 Adapter The Adapter is a software component that establishes connections with other two components: the Administration Client and the Gateway. It is responsible for two main actions: 1. Administration: allows users to administrate the aspects related to his SONAR Wireless Sensor Network deployment using the Administration Client. This connection is only active when the administrator is using the Administration Client. 2. Forwarding: gathers coming messages from the Gateway with the data generated in each node and forward it to the Broker. This connection is always active when the deployment is running. Figure 3.7 depicts the data flow associated with the forwarding function of the Adapter. Red arrows and radio signals indicate the path done by the data generated at the nodes. For each running task that produces data, each node sends that data to the deployment Gateway, who analyze the message and add parameters to unequivocally identify the origin of the message. After that, it simply forward the message to the adapter, who then forward it to the Broker. 3.5.2 Gateway and Nodes The Gateway is a typical node equipped with a radio device capable of receiving and forwarding tasks to a previously configured set of nodes. It is responsible to radio the
CHAPTER 3. SONAR ARCHITECTURE 26 Figure 3.7: Data flow generated in nodes commands and tasks sent by the administrator to all the nodes, as well as receiving the data produced in the nodes and forwarding it to the adapter. Figure 3.8a depicts a high level hardware representation of a typical node and Figure 3.8b presents a picture of a SONAR Gateway. (a) Typical node scheme (b) SONAR Gateway Sensor. Figure 3.8: Typical node scheme and SONAR Gateway node The nodes used in SONAR follow the same hardware configuration as the gateway, with the addition of some sensors and actuators. Currently, they contain temperature, humidity, and light sensors, as well as a LED functioning as an actuator. In the next chapter we are going to formally describe the software installed in the gateway
CHAPTER 4. CLIENT LAYER AND BROKER LAYER 33 Python Script Code 4.2.1 Python Script to insert data received in the STDIN to a MySQL Database Import MySQLdb con ne ct io n = MySQLdb . connect ( host= ” l o c a l h o s t ” , user= ” root ” , passwd= ” rootpasswd ” , db= ”room1 .83 dep ”) c u r s o r = conn . c u r s o r ( ) whi l e tr u e : data = raw inp ut ( ) . s p l i t (” ”) deployment = data [ 0 ] t a s k i d = data [ 1 ] mac sensor = data [ 2 ] data type = data [ 3 ] value = data [ 4 ] t r y : c u r s o r . e xe cut e (” ’ ’ INSERT INTO data VALUES (%s ,%s ,%s ,%s ,% s ) ” ’ ’ , ( deployment , t a s k i d , mac sensor , data type , value)) except : conn . r o l l b a c k ( ) conn . commit () conn . c l o s e ( )
Chapter 5 Data Layer In this chapter we present the specification and implementation of the SONAR data layer. This software runs in the gateway and nodes of the deployments and is pre-installed. It includes an operating system, a domain-specific programming language, and a virtual machine. In Section 5.1 we describe the programming language used to implement tasks in SONAR, SONAR Task Language (STL). Thereafter, in Section 5.2 we describe the SONAR Virtual Machine and the compiler used to produce the byte-code executed in the nodes. Section 5.3 describes the operating system running both in the nodes and in the gateway. This chapter ends with Section 5.4 that describes the data flow associated with each node. 5.1 Programming Language In this section we describe the syntax and semantics of the domain-specific programming language used to implement periodic tasks - the SONAR Task Language (STL). 5.1.1 Syntax The syntax for tasks is described in Figure 5.1. The notation ˜αis used to denote a sequence of pairwise distinct elements, α, of a given syntatic cathegory. A task Tuses two sets of identifiers, sand a, to specify the available sensors and actuators in a given platform. Each 34
CHAPTER 5. DATA LAYER 35 T::= sensors {s1:σ1. . . sn:σn}Tasks actuators {a1:σ1. . . am:σm} init {˜q} [˜τ]loop {˜r} σ::= ˜τ7→ τTypes τ::= bool |int |float |void q::= τ x =vInitializations r::= x=eInstructions |a(˜e) |radio [˜e] |if e{˜r}else {˜r} |while e{˜r} e::= s(˜e)|eop e|op e|(e)|vExpressions v::= x|uValues u::= bools |ints |floats Constants Figure 5.1: The syntax of STL. of these identifiers maps to a unique sensor or actuator in the hardware. This declaration is thus similar for all tasks running on the same hardware configuration and in a more concrete syntax would simply be included by the programmer using a compiler directive. The code that is actually specific for the task starts with the init block, used to initialize global task variables. This code is not executed, rather the compiler copies the initial values for each variable directly to the data segment of the byte-code generated for the program. The loop block, on the other hand, is the code executed for every (periodic) activation of the task. It is immediately preceded by the type of message sent back by the task to the gateway using the construct [˜τ]. The task only sends messages of this type to the gateway and the type is checked against all radio statements in the task. The instructions available to the programmer include: assignment, actuation - a(˜e), sending a set of evaluated expressions to the gateway - radio [˜e], a conditional execution construct - if e{˜r}else {˜r}, and a while loop - while e{˜r}. The expressions are standard except for s(˜e) that is used to read a value from a given sensor. As we said, for a given platform and configuration, the hardware description provided by the constructs sensors and actuators is the same. We use a preprocessing directive - use - to include this description at the top of all programming examples in this thesis (Figure 5.1.1).
CHAPTER 5. DATA LAYER 36 STL Code 5.1.1 Hardware description for Arduino 2560 prototype WSN - file ”ard2560.hw”. sensors { temperature : void −>float , humidity : void −>float , l i g h t : void −>float } actuators { led :bool −>void } The example in Figure 5.1.2 shows a STL program that at each activation reads the temperature and humidity and radios the values to the gateway. A similar implementation in Arduino C++ is presented in Appendix A.0.1. The example uses two sensors, designated as temperature and humidity, whose types are declared in hardware description file “ard2560.hw”. Notice that the periodicity of the task is not included in the code. It is an external attribute set with the administration client when the task is sent to the gateway to be radioed to the nodes. In this way, users with administration access can dynamically change the period of running tasks using simple control messages. STL Code 5.1.2 STL program that reads the temperature and humidity and radio the results to the gateway. use ” ard2560 . hw” init { float t = 0 . 0 ; float h = 0 . 0 ; } [float @ ” temperature : C e l s i u s ” , float @ ” Humidity : Pe rcentag e ” ] loop { t = temperature ( ) ; h = humidity ( ) ; radio [ t , h ] ; } The language specification is complete with both the operational and static semantics that together define how well-formed programs are executed. The operational semantics is defined through a reduction relation →on the program state. The latter is defined as either the halted state, ⊥, or, if the task is active, as a tuple
CHAPTER 5. DATA LAYER 37 (S, A, V, ˜r). In the latter, Sand Aare of type Set(Vars) and keep the identifiers for the built-in functions declared at the beginning of an STL program and that provide access to sensors and actuators, respectively; V, of type Map(Vars,Values) keeps the values of the variables during the execution of the program. Thus, the initial state for the task: sensors {s1:σ1. . . sn:σn} actuators {a1:σ1. . . am:σm} init {˜q}[˜τ]loop {˜r} is the tuple (S0, A0, V0,˜r), where: S0={s1, . . . , sn} A0={a1, . . . , am} V0={(x:v)|τ x =v∈˜q} The reduction rules are presented in Figures 5.2 and 5.3, where the identifiers sand aare built-in functions, as well as the function radio. We also simplify the notation somewhat by not including Sand Aexplicitly in the state, i.e., we represent the tuple (S, A, V, ˜r) tuple as the shorter version (V, ˜r). The rules have the structure: c1. . . cn (V1,˜r1)→(V2,˜r2) where the ciare preconditions or actions that must be fulfilled to make the transition from the current state, (V1,˜r1), to a given state, (V2,˜r2), possible. For example, rule (2) for instructions executes a(˜e) statements, underlined and the next in the code sequence. It evaluates the expressions ˜einto values ˜vfirst. It then calls a built-in function write(a, ˜v) that actually performs the low-level operation for the program. When it returns the state of the program is (V, ˜r). The reasoning is similar in rule (2) for expressions, where we read data from a sensor. Here, however, the value returned from the built-in function, v=read(s, ˜v), is the value of the expression. Rule (8) for instructions, another example, is invoked when the code sequence in the text block ends, the next state is ⊥.
CHAPTER 5. DATA LAYER 38 v=eval(V, e) (V, x =e˜r)→(V+{x:v},˜r)(1) ˜v=eval(V, ˜e)a∈Awrite(a, ˜v) (V, a(˜e) ˜r)→(V, ˜r)(2) ˜v=eval(V, ˜e)send(˜v) (V, radio [˜e] ˜r)→(V, ˜r)(3) eval(V, e) = true (V, if e{˜r1}else {˜r2}˜r3)→(V, ˜r1˜r3)(4) eval(V, e) = false (V, if e{˜r1}else {˜r2}˜r3)→(V, ˜r2˜r3)(5) eval(V, e) = false (V, while e{˜r1}˜r2)→(V, ˜r2)(6) eval(V, e) = true (V, while e{˜r1}˜r2)→(V, ˜r1while e{˜r1}˜r2)(7) (V, )→ ⊥ (8) Figure 5.2: Reduction rules for STL instructions.
CHAPTER 5. DATA LAYER 39 ˜e=e1. . . envi=eval(V, ei),1≤i≤n eval(V, ˜e) = ˜v(1) ˜v=eval(V, ˜e)s∈S v =read(s, ˜v) s(˜e) = v(2) v1=eval(V, e1)v2=eval(V, e2) eval(V, e1op e2) = v1op v2 (3) v=eval(V, e) eval(V, op e) = op v(4) eval(V, x) = V(x) (5) eval(V, v) = v(6) Figure 5.3: Reduction rules for STL expressions. 5.1.2 Static Semantics The static semantics of a task is provided in the form of a type system (Figure 5.4). The rules are fairly standard and use a typing environment Γ that keeps track of the types for identifiers. The rules are written as Γ `rfor instructions, meaning that the instruction is well-formed, and Γ `e:τfor expressions, meaning that expression ehas type τ. Some rules have side effects, in which the environment Γ is enriched with new entries and becomes Γ0, as in Γ ` · · · a Γ0. An example is rule (4): Γ `[˜τ]aΓ,radiates : ˜τ(Γ0is Γ plus the type collected from the radiates construct). Besides this rule, three others are worthy of note. Rule (10) checks that messages sent by the task have types that match the one declared in the radiates construct. Rule (12) checks that the sensor, s, is of type ˜τ7→ τ0, that the arguments ˜ematch the type ˜τto infer that the value returned by s(˜e) is of type τ0. The logic is similar for rule (9), where the type system just checks that the instruction a(˜e) is well formed (instructions do not evaluate to values). Rules (15), (16), and (17) are axioms and allow booleans, integers, and floating point values to be typed.
CHAPTER 5. DATA LAYER 40 ∅ ` sensors {s1:σ1. . . sn:σn} a Γ1 ∅ ` actuators {a1:σ1. . . am:σm} a Γ2 ∅ ` init {q1. . . ql} a Γ3 Γ1,Γ2,Γ3,radiates : ˜τ`loop {˜r} ` sensors {s1:σ1. . . sn:σn} actuators {a1:σ1. . . am:σm} init {q1. . . ql} [˜τ]loop {˜r} (1) ∅ ` sensors {s1:σ1. . . sn:σn}a{s1:σ1. . . sn:σn}(2) ∅ ` actuators {a1:σ1. . . am:σm}a{a1:σ1. . . am:σm}(3) Γ`q1aΓ1Γ`qlaΓl Γ`init {q1. . . ql} a Γ1,...,Γl (4) ∅ ` v:τ Γ`τ x =vaΓ, x :τ Γ`˜r Γ`loop {˜r}(5,6) Γ`r1. . . Γ`rn Γ`˜r Γ`x:τΓ`e:τ Γ`x=e(7,8) Γ`a: ˜τ7→ void Γ`˜e: ˜τ Γ`a(˜e)(9) Γ`˜e: ˜τΓ(radiates) = ˜τ Γ`radio [˜e](10) Γ`e:bool Γ`˜r1Γ`˜r2 Γ`if e{˜r1}else {˜r2}(11) Γ`s: ˜τ7→ τ0Γ`˜e: ˜τ Γ`s(˜e) : τ0(12) Γ(x) = τ Γ`x:τ(13) Γ`e1:τ1. . . Γ`en:τn Γ`e1. . . en:τ1. . . τn (14) ∅ ` v:bool ∅ ` v:int ∅ ` v:float (15,16,17) Figure 5.4: Type system for STL.
CHAPTER 5. DATA LAYER 41 p::= h d b Program h::= i1i2Header d::= ˜vData Segment v::= bools |ints |floats Values b::= ˜rText Segment r::= ld i|st i|wrt i1i2|rd i1i2Instructions |rad i|bf i|jp i|ret |bop |uop Figure 5.5: Byte-code syntax. 5.2 Compiler and Virtual Machine In this section we give the specification for the SONAR Virtual Machine (SVM), one of the modules pre-installed in the nodes. The virtual machine executes STL tasks, translated into byte-code by a compiler. We begin by defining the byte-code format and then give the translation function for the STL source code. 5.2.1 Formal Description The byte-code is composed of 4 segments: header, data, stack, and text (Figure 5.5). The header contains the total size of the byte-code as well as the offset to the beginning of the text segment. The stack segment is allocated between the data and text segment, growing towards the lower addresses. Its size is calculated at compile time since there are no calls to user defined functions. The data segment provides space for all the variables in a STL program. Constants and the initial values of global variables are stored there by the compiler. The data segment can be seen as the only activation record required for the virtual machine since, again, there are no calls to user functions or user functions in tasks. All variables, of types bool,int, and float, use 4 bytes in the data segment in this version, but this can and should be optimized to minimize the size of the byte-code. The text segment is composed of instructions that have a 1 byte opcode and eventually 1 or 2 extra bytes for arguments. There are instructions for loading a value to the stack (ld ), storing a value from the stack (st ), sending an actuation command (wrt ), reading a sensor (rd ), sending a message over the radio (rad ), the usual control flow (bf ,jp ,ret ) and, the usual integer and floating-point arithmetic and logic and relational operators (bop ,uop ).
CHAPTER 5. DATA LAYER 42 Byte-code instructions map almost one-to-one with reduction rules from the operational semantics. This correspondence is important for proving that the virtual machine correctly executes the byte-code, but this is a problem we will not address here. The translation function receives a syntactic term and returns a pair of sequences (D, B) (Figures 5.6 and 5.7). The first, D, is the contribution of the term to the data segment, the latter, B, is the contribution to the text segment. The top level translation function [[·]], for STL tasks, breaks the translation into a sequence of pairwise concatenations (operator ”:”) and uses appropriate translation functions for each syntactic category. We use the same [[·]] to simplify the notation, but these should be seen as distinct functions. The translation function uses 3 sets which hold integer identifiers for sensors and actuators, Sand A, and data segment offsets for variables (set Var) and constants (set Const), Vand U, defined as follows: S={(si, i)|si∈gs:τ} A={(ai, i)|ai∈ga:τ} V={(x, i)|x∈Var ∧i= offset(x)} U={(u, i)|u∈Const ∧i= offset(u)} The translation function is quite straightforward. The translation of an actuation command, a(˜e), is simply the translation of the arguments ˜e, followed by a wrt instruction with the integer identifier for the actuator A(a) and the number of expressions, |˜e|, as the arguments. Similarly, reading a sensor, s(˜e), translates into the translation of the expressions followed by a rd instruction with the integer identifier for the sensor S(s) and the number of expressions, |˜e|, as the arguments. Likewise, the translation for radio [˜e] is simply the translation of the expressions to be sent, followed by a rad instruction with the number of expressions, |˜e|, as the argument. The state of the virtual machine is represented as the term [D|S|B]j, where jis the program counter and is used to travel the instructions in the text segment. The halted machine is represented by a special state denoted ⊥. To run a task Tin the virtual machine we use the translation function to get its byte code [[T]] = (D, B) and set its initial state to: [D|0. . . 0 | {z } k |B]0
CHAPTER 5. DATA LAYER 49 closest activation time. This becomes the next task to be executed by the operating system. Otherwise the predicate TableEmpty will evaluate to true. Algorithm 5 Sleep until next task activation function sleep() if ¬tableEmpty() then t←getNextActiv(curr) rtcAlarm(t) end if microSleep() end function Procedure Sleep (Algorithm 5) computes the time until the next task activation and programs an alarm to wake up the node. The node then goes to sleep. This specification builds on the underlying assumption that tasks, being so small, execute in only a tiny fraction of their corresponding periods. In other words, if a task has a period pand an execution time, per activation, of t, then tp. Otherwise we make no effort to schedule tasks within their periods. Since tis in the order of milliseconds we find this assumption adequate for practical purposes. Finally, procedure Listen (Algorithm 6) checks for any incoming messages while the main loop was running. We assume that the nodes have the means to receive and to buffer messages asynchronously, by programming an appropriate handler to process the corresponding hardware interrupts. If a message is received, its tag is checked to identify its type and it is processed accordingly. At this point, there are 4 types of control messages: TASK - sends the identifier, the period and the byte-code for a new task to be executed in the node; PERIOD - sends the identifier and the new period for a running task in the node; KILL - sends the identifier of a task to be invalidated in the node, and; RESET - that invalidates all tasks running on a node. When a new task is reassembled and copied to the task table, its next activation is set to getNextActiv(curr) + δ, where δis a delay introduced to make sure that the task is schedulable in the next loop run, i.e., its activation time is in the future when the Schedule procedure is called. 5.4 Implementation and Data Flow Figure 5.9 depicts an high level overview of the implementation and the data flow in a deployment gateway.
CHAPTER 5. DATA LAYER 50 Algorithm 6 Handle Incoming Radio Message function handleRadioInterrupt() interrupted ←True end function function listen() if interrupted then msg ←readRadioRCVBuffer() tag ←getTag(msg) switch (tag ) case TASK : i←getId(msg) p←getPeriod(msg) b←getBytes(msg) addTask(i, p, b) case PERIOD : i←getId(msg) p←getPeriod(msg) changePeriod(i, p) case KILL : i←getId(msg) removeTask(i) case RESET : for i= 0 . . . TableSize −1do removeTask(i) end for end switch interrupted ←False end if end function
CHAPTER 5. DATA LAYER 51 Figure 5.9: Message flow in SONAR gateway The gateway software is composed by two main parts: •a forwarding loop, which listens to control messages received from the deployment adapter and data messages received from the deployment nodes; •a set of hardware libraries, used to access and control the sensors, actuators and other harware modules present in the board. As presented in the same figure, the gateway is always listening to two different type of data: control messages, sent by the adapter, which contains the management commands sent by the Administration Client and data messages, sent by the deployment nodes, containing the data produced in each running task. Figure 5.10 depicts the same high level overview of the implementation and the data flow, this time about the nodes. Each node is composed by three main components: •a receiving and scheduling loop, which is responsible for listening to new data radioed by the gateway and containing the control messages sent by the Administration Client, as well as by the scheduling of the running tasks in the node; •a virtual machine, used to run the byte-code tasks stored at the node; •a set of hardware libraries, used to access and control the sensors, actuators and other harware modules present in the board.
CHAPTER 5. DATA LAYER 52 Figure 5.10: Message flow in SONAR nodes As shown in the figure, a node receives control messages from the gateway via the XBee antenna and processes it. These messages are used to change to reprogram the tasks in the node, allowing to add or remove a task, change the period of a task and remove all the tasks. All the data produced in a running task is directly sent to the gateway by the virtual machine, which uses the hardware libraries present in the node. 5.5 Summary In this chapter we presented the formal description of the the data layer components. We started by formally presenting the STL syntax, depicting thereafter some STL examples and the respective reduction rules for the language instructions. Next we described the operating systems pre-installed in SONAR nodes, depicting the most important routines that compose both the nodes and the gateway. We finished this chapter with the formal description of SONAR virtual machine, as well as the description of the STL compiler.
Chapter 6 Setup, Evaluation and Discussion In this chapter we analyze the impact of using our virtual machine and operating system in terms of energy consumption and memory footprint. We start by detailing the setup process of our system, presenting an example on how to use all the components. Next, we describe the hardware configuration of the nodes, a relevant point in the energy consumption. Thereafter, we present the experimental results obtained, followed by the analysis and discussion of the data gathered. We end this chapter with a brief summary. 6.1 Setup We start this chapter by depicting the full process of using the SONAR prototype, explaining all the steps in the initialization process, the data flow happening when the Administration submits a new task, and the data flow related with the subscription and reception of the respective data by the Publish/Subscribe client. 6.1.1 Initialization To start using SONAR, the user must own a computer with an USB interface, as simple as a Raspbery-Pi, where he can connect the gateway node. This computer must have access to the Internet, allowing the deployment to send the data to the Broker Web Service. Using the previously installed SONAR software, the user starts the Adapter Web Service, 53
CHAPTER 6. SETUP, EVALUATION AND DISCUSSION 54 which automatically connects to a SONAR Broker, and connects the gateway to the computer. After finishing the boot, the gateway sends a message to the Adapter containing some information that needs to register the deployment in the Broker. At this point, the user can start the Administration Client. It starts by opening a connection with the Adapter, then displaying in the user interface a list containing the available commands. Before starting the management of the deployment, the user must register his own deployment in the Broker using the reg command, which sends the necessary information to the Broker in order to insert the deployment in the Broker running deployments list. Now, the initialization process is finished and the user can fully use his own SONAR deployment. 6.1.2 Managing the running tasks To add a new task, the user must use the task command, providing the paths to previously created byte-code and description files. Using this information, the Adapter starts two distinct data flows: one targeting the Broker, sending the information that a new task had been added to the deployment and another to the gateway, containing the byte-code that must be radioed to the nodes. The same data flows are generated when the user submits the period,kill, and reset commands, affecting the nodes in the Data layer and changing the information about the tasks in the Broker. 6.1.3 Client subscription To subscribe a set of tasks, a user must start the Publish/Subscribe client Web Service, which opens a connection to the Broker, and send a ld command. This command contacts the Broker and retrieves all the available deployments (and the respective tasks) that are connected in that moment. Using that information, the client is able to subscribe a task using the sub command, which tells the Broker that this Client intends to receive all the data produced by a given task. The Broker receives that information and adds the ID of the client in the Tasks Table. From this moment, until the client closes the connection or unsubscribes the task, every
CHAPTER 6. SETUP, EVALUATION AND DISCUSSION 55 time the Broker receives data from that task, it automatically forwards it to the Client. 6.2 Node Configuration In the current configuration of our prototype, each node is composed by an Arduino Mega2560 board connected to an Arduino Wireless Protoshield, equipped with a XBee Series 2 antenna, a SHT-15 temperature and humidity sensor, a Light-Dependent Resistor (LDR), one red LED and a Adafruit Chronodot Real-Time Clock. Figure 6.1 presents the hardware scheme of the nodes, depicting the connection between all the hardware components. 6.2.1 Jumper Connections As depicted in Figure 6.1, we are currently using 3 jumpers from the wireless shield to the Mega2560 board: one jumper from pin 3 to pin 18, which connects the XBee Rx to the Arduino Tx 0, used to wake up the node when a new message is received from the gateway; a second jumper from pin 2 to pin 19, which connects the XBee TX to the Arduino Rx 0, used to pass to the antenna all the data produces in the tasks; and a third jumper from pin 8 to pin 20, which connects the Chronodot SQW pin to the Arduino SDA pin, used to wake up the node when a task must be executed. 6.2.2 XBee setup To get a full description of the nodes in our prototype, it is relevant to describe how the XBee antennas are configured, since it significantly affect the energy consumption of this device. When developing the software for our nodes, one important decision made was related with the network organization, which determines how a node communicate with the others. Currently, we are taking benefits from the fact that the XBee antennas allows the usage of a mesh architecture, with multi-hop communication and message reliability. It was a feature we thought that would be important given the fact that in some deployments, a node can be physically placed in locals that are out-of-reach to a direct communication with
CHAPTER 6. SETUP, EVALUATION AND DISCUSSION 56 XBEE-1B1 SHT1XSMD CHRONODOT GND GND GND GND GND +5V CTS DIN 3 DIO0 DIO1 DIO2 DIO3 DIO4 DIO5 DIO9 DIO11 7 DIO12 4 DOUT 2 DTR 9 GND 10 RES 8 RES RESET 5 RSSI 6 RTS VDD 1 DATA GND SCK VDD BAT 32K SQW RST SDA SCL VCC GND SV4 1 2 3 4 5 6 7 8 SV5 1 2 3 4 5 6 7 8 SV2 1 2 3 4 5 6 SV3 1 2 3 4 5 6 SCL1 SDA1 AREF AREF GND 13 12 11 10 9 8 SCL1 SDA1 GND 13 12 11 10 9 8 7 7 6 6 5 5 4 4 3 3 2 2 1(TX) 1 0(RX) 0 A5A5 A4A4 A3A3 A2A2 A1 A1 A0A0 VIN GND GND 5V 3.3V RESET VIN GND GND 5V 3.3V RESET IOREF I/OREF (N/C)N/C <PWR>-V<PWR>-V <PWR>+V<PWR>+V <USB>GND<USB>GND <USB>D- <USB>D- <USB>D+<USB>D+ <USB>+V<USB>+V 14 15 16 17 18 19 20 14(TX3) 15(RX3) 16(TX2) 17(RX2) 18(TX1) 19(RX1) 20(SDA) 21(SCL) 21 A15 A15 A14 A14 A13 A13 A12 A12 A11 A11 A10 A10 A9 A9 A8 A8 A6A6 A7A7 5V 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 5V 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 GND GND GND 52 50 48 46 44 42 40 38 36 34 32 30 28 26 24 22 GND 52 50 48 46 44 42 40 38 36 34 32 30 28 26 24 22 5V 5V D2 23 5V 5V 8 8 A5 A5 7 7 6 6 9 9 10 10 12 20 19 18 17 11 15 13 14 16 ARDUINO MEGA 2560 ICSP JUMPER -> [20->PD1(SDA / INT1)] , [8->PH5(OC4C)] - ChronoDot Alarme JUMPER -> [19->PD2 (RXD1 / INT2)] , [2->PE4(OC3B/INT4)] - Xbee_TX>Ard_RX (Comm Wakeup) JUMPER -> [18->PD3(TXD1 / INT3)] , [3->PE5(OC3C/INT5)] - Xbee_RX>Ard_TX 3 2 Figure 6.1: SONAR node scheme - Arduino Mega 2560
CHAPTER 6. SETUP, EVALUATION AND DISCUSSION 57 the gateway. The mesh architecture can be very useful in this situations, using message forwarding through the network and allowing this nodes to send data to the gateway. Despite very useful, the mesh architecture brings an increase in the energy consumption, since all the nodes have to be configured has routers. This could in some cases be very undesirable, since a node marked as router disallows the transition of the XBee antenna to a sleep state, enabling power saving. A full description about all the possible XBee antenna configurations can be accessed in [34]. Other important parameters of our XBee configuration are: •The RF interface is configured to use the Highest Power Level, with Boost Mode Enabled, increasing the amount of energy consumed by the antenna; •There is no encryption in the radio messages and the network do no use any type of security, which would increase the energy consumption. Although there are a bigger set of XBee configuration parameters, we are only analyzing a reduced number parameters since these are the ones that influence the most the energy consumption of this device. 6.3 Evalutation The following tests have the purpose to determine the energy consumption and computation overhead of our prototype. The tasks test radio transmission, access to sensors and actuators and computation. Each test was implemented both in STL, running on top of SVM in each node, and directly in Arduino’s native C/C++/Wiring. To measure the timings and the energy consumption, we connected a multimeter in series with one node (Figure 6.2) and registered the electric current variation associated with the execution of each task. The multimeter we used was a TENMA 72-7732A [35]. A Keysight InfiniiVision MSO-X 2002A oscilloscope [36] was also used for some time related measurements. 6.3.1 Experimental Results The first tasks test radio transmissions. Figure 6.3.1 presents the STL code for a task that radioes 64 bytes, simulating a case where, for example, a task is programmed to
CHAPTER 6. SETUP, EVALUATION AND DISCUSSION 58 Figure 6.2: Multimeter and oscilloscope setup. radio 16 sensor readings (floating point values) to the gateway. The 64 bytes refer only to the payload of the messages that carry an additional 10 bytes of header information. Appendix A.0.2 presents a similar implementation in Arduino C++. STL Code 6.3.1 Transmission of data. use ” ard2560 . hw” [float @ ” f l o a t 1 : s en sor1 ” , float @ ” f l o a t 2 : s en sor2 ” , float @ ” f l o a t 3 : s en sor3 ” , . . . , float @ ” f l o a t 1 6 : s ensor 16 ” ] loop { radio [ 2.0 , 2.0 , 2.0 , 2.0 , 2.0 , 2.0 , 2.0 , 2.0 , 2.0 , 2.0 , 2.0 , 2.0 , 2.0 , 2.0 , 2.0 , 2.0 ] ; } Figure 6.3 (blue line) shows current intensity vs. time when running the task with a period of 10 seconds. The first records the successful reception of the message by the node (our code puts the red LED on for 1.0 second). After the reception, one more peak (around t= 20) is visible, corresponding to the moments where the node radioed the 64 bytes.
CHAPTER 6. SETUP, EVALUATION AND DISCUSSION 65 the temperature sensor, we cannot yet explain the lower overhead (only a factor of 1.1 slower) relative to the other sensors and actuators (globally around 3 times slower). As the energy consumed is proportional to the time the task takes to execute, clearly the optimizations must focus on this aspect, all other being the same for STL tasks and for Arduino programs. We believe, however, that even in this unoptimized state our prototype compares well with Arduino native code with the added benefits of simplified programming and dynamic reprogramming. 0 0.2 0.4 0.6 0.811.2 1.4 1.6 ·104 4 6 8 10 Iterations STL Ard Figure 6.9: SVM overhead vs. size of problem. The possibility to dynamically reprogram the network allow us to change the running tasks at a small energy cost, avoiding simultaneously the need to flash the board. When programing in the Arduino native language, this process is much more complex, forcing the user to upload the code to the flash memory. Figure 6.10 presents the profile obtained using the oscilloscope when flashing one node to change the running program in Arduino native language. This data was obtained then flashing the board with the code used to test the temperature sensor access. The first two visible peaks represents the moment when the board is reseting, a mandatory step so it can access the bootloader. After accessing the bootloader, there is a visible plateau where the board is waiting for a command indicating that there is a new program to be flashed to the board (presented in the plot from t= 0.750 to t= 1.000 approximately). Next, the flash starts and the data is written to the board (from t= 1.000 to t= 2.500 approximately), followed by a period where it is verified that all the data had been correctly written. The whole process took 4294ms to occur, being the board fully active for a period of 4024ms. Applying the formulas previously presented, flashing the board to upload a new program consumed about 1991.9mJ.
CHAPTER 6. SETUP, EVALUATION AND DISCUSSION 66 0.000 0.500 1.000 1.500 2.000 2.500 3.000 3.500 4.000 600 650 700 750 Time (ms) ∆ Voltage (mV) Board Flashing Profile Figure 6.10: Board Flash Profile To perform the same action using our prototype, the only consumption is the reception of the message, plus a very small overhead when the code is being stored and scheduled. In this case, it took us 100ms to receive the message, store the code and schedule it, with a consumption of about 49.5mJ, 40 times less that flashing the board in Arduino. 6.4 Summary In this chapter we describe the usage of SONAR and present the benchmarking of our prototype. We describe the setup used to measure the energy consumption and execution time of each tested task, presenting all the plots obtained in each execution. We compare the values obtained using our prototype with the values obtained when running a task written using the Arduino native language. The ratio between these values allowed us to study the impact of our prototype in terms of energy consumption and execution time.
Chapter 7 Port to Arduino Uno In this chapter we describe the process of porting our prototype to a new node based on a Arduino Uno board. We start by presenting an overview of the parameters we analyzed before starting to port our solution. Next, we describe the implementation of a hardware test tool we created to provide a simple and fast way to test the hardware components present on the board. We finish this chapter by describing the changes made to port our prototype to the Uno board, detailing the main problems found and quantifying the amount of code added or re-written. 7.1 Overview In order to port the current solution to a new sensor based on the Arduino Uno, two main steps were taken to adapt all the needed code which makes our solution possible to run in a different node. First, we analyzed the used pins in Arduino Mega2560 and mapped it in the Arduino Uno pins, focusing in the used Universal Asynchronous Receiver/Transmitter (UART) connections used. Second, given the memory constrains of the Arduino Uno, we analyzed the memory consumption of our prototype and parameterized the operating system and virtual machine to reduce the maximum number of tasks allowed to run simultaneously in a node Figure 7.1 presents a picture of both boards: the Mega2560 and the Uno. Both boards have the same hardware configuration, despite the differences in the jumpers connections, depicted in the picture. 67
CHAPTER 7. PORT TO ARDUINO UNO 68 Figure 7.1: SONAR nodes - Mega2560 and Uno 7.2 Hardware Test Tool At this point we concluded that currently, the SONAR nodes were using two UART pins in order to allow external interrupt events: one reserved to the XBee event, used to wake the nodes when a control message is being received and one for the RTC alarm, used to wake up the node when a deployed task must start to execute. At this point, one major difference between the Arduino Mega2560 and the Arduino Uno arises: the former has four UART pins and the latter only has one. This lead us to make some significant changes in the way our nodes implement the external events to wake up. In order to test all the needed changes, we decided to implement a simple test project that allows us to interact with each module of our node, using the same hardware libraries we were using before. In the next two subsection we describe the implementation process of this tool. 7.2.1 XBee external event The first change we have done was the XBee connection to the board. In the previous implementation, the XBee antenna was connected to the Arduino Mega2560 board through jumpers using the serial communication pins 18 and 19 (RX1 and TX1 respectively). Given
CHAPTER 7. PORT TO ARDUINO UNO 69 the current wire welding, we would need to use software serial communication to allow the serial communication between the XBee antenna and the Uno board. Since version 1.0, Arduino offers by default a library that emulates the serial communication on other digital pins, the SoftwareSerial [38] library. Using this library, we mapped two serial communication pins in digital pin 2 and 3, connecting the XBee TX pin to the Uno RX pin and the XBee RX pin to the Uno Tx pin. With this configuration, we created a simple example that tries to send some floating point values to the gateway using unicast radio messages. The gateway correctly received the message sent, proving that the XBee antenna and the Uno board are correctly connected and working. 7.2.2 RTC alarm After changing the XBee connection and event in the Arduino Uno board, we started to solve the RTC alarm problem. Given the fact that at this point we did not have any more serial communication pins available in our board, we searched for a different way of allowing events to wake up the board using the RTC. After some research, we found a simple solution that can be used to overcome this restriction: Pin Change Interrupt (PCInt). A Pin Change Interruption can be enabled on any of the Arduino Uno signal pin, allowing the trigger of events ON CHANGE of the pin value. To test this feature we used the same library, PinChangeInt [39]. With this library, we were able to enable software interrupts in a given digital pin, allowing to receive the alarm event generated at the RTC. At this point we analyzed the circuit connections used in the previous implementation (Figure 6.1) and decided to use pin 8 as the target pin. With this choice, we were able to maintain the same welded wires and allow the RTC to wake the board using pin CHANGE interrupt. To test if this approach works with our node configuration, we have written a very simple test in C++ where we simply start the node, schedule an alarm for 5 seconds later, put the node in sleep mode and wait for the alarm to wake it. With this test we were able to verify that the chosen configuration allows the RTC to correctly generate wake up events using PCInt.
CHAPTER 7. PORT TO ARDUINO UNO 70 7.2.3 Gathering all together After testing each of the previous changes, we tried to incorporate all the features in a simple tool that allows the test the complete hardware components present in the board. For this tool, we uses the same libraries used in SONAR, in order to guarantee that no library conflicts occurs. In the process of gathering all together, an error arises when incorporating the PCInt library and the SoftwareSerial library. After some code analysis, we discovered that the error was related with the fact that the SoftwareSerial library uses some PCInt definition to work properly. More specifically, both libraries are defining a set of interrupt vectors, which enter in conflict. To solve this problem, we analyzed the set of pins that each of this vectors is using, getting the following results: •ISR (PCINT0 vect) pin change interrupt for digital pins from 8 to 13 •ISR (PCINT1 vect) pin change interrupt for analogical pins from 0 to 5 •ISR (PCINT2 vect) pin change interrupt for digital pins from 0 to 7 Given the pin configuration we previously used, the solution to this problem was to simply split which vector pins are used by each library: PCInt library defined the PCINT0 vect and PCINT1 vect, allowing the usage of interrupts in pin 8, and the SoftwareSerial library defined the PCINT2 vect, allowing the creation of software serial communication in pins 2 and 3. With these changes, we were able to use both libraries simultaneous without conflicts, finishing the implementation of the hardware test tool. Figure 7.2 shows an example of the interface: the user is asked which hardware component he wants to test and then the output is retrieved by the selected component. 7.3 SONAR porting The Hardware Test Tool allowed us to prove that it is possible to use all the hardware components simultaneously using the Arduino Uno. At this point, we started to adapt all the software code to run in the board. We started by adding the PCInt and SoftwareSerial libraries, allowing the XBee to correctly communicate with the board and the RTC to
CHAPTER 7. PORT TO ARDUINO UNO 71 Welcome to the Hardware Test Tool for Arduino Uno Select one of the following options: 1 - Read SHT-15 temperature 2 - Read SHT-15 humidity 3 - Read LDR luminosity 4 - Read RTC time 5 - Turn on LED for 1.5 seconds 6 - Test board IDLE mode 7 - Test XBee Radio antenna Option: 2 Humidity: 46.89 % Figure 7.2: Hardware Test Tool Example Section Size (kB) Total Size (kB) #Tasks .data .test .bss FLASH SRAM 8 0.48 23.3 2.31 23.3 2.79 4 0.48 23.3 1.57 23.3 1.95 20.48 23.3 1.04 23.4 1.53 Table 7.1: Memory usage: max. of 8, 4, and 2 tasks trigger the wake up events when a task must be executed. With these changes, we expected to be able to run the full implementation using the Arduino Uno. To test the port, we compiled all the code with the new libraries added. We adjusted the number of maximum tasks to 4 and 2, in order to save some SRAM space. Table 7.1 presents all the values obtained when compiling the code. As shown in 7.1, the 2kB of SRAM available in Arduino Uno do not allow to schedule 8 tasks simultaneously without some code optimization. However, reducing the maximum number of tasks to 4 or 2 reduces the SRAM usage to about 1.95kB and 1.53kB respectively, which fits in the Uno parameters (98% and 77% of total Uno SRAM size). Despite it was possible to run the software with 4 tasks, we decided to configure the maximum number of tasks as 2 for our porting test.
CHAPTER 7. PORT TO ARDUINO UNO 72 7.3.1 Port Tests After uploading the software to the Uno board, we used the previously presented STL programs to test if everything is working correctly. When the node is turned on, it broadcasts a message to its PAN announcing himself as a new node. As expected, the gateway receives that message and stores the node Mac Address as a new deployment node. At this point we tried to radio a task from the gateway to verify if the node is receiving and executing it correctly. Contrarily to what we expected, the node did not react to the task reception, turning on the LED. In order to verify if the message was reaching the board causing it to wake from the sleep mode, we again connected the node to the multimeter and the oscilloscope. After resending the task to the node, we registered a peak in the voltage, proving that the node is waking from sleep and receiving some radio message. As we started to debug this problem, we discovered that it was related with the fact that when a message is received through the XBee, the board is waking but for an unknown reason the interruption was not being correctly generated. We suspected that this problem may be related with the SoftwareSerial connections previously created, so we decided to try a different approach. Another way to allow the XBee to wake the board is using the same interrupts we had previously used with the RTC, an PCInt. Given the current board wiring already presented, we changed the XBee interruption attachment from pin 3 to pin 11, which we connected with a jumper, and added another PCInt in pin 11, allowing the board to wake when a radio message is received. After these changes, we were able to correctly receive some messages from the gateway: MAC, kill and period commands. When testing the reception of new tasks, another problem occurred: when trying to send new tasks, the node only receives and executes them if the byte-code size of that task is smaller than 55 bytes. After inspecting the SoftwareSerial library, we found that this problem was related with the fact that the a SoftwareSerial port uses a 64 bytes reception buffer, which will not be sufficient for receiving tasks with size greater than 54 bytes (plus the 10 bytes header always sent). Given the fact that this is a software limitation, we solved the problem by changing the communication protocol created to divide the tasks in packets, reducing the maximum size of each packet to 54 bytes. After this change, we tested again the reception of tasks with size greater than 54 bytes and everything worked correctly, finishing the port to the Arduino Uno board. The schematic representation of the new node is presented in Figure 7.3.
CHAPTER 7. PORT TO ARDUINO UNO 73 XBEE-1B1 SHT1XSMD CHRONODOT GND GND GND GND 5V VCC VCC VCC VCC GND CTS 12 DIN 3 DIO0 20 DIO1 19 DIO2 18 DIO3 17 DIO4 11 DIO5 15 DIO9 13 DIO11 7 DIO12 4 DOUT 2 DTR 9 GND 10 RES 8 RES 14 RESET 5 RSSI 6 RTS 16 VDD 1 DATA GND SCK VDD BAT 32K SQW RST SDA SCL VCC GND SV4 1 2 3 4 5 6 7 8 SV5 1 2 3 4 5 6 7 8 SV2 1 2 3 4 5 6 SV3 1 2 3 4 5 6 D2 SCL SDA AREF GND 13 12 11 10 9 28(SCL) 27(SDA) AREF GND 13 12 11~ 10~ 9~ 8 8 7 6~ 5~ 4 3~ 2 1(TX) 0(RX) 7 6 5 4 3 2 1 0A5 A4 A3 A2 A1 A0 VIN GND GND 5V 3.3V RESET I/OREF N/C <PWR>-V<PWR>-V <PWR>+V <PWR>+V <USB>GND <USB>GND <USB>D-<USB>D- <USB>D+<USB>D+ <USB>+V<USB>+V 23 3 7 7 6 6 9 9 10 10 JUMPER -> [11-> PB3(PCINT3)] , [2->PD2(INT0)] - Xbee_TX>Ard_RX (Comm Wakeup) ARDUINO UNO ICSP 11 A5 A4 A3 A2 A1 A0 VIN GND GND 5V 3.3V RESET I/OREF N/C Figure 7.3: SONAR node scheme - Arduino Uno
CHAPTER 7. PORT TO ARDUINO UNO 74 7.3.2 Port effort The effort to port all the available code to a new Arduino board with less memory capacity was essentially related with the new connections and the limitation introduced by the different speed when using SoftwareSerial communications. Table 7.2 present a brief quantification of changes needed, in terms of lines of code, connections and libraries added. Gateway Node Added Changed Added Changed Lines of Code 0 3 13 4 Libraries 0 0 2 2 Wire Connections 0 0 1 3 Table 7.2: Port effort quantification: lines of code, libraries, and wire connections As described in the previous section, the biggest difficult associated with the port was the connection scheduling, allowing all the hardware components to correctly communicate with the others. Although in this case we opted to port our solution to a similar platform with less memory and UART pins, the easiness of the process suggest that the effort to port our prototype to a completely different platform with similar capacities would reside mostly in discovering hardware libraries for all the components and adjust some parameters to fit the platform memory constrains. 7.4 Summary In this chapter we presented a port of SONAR to the Arduino Uno platform. We described in detail the creation of a simple hardware test tool, used to test all the hardware connections in the new board, as well as all the changes in the code to adapt the prototype to the new board, with less SRAM memory capacity and only one available UART pin. To test the port we used the same STL tasks presented in Chapter 6, leading to a set of errors related with the SoftwareSerial Library. We then solved this issue and successfully ported the system to Uno. We finish this chapter by trying to quantify the effort of this port, analyzing the amount of code we needed to rewrite and the changes in the connections.
REFERENCES 81 [30] N. Sharma, “Push technology–long polling,” http://www.ijcsmr.org/vol2issue5/paper398.pdf, 2013. [31] (2012, December) Server Sent Events - W3C Standard. Visited in November, 2014. http://www.w3.org/TR/2009/WD-eventsource-20091029/ [32] (2012, September) Web Sockets - W3C Standard. http://tools.ietf.org/pdf/rfc6455.pdf [33] Amazon S3 Web Service. Visited in June, 2015. https://aws.amazon.com/s3/?nc2=h ls [34] (2009) XBee Datasheet. Last seen in 14 February, 2015. https://www.sparkfun.com/datasheets/Wireless/Zigbee/XBee-Datasheet.pdf [35] (2006) TENMA 72-7732A Datasheet. Last seen in February, 2015. http://www.farnell.com/datasheets/1653479.pdf [36] (2014) Keysight InfiniiVision MSO-X 2002A Datasheet. Last seen in June, 2015. https://www.upc.edu/sct/es/documents equipament/d 332 dsox2012a.pdf [37] J. C. Sprott, Chaos and Time-Series Analysis. Oxford University Press, 2003. [38] SoftwareSerial Library. Last seen in May, 2015. http://www.arduino.cc/en/Reference/SoftwareSerial [39] PinChangeInt Library. Last seen in May, 2015. https://code.google.com/p/arduino-pinchangeint/ [40] G. Ferro, R. Silva, and L. Lopes, “Towards Out-of-the-Box Programming of Wireless Sensor-Actuator Networks,” 2015, manuscript submitted for publication.
Appendix A Code Blocks In this Appendix we present the similar implementation of the tasks presented in Chapter 6. All the examples are using the same libraries used in our prototype, which significantly reduce the amount of code written in each example. 82
APPENDIX A. CODE BLOCKS 83 Arduino Code A.0.1 Arduino Sensors and Radio Test Program #include ” L i b r a r i e s /RTC/RTC. h” #include ” L i b r a r i e s /SHT15/SHT15 . h” #include ” L i b r a r i e s / Radio /Radio . h” #def ine SHTx DATA PIN 7 #def ine SHTx CLOCK PIN 6 v o l a t i l e bool wake = f a l s e ; SHT15 s h t 1 5 o b j ; SendBuf s e n d b u f f e r ; float s e n s o r v a l u e s [ 2 ] ; void setup ( ) { a t t a c h I n t e r r u p t (3 , wakeAlarm , FALLING ) ; s h t 1 5 o b j (SHTx DATA PIN , SHTx CLOCK PIN ) ; r a d i o : : g et m y a dd re ss ( ) ; ti m e t time = r t c : : time ( ) ; r t c : : alarm ( time + 5 ) ; s l e e p ( ) ; } void loop ( ) { s e n s o r v a l u e s [ 0 ] = s ht15 o bj . getTemperature ( ) ; s e n s o r v a l u e s [ 1 ] = s ht15 o bj . getHumidity ( ) ; s e n d b u f f e r = r a d i o : : new send bu f ( r a d i o : : myaddress , 1 , 2 , s e n s o r v a l u e s ) ; r ad i o : : send dat a ( s e n d b u f f e r ) ; r t c : : alarm ( time + 5 ) ; s l e e p ( ) ; } void wakeAlarm() { wake = tru e ; } void sleep() { wake = f a l s e ; se t sl e e p m o d e (SLEEP MODE IDLE ) ; sleep enable (); power adc disable (); p o w e r s p i d i s a b l e ( ) ; power timer0 disable (); power timer1 disable (); power timer2 disable (); p o w e r t w i d i s a b l e ( ) ; sleep mode ( ) ; sleep disable (); p o w e r a l l e n a b l e ( ) ; }
APPENDIX A. CODE BLOCKS 84 Arduino Code A.0.2 Arduino Radio 64 bytes Program #include ” L i b r a r i e s /RTC/RTC. h” #include ” L i b r a r i e s / Radio /Radio . h” v o l a t i l e bool wake = f a l s e ; SendBuf s e n d b u f f e r ; float radio values [16]; void setup ( ) { a t t a c h I n t e r r u p t (3 , wakeAlarm , FALLING ) ; r a d i o : : g et m y a dd re ss ( ) ; f o r ( int i =0; i <16; i++) { r a d i o v a l u e s [ i ] = 2 . 0 ; } ti m e t time = r t c : : time ( ) ; r t c : : alarm ( time + 5 ) ; s l e e p ( ) ; } void loop ( ) { s e n d b u ff e r = r adi o : : new send buf ( r adi o : : myaddress , 1 , 16 , r a d i o v a l u e s ) ; r ad i o : : send dat a ( s e n d b u f f e r ) ; r t c : : alarm ( time + 5 ) ; s l e e p ( ) ; } void wakeAlarm() { wake = tru e ; } void sleep() { wake = f a l s e ; se t sl e e p m o d e (SLEEP MODE IDLE ) ; sleep enable (); power adc disable (); p o w e r s p i d i s a b l e ( ) ; power timer0 disable (); power timer1 disable (); power timer2 disable (); p o w e r t w i d i s a b l e ( ) ; sleep mode ( ) ; sleep disable (); p o w e r a l l e n a b l e ( ) ; }
APPENDIX A. CODE BLOCKS 85 Arduino Code A.0.3 Arduino Sensors Test Program #include ” L i b r a r i e s /RTC/RTC. h” #include ” L i b r a r i e s /SHT15/SHT15 . h” #def ine SHTx DATA PIN 7 #def ine SHTx CLOCK PIN 6 v o l a t i l e bool wake = f a l s e ; SHT15 s h t 1 5 o b j ; void setup ( ) { a t t a c h I n t e r r u p t (3 , wakeAlarm , FALLING ) ; s h t 1 5 o b j (SHTx DATA PIN , SHTx CLOCK PIN ) ; ti m e t time = r t c : : time ( ) ; r t c : : alarm ( time + 5 ) ; s l e e p ( ) ; } void loop ( ) { float te mp era tu re = s h t 1 5 o b j . getTemperature ( ) ; float hu mid it y = s h t 1 5 o b j . g et Humidi ty ( ) ; r t c : : alarm ( time + 5 ) ; s l e e p ( ) ; } void wakeAlarm() { wake = tru e ; } void sleep() { wake = f a l s e ; se t sl e e p m o d e (SLEEP MODE IDLE ) ; sleep enable (); power adc disable (); p o w e r s p i d i s a b l e ( ) ; power timer0 disable (); power timer1 disable (); power timer2 disable (); p o w e r t w i d i s a b l e ( ) ; sleep mode ( ) ; sleep disable (); p o w e r a l l e n a b l e ( ) ; }
APPENDIX A. CODE BLOCKS 86 Arduino Code A.0.4 Arduino Computation Test Program #include ” L i b r a r i e s /RTC/RTC. h” v o l a t i l e bool wake = f a l s e ; bool s t a t e = t rue ; void setup ( ) { a t t a c h I n t e r r u p t (3 , wakeAlarm , FALLING ) ; ti m e t time = r t c : : time ( ) ; r t c : : alarm ( time + 5 ) ; s l e e p ( ) ; } void loop ( ) { float x = 0 . 2 ; float k = 4 . 0 ; int i =0; whi l e ( i <1000) { x = k ∗x∗(1. 0 −x ) ; i ++; } r t c : : alarm ( time + 5 ) ; s l e e p ( ) ; } void wakeAlarm() { wake = tru e ; } void sleep() { wake = f a l s e ; se t sl e e p m o d e (SLEEP MODE IDLE ) ; sleep enable (); power adc disable (); p o w e r s p i d i s a b l e ( ) ; power timer0 disable (); power timer1 disable (); power timer2 disable (); p o w e r t w i d i s a b l e ( ) ; sleep mode ( ) ; sleep disable (); p o w e r a l l e n a b l e ( ) ; }
APPENDIX A. CODE BLOCKS 87 Arduino Code A.0.5 Arduino Actuator Test Program #include ” L i b r a r i e s /RTC/RTC. h” v o l a t i l e bool wake = f a l s e ; bool s t a t e = t rue ; int ledPin = A5 ; void setup ( ) { a t t a c h I n t e r r u p t (3 , wakeAlarm , FALLING ) ; pinMode ( ledPin , OUTPUT) ; ti m e t time = r t c : : time ( ) ; r t c : : alarm ( time + 5 ) ; s l e e p ( ) ; } void loop ( ) { i f ( s t a t e ) { d i g i t a l W r i t e ( ledPin , HIGH ) ; } else { d i g i t a l W r i t e ( ledPin , LOW) ; } s t a t e = ! s t a t e ; r t c : : alarm ( time + 5 ) ; s l e e p ( ) ; } void wakeAlarm() { wake = tru e ; } void sleep() { wake = f a l s e ; se t sl e e p m o d e (SLEEP MODE IDLE ) ; sleep enable (); power adc disable (); p o w e r s p i d i s a b l e ( ) ; power timer0 disable (); power timer1 disable (); power timer2 disable (); p o w e r t w i d i s a b l e ( ) ; sleep mode ( ) ; sleep disable (); p o w e r a l l e n a b l e ( ) ; }