]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/platforms/tmirws/sensors/WindVaneReadP.nc
Address possible dead zone discontinuities when reading in WindVaneReadP.
[tinyos-2.x.git] / tos / platforms / tmirws / sensors / WindVaneReadP.nc
index 69d97c978c23d8abd97fd8fa555802f02bcc49df..765668f6d16d55600cdd384d8192e16b133a4909 100644 (file)
  */
  
 /**
- * Take an instantaneous reading of the wind vane position.
+ * Take an instantaneous reading of the wind vane position as a 10 bit unsigned
+ * value.  In this case, the instantaneous reading is 4 very fast 12-bit samples
+ * plus the possibility of an additional four to deal with the dead band.
  * 
  * @author R. Steve McKown <smckown@gmail.com>
  */
  
-module WindVaneReadP @safe()
+generic module WindVaneReadP(uint16_t count) @safe()
 {
   provides interface Read<uint16_t>;
   uses {
-    interface Get<uint16_t> as Count;
-    interface Read<uint16_t> as SubRead;
+    interface ReadRef<uint16_t>;
     interface GeneralIO as WPower;
     interface GeneralIO as WDead;
     interface State;
@@ -55,7 +56,7 @@ implementation
     /* The wind vane has a dead zone where it returns an ADC value that also
      * represents another angular location.  Therefore, we implement special
      * dead zone checking over a certain range of return values from the
-     * wind vane.
+     * wind vane, with hardware assistance (WDead).
      *
      * Note: the wind vane's dead zone is probably 5-10 degrees.  We would be
      * more accurate if we took the ADC range over 350 or 355 degrees, then
@@ -64,12 +65,23 @@ implementation
      * within the dead zone, of course, but would be even if we did implement
      * the extra logic.
      */
-    DEAD_BEGIN = 6000,         /* 4 12-bit ADC readings; about 120 degrees */
-    DEAD_END = 10000,          /* About 198 degrees */
-    DEAD_THRESH = 14472,       /* > when checking means in dead zone */
+    DEAD_BEGIN = 1500 * count, /* About 132 degrees */
+    DEAD_END = 2500 * count,   /* About 220 degrees */
+    DEAD_THRESH = 3618 * count,        /* > when checking means in dead zone */
+
+    /* If we assume the greatest angular velocity of the wind vane is 4 full
+     * rotations in a second, then in the 460us it takes to read the vane 4
+     * times, it could move over 6 degrees.  This means that the vane could
+     * cross into, out of, or over the dead band, causing readings that can
+     * not be averaged.  If we see a delta from min reading to max reading
+     * suggesting a large enough deflection, we can assume the reading is
+     * invalid.
+     */
+    MAX_DEFLECT = 1024,                /* 90 degrees */
   };
 
-  char m_msg[80];
+  uint16_t m_value;
+  uint16_t m_samples[count];
 
   command error_t Read.read()
   {
@@ -77,7 +89,7 @@ implementation
       return EBUSY;
 
     call WPower.set();
-    if (call SubRead.read() == SUCCESS) {
+    if (call ReadRef.read(m_samples) == SUCCESS) {
       call State.forceState(S_READ);
       return SUCCESS;
     } else {
@@ -91,44 +103,57 @@ implementation
     call WDead.makeInput();
     call WPower.clr();
 
-    /* Value is the sum of multiple 12-bit ADC acquisitions, per the attached
-     * MultiSampleC component.  Convert the value to degrees.  Note, the values
-     * 360 and 0 (zero) represent the same angular position.  We don't do a
-     * modulus operation here because we fully expect the client will do
-     * additional processing that will likely involve a modulus function anyway.
-     */
-    value = (uint16_t)(((uint32_t)(value / call Count.get()) * 360 + 2047) /
-       4096);
-
     call State.toIdle();
+    /* Read has returned a value that is count * 12-bit ADC values.  Convert
+     * this to a 10-bit value, with rounding.
+     */
+    value = (value + (count / 2)) / count / 4;
     signal Read.readDone(error, value);
   }
 
-  event void SubRead.readDone(error_t error, uint16_t result)
+  bool badReading(uint16_t* result)
   {
-    static uint16_t m_value;
+    unsigned i;
+    uint16_t min = result[0];
+    uint16_t max = result[0];
 
-    if (error != SUCCESS) {
-      signalReadDone(error, 0);
-      return;
+    for (i = 1; i < count; i++) {
+      if (result[i] < min)
+       min = result[i];
+      if (result[i] > max)
+       max = result[i];
     }
+    return (max - min) > MAX_DEFLECT;
+  }
+
+  event void ReadRef.readDone(error_t error, uint16_t* result)
+  {
+    if (error != SUCCESS || badReading(result))
+      signalReadDone(error, 0);
+    else {
+      unsigned i;
+      uint16_t value = result[0];
+
+      for (i = 1; i < count; i++)
+       value += result[i];
 
-    switch (call State.getState()) {
-      case S_READ:
-       if (result < DEAD_BEGIN || result > DEAD_END)
-         signalReadDone(SUCCESS, result);
-       else {
-         m_value = result;
-         call WDead.makeOutput();
-         if (call SubRead.read() == SUCCESS)
-           call State.forceState(S_CHECK);
-         else
-           signalReadDone(FAIL, 0);
-       }
-       break;
-      case S_CHECK:
-       signalReadDone(SUCCESS, (result > DEAD_THRESH) ? 0 : m_value);
-       break;
+      switch (call State.getState()) {
+       case S_READ:
+         if (value < DEAD_BEGIN || value > DEAD_END)
+           signalReadDone(SUCCESS, value);
+         else {
+           m_value = value;
+           call WDead.makeOutput();
+           if (call ReadRef.read(m_samples) == SUCCESS)
+             call State.forceState(S_CHECK);
+           else
+             signalReadDone(FAIL, 0);
+         }
+         break;
+       case S_CHECK:
+         signalReadDone(SUCCESS, (value > DEAD_THRESH) ? 0 : m_value);
+         break;
+      }
     }
   } 
 }