1. TinyOS programming 1st Edition Philip Levis
download
https://ebookgate.com/product/tinyos-programming-1st-edition-
philip-levis/
Get Instant Ebook Downloads – Browse at https://ebookgate.com
2. Get Your Digital Files Instantly: PDF, ePub, MOBI and More
Quick Digital Downloads: PDF, ePub, MOBI and Other Formats
Sheep 1st Edition Philip Armstrong
https://ebookgate.com/product/sheep-1st-edition-philip-armstrong/
The Collected Poems of Philip Lamantia First Edition
Philip Lamantia
https://ebookgate.com/product/the-collected-poems-of-philip-
lamantia-first-edition-philip-lamantia/
Dear Zoe 1st Edition Edition Philip Beard
https://ebookgate.com/product/dear-zoe-1st-edition-edition-
philip-beard/
Philip Kaufman 1st Edition Edition Annette Insdorf
https://ebookgate.com/product/philip-kaufman-1st-edition-edition-
annette-insdorf/
3. Alec Wilder 1st Edition Edition Philip Lambert
https://ebookgate.com/product/alec-wilder-1st-edition-edition-
philip-lambert/
Valode Pistre Architects 1st Edition Philip Jodidio
https://ebookgate.com/product/valode-pistre-architects-1st-
edition-philip-jodidio/
Computer Programming 1st Edition E. Balagurusamy
https://ebookgate.com/product/computer-programming-1st-edition-e-
balagurusamy/
Carbon Programming 1st Edition Kevin Bricknell
https://ebookgate.com/product/carbon-programming-1st-edition-
kevin-bricknell/
Programming Clojure 1st Edition Stuart Halloway
https://ebookgate.com/product/programming-clojure-1st-edition-
stuart-halloway/
6. TinyOS Programming
Do you need to know how to write systems, services, and applications using the TinyOS
operating system? Learn how to write nesC code and efficient applications with this
indispensable guide to TinyOS programming.
Detailed examples show you how to write TinyOS code in full, from basic applications
right up to new low-level systems and high-performance applications. Two leading
figures in the development of TinyOS also explain the reasons behind many of the
design decisions made and explain for the first time how nesC relates to and differs
from other C dialects. Handy features such as a library of software design patterns,
programming hints and tips, end-of-chapter exercises, and an appendix summarizing
the basic application-level TinyOS APIs make this the ultimate guide to TinyOS for
embedded systems programmers, developers, designers, and graduate students.
Philip Levis is Assistant Professor of Computer Science and Electrical Engineering at
Stanford University. A Fellow of the Microsoft Research Faculty, he is also Chair of the
TinyOS Core Working Group and a Member of the TinyOS Network Protocol (net2),
Simulation (sim), and Documentation (doc) Working Groups.
David Gay joined Intel Research in Berkeley in 2001, where he has been a designer
and the principal implementer of the nesC language, the C dialect used to implement
the TinyOS sensor network operating system, and its applications. He has a diploma in
Computer Science from the Swiss Federal Institute of Technology in Lausanne and a
Ph.D. from the University of California, Berkeley.
10. Contents
List of Code examples page xi
Preface xvii
Acknowledgements xix
Programming hints, condensed xxi
Part I TinyOS and nesC 1
1 Introduction 3
1.1 Networked, embedded sensors 3
1.1.1 Anatomy of a sensor node (mote) 4
1.2 TinyOS 5
1.2.1 What TinyOS provides 6
1.3 Example application 7
1.4 Compiling and installing applications 8
1.5 The rest of this book 8
2 Names and program structure 10
2.1 Hello World! 10
2.2 Essential differences: components, interfaces, and wiring 13
2.3 Wiring and callbacks 15
2.4 Summary 16
Part II Basic programming 19
3 Components and interfaces 21
3.1 Component signatures 21
3.1.1 Visualizing components 22
3.1.2 The “as” keyword and clustering interfaces 23
3.1.3 Clustering interfaces 24
3.2 Interfaces 24
3.2.1 Generic interfaces 27
3.2.2 Bidirectional interfaces 28
11. vi Contents
3.3 Component implementations 29
3.3.1 Modules 30
3.3.2 A basic configuration 31
3.3.3 Module variables 32
3.3.4 Generic components 33
3.4 Split-phase interfaces 34
3.4.1 Read 36
3.4.2 Send 36
3.5 Module memory allocation, avoiding recursion, and other details 36
3.5.1 Memory ownership and split-phase calls 38
3.5.2 Constants and saving memory 41
3.5.3 Platform-independent types 42
3.5.4 Global names 44
3.5.5 nesC and the C preprocessor 46
3.5.6 C libraries 47
3.6 Exercises 48
4 Configurations and wiring 49
4.1 Configurations 50
4.1.1 The −> and <− operators 51
4.1.2 The = operator 52
4.1.3 Namespace management 53
4.1.4 Wiring rules 54
4.1.5 Wiring shortcuts 56
4.2 Building abstractions 57
4.2.1 Component naming 58
4.2.2 Component initialization 59
4.3 Component layering 60
4.3.1 Extensibility 61
4.3.2 Hardware specificity 61
4.4 Multiple wirings 63
4.4.1 Fan-in and fan-out 64
4.4.2 Uses of multiple wiring 65
4.4.3 Combine functions 66
4.5 Generics versus singletons 68
4.5.1 Generic components, revisited 68
4.5.2 Singleton components, revisited 70
4.6 Exercises 70
5 Execution model 71
5.1 Overview 71
5.2 Tasks 72
5.2.1 Task timing 74
12. Contents vii
5.2.2 Timing and event handlers 75
5.3 Tasks and split-phase calls 75
5.3.1 Hardware versus software 75
5.3.2 Tasks and call loops 76
5.4 Exercises 78
6 Applications 79
6.1 The basics: timing, LEDs, and booting 79
6.1.1 Deadline-based timing 81
6.1.2 Wiring AntiTheftC 83
6.2 Sensing 83
6.2.1 Simple sampling 84
6.2.2 Sensor components 85
6.2.3 Sensor values, calibration 86
6.2.4 Stream sampling 87
6.3 Single-hop networking 89
6.3.1 Sending packets 90
6.3.2 Receiving packets 93
6.3.3 Selecting a communication stack 94
6.4 Multi-hop networking: collection, dissemination, and base stations 95
6.4.1 Collection 96
6.4.2 Dissemination 97
6.4.3 Wiring collection and dissemination 97
6.4.4 Base station for collection and dissemination 98
6.5 Storage 101
6.5.1 Volumes 102
6.5.2 Configuration data 103
6.5.3 Block and Log storage 105
6.6 Exercises 111
7 Mote-PC communication 112
7.1 Basics 112
7.1.1 Serial communication stack 113
7.2 Using mig 114
7.2.1 Sending and receiving mig-generated packets 116
7.3 Using ncg 118
7.4 Packet sources 119
7.5 Example: simple reliable transmission 120
7.5.1 Reliable transmission protocol 121
7.5.2 Reliable transmission in Java 121
7.5.3 Reimplementing TestSerial 125
7.6 Exercises 125
16. Code examples
2.1 Powerup in C page 10
2.2 PowerupC module in nesC 11
2.3 Simple nesC interfaces 11
2.4 PowerupAppC configuration in nesC 12
2.5 Powerup with blinking LED in C 15
2.6 Powerup with blinking LED in nesC (slightly simplified) 15
2.7 Powerup with blinking LED configuration (slightly simplified) 16
3.1 The signature and implementation blocks 21
3.2 Signatures of PowerupC and LedsC 22
3.3 MainC’s signature 22
3.4 The LedsP module 23
3.5 PowerupC and an alternative signature 24
3.6 Interface declarations for Leds and Boot 25
3.7 The Init and Boot interfaces 25
3.8 Signatures of MainC and PowerupC 26
3.9 The Queue interface 27
3.10 Using a queue of 32-bit integers 27
3.11 Providing a 16-bit or a 32-bit queue 27
3.12 The Notify interface 28
3.13 UserButtonC 28
3.14 Simplified Timer interface showing three commands and one event 29
3.15 PowerupC module code 30
3.16 The module PowerupToggleC 30
3.17 The PowerupToggleAppC configuration 31
3.18 Example uses of the components keyword 31
3.19 The Get interface 32
3.20 A self-incrementing counter 32
3.21 Generic module SineSensorC and generic configuration TimerMilliC 33
3.22 Instantiating a generic component 34
3.23 Signature of BitVectorC 34
3.24 QueueC signature 34
3.25 The Read interface 36
3.26 The split-phase Send interface 36
3.27 The Send interface 38
17. xii List of code examples
3.28 The Receive interface 39
3.29 The signature of PoolC 41
3.30 CC2420 packet header 42
3.31 The dreaded “packed” attribute in the 1.x MintRoute library 43
3.32 The CC2420 header 44
3.33 TinyError.h, a typical nesC header file 45
3.34 Including a header file in a component 45
3.35 Indirectly including a header file 46
3.36 Fancy.nc: C preprocessor example 46
3.37 FancyModule.nc: C preprocessor pitfalls 47
3.38 Fancy.h: the reliable way to use C preprocessor symbols 47
3.39 Using a C library function 47
4.1 Signature of part of the CC1000 radio stack 49
4.2 The PowerupToggleAppC configuration revisited 51
4.3 C code generated from the PowerupToggleAppC configuration 51
4.4 The LedsC configuration 52
4.5 CC2420ReceiveC’s use of the as keyword 53
4.6 Naming generic component instances 54
4.7 MainC and LedsP 55
4.8 Valid alternate of PowerupToggleAppC 55
4.9 Invalid alternate of PowerupToggleAppC 55
4.10 LedsC revisited 56
4.11 BlinkC signature 56
4.12 The RandomC configuration 57
4.13 The RandomMlcgC signature 58
4.14 Seed initialization in RandomMlcgP 59
4.15 ActiveMessageC for the CC2420 61
4.16 The signature of CC2420ActiveMessageC 62
4.17 Fan-out on CC2420TransmitC’s Init 63
4.18 StdControl and SplitControl initialization interfaces 64
4.19 Why the metaphor of “wires” is only a metaphor 65
4.20 The combine function for error_t 66
4.21 Fan-out on SoftwareInit 67
4.22 Resulting code from fan-out on SoftwareInit 67
4.23 AMSenderC signature 68
4.24 RadioCountToLedsAppC 68
4.25 PoolC 69
4.26 Exposing a generic component instance as a singleton 70
5.1 The main TinyOS scheduling loop from SchedulerBasicP.nc 72
5.2 A troublesome implementation of a magnetometer sensor 76
5.3 Signal handler that can lead to an infinite loop 77
5.4 An improved implementation of FilterMagC 77
6.1 Anti-theft: simple flashing LED 80
6.2 The Leds interface 80
18. List of code examples xiii
6.3 The Boot interface 81
6.4 The full Timer interface 81
6.5 WarningTimer.fired with drift problem fixed 82
6.6 Anti-Theft: application-level configuration 83
6.7 The Read interface 84
6.8 Anti-theft: detecting dark conditions 84
6.9 Anti-Theft: wiring to light sensor 86
6.10 ReadStream Interface 87
6.11 Anti-theft: detecting movement 88
6.12 The AMSend interface 90
6.13 Anti-Theft: reporting theft over the radio 91
6.14 The SplitControl interface 92
6.15 The Receive interface 93
6.16 Anti-Theft: changing settings 93
6.17 Serial vs Radio-based AM components 94
6.18 The Send interface 96
6.19 Anti-Theft: reporting theft over a collection tree 96
6.20 DisseminationValue interface 97
6.21 Anti-Theft: settings via a dissemination tree 97
6.22 The StdControl interface 97
6.23 The DisseminationUpdate interface 99
6.24 AntiTheft base station code: disseminating settings 99
6.25 The RootControl interface 100
6.26 AntiTheft base station code: reporting thefts 101
6.27 AntiTheft base station wiring 101
6.28 ConfigStorageC signature 102
6.29 Mount interface for storage volumes 103
6.30 ConfigStorage interface 103
6.31 Anti-Theft: reading settings at boot time 104
6.32 Anti-Theft: saving configuration data 105
6.33 BlockStorageC signature 106
6.34 The BlockWrite interface 106
6.35 Simultaneously sampling and storing to flash
(most error checking omitted) 108
6.36 The BlockRead interface 108
6.37 LogStorageC signature 108
6.38 The LogWrite interface 109
6.39 The LogWrite interface 110
6.40 The LogRead interface 111
7.1 Serial AM Packet layout 113
7.2 TestSerial packet layout 114
7.3 Backing array methods 115
7.4 Sending packets with mig and MoteIF 117
7.5 Interface for handling received packets 117
19. xiv List of code examples
7.6 Receiving packets with mig and MoteIF 117
7.7 Constants and packet layout for Oscillscope application 118
7.8 Class generated by ncg 119
7.9 Simplified code to save received samples 119
7.10 Reliable transmission protocol in Java – transmission 121
7.11 Reliable transmission protocol in Java – transmission 123
7.12 A reliable TestSerial.java 125
8.1 Instantiation within a generic configuration 130
8.2 The fictional component SystemServiceVectorC 131
8.3 QueueC excerpt 131
8.4 A generic constant sensor 132
8.5 Queue interface (repeated) 133
8.6 QueueC implementation 133
8.7 Representing an ADT through an interface in TinyOS 1.x 135
8.8 Timers without parameterized interfaces 135
8.9 Timers with a single interface 136
8.10 HilTimerMilliC signature 137
8.11 ActiveMessageC signature 138
8.12 Signature of TestAMC 138
8.13 Wiring TestAMC to ActiveMessageC 138
8.14 A possible module underneath ActiveMessageC 139
8.15 Parameterized interface syntax 140
8.16 Dispatching on a parameterized interface 140
8.17 How active message implementations decide on whether
to signal to Receive or Snoop 140
8.18 Defining a parameter 141
8.19 Wiring full parameterized interface sets 141
8.20 Default events in an active message implementation 142
8.21 nesC attributes 143
9.1 Partial HilTimerMilliC signature 146
9.2 VirtualizeTimerC 148
9.3 Instantiating VirtualizeTimerC 148
9.4 VirtualizeTimerC state allocation 149
9.5 The TimerMilliC generic configuration 151
9.6 TimerMilliP auto-wires HilTimerMilliC to Main.SoftwareInit 151
9.7 The Blink application 151
9.8 The full module-to-module wiring chain in Blink (BlinkC to
VirtualizeTimerC) 152
9.9 CC2420SpiC 153
9.10 CC2420SpiP 154
9.11 CC2420SpiC mappings to CC2420SpiP 154
9.12 The strobe implementation 155
9.13 The AMSenderC generic configuration 158
9.14 AMSendQueueEntryP 159
20. List of code examples xv
9.15 AMQueueP 159
9.16 AMSendQueueImplP pseudocode 160
9.17 BlockStorageC 161
9.18 The full code of HilTimerMilliC 163
9.19 VirtualizeTimerC virtualizes a single timer 164
10.1 AMReceiverC 169
10.2 VirtualizeTimerC 172
10.3 Telos ActiveMessageC 181
10.4 The Matchbox facade 184
10.5 The CC2420CsmaC uses a Facade 185
10.6 AlarmToTimerC implementation 190
11.1 The Send interface 192
11.2 The Leds interface 193
11.3 Toggling a state variable 193
11.4 A call sequence that could corrupt a variable 194
11.5 State transition that is not async-safe 194
11.6 Incrementing with an atomic statement 195
11.7 Incrementing with two independent atomic statements 195
11.8 The first step of starting the CC2420 radio 198
11.9 The handler that the first step of starting the CC2420 is complete 198
11.10 The handler that the second step of starting the CC2420 is complete 198
11.11 The handler that the third step of starting the CC2420 radio is complete 199
11.12 State transition so components can send and receive packets 199
11.13 The Resource interface 201
11.14 Msp430Spi0C signature 202
11.15 Msp320Adc12ClientC signature 202
11.16 The ResourceDefaultOwner interface 203
11.17 The ResourceConfigure interface 204
12.1 ActiveMessageC signature 212
12.2 Arbitration in Stm25pSectorC 215
12.3 McuSleepC: platform-specific sleep code 218
13.1 SynchronizerC: time synchronization for SoundLocalizer 225
13.2 The Counter interface 226
13.3 DetectorC: loud sound detection for SoundLocalizer 231
13.4 The Alarm interface 231
13.5 Atm128AdcSingle: low-level single-sample ATmega128 A/D
converter interface 232
13.6 The GeneralIO digital I/O pin interface 235
13.7 The I2CPacket interface for bus masters 236
22. Preface
This book provides an in-depth introduction to writing nesC code for the TinyOS
2.0 operating system. While it goes into greater depth than the TinyOS tutorials on
this subject, there are several topics that are outside its scope, such as the structure
and implementation of radio stacks or existing TinyOS libraries. It focuses on how
to write nesC code, and explains the concepts and reasons behind many of the
nesC and TinyOS design decisions. If you are interested in a brief introduction to
TinyOS programming, then you should probably start with the tutorials. If you’re
interested in details on particular TinyOS subsystems you should probably consult TEPs
(TinyOSEnhancementProposals),whichdetailthecorrespondingdesignconsiderations,
interfaces, and components. Both of these can be found in the doc/html directory of
a TinyOS distribution.
While some of the contents of this book are useful for 1.x versions of TinyOS , they
do have several differences from TinyOS 2.0 which can lead to different programming
practices. If in doubt, referring to the TEP on the subject is probably the best bet, as TEPs
often discuss in detail the differences between 1.x and 2.0.
For someone who has experience with C or C++, writing simple nesC programs is
fairly straightforward: all you need to do is implement one or two modules and wire
them together. The difficulty (and intellectual challenge) comes when building larger
applications. The code inside TinyOS modules is fairly analogous to C coding, but
configurations – which stitch together components – are not.
This book is a first attempt to explain how nesC relates to and differs from other C
dialects, stepping through how the differences lead to very different coding styles and
approaches. As a starting point, this book assumes that
1. you know C, C++, or Java reasonably well, understand pointers and that
2. you have taken an undergraduate level operating systems class (or equivalent) and
know about concurrency, interrupts, and preemption.
Of course, this book is as much a description of nesC as it is an argument for a particular
way of using the language to achieve software engineering goals. In this respect, it is the
product of thousands of hours of work by many people, as they learned and explored the
use of the language. In particular, Cory Sharp, Kevin Klues, and Vlado Handziski have
always pushed the boundaries of nesC programming in order to better understand which
practices lead to the simplest, most efficient, and robust code. In particular, Chapter 10
23. xviii Preface
is an edited version of a paper we wrote together, while using structs as a compile-time
checking mechanism in interfaces (as Timer does) is an approach invented by Cory.
This book is divided into four parts. The first part, Chapters 1–2, gives a high-level
overviewofTinyOSandthenesClanguage.Thesecondpart,Chapters3–7goesintonesC
and TinyOS at a level sufficient for writing applications. The third part, Chapters 8–13
goes into more advanced TinyOS and nesC programming, as is sometimes needed when
writing new low-level systems or high performance applications. The book ends with
an appendix summarizing the basic application-level TinyOS APIs.
26. Programming hints, condensed
Programming Hint 1 Use the “as” keyword liberally. (page 24)
Programming Hint 2 Never write recursive functions within a module. In combination
with the TinyOS coding conventions, this guarantees that all programs have bounded
stack usage. (page 38)
Programming Hint 3 Never use malloc and free. Allocate all state in components. If
your application requirements necessitate a dynamic memory pool, encapsulate it in a
component and try to limit the set of users. (page 38)
Programming Hint 4 When possible, avoid passing pointers across interfaces; when
this cannot be avoided only one component should be able to modify a pointer’s data at
any time. (page 39)
Programming Hint 5 Conserve memory by using enums rather than const variables for
integer constants, and don’t declare variables with an enum type. (page 42)
Programming Hint 6 Never, ever use the “packed” attribute in portable code. (page 43)
Programming Hint 7 Use platform-independent types when defining message
structures. (page 44)
Programming Hint 8 If you have to perform significant computation on a
platform-independent type or access it many (hundreds or more) times, temporarily
copy it to a native type. (page 44)
Programming Hint 9 Interfaces should #include the header files for the types they use.
(page 46)
Programming Hint 10 Always #define a preprocessor symbol in a header file. Use
#include to load the header file in all components and interfaces that use the symbol.
(page 47)
Programming Hint 11 If a component is a usable abstraction by itself, its name should
end with C. If it is intended to be an internal and private part of a larger abstraction,
its name should end with P. Never wire to P components from outside your package
(directory). (page 58)
Programming Hint 12 Auto-wire Init to MainC in the top-level configuration of a
software abstraction. (page 60)
Programming Hint 13 When using layered abstractions, components should not wire
across multiple abstraction layers: they should wire to a single layer. (page 63)
Programming Hint 14 Never ignore combine warnings. (page 68)
27. xxii Programming hints, condensed
Programming Hint 15 Keep tasks short. (page 74)
Programming Hint 16 If an event handler needs to make possibly long-executing
command calls, post a task to make the calls. (page 75)
Programming Hint 17 Don’t signal events from commands – the command should post
a task that signals the event. (page 77)
Programming Hint 18 Use a parameterized interface when you need to distinguish
callers or when you have a compile-time constant parameter. (page 141)
Programming Hint 19 If a component depends on unique, then #define the string to
use in a header file, to prevent bugs due to string typos. (page 149)
Programming Hint 20 Whenever writing a module, consider making it more
general-purpose and generic. In most cases, modules must be wrapped by configurations
to be useful, so singleton modules have few advantages. (page 165)
Programming Hint 21 Keep code synchronous when you can. Code should be async
only if its timing is very important or if it might be used by something whose timing is
important. (page 195)
Programming Hint 22 Keep atomic statements short, and have as few of them as
possible. Be careful about calling out to other components from within an atomic
statement. (page 199)
30. 1 Introduction
This book is about writing TinyOS systems and applications in the nesC language. This
chapter gives a brief overview ofTinyOS and its intended uses.TinyOS is an open-source
project which a large number of research universities and companies contribute to.
The main TinyOS website, www.tinyos.net, has instructions for downloading and
installing the TinyOS programming environment. The website has a great deal of useful
information which this book doesn’t cover, such as common hardware platforms and
how to install code on a node.
1.1 Networked, embedded sensors
TinyOS is designed to run on small, wireless sensors. Networks of these sensors have the
potential to revolutionize a wide range of disciplines, fields, and technologies. Recent
example uses of these devices include:
Golden Gate Bridge safety High-speed accelerometers collect synchonized data on
the movement of and oscillations within the structure of San Francisco’s Golden Gate
Bridge. This data allows the maintainers of the bridge to easily observe the structural
health of the bridge in response to events such as high winds or traffic, as well as quickly
assess possible damage after an earthquake [10]. Being wireless avoids the need for
installing and maintaining miles of wires.
Volcanic monitoringAccelerometers and microphones observe seismic events on the
Reventador and Tungurahua volcanoes in Ecuador. Nodes locally compare when they
observe events to determine their location, and report aggregate data to a camp several
kilometers away using a long-range wireless link. Small, wireless nodes allow geologists
and geophysicists to install dense, remote scientific instruments [30], obtaining data that
answers other questions about unapproachable environments.
Data center provisioning Data centers and enterprise computing systems require
huge amounts of energy, to the point at which they are placed in regions that have low
power costs. Approximately 50% of the energy in these systems goes into cooling, in
part due to highly conservative cooling systems. By installing wireless sensors across
machine racks, the data center can automatically sense what areas need cooling and
can adjust which computers do work and generate heat [19]. Dynamically adapting
31. 4 Introduction
patch of sensors data sink gateway Internet
sensor code
(nesC/TinyOS)
base station code
(nesC/TinyOS)
gateway code
(Java, C, ...)
Figure 1.1 A typical sensor network architecture. Patches of ultra-low power sensors, running
nesC/TinyOS, communicate to gateway nodes through data sinks. These gateways
connect to the larger Internet.
these factors can greatly reduce power consumption, making the IT infrastructure more
efficient and reducing environmental impact.
While these three application domains are only a small slice of where networks
of sensors are used, they show the key differences between these networks and most
other computing systems. First, these “sensor networks” need to operate unattended for
long periods of time. Second, they gather data from and respond to an unpredictable
environment. Finally, for reasons of cost, deployment simplicity, and robustness,
they are wireless. Together, these three issues – longevity, embedment, and wireless
communication – cause sensor networks to use different approaches than traditional,
wired, and human-centric or machine-centric systems.
The sheer diversity of sensor network applications means that there are many network
architectures, but a dominant portion of deployments tend to follow a common one,
shown in Figure 1.1 [21, 26, 30] of ultra-low power sensors self-organized to form an
ad-hoc routing network to one or more data sink nodes. These sensor sinks are attached to
gateways, which are typically a few orders of magnitude more powerful than the sensors:
gateways run an embedded form of Linux, Windows, or other multitasking operating
system. Gateways have an Internet connection, either through a cell phone network,
long-distance wireless, or even just wired Ethernet.
Energy concerns dominate sensor hardware and software design. These nodes need to
be wireless, small, low-cost, and operate unattended for long periods. While it is often
possible to provide large power resources, such as large solar panels, periodic battery
replacement, or wall power, to small numbers of gateways, doing so to every one of
hundreds of sensors is infeasible.
1.1.1 Anatomy of a sensor node (mote)
Since energy consumption determines sensor node lifetime, sensor nodes, commonly
referred to as motes, tend to have very limited computational and communication
resources. Instead of a full-fledged 32-bit or 64-bit CPU with megabytes or gigabytes of
RAM, they have 8-bit or 16-bit microcontrollers with a few kilobytes of RAM. Rather
than gigahertz, these microcontrollers run at 1–10 megahertz. Their low-power radios
32. 1.2 TinyOS 5
Antenna Radio Circuitry USB Serial
Expansion
Connector
Sensors
Figure 1.2 A Telos sensor produced by Moteiv. The top of the node has the radio, sensors, and circuitry for
the USB connector. The bottom, not shown, has the processor and flash storage chip. The
antenna is part of the printed circuit board (PCB).
can send tens to hundreds of kilobits per second (kbps), rather than 802.11’s tens of
megabits. As a result, software needs to be very efficient, both in terms of CPU cycles
and in terms of memory use.
Figure 1.2 shows a sample node platform, the Telos , which is designed for easy
experimentation and low-power operation. It has a TI MSP430 16-bit microcontroller
with 10 kB of RAM and 48 kB of flash program memory. Its radio, a TI CC2420 which
follows the IEEE 802.15.4 standard, can send up to 250 kbps. In terms of power, the
radio dominates the system: on a pair of AA batteries, a Telos can have the radio on for
about four days. Lasting longer than four days requires keeping the node in a deep sleep
state most of the time, waking only when necessary, and sleeping as soon as possible.
Theothermotediscussedinthisbook,themicazfromCrossbowTechnologyissimilar:
it has an Atmel ATmega128 8-bit microcontroller with 4 kB of RAM, 128 kB of flash
program memory, uses the same CC2420 radio chip, also runs off a pair of AA batteries
and has a similar power consumption profile.
Networks, once deployed, gather data uninterrupted for weeks, months, or years.
As the placement of sensors is very application-specific, it is rare for networks to
need to support multiple concurrent applications, or even require more than the
occasional reprogramming. Therefore, unlike general-purpose computing systems,
which emphasize run-time flexibility and composability, sensor network systems tend
to be highly optimized. Often, the sensor suite itself is selected for the specific
application:volcanicmonitoringusesaccelerometersandmicrophones,whiledatacenter
provisioning uses temperature sensors.
1.2 TinyOS
TinyOS is a lightweight operating system specifically designed for low-power wireless
sensors. TinyOS differs from most other operating systems in that its design focuses
on ultra low-power operation. Rather than a full-fledged processor, TinyOS is designed
33. 6 Introduction
for the small, low-power microcontrollers motes have. Furthermore, TinyOS has very
aggressive systems and mechanisms for saving power.
TinyOS makes building sensor network applications easier. It provides a set of
importantservicesandabstractions,suchassensing,communication,storage,andtimers.
It defines a concurrent execution model, so developers can build applications out of
reusable services and components without having to worry about unforeseen interactions.
TinyOS runs on over a dozen generic platforms, most of which easily support adding
new sensors. Furthermore, TinyOS’s structure makes it reasonably easy to port to new
platforms.
TinyOS applications and systems, as well as the OS itself, are written in the nesC
language. nesC is a C dialect with features to reduce RAM and code size, enable
significant optimizations, and help prevent low-level bugs like race conditions. Chapter 2
goes into the details on how nesC differs significantly from other C-like languages, and
most of this book is about how to best use those features to write robust, efficient code.
1.2.1 What TinyOS provides
At a high level, TinyOS provides three things to make writing systems and applications
easier:
• a component model, which defines how you write small, reusable pieces of code and
compose them into larger abstractions;
• a concurrent execution model, which defines how components interleave their
computations as well as how interrupt and non-interrupt code interact;
• application programming interfaces (APIs), services, component libraries and an
overall component structure that simplify writing new applications and services.
The component model is grounded in nesC. It allows you to write pieces of reusable
code which explicitly declare their dependencies. For example, a generic user button
component that tells you when a button is pressed sits on top of an interrupt handler. The
component model allows the button implementation to be independent of which interrupt
that is – e.g. so it can be used on many different hardware platforms – without requiring
complex callbacks or magic function naming conventions. Chapter 2 and Chapter 3
describe the basic component model.
TheconcurrentexecutionmodelenablesTinyOStosupportmanycomponentsneeding
to act at the same time while requiring little RAM. First, every I/O call in TinyOS is
split-phase: rather than block until completion, a request returns immediately and the
caller gets a callback when the I/O completes. Since the stack isn’t tied up waiting
for I/O calls to complete, TinyOS only needs one stack, and doesn’t have threads.
Instead, Chapter 5 introduces tasks, which are lightweight deferred procedure calls. Any
component can post a task, whichTinyOS will run at some later time. Because low-power
devices must spend most of their time asleep, they have low CPU utilization and so in
practice tasks tend to run very soon after they are posted (within a few milliseconds).
Furthermore, because tasks can’t preempt each other, task code doesn’t need to worry
about data races. Low-level interrupt code (discussed in the advanced concurrency
34. 1.3 Example application 7
chapter, Chapter 11) can have race conditions, of course: nesC detects possible data
races at compile-time and warns you.
Finally, TinyOS itself has a set of APIs for common functionality, such as sending
packets, reading sensors, and responding to events. Uses of these are sprinkled
throughpout the entire book, and presented in more detail in Chapter 6 and Appendix 1.
In addition to programming interfaces, TinyOS also provides a component structure and
component libraries. For example, Chapter 12 describes TinyOS’s HardwareAbstraction
Architecture (HAA), which defines how to build up from low-level hardware (e.g. a
radio chip) to a hardware-independent abstraction (e.g. sending packets). Part of this
component structure includes resource locks, covered in Chapter 11, which enable
automatic low-power operation, as well as the component libraries that simplify writing
such locks.
TinyOS itself is continually evolving. Within the TinyOS community, “Working
Groups” form to tackle engineering and design issues within the OS, improving existing
services and adding new ones. This book is therefore really a snapshot of the OS in
time. As Chapter 12 discusses and Appendix 1 presents, TinyOS has a set of standard,
stable APIs for core abstractions, but this set is always expanding as new hardware and
applications emerge. The best way to stay up to date with TinyOS is to check its web page
www.tinyos.net and participate in its mailing lists. The website also covers advanced
TinyOS and nesC features which are well beyond the scope of this book, including
binary components, over-the-air reprogramming services, debugging tools, and a nesC
reference manual.
1.3 Example application
To better understand the unique challenges faced by sensor networks, we walk through a
basic data-collection application. Nodes running this application periodically wake up,
sample some sensors, and send the data through an ad hoc collection tree to a data sink
(as in Figure 1.1). As the network must last for a year, nodes spend 99% of their time in
a deep sleep state.
In terms of energy, the radio is by far the most expensive part of the node. Lasting a year
requires telling the radio to be in a low power state. Low power radio implementation
techniques are beyond the scope of this book, but the practical upshot is that packet
transmissions have higher latency. [23]
Figure 1.3 shows the four TinyOS APIs the application uses: low power settings for
the radio, a timer, sensors, and a data collection routing layer. When TinyOS tells the
application that the node has booted, the application code configures the power settings
on the radio and starts a periodic timer. Every few minutes, this timer fires and the
application code samples its sensors. It puts these sensor values into a packet and calls
the routing layer to send the packet to a data sink. In practice, applications tend to be
more complex than this simple example. For example, they include additional services
such as a management layer which allows an administrator to reconfigure parameters
and inspect the state of the network, as well as over-the-air programming so the network
35. 8 Introduction
Application
Timer Routing
Sensors Radio
Figure 1.3 Example application architecture. Application code uses a timer to act periodically, sensors to
collect data, and a routing layer to deliver data to a sink.
can be reprogrammed without needing to collect all of the nodes. However, these four
abstractions – power control, timers, sensors, and data collection – encompass the entire
datapath of the application.
1.4 Compiling and installing applications
You can download the latest TinyOS distribution, the nesC compiler, and other tools at
www.tinyos.net. Setting up your programming environment is outside the scope of
this book; the TinyOS website has step-by-step tutorials to get you started. One part of
TinyOS is an extensive build system for compiling applications. Generally, to compile a
program for a sensor platform, one types make <platform>, e.g. make telosb.
This compiles a binary. To install that binary on a node, you plug the node into your
PC using a USB or serial connection, and type make <platform> install. The
tutorials go into compilation and installation options in detail.
1.5 The rest of this book
The rest of this book goes into how to program in nesC and write TinyOS applications.
It is divided into three parts. The first is a short introduction to the major programming
concepts of nesC. The second part addresses basic application programming using
standardTinyOSAPIs.Thethirdpartdigsalittledeeper,andlooksintohowthoseTinyOS
APIs are implemented. For example, the third part describes how TinyOS abstracts
hardware, so you can write a driver for a new sensor.
Chapter by chapter, the book is structured as follows:
• Chapter 1 is this chapter.
• Chapter 2 describes the major way that nesC breaks from C and C-like languages:
how programs are built out of components, and how components and interfaces help
manage programs’ namespaces.
• Chapter 3 presents components and how they interact via interfaces.
• Chapter 4 goes into greater detail into configurations, components which connect
other components together.
• Chapter 5 covers the basic TinyOS execution model and gives guidance on how and
when to use tasks.
36. 1.5 The rest of this book 9
• Chapter 6 takes the material from the prior three chapters and brings it together into
an example of writing a fully-fledged application that sends an alarm when a node
observes a change in its environment. In the process, it covers the major TinyOS APIs
(timing, sensing, communication, and storage).
• Chapter 7 details the PC-side tools for communicating with nodes connected over
the serial port, and covers the TinyOS serial stack and packet formats.
• Chapter 8 introduces more advanced component topics, such as parameterized
interfaces and attributes. While applications typically don’t use these mechanisms,
they are indispensable when writing reusable libraries and systems.
• Chapter 9 goes into wiring parameterized interfaces, which form the basis for most
reusable systems.After describing the basic mechanisms for managing interface keys,
it goes through four examples of increasing complexity.
• Chapter 10 presents eight common TinyOS design patterns: commonly useful and
powerful ways of organizing components.
• Chapter 11 concludes the advanced programming topics by covering concurrency. It
describes asynchronous code, the TinyOS task model, and power locks.
• Chapter 12 describes the Hardware Abstraction Architecture (HAA), the
three-level hierarchy TinyOS uses to raise low-level hardware abstractions to
hardware-independent, application-level services.
• Chapter 13 goes step-by-step through an advanced application that identifies the
location of an event based on when nodes sense it. It uses lower-layer interfaces to
implement time synchronization and high-frequency sampling.
• Appendix gives a concise overview of major TinyOS application interfaces.
Throughout the book, you will find programming hints: general best-use practices
that we’ve distilled from the many users of TinyOS and nesC. These are all listed on the
sheet at the front of the book.
Finally, the complete source code for example applications presented in this book (in
Chapters 6, 7 and 13) is available in TinyOS’s contributed code directory, under the name
“TinyOS Programming” – see www.tinyos.net for details.
37. 2 Names and program structure
Program structure is the most essential and obvious difference between C and nesC.
C programs are composed of variables, types, and functions defined in files that are
compiled separately and then linked together. nesC programs are built out of components
that are connected (“wired”) by explicit program statements; the nesC compiler connects
and compiles these components as a single unit.To illustrate and explain these differences
in how programs are built, we compare and contrast C and nesC implementations of two
very simple “hello world”-like mote applications, Powerup (boot and turn on a LED)
and Blink (boot and repeatedly blink a LED).
2.1 Hello World!
The closest mote equivalent to the classic “Hello World!” program is the “Powerup”
application that simply turns on one of the motes LEDs at boot, then goes to sleep.
A C implementation of Powerup is fairly simple:
# include " mote .h"
int main ()
{
mote_init ();
led0_on ();
sleep ();
}
Listing 2.1 Powerup in C
The Powerup application is compiled and linked with a “mote” library which provides
functions to perform hardware initialization (mote_init), LED control (led0_on) and put
the mote in to a low-power sleep mode (sleep). The “mote.h” header file simply provides
declarations of these and other basic functions. The usual C main function is called
automatically when the mote boots.1
1 The C compiler, library, and linker typically arrange for this by setting the mote’s hardware reset vector to
point to a piece of assembly code that sets up a C environment, then calls main.
38. 2.1 Hello World! 11
The nesC implementation of Powerup is split into two parts. The first, the PowerupC
module, contains the executable logic of Powerup (what there is of it …):
module PowerupC {
uses interface Boot ;
uses interface Leds ;
}
implementation {
event void Boot . booted () {
call Leds . led0On ();
}
}
Listing 2.2 PowerupC module in nesC
This code says that PowerupC interacts with the rest of the system via two interfaces,
Boot and Leds, and provides an implementation for the booted event of the Boot
interface that calls the led0On2 command of the Leds interface. Comparing with the
C code, we can see that the booted event implementation takes the place of the main
function, and the call to the led0On command the place of the call to the led0_on library
function.
This code shows two of the major differences between nesC and C: where C programs
are composed of functions, nesC programs are built out of components that implement a
particular service (in the case of PowerupC, turning a LED on at boot-time). Furthermore,
C functions typically interact by calling each other directly, while the interactions
between components are specified by interfaces: the interface’s user makes requests
(calls commands) on the interface’s provider, the provider makes callbacks (signals
events) to the interface’s user. Commands and events themselves are like regular
functions (they can contain arbitrary C code); calling a command or signaling an event
is just a function call. PowerupC is a user of both Boot and Leds; the booted event is
a callback signaled when the system boots, while the led0On is a command requesting
that LED 0 be turned on.
nesC interfaces are similar to Java interfaces, with the addition of a command or
event keyword to distinguish requests from callbacks:
interface Boot } {
event void } booted ();
}
interface Leds {
command void led0On ();
command void led0Off ();
2 LEDs are numbered in TinyOS, as different platforms have different color LEDs.
39. 12 Names and program structure
command void led0Toggle ();
...
}
Listing 2.3 Simple nesC interfaces
The second part of Powerup, the PowerupAppC configuration, specifies how
PowerupC is connected to TinyOS’s services:
configuration PowerupAppC { }
implementation {
components MainC , LedsC , PowerupC ;
MainC . Boot -> PowerupC . Boot ;
PowerupC . Leds -> LedsC . Leds ;
}
Listing 2.4 PowerupAppC configuration in nesC
This says that the PowerupAppC application is built out of three components
(modules or configurations), MainC (system boot), LedsC (LED control), and PowerupC
(our powerup module). PowerupAppC explicitly specifies the connections (or wiring)
betweentheinterfacesprovidedandusedbythesecomponents.WhenMainChasfinished
booting the system it signals the booted event of its Boot interface, which is connected
by the wiring in PowerupAppC to the booted event in PowerupC. This event then
calls the led0On command of its Leds interface, which is again connected (wired) by
PowerupAppC to the Leds interface provided by LedsC. Thus the call turns on LED 0.
The resulting component diagram is shown in Figure 2.1 – this diagram was generated
automatically from PowerupAppC by nesdoc, nesC’s documentation generation tool.
PowerupAppCillustratesthethirdmajordifferencebetweenCandnesC:wiringmakes
the connections expressed by linking the C version of Powerup with its “mote” library
explicit. In the C version, Powerup calls a global function named led0_on which is
connected to whatever library provides a function with the same name; if two libraries
PowerupC
MainC LedsC
Boot Leds
Figure 2.1 Wiring Diagram for Powerup application
40. 2.2 Essential differences: components, interfaces, and wiring 13
.nc
.nc
.nc app.c binary
nesC
compiler
Native C
compiler
Figure 2.2 The nesC compilation model. The nesC compiler loads and reads in nesC components, which it
compiles to a C file. This C file is passed to a native C compiler, which generates a mote binary.
provide such a function then (typically) the first one named on the linker command line
“wins.” Using a nesC configuration, the programmer instead explicitly selects which
component’s implementation of the function to use.
The nesC compiler can take advantage of this explicit wiring to build highly optimized
binaries. Current implementations of the nesC compiler (nesc1) take nesC files
describing components as input and output a C file. The C file is passed to a native C
compiler that can compile to the desired microcontroller or processor. Figure 2.2 shows
this process. The nesC compiler carefully constructs the generated C file to maximize the
optimization abilities of the C compiler. For example, since it is given a single file, the
C compiler can freely optimize across call boundaries, inlining code whenever needed.
The nesC compiler also prunes dead code which is never called and variables which are
never accessed: since there is no dynamic linking in nesC, it has a complete picture of
the application call graph. This speeds the C compilation and reduces program size in
terms of both RAM and code.
2.2 Essential differences: components, interfaces, and wiring
The three essential differences between C and nesC – components, interfaces, and
wiring – all relate to naming and organizing a program’s elements (variables, functions,
types, etc). In C, programs are broken into separate files which are connected via a global
namespace: a symbol X declared in one file is connected by the linker to a symbol X
defined in another file. For instance, if file1.c contains:
extern void g( void ); /* declaration of g */
int main () /* definition of main */
{
g(); g ();
}
and file2.c contains:
void g( void )
{
printf (" hello world !");
}
41. 14 Names and program structure
then compiling and linking file1.c and file2.c connects the calls to g() in main
to the definition of g in file2.c. The resulting program prints “hello world!” twice.
Organizing symbols in a global namespace can be tricky. C programmers use a number
oftechniquestosimplifythistask,includingheaderfilesandnamingconventions.Header
files group declarations so they can be used in a number of files without having to retype
them, e.g. a header file file1.h for file1.c would normally contain:
# ifndef FILE1_H
# define FILE1_H
extern void g( void ); /* declaration of g */
# endif
Naming conventions are designed to avoid having two different symbols with the
same name. For instance, types are often suffixed with _t guaranteeing that a type and
function won’t have the same name. Some libraries use a common prefix for all their
symbols, e.g. Gtk and gtk_ for the GTK+ graphical toolkit. Such prefixes remind users
that functions are related and avoid accidental name collisions with other libraries, but
make programs more verbose.
nesC’s components provide a more systematic approach for organizing a program’s
elements. A component (module or configuration) groups related functionality (a timer,
a sensor, system boot) into a single unit, in a way that is very similar to a class in an
object-oriented language. For instance, TinyOS represents its system services as separate
components such as LedsC (LED control, seen above), ActiveMessageC (sending and
receivingradiomessages),etc.Onlytheservice(component)nameisglobal,theservice’s
operations are named in a per-component scope:ActiveMessageC.SplitControl starts and
stops the radio, ActiveMessageC.AMSend sends a radio message, etc.
Interfaces bring further structure to components: components are normally specified
in terms of the set of interfaces (Leds, Boot, SplitControl,AMSend) that they provide and
use, rather than directly in terms of the actual operations. Interfaces simplify and clarify
code because, in practice, interactions between components follow standard patterns:
many components want to control LEDs or send radio messages, many services need
to be started or stopped, etc. Encouraging programmers to express their components in
terms of common interfaces also promotes code reuse: expressing your new network
protocol in terms of the AMSend message transmission interface means it can be used
with existing applications, using AMSend in your application means that it can be used
with any existing or future network protocol.
Rather than connect declarations to definitions with the same name, nesC programs
use wiring to specify how components interact: PowerupAppC wired PowerupC’s Leds
interface to that provided by the LedsC component, but a two-line change could switch
that wiring to the NoLedsC component (which just does nothing):
components PowerupC , NoLedsC ;
PowerupC . LedsC -> NoLedsC . Leds ;
without affecting any other parts of the program that wish to use LedsC. In C, one could
replace the “mote” library used by Powerup by a version where the LED functions did
nothing, but that change would affect all LED users, not just Powerup.
42. 2.3 Wiring and callbacks 15
2.3 Wiring and callbacks
Leaving the component connection decisions to the programmer does more than just
simplify switching between multiple service implementations. It also provides an
efficient mechanism for supporting callbacks, as we show through the example of timers.
TinyOS provides a variable number of periodic or deadline timers; associated with each
timer is a callback to a function that is executed each time the timer fires. We first look
at how such timers would be expressed in C, by modifying Powerup to blink LED 0 at
2 Hz rather than turn it on once and for all:
# include " mote .h"
timer_t mytimer ;
void blink_timer_fired ( void )
{
leds0_toggle ();
}
int main ()
{
mote_init ();
timer_start_periodic (& mytimer , 250 , blink_timer_fired );
sleep ();
}
Listing 2.5 Powerup with blinking LED in C
In this example, the Blink application declares a global mytimer variable to hold
timer state, and calls timer_start_periodic to set up a periodic 250 ms timer. Every time
the timer fires, the timer implementation performs a callback to the blink_timer_fired
function specified when the timer was set up. This function simply calls a library function
that toggles LED 0 on or off.
The nesC version of Blink is similar to the C version, but uses interfaces and wiring
to specify the connection between the timer and the application:
module BlinkC {
uses interface Boot ;
uses interface Timer ;
uses interface Leds ;
}
implementation {
event void Boot . booted () {
call Timer . startPeriodic (250);
}
event void Timer . fired () {
43. 16 Names and program structure
call Leds . led0Toggle ();
}
}
Listing 2.6 Powerup with blinking LED in nesC (slightly simplified)
The BlinkC module starts the periodic 250 ms timer when it boots. The connection
between the startPeriodic command that starts the timer and the fired event which blinks
the LED is implicitly specified by having the command and event in the same interface:
interface Timer {
command void startPeriodic ( uint32_t interval );
event void fired ();
...
}
Finally, this Timer must be connected to a component that provides an actual timer.
BlinkAppC wires BlinkC.Timer to a newly allocated timer MyTimer:
configuration BlinkAppC { }
implementation {
components MainC , LedsC , new TimerC () as MyTimer , BlinkC ;
BlinkC . Boot -> MainC . Boot ;
BlinkC . Leds -> LedsC . Leds ;
BlinkC . Timer -> MyTimer . Timer ;
}
Listing 2.7 Powerup with blinking LED configuration (slightly simplified)
In the C version the callback from the timer to the application is a run-time argument to
the timer_start_periodic function. The timer implementation stores this function pointer
in the mytimer variable that holds the timer’s state, and performs an indirect function
call each time the timer fires. Conversely, in the nesC version, the connection between
the timer and the Blink application is specified at compile-time in BlinkAppC. This
avoids the need to store a function pointer (saving precious RAM), and allows the nesC
compiler to perform optimizations (in particular, inlining) across callbacks.
2.4 Summary
Table 2.1 summarizes the difference in how programs are structured in C, C++ and nesC.
In C, the typical high-level programming unit is the file, with an associated header file
that specified and documents the file’s behavior. The linker builds applications out of
files by matching global names; where this is not sufficient to express program structure
(e.g. for callbacks), the programmer can use function pointers to delay the decision of
which function is called at what point.
44. 2.4 Summary 17
Table 2.1. Program Structure in C, C++ and nesC
structural element C C++ nesC
program unit file class component
unit specification header file class declaration component specification
specification pattern – abstract class interface
unit composition name matching name matching wiring
delayed composition function pointer virtual method wiring
C++ provides explicit language mechanisms for structuring programs: classes are
typically used to group related functionality, and programs are built out of interacting
objects (class instances). An abstract class can be used to define common class
specification patterns (like sending a message); classes that wish to follow this pattern
then inherit from the abstract class and implement its methods – Java’s interfaces provide
similar functionality. Like in C, the linker builds applications by matching class and
function names. Finally, virtual methods provide a more convenient and more structured
way than function pointers for delaying beyond link-time decisions about what code to
execute.
In nesC, programs are built out of a set of cooperating components. Each component
uses interfaces to specify the services it provides and uses; the programmer uses wiring
to build an application out of components by writing wiring statements, each of which
connects an interface used by one component to an interface provided by another. Making
these wiring statements explicit instead of relying on implicit name matching eliminates
the requirement to use dynamic mechanisms (function pointers, virtual methods) to
express concepts such as callbacks from a service to a client.
48. 3 Components and interfaces
This chapter describes components, the building blocks of nesC programs. Every
component has a signature, which describes the functions it needs to call as well as the
functions that others can call on it. A component declares its signature with interfaces,
whicharesetsoffunctionsforacompleteserviceorabstraction. Modulesarecomponents
that implement and call functions in C-like code. Configurations connect components
into larger abstractions. This chapter focuses on modules, and covers configurations only
well enough to modify and extend existing applications: Chapter 4 covers writing new
configurations from scratch.
3.1 Component signatures
A nesC program is a collection of components. Every component is in its own source
file, and there is a one-to-one mapping between component and source file names. For
example, the file LedsC.nc contains the nesC code for the component LedsC, while
the component PowerupC can be found in the file PowerupC.nc. Components in nesC
reside in a global namespace: there is only one PowerupC definition, and so the nesC
compiler loads only one file named PowerupC.nc.
There are two kinds of components: modules and configurations. Modules and
configurations can be used interchangeably when combining components into larger
services or abstractions. The two types of components differ in their implementation
sections. Module implementation sections consist of nesC code that looks like C. Module
code declares variables and functions, calls functions, and compiles to assembly code.
Configuration implementation sections consist of nesC wiring code, which connects
components together. Configurations are the major difference between nesC and C (and
other C derivatives).
All components have two code blocks. The first block describes its signature, and the
second block describes its implementation:
module PowerupC { configuration LedsC {
// signature // signature
} }
implementation { implementation {
// implementation // implementation
} }
Listing 3.1 The signature and implementation blocks
50. it emitted no X-rays, but when the platinum was made the anode,
there was profuse radiation of X-rays in all directions from that side
of the platinum struck by the cathode rays, and no radiation from
the other side. § 91. (See also Roentgen and Tesla, concerning 1/2
platinum and 1/2 aluminum and radiation therefrom.) They inferred
as a final conclusion in connection with this point, “That the
necessary condition for the production of X-rays is an anode
bombardment by the cathode discharge.” § 113. They recognized
apparently that it had been conclusively proved that X-rays radiated
from the phosphorescent spot on the glass. They held that such a
spot is “The induced anode formed on the glass.” § 49, at end. They
did not prove this by an experiment according to the article referred
to, but based it upon “The fact that the bombarding cathode rays
coming in periodical electrified showers alternately raise and lower
the potential of the glass, thus making it alternately an anode and a
cathode. In the case of the platinum, this could not occur to the
same extent.”
117. Salvioni’s Experiment. Transposition of Phosphorescent Spot. Elect.
Rev., Lon., Apr. 24, ’96, p. 550; Med. Sur. Acad., of Perugia, Italy,
Feb. 22, ’96. Personal interview with Prof. Salvioni in Elect. Rev.,
N.Y., Apr. 8, ’96, p. 181.—In order to change the location of the
phosphorescent spot when desired, without a magnet, and at the
same time to concentrate or intensify the source of X-rays, he placed
near the same, on the outside of the tube, the hand or a metal mass
connected to earth. The spot immediately jumped to the other side
of the tube, § 49, near centre, and to all appearances was smaller
and brighter. Elster and Geitel had performed similar experiments at
an earlier date. (See Wied. Ann., LVI., 12, p. 733, also Elect. Eng.,
about April, ’96.) They carried on the most minute investigations as
to the deflection of the cathode rays by an outside conductor. Tesla
had also noticed a similar deviation. See Martin’s Tesla’s Researches.
He used alternating currents as described in his system in § 51.
Elster and Geitel used the Tuma Alternating system. (See Wied.
Ann., Ber. 102, part 2A, p. 1352, ’94.) The source from which
51. Salvioni’s description was taken had no sketch, therefore the
diagram made by Elster and Geitel is reproduced. See Fig. 1. The
cathode was aluminum and was connected to one terminal of the
transformer. The anode was connected to earth, and also was the
other terminal. Upon bringing the hand or other conductor
connected to earth to the phosphorescent spot, the cathode rays
deviated and the spot jumped over to the other side. § 50. The
anode was a ring surrounding the leading-in wires of the cathode,
and the two leading-in wires were surrounded by glass. It may be
asked why the cathode rays bent downward in the first place? Elster
and Geitel found that they were thrown thus in view of the nearness
of some neighboring object connected to earth. To overcome the
action of surrounding objects, the tube was surrounded by a ring as
shown in Fig. 2. However, the rays were still sensitive to objects well
connected to earth, and when brought quite close to the tube.
Figs. 1 and 2.
117a. Hammer and Fleming’s Molecular Sciagraph, within a Vacuum Tube.
(Citations below.)—In view of the overwhelming evidence
concerning the generation of X-rays by the impact of cathode rays,
within a high vacuum upon the glass or material which preferably
forms the anode, it becomes appropriate, it is thought, to review the
state of this department of science, in order to arrive a little more
closely at the relations which exist between phenomena of low and
high vacua. With the former, in that condition in which striae are
52. formed, permanent black bands or deposits are produced upon the
surface of the glass; the motion of the particles, therefore,
appearing to be in planes at right angles to the line joining the
anode and cathode. § 40. That the striae should touch the walls of
the tube seems to be necessary for the production of the deposit. §
44. With a high vacuum, the direction of the cathode rays may be
any that one desires, it being only necessary to shape the cathode
properly, on the principle that the rays radiate normally from the
surface. It is known that the radiation is normal as much from the
position of the deposit as from that of the phosphorescent spot. It is
certain that they are rectilinear. § § 57 and 58. The phosphorescent
spot becomes always, sooner or later, when occurring upon the
same part of the glass, the location of a deposit from the cathode (§
123), even when the cathode is aluminum. § 123. The deposit is not
the cause of the fatigue of the glass. § 58. Puluj verified this. A
wheel was made to rotate by the radiations from the cathode, and
therefore it is highly probable that the motion of the molecules,
which caused the deposit, is the force that made the wheel rotate. §
58a. Why does it not follow that with increase of E. M. F. the particles
are thrown with such rapidity that upon striking the proper surface
(§ 80), X-rays are generated, but that they are not generated when
the velocity of the molecules is insufficient. § 61b, p. 46. Attention is
now invited to a phenomenon which illustrates that a permanent
sciagraph of objects may be impressed upon the inner surface of a
vacuum tube, by the deposit of molecules of one of the electrodes.
Refer, therefore, to the figure on page 30, “Hammer and Fleming’s
Molecular Sciagraph.” As will be seen from further explanation and
from the picture itself, the sciagraph a b is made because of the
projection, in rectilinear lines, of molecules of carbon or metal, from
one of the electrodes, or at least from one more than the other. One
leg of the carbon, being in the way of the other, causes a less
deposit to be produced upon the glass at the intersection of the
plane of the horse-shoe filament and the wall of the vacuum tube.
Electrodes exist because the filament is of such a high resistance as
to produce a difference of potential between the two straight lower
portions of the filament. Mr. William J. Hammer possesses a
53. remarkable faculty for observing phenomena often overlooked by
others. He first observed a molecular shadow in 1880 and made
records of his observations in the Edison Laboratory note book.
Since that time he has examined over 600 lamps, which were made
at various periods during thirteen or fourteen years, by twelve
different manufacturers. (Trans. Amer. Inst. Electrical Eng., Mar. 21,
p. 161.) Every one, more or less, exhibited the molecular shadow. It
is a principle, therefore, that if the carbon filament has both legs in
the same plane, a sciagraph of one of them will be produced. As the
shadow is on one side of the bulb only, the molecules fly off from
only one electrode, viz., the cathode. By means of photography, the
effect is increased because of certain well-known principles. The
figure heretofore referred to is taken from a photograph, but, of
course, does not represent the sciagraph as well as the original
photograph, in view of the loss of effect by re-production by the
half-tone process. For further theoretical considerations, see the
Institute paper referred to, where the matter was discussed by Profs.
Elihu Thomson, Anthony and others. Independently of Mr. Hammer’s
discovery, Prof. J. A. Fleming, professor of electrical engineering in
the University College, London, England, discovered and studied the
matter, and presented it before the Phys. Soc. of London, appearing
about 1885 (from memory). The name “molecular sciagraph” is
given by the author because it is an accepted explanation that the
deposit is due to either molecules or atoms of the electrode, given
off by evaporation (page 46, lines 5 to 10), or electrical repulsion (§
61a, lines 22 to 25), or, as some hold, by mere volatilization by the
intense heat of incandescence, or one or more combined; but
electrical repulsion certainly has something to do with the rectilinear
propagation, for the molecules are charged according to § 4.
56. CHAPTER X
118. Edison’s Experiments. Characteristics of Discharge Tube,
Photographic Plates, Electrical Apparatus, Fluorescence, Etc. Elec. Eng.,
N.Y., Feb. 19, ’96; Mar. 18 and 25; Apr. 1, 8, 15 and 29, ’96. X-Rays
Begin Before Striae End.—The reader may remember a former
section, § 10, pointing out that striae were usually obtainable
without very high vacua, and that phosphorescence of the glass
occurs only with high vacua. § 54. In carrying the vacuum up higher
and higher, Edison observed that feeble Roentgen rays were
detected before the striae ceased. Prof. Elihu Thomson
independently performed a like experiment and found that the
Roentgen rays could be obtained even when the vacuum was so low
as to produce striae. (Elec. Eng., N.Y., Apr. 15, ’96.) Victor Chabaud
and D. Hurmuzescu also obtained X-rays from a vacuum .025 mm.,
being lower than Crookes employed, which was at a maximum .001
mm. (L’Industrie Elect., Paris, May 25, ’96. From trans. by Louis M.
Pignolet.)
119. Reason Why Thin Walls are Better Than Thick. X-Rays and Post-
Phosphorescence.—This may be understood by explanation of the
discharge tube in Fig. 1. In one experiment, the portion struck by
the cathode rays, namely B, was made 1/8 inch thick. It became
soon hot and very luminous and melted, § 61, but the X-rays were
weak. When blown thin, (§ 83) however, the glass remained cool
and the X-rays were much stronger. What is known on the market as
German glass (phosphoresces green, § 55, at centre) was found
more permeable than lead glass, the thickness of the walls being the
57. same in both cases. There were no lingering X-rays from after-
phosphorescence, (§ 54, at end) or, if any, could not be detected by
the sciascope. The photographic test would be objectionable
because of the brief duration. Prof. Battelli and Dr. Garbasso, of Pisa,
made a very sensitive test in this connection, proving by the
discharge of an electrified body (§ § 90 and 90a) that feeble X-rays
were emitted after the current was cut off from the discharge tube.
(From trans. by Mr. Pignolet.)
59. 120. To Prevent Puncture of the Discharge Tube by Sparks.—In the
illustration, Discharge Tube Fig. 2. shows a suitable type. It is drawn
to scale, showing the correct proportion of the length to the
diameter. The shaded ends represent tinfoil on the outside and
connecting with the leading-in wires, the same preventing puncture
of the glass by the spark. They may be caused to adhere by shellac
or similar glue. In place of the metallic coating detached
supplementary electrodes may be employed, as seen in the
illustration marked “Discharge Tube Fig. 3.” The power of the X-rays
was increased, being due, it was thought, to the fact that the
construction embodied the combination of internal and external
electrodes. § 121.
121. Variation of Vacuum by Discharge and by Rest.—Prof. Pupin was
among the first to test the efficiency of external electrodes for
generating X-rays. Independently of the quality of the glass and of
the kind of pump and of the presence or absence of phosphoric
anhydride, the following peculiarities were noticed, which Edison
attributed to a kind of atomic electrolysis. § 47. 80 per cent. of the
lamps exhibited the phenomena as follows: First, such a high
vacuum was obtained by the pump that the line spectrum
disappeared and pure fluorescence and generation of X-rays at a
maximum occurred. The lamp was then sealed off. After three or
four hours of rest, the vacuum deteriorated, so that striae and other
characteristics of low vacuum were obtained when connected up in
circuit, but upon continuing the current, the high vacuum gradually
came back, the line spectrum vanished, and suddenly X-rays were
generated. Again the bulb was left at rest for 24 hours, after which
X-rays could not be generated until the discharge had been
continued for 4-1/2 hours.
60. Discharge Tube, Fig. 2. § 120.
122. External Electrodes Discharge through Higher Vacuum than
Internal.—A vacuum that was so high that no discharge took place
with internal electrodes was made luminous by the use of electrodes
on the outside of the glass bulb. Then he made the vacuum so high
that even with a 12-inch spark from Leyden jars, no discharge took
place with external electrodes, and the tube was dark, this part of
the experiment indicating another limit at which an extremely high
vacuum is not a conductor and appearing to overthrow, as Edison
intimated, Edlund’s theory that a vacuum is a perfect conductor. §
25.
123. Deposit on Glass from Aluminum Electrode.—It has always been
common to employ aluminum for electrodes in vacuum tubes, on the
ground that no deposit took place, and therefore no blackening, nor
whitening of the glass wall. § 40. Edison observed also that no
blackening was visible, but stated that his glass blower, Mr. Dally,
upon breaking the bulb and submitting the interior surface of the
glass to an oxydizing process, the oxide of aluminum was so thick as
to be opaque to light. With magnesium, also, a mirror was produced,
of a lavender color, by transmitted light. In the case of aluminum, he
was able to obtain a visible spot at the phosphorescent portion, but
only after a great many hours of use. See cut from a photograph of
a discharge tube used for several months by Prof. Dayton C. Miller,
and having a heavy aluminum deposit opposite the aluminum
cathode. With the increase of the deposit, the power of the X-rays
diminished, but, he thought, not on account of the absorption, but
because, “through lack of elasticity at the surface.”
61. Discharge Tube, § 123.
124. Fluorescent Lamp. In an English patent of ’82, granted to
Rankin Kennedy, there is described a vacuum bulb in which the
62. electrodes are covered with fluorescent or phosphorescent
substances, intended for the purpose of obtaining greater candle
power by impact of cathode rays upon anode of platinum, covered
with alumina or magnesia. Edison coated the inner wall of the
discharge tube, for generating X-rays, with calcic tungstate in the
crystalline form. The luminosity, when measured, amounted to about
2-1/2 C. P. As to the efficiency, he stated that this was accomplished
“with an extremely small amount of energy.” Such a coating was
found to weaken the X-rays radiated therefrom, which, of course,
was natural, because they had been converted into phosphorescent
light. The spectrum showed strongly at the red line, thereby
suggesting the reason why the light was of a pleasant character.
124a. Piltchikoff’s Experiment. Greater emission of X-rays by a tube
containing an easily fluorescent substance. Comptes Rendus, Feb.,
24, ’96. From trans. by Mr. Louis M. Pignolet. As the X-rays emanate
from the fluorescent spots on the glass of the discharge tube, he
reasoned that more powerful effects would be obtained by replacing
the glass by a more fluorescent material. He therefore tried a Puluj
tube and found that it shortened the time necessary for taking a
photograph in a “singular” degree. Experiments of others have
certainly shown that as phosphorescence decreases with increase of
vacuum, the X-rays increase to a certain maximum, § 105. Let it be
noticed however, that this does not prove that with the same
vacuum, an increase of phosphorescence by a superior
phosphorescent material of equal thickness would not increase the
power of the X-rays. The best way to determine such points, is to go
to extremes. Edison applied so much easily phosphorescent material
(calcic tungstate) to the inside of the discharge tube, that much light
was radiated, but only feeble X-rays. On the other hand, without any
of the tungstate, the rays were strong, § 124. Experiments generally
tend to prove that it depends upon the chemical nature of the
material rather than its phosphorescing power, in other words upon
the permeability. § 119, near end.
63. 125. Electrodes of Silicon Carbide. (Carborundum.) Edison called
attention to Tesla’s discovery that this substance is a good conductor
for high tension currents. Its advantages for electrodes in the
discharge tube are its high conductivity, no absorbed nor released
gas bubbles, and its infusibility and non-blackening power of glass
even when the voltage was increased to a point where the glass
melted.
64. Edison (at right) and T. Commerford Martin using the Sciascope. § 97, p.
84.
65. Cut also shows Sprengel vacuum-pump. Discharge-tube is in the box.
126. Chemical Decomposition of the Glass Bulb. During the generation
of the X-rays the sodium line of the spectrum appeared in the
spectroscope, thereby indicating decomposition of the glass. With
combustion tubes the glass gave the weakest soda line, while lime
soda glass gave the strongest, and was most permeable to the X-
rays. “The continuous decomposition of the glass makes it almost
impossible to maintain a vacuum except when connected to the
pump and even then the effect of the current is greater in producing
gas than the capacity of the pump to exhaust, but the ray is very
powerful.” It is supposed that for this reason, as well as for others
easily apparent that Edison as well as other experimenters have
always carried on their investigations with the discharge tube
permanently connected to the pump. The next best thing is to let
the tube contain a stick of caustic potash for maintaining an
exceedingly high vacuum. By gradually heating this, the desired
degree of vacuum can be obtained. § 54.
127. Sciagraphs. Duration of Exposure Dependent Upon Distances. With
the given discharge tube, he obtained sciagraphs at a distance of
3/8 inch from the phosphorescent spot in one second, a vulcanized
cover being between; at two ft. distant the time was 150 sec.; at
three ft., 450 sec.; the opaque plate being interposed each time.
Consequently “Roughly, the duration of exposure may be reckoned
as proportional to the square of the distance.”
128. Difference Between X-rays and Light Illustrated by Different
Photographic Plates. Time of Exposure. The rapid plate for light gave
not the deepest images by X-rays. Several different kinds of small
sensitive plates were laid side by side. A sciagraph of a metal bar
was taken upon them all simultaneously. In this way, he obtained
the result, whereby it would appear preferable to employ the mean
rapid plate for the purpose of obtaining sciagraphs. On account of
66. the opacity of platinum, it occured to E. B. Frost, (Sci., N.Y., Mar. 27,
’96,) to try platinum photographic paper of the kind used for
portraits, but such paper (intended for long exposures in printing in
sunlight) was far too lacking in sensitiveness to produce any effect.
128a. Georges Meslins insured a reduction of time for taking sciagraphs
by the deflection of the cathode rays by means of a magnetic field.
Comptes Rendus, March 23 and 30, 1896. From trans. by Louis M.
Pignolet. The method consists in using a permanent or electro-
magnet to create a magnetic field perpendicular to the cathode rays
in the tube. By this means, the active fluorescent spot on the tube is
condensed, and the intensity of the X-rays generated there is
increased. Another advantage is that, when the active part of the
tube becomes inactive owing to the formation of a light brown
deposit upon it, another part can be used by very slightly altering
the position of the magnets. Thus, each time a new part of the tube
can be used. The magnetic field must not be uniform but must have
a suitable variation to produce the desired concentration of the
cathode rays.
A. Imbert and H. Bertin-Sans’ Experiment. (Comptes Rendus, March
23, ’96. (From trans. by L. M. P.) They shortened the time by use of
a magnet.
James Chappin’s Experiment. (Comptes Rendus, Mar. 30,’96. (From
trans. by L. M. P.)—Claimed priority in having shown publicly, on Feb.
19, a sciagraph of a hand, marked “Photograph obtained by
concentration of the cathode rays, by means of a magnetic field.”
The increase of the intensity of the X-rays obtained by this means
was in the proportion of 8 to 5, as measured by the time of fall of
the leaves of a Hurmuzescu electroscope.
Prof. Trowbridge, of Harvard University, in a lecture, gave an
interesting review (Western Elect., Feb. 29, ’96) of the length of time
required in the early days of photography. Improvements are being
made whereby the duration required in sciagraphy becomes less and
less. In 1827, by heliography, 6 hours’ exposure was necessary; in
67. 1839, by daguerreotype, 30 minutes; in 1841, by calotype, 3
minutes; in 1851, by collodion, 10 seconds; in 1864, by collodion, 5
seconds; in 1878, by gelatine, 1 second. The author remembers the
photographs for use in the Edison kinetoscope were taken at the
rate of 20 per second. The focus tube brings the time of exposure in
behalf of X-rays down to a matter of seconds instead of minutes. For
an admirable review of authorities, facts and theories relating to the
causes of the darkening of photographic plates by light, see Cottier,
in Elect. World, N.Y., May 23, ’96.
129. Size of Discharge Tube to Employ for Given Apparatus.—A small
tube required but a small E. M. F., and therefore should be employed
with a small induction coil. The greater the distance of the sensitive
plate and the object, considered together, from the discharge tube,
the sharper the shadow. In short exposures, the tube should be
small and at a short distance.
130. Preventing Puncture at the Phosphorescent Spot.—In
experiments where he employed a flat cathode, a very thin pencil of
rays of increased power came from the exact centre, and in two or
three seconds made the glass red hot at the centre of the
phosphorescent spot. Immediately, the atmospheric pressure
perforated the bulb. This occurred several times. He stated that “the
best remedy is to permit the central ray to strike the glass at a low
angle; this greatly increases the area and prevents the trouble.”
Edison.
Mr. Ludwig Gutmann furnished a translation of a note by Prof.
Walter König, found in Eleck. Zeit. of May 14, ’96, relating to this
same subject matter. Recognizing that the sharpness of the outlines
is the most important requirement in connection with sciagraphy,
and that if the rays start from a large surface the impressed
shadows will be uncertain in configuration, and noticing, as Edison
and Tesla did, § 130, the frequent destruction of the tube at the
place where the rays were concentrated to a focus, he placed over
68. the inner surface of the glass, aluminum foil for distributing the heat
over a larger area, at the same time causing radiation of X-rays from
a single point. The focus tube outweighs this in importance. § 91.
131. Electrical Dimensions of Apparatus. The best kind of instruction
for the student in reference to equipping a plant is to follow the
construction employed by those who have been successful. § § 106,
109, 114, 137. Edison used the usual incandescent-lamp current,
voltage at 110 to 120 volts, current being continuous, but not
connected directly to the induction coil, there being a bank of eight
to twenty 16 candle power incandescent lamps arranged in parallel.
The interrupter for the primary consisted of a rotating wheel in
appearance like a commutator of a dynamo, and was rotated rapidly
by a small electric motor, making about 400 interruptions per
second, and so constructed that the circuit was closed twice as long
as it was open. A sudden interruption was caused by an air blast
playing at the point of make and break, the use of which made that
of a condenser needless. § 3. The discharge tube terminals were
connected respectively and directly to those of the secondary. Prof.
Pupin, Columbia Univ. N.Y. (Lect. N.Y., Acad. Sci., April 6, ’96, and
Science, N.Y., April 10, ’96) gave valuable and practical instruction
concerning the apparatus, which the author witnessed. “A powerful
coil was found indispensable for strong effects and satisfactory work.
The vibrating interrupter is too slow and otherwise unsatisfactory,
and it was replaced by a rotary interrupter, consisting of a brass
pulley, 6 inches in diameter and 1-1/4 inches in thickness. A slab of
slate 3/4 inch thick was inserted and the circumference was kept
carefully polished. This pulley was mounted on the shaft of a
Crocker-Wheeler 1/8 H. P. motor giving 30 revolutions, and, therefore,
60 breaks per second. Two adjustable Marshall condensers of three
microfarads each were connected in shunt with the break, and the
capacity adjusted carefully until the break-spark was a minimum and
gave a sharp cracking sound. Too much capacity will not necessarily
increase the sparking, but it will diminish the inductive effect which
is noticed immediately in the diminished intensity of the discharge. A
69. powerful coil with a smoothly working rotary interrupter will be
found a most satisfactory apparatus in experiments with Röntgen
radiance.” § 106, 109, 114, 131, 137.
132. Salts Fluorescence by X-rays. See also, Elect. Rev., N.Y., April
19, ’96, p. 165. Edison examined over 1800 chemicals to detect and
compare their fluorescent powers if any, under the action of X-rays
first transmitted through some opaque material such as thick
cardboard. Of all these, calcic tungstate by measurement, fluoresced
with six times the luminosity of barium platino cyanide, which was
referred to in connection with Roentgen’s experiment. Other
authorities agree as to its great sensitiveness. In making this
comparison, it was assumed that the power of the X-rays varied
inversely as the square of the distance from the discharge tube.
Between the two above chemicals came strontic tungstate. Baric and
plumbic tungstate scarcely fluoresced. Salicylate of ammonium
crystals equalled the double cyanide of platinum and barium, and
differed therefrom in that the fluorescence increased with the
thickness of the layer of crystals up to 1/4 of an inch, showing great
fluorescing power and low absorptivity. This experiment showed that
the best fluorescent materials were not necessarily the salts of the
heaviest metals, like platinum. It is assumed that the reader knows
the difference between phosphorescence and fluorescence, but the
dividing line is so difficult in some cases and the one not being
distinguished from the other by experimenters, that the author has
used the same words as the experimenters, although he admits that
fluorescence is often meant where phosphorescence is stated, and
vice versa. An anomaly presented itself as to rock salt, which
although transparent to light yet powerfully absorbed X-rays and was
strongly fluoresced thereby. Again, fluorite which is transparent to
light, fluoresced strongly with the X-rays, and under their action
became brighter and brighter and continued after cutting off the X-
rays, the material therefore, being highly phosphorescent, the light
enduring for several minutes. Upon watching the phosphorescence
of fluorite, the same penetrated the plate very slowly to the depth of
70. one-sixteenth of an inch, but beyond that depth there was complete
darkness. The only other truly phosphorescent substance noticed
was calcic tungstate, especially in thick layers, so that the shadow of
the bones of the hand remained thereon for a minute or two upon
cutting out the discharge tube from the circuit. Some chemicals,
within a dark box and very close to the discharge tube,
phosphoresced by giving spots here and there, but they did not
phosphoresce at a greater distance, and the light was probably not
due to the X-rays. Edison attributed the result directly to the
“electrical discharge.” The list is as follows: ammonium sulphur
cyanide, calcic formate, and nitrate, ferric citrate, argentic nitrate,
calcic and iron citrate, soda, lime, “zinc, cyanide” (perhaps this
means cyanide of zinc), zinc hypermanganate, and zinc valeriate.
The salts of the following metals did not fluoresce under the
influence of the X-rays. Aluminum, antimony, arsenic, boron,
beryllium, bismuth, barium, chromium, cobalt, copper, gold, iridium,
magnesium, manganese, nickel, tin, and titanium.
71. Roentgen Rays at the University of Minnesota.
1. Watch and chain.
2. College badges in mahogany box.
3. Copper coin.
4. Weights in heavy velvet-lined mahogany box; blank space
contains aluminum.
5. Coins in inner pocket of heavy seal purse.
6 and 7. Colored glass.
8. Key
9. Lead-pencil.
West. Elect., Mar. ’96.
Edison stated that the following substances were among those
which fluoresced more or less under the action of the X-rays.
72. Welcome to Our Bookstore - The Ultimate Destination for Book Lovers
Are you passionate about books and eager to explore new worlds of
knowledge? At our website, we offer a vast collection of books that
cater to every interest and age group. From classic literature to
specialized publications, self-help books, and children’s stories, we
have it all! Each book is a gateway to new adventures, helping you
expand your knowledge and nourish your soul
Experience Convenient and Enjoyable Book Shopping Our website is more
than just an online bookstore—it’s a bridge connecting readers to the
timeless values of culture and wisdom. With a sleek and user-friendly
interface and a smart search system, you can find your favorite books
quickly and easily. Enjoy special promotions, fast home delivery, and
a seamless shopping experience that saves you time and enhances your
love for reading.
Let us accompany you on the journey of exploring knowledge and
personal growth!
ebookgate.com