📄 sensing - tinyos documentation wiki.htm
字号:
interface Boot;
interface Leds;
interface Timer<TMilli>;
interface Read<uint16_t>;
}
}
</PRE>
<P>Like the <CODE>BlinkC.nc</CODE> module the <CODE>SenseC.nc</CODE> module uses
the interfaces <CODE>Boot</CODE>, <CODE>Leds</CODE> and
<CODE>Timer<TMilli></CODE>. Additionally, it uses the
<CODE>Read<uint16_t></CODE> interface. The sequence of actions in the
<CODE>SenseC.nc</CODE> implementation is as follows: <CODE>SenseC.nc</CODE> uses
the <CODE>Boot</CODE> interface to start a periodic timer after the system has
been initialized. Every time the timer expires <CODE>SenseC.nc</CODE> is
signalled a timer event and reads data via the <CODE>Read<uint16_t></CODE>
interface. Reading data is a split-phase operation, it is divided in a command
<CODE>Read.read()</CODE> and an event <CODE>Read.readDone()</CODE>. Thus every
time the timer expires <CODE>SenseC.nc</CODE> calls <CODE>Read.read()</CODE> and
waits for the <CODE>Read.readDone()</CODE> event. When data is signalled in the
<CODE>Read.readDone()</CODE> event <CODE>SenseC.nc</CODE> displays it on the
leds: the least significant bit is displayed on LED 0 (0 = off, 1 = on), the
second least significant bit is displayed on LED 1 and so on. </P>
<P>The <CODE><A class="external text"
title=http://www.tinyos.net/tinyos-2.x/tos/interfaces/Read.nc
href="http://www.tinyos.net/tinyos-2.x/tos/interfaces/Read.nc"
rel=nofollow>Read</A></CODE> interface (in
<CODE>tinyos-2.x/tos/interfaces</CODE>) can be used to read a single piece of
sensor data, let's look at it in detail: </P><PRE>interface Read<val_t> {
/**
* Initiates a read of the value.
*
* @return SUCCESS if a readDone() event will eventually come back.
*/
command error_t read();
/**
* Signals the completion of the read().
*
* @param result SUCCESS if the read() was successful
* @param val the value that has been read
*/
event void readDone( error_t result, val_t val );
}
</PRE>
<P>If you are not familiar with generic interfaces you will wonder what the
meaning of <CODE><val_t></CODE> (in the first line) is and why the
signature of <CODE>SenseC.nc</CODE> is using <CODE>Read<uint16_t></CODE>.
What you see above is a <I>generic interface definition</I>, because the
<CODE>Read</CODE> interface takes a type parameter. Generic interfaces are
explained in the nesC Language Reference Manual (version 1.2 and above). For now
it is enough to know that generic interfaces have at least one type parameter
and two components can be wired together only if they provide/use the interface
with the same types (note that the <CODE>readDone</CODE> event passes a
parameter of the <CODE><val_t></CODE> parameter, which is a placeholder
for the actual data type). This means that since <CODE>SenseC.nc</CODE> is using
the <CODE>uint16_t</CODE> variant of the <CODE>Read</CODE> interface, it can
only be wired to a component that provides the <CODE>Read<uint16_t></CODE>
interface and thus <CODE>SenseC.nc</CODE> expects to read 16 bit unsigned
integer sensor data. If you tried to wire <CODE>SenseC.nc</CODE> to a component
that provides, for example, a <CODE>Read<uint8_t></CODE> interface you
would get an error from the nesC compiler. </P>
<P>Recall that the wiring is defined in the <CODE>SenseAppC.nc</CODE>
configuration. Let's again take a look at which component <CODE>SenseC.nc</CODE>
is wired to using the <CODE>Read<uint16_t></CODE> interface in the
<CODE>SenseAppC</CODE> configuration. The interesting lines are </P><PRE> components new DemoSensorC() as Sensor;
</PRE>
<P>and </P><PRE> SenseC.Read -> Sensor;
</PRE>
<P>This means that the <I>generic</I> <CODE>DemoSensorC</CODE> component
provides the <CODE>Read<uint16_t></CODE> interface to
<CODE>SenseC.nc</CODE> </P>
<P>It is important to understand that the <CODE>SenseC.nc</CODE> module has no
way of telling which sensor it is connected to; in fact it cannot even tell
whether it is getting data from a sensor at all, because it can be wired to any
component that provides a <CODE>Read<uint16_t></CODE> interface. On a
platform without any built-in sensors (like <I>micaz</I>) and no attached
sensorboard the <CODE>DemoSensorC</CODE> component could simply return constant
values. The last sentence hints that the <CODE>DemoSensorC</CODE> component is
different for every platform: therefore you will not find
<CODE>DemoSensorC.nc</CODE> in the TinyOS libraries. Instead, a different
<CODE>DemoSensorC.nc</CODE> has to be written for every platform, i.e. the
<CODE>DemoSensorC.nc</CODE> implementation for telosb will be different than the
<CODE>DemoSensorC.nc</CODE> implementation for micaz. This is the answer to the
first question asked in the <A title=Sensing
href="http://docs.tinyos.net/index.php/Sensing#Introduction_introduction">Sensing#Introduction
introduction</A> section: the <I>platform dependent</I> <CODE>DemoSensorC</CODE>
component defines which sensor the <CODE>Sense</CODE> or
<CODE>Oscilloscope</CODE> application is sampling and every platform that wants
to run sensing applications such as <CODE>Oscilloscope</CODE>,
<CODE>Sense</CODE> or <CODE>RadioSenseToLeds</CODE> has to provide its own
version of <CODE>DemoSensorC</CODE>. Additionally, sensor boards may come with
their own version of <CODE>DemoSensorC</CODE> (e.g., the <CODE>basicsb</CODE>
sensorboard for the mica-family of motes define <CODE>DemoSensorC.nc</CODE> to
be that board's light sensor). </P><A name=The_DemoSensorC_component></A>
<H2><SPAN class=mw-headline>The DemoSensorC component</SPAN></H2>
<P>Let's take a closer look at the <CODE>DemoSensorC</CODE> component. Every
<CODE>DemoSensorC</CODE> component has the following signature: </P><PRE>generic configuration DemoSensorC()
{
provides interface Read<uint16_t>;
}
</PRE>
<P>In its implementation section, however, <CODE>DemoSensorC</CODE> may differ
from platform to platform. For example, on the <I>telosb</I> platform
<CODE>DemoSensorC</CODE> instantiates a component called <CODE>VoltageC</CODE>,
which reads data from the MCU-internal voltage sensor. Because the <I>micaz</I>
doesn't have any built-in sensors its <CODE>DemoSensorC</CODE> uses system
library component like <CODE>ConstantSensorC</CODE> or <CODE>SineSensorC</CODE>,
which return "fake" sensor data. Thus <CODE>DemoSensorC</CODE> is a means of
indirecting sensor data acquisition from a platform-specific sensor component
(like <CODE>VoltageC</CODE>) to platform-independent applications like
<CODE>Sense</CODE> or <CODE>Oscilloscope</CODE>. Usually the configuration of a
sensor is done in the component that <CODE>DemoSensorC</CODE> instantiates. </P>
<P>How can <CODE>Sense</CODE> be changed to sample a sensor other than the
platform's default sensor? Usually this requires changing only a single line of
code in <CODE>DemoSensorC</CODE>; for example, if you wanted to replace the
<CODE>VoltageC</CODE> component on <I>telosb</I> by the constant sensor
component <CODE>ConstantSensorC</CODE> you could change the follwoing line in
<CODE>DemoSensorC</CODE> from: </P><PRE>components new VoltageC() as DemoSensor;
</PRE>
<P>to something like </P><PRE>components new ConstantSensorC(uint16_t, 0xbeef) as DemoSensor;
</PRE>
<P>What sensors are available depends on the platform. Sensor components are
usually located in the respective platform subdirectory
(<CODE>tinyos-2.x/tos/platforms</CODE>), in the respective sensorboard
subdirectory (<CODE>tinyos-2.x/tos/sensorboards</CODE>) or, in case of
microprocessor-internal sensors, in the respective chips subdirectory
(<CODE>tinyos-2.x/tos/chips</CODE>). <CODE>ConstantSensorC</CODE> and
<CODE>SineSensorC</CODE> can be found in <CODE>tinyos-2.x/tos/system</CODE>.
</P><A name=Running_the_Sense_application></A>
<H2><SPAN class=mw-headline>Running the Sense application</SPAN></H2>
<P>To compile the <CODE>Sense</CODE> application, go to the
<CODE>apps/Sense</CODE> directory and depending on which hardware you have, type
something similar to <CODE>make telosb install</CODE>. If you get errors such as
the following, </P><PRE>SenseAppC.nc:50: component DemoSensorC not found
SenseAppC.nc:50: component `DemoSensorC' is not generic
SenseAppC.nc:55: no match
</PRE>
<P>your platform has not yet implemented the <CODE>DemoSensorC</CODE> component.
For a quick solution you can copy <CODE>DemoSensorC.nc</CODE> from
<CODE>tinyos-2.x/tos/platforms/micaz</CODE> to your platform directory (a good
starting point on how to create sensor components is probably <A
class="external text"
title=http://www.tinyos.net/tinyos-2.x/doc/html/tep101.html
href="http://www.tinyos.net/tinyos-2.x/doc/html/tep101.html" rel=nofollow>TEP
101</A> and <A class="external text"
title=http://www.tinyos.net/tinyos-2.x/doc/html/tep114.html
href="http://www.tinyos.net/tinyos-2.x/doc/html/tep114.html" rel=nofollow>TEP
114</A>). </P>
<P>If you have a mica-family mote and a "basic" (mda100) sensor board, you can
get a more interesting test by compiling with </P><PRE>SENSORBOARD=basicsb make <I>platform</I> install
</PRE>
<P>to run <CODE>Sense</CODE> using the mda100's light sensor. </P>
<P>Once you have installed the application the three least significant bits of
the sensor readings are displayed on the node's LEDs (0 = off, 1 = on). It is
the least significant bits, because <CODE>Sense</CODE> cannot know the precision
(value range) of the returned sensor readings and, for example, the three most
significant bits in a <CODE>uint16_t</CODE> sensor reading sampled through a
12-bit ADC would be meaningless (unless the value was left-shifted). If your
<CODE>DemoSensorC</CODE> represents a sensor whose readings are fluctuating you
may see the LEDs toggle, otherwise <CODE>Sense</CODE> is not very impressive.
Let's take a look at a more interesting application: <CODE>Oscilloscope</CODE>.
</P><A name=The_Oscilloscope_application></A>
<H1><SPAN class=mw-headline>The Oscilloscope application</SPAN></H1>
<P><CODE>Oscilloscope</CODE> is an application that let's you visualize sensor
readings on the PC. Every node that has <CODE>Oscilloscope</CODE> installed
periodically samples the default sensor via (<A title=Sensing
href="http://docs.tinyos.net/index.php/Sensing#The_DemoSensorC_component">
<CODE>DemoSensorC</CODE></A>) and broadcasts a message with 10 accumulated
readings over the radio. A node running the <CODE>BaseStation</CODE> application
will forward these messages to the PC using the serial communication. To run
<CODE>Oscilloscope</CODE> you therefore need at least two nodes: one node
attached to your PC running the <CODE>BaseStation</CODE> application
(<CODE>BaseStation</CODE> can be found at
<CODE>tinyos-2.x/apps/BaseStation</CODE> and was introduced in the <A
title="Mote-PC serial communication and SerialForwarder"
href="http://docs.tinyos.net/index.php/Mote-PC_serial_communication_and_SerialForwarder">previous
lesson</A>) and one or more nodes running the <CODE>Oscilloscope</CODE>
application. </P>
<P>Let's take a look at the <CODE><A class="external text"
title=http://www.tinyos.net/tinyos-2.x/apps/Oscilloscope/OscilloscopeAppC.nc
href="http://www.tinyos.net/tinyos-2.x/apps/Oscilloscope/OscilloscopeAppC.nc"
rel=nofollow>OscilloscopeAppC.nc</A></CODE> configuration: </P><PRE>configuration OscilloscopeAppC
{
}
implementation
{
components OscilloscopeC, MainC, ActiveMessageC, LedsC,
new TimerMilliC(), new DemoSensorC() as Sensor,
new AMSenderC(AM_OSCILLOSCOPE), new AMReceiverC(AM_OSCILLOSCOPE);
OscilloscopeC.Boot -> MainC;
OscilloscopeC.RadioControl -> ActiveMessageC;
OscilloscopeC.AMSend -> AMSenderC;
OscilloscopeC.Receive -> AMReceiverC;
OscilloscopeC.Timer -> TimerMilliC;
OscilloscopeC.Read -> Sensor;
OscilloscopeC.Leds -> LedsC;
}
</PRE>
<P>The actual implementation of the application is in <CODE><A
class="external text"
title=http://www.tinyos.net/tinyos-2.x/apps/Oscilloscope/OscilloscopeC.nc
href="http://www.tinyos.net/tinyos-2.x/apps/Oscilloscope/OscilloscopeC.nc"
rel=nofollow>OscilloscopeC.nc</A></CODE>. This is the signature of
<CODE>OscilloscopeC.nc</CODE>: </P><PRE>module OscilloscopeC
{
uses {
interface Boot;
interface SplitControl as RadioControl;
interface AMSend;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -