]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
Address possible dead zone discontinuities when reading in WindVaneReadP.
authorsmckown <smckown@4bc1554a-c7f2-4f65-a403-e0be01f0239c>
Mon, 9 Nov 2009 19:31:00 +0000 (19:31 +0000)
committerR. Steve McKown <rsmckown@gmail.com>
Tue, 1 Dec 2009 03:01:52 +0000 (20:01 -0700)
tos/platforms/tmirws/sensors/WindVaneReadC.nc
tos/platforms/tmirws/sensors/WindVaneReadP.nc

index 732db2640d909bfe931c1d43de9971ff93c7f77f..98c1bfeb0132bf1501ca8e9cd7851825d0081cc3 100644 (file)
@@ -53,9 +53,6 @@ implementation {
   WindVaneReadP.WPower -> HalWindVaneC.WPower;
   WindVaneReadP.WDead -> HalWindVaneC.WDead;
 
-  components new AverageAngleC(SAMPLES_PER_READ);
-  WindVaneReadP.Average -> AverageAngleC;
-
   components new StateC();
   WindVaneReadP.State -> StateC;
 }
index 4bbb1e383e81899697ca9d5d36708d8e22dbdc71..765668f6d16d55600cdd384d8192e16b133a4909 100644 (file)
@@ -29,7 +29,8 @@
  
 /**
  * Take an instantaneous reading of the wind vane position as a 10 bit unsigned
- * value.
+ * 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>
  */
@@ -41,7 +42,6 @@ generic module WindVaneReadP(uint16_t count) @safe()
     interface ReadRef<uint16_t>;
     interface GeneralIO as WPower;
     interface GeneralIO as WDead;
-    interface Average<uint16_t>;
     interface State;
   }
 }
@@ -56,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
@@ -65,9 +65,19 @@ implementation
      * within the dead zone, of course, but would be even if we did implement
      * the extra logic.
      */
-    DEAD_BEGIN = 1500,         /* 10-bit degree value; about 120 degrees */
-    DEAD_END = 2500,           /* About 220 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 */
   };
 
   uint16_t m_value;
@@ -94,49 +104,56 @@ implementation
     call WPower.clr();
 
     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);
   }
 
-  void averageAngle();
-
-  event void ReadRef.readDone(error_t error, uint16_t* result)
-  {
-    if (error != SUCCESS)
-      signalReadDone(error, 0);
-    else
-      averageAngle();
-  }
-
-  void averageAngle()
+  bool badReading(uint16_t* result)
   {
     unsigned i;
+    uint16_t min = result[0];
+    uint16_t max = result[0];
 
-    /* Submit a full set of values to be averaged, which will cause
-     * Average.average() to be signalled.
-     */
-    call Average.reset();
-    for (i = 0; i < count; i++)
-      call Average.submit(m_samples[i]);
+    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 Average.average(uint16_t result)
+  event void ReadRef.readDone(error_t error, uint16_t* result)
   {
-    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 ReadRef.read(m_samples) == SUCCESS)
-           call State.forceState(S_CHECK);
-         else
-           signalReadDone(FAIL, 0);
-       }
-       break;
-      case S_CHECK:
-       signalReadDone(SUCCESS, (result > DEAD_THRESH) ? 0 : m_value);
-       break;
+    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 (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;
+      }
     }
   } 
 }