My current project involves sampling data with the Crossbow Iris and MTS310 sensorboard. I wish to sample data at regular intervals, say 20ms, using all available modalities on the MTS310: x and y-axis accelerometer, x and y-axis magnetometer, light, temperature, and acoustic. Every 20ms, a timer fires and collects data samples from each sensor using the Read interface. As it turns out, the current TinyOS 2.x code for the MTS300/310 does not allow this.
I found that every time I called Read.read() for some of the sensors, that there would often be a delay in getting my data back with Read.readDone(). This delay was because each call to Read.read() would power on the sensor, requiring a warm-up time before a sample could be retrieved. While the warm-up time for the accelerometer is 17ms, the warm-up time for the light sensor is an excruciatingly long 1200ms! So, I would call Read.read() at 20ms intervals, but have to wait over a second to get data from the light sensor. When the data sample is returned at Read.readDone(), the sensor would power off again, thus requiring another warm-up the next time a sample is requested. Basically, the constant warm-up lag in the current TinyOS code prevents sampling at a reasonably fast rate using Read.
I also found that if I wished to get both axes of the accelerometer or magnetometer simultaneously, that only one axis would ever return data. The accelerometer, magnetometer, and light/photo sensors use the ArbitratedResource interface to block all other sensors that use the same resource when one sensor has a lock on the resource. If the x-axis accelerometer was sampling with Read.read(), it would have a lock on a UQ_ACCEL_RESOURCE identifier, preventing the y-axis from sampling simultaneously, since its resource is also identified by UQ_ACCEL_RESOURCE. I wasn’t the only one with these problems, as illustrated by this TinyOS mailing list post. The mailing list poster also points out that the ReadStream interface blocks data sampling for all sensors but the first one that calls it: if you try using ReadStream to get streaming data for the accelerometer x-axis and the magnetometer x-axis, the call to ReadStream.read() for the accelerometer would block the sampling of the magnetometer if it was called first. With ReadStream, all sensors use the same resource identifier, so when one is sampling, it has the lock, and all others must wait. The resource arbitration effectively prevents multiple sensors from sampling data simultaneously using ReadStream.
This automated power control for Read as well as the blocking for Read and ReadStream really limits the functionality of the sensorboard. Initially, I thought it was a hardware constraint. You would think that since the board has all those sensors on it, the manufacturers would have designed it such that you can use all the sensors at the same time. It turns out, that it isn’t a hardware problem — it’s just that the MTS300/310 sensorboard code is written so you can only effectively use one sensor at a time. I managed to change this by modifiying the behavior of the Read.read() of every MTS sensor.
The current TinyOS code uses SplitControlPowerManagerC to power on the sensor when you call Read.read(). Read.read() triggers the power manager to call the sensor’s SplitControl interface. Supposedly, when Read.readDone() is signaled and the sensor data is ready, the power manager will keep the sensor powered on for some amount of time in case the sensor is needed again — this is from the comments in PowerManagerP.nc. However, from my testing, there is no evidence that the sensor stays on after Read.readDone() is signaled. The warm-up routine starts all over again the next time Read.read() is called. It’s possible that 20ms is too much time between samples, but it appears from the power manager code that the sensor is turned off immediately if no resource requests for that sensor are pending. Currently, I can’t find anywhere in the MTS310 sensorboard code or in the power manager code where some kind of backoff timer is set before powering down the sensor.
To that end, I eliminated this automated power control through the power manager. I altered each sensor’s interface in the mts300 code library so that each sensor provided a SplitControl interface. This now allows me to manually power on each sensor I want to use before I start sampling. I then have a timer call Read.read() at regular intervals for each sensor I want, which returns the data with Read.readDone(). When I’m done sampling, I can turn the sensors off.
The current code is more a less a hack and has a weird side effect. For example, since the x and y-axis accelerometers use the same AccelP module with the same SplitControl power interface, only one accelerometer has to call SplitControl.start() to turn the sensor on. The same goes for the magnetometer and the light/photo sensors, as well as for calling SplitControl.stop() to power down the sensors. Otherwise, the warm-up/power on sequence is triggered twice for the same sensor if you want to use both axes of the accelerometer or magnetometer, or wish to use both light and temperature sensors. Edit: this issue has been fixed in the code. Calling SplitControl.start() for both axes of the accelerometer/magnetometer will only run the power on sequence once, but both calls will return SplitControl.startDone(). The same applies for SplitControl.stop().
The modified sensorboard code can be downloaded here, which is a zipped directory of all the mts300 sensor code, but changed to mts310. Just unzip it into the tos/sensorboards directory. The configurations AccelXC, AccelYC, MagXC, MagYC, MicC, PhotoC, and TempC have all been modified to provide the SplitControl interface, so for example you can call AccelXC.start() to power on the accelerometer, then AccelXC.read() to get data, and then AccelXC.stop() to power the accelerometer off. I’ve used this extensively with the accelerometers, magnetometers, acoustic, and light sensors and it seems to work without any issues.
#1 by Rahul Sen on May 26, 2009 - 5:27 am
I want to know if you have used the magnetometer with tinyos 2.0 because i am not able to set the gain of magnetometer.
#2 by Matt on May 26, 2009 - 7:45 am
I did get the magnetometer to work, but I never bothered to set the gain. To get significant readings from it, I got best results using magnets.
#3 by Andreas H. on July 19, 2009 - 7:28 pm
Have you tried to read light/photo sensor and the temp sensor at one shot? After PhotoC.SplitControl.start() and TempC().SplitControl.start() the signal TempC.Read.ReadDone() never fires. Is it possible to use light/photo sensor and temp sensor at the same time, or have you to stop light sensor before you can read the temp sensor?
#4 by Matt on July 20, 2009 - 1:47 pm
From the Crossbow MTS Users Manual: “The light and temperature sensor share the same A/D converter channel (ADC1). Only turn one sensor on at a time, or the reading at ADC1 will be corrupted and meaningless.”
This is also reflected in the sensorboard code, so either only light or only temperature can be used at any given time. The currently active light or temperature sensor has to be turned off and the other turned on.