]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/platforms/tmirws/sensors/WindVaneP.nc
Work in process to support Davis instruments aerovane (wind vane).
[tinyos-2.x.git] / tos / platforms / tmirws / sensors / WindVaneP.nc
index a6976e951ef646011dc62fc67ad0e2eb50d17462..4042470e241704a7d22fbc33c91024bbd508bf6c 100644 (file)
@@ -39,11 +39,17 @@ module WindVaneP {
   provides interface ReadRef<wind_vane_t>;
   uses {
     interface Tick as Second;
-    interface AsyncGet<uint8_t> as Vane;
+    interface Read<uint16_t> as Vane;
   }
 }
 implementation {
-#define COMPASS_COUNT  32
+  enum {
+    /* Compass count should ideally be a power of 2, or at least even */
+    COMPASS_COUNT = 36,
+    ADC_PER_HEADING = (4096 + COMPASS_COUNT - 1) / COMPASS_COUNT,
+    ADC_OFFSET = (ADC_PER_HEADING + 1) / 2,
+    ADC_BITMASK = 0x0fff,
+  };
 
   wind_vane_t* m_data;
   /* compass[0] = North, 0 degrees,
@@ -156,22 +162,26 @@ implementation {
 
   /*** Method implementations ***/
 
+  task void startRead()
+  {
+    call Vane.read();
+  }
 
   async event void Second.fired()
   {
-    const static uint8_t lookup[] = {
-      0x01, 0x03, 0x02, 0x06, 0x04, 0x0c, 0x08, 0x18,
-      0x10, 0x30, 0x20, 0x60, 0x40, 0xc0, 0x80, 0x81
-    };
-    uint8_t wind;
-    uint8_t i = 0;
-
-    wind = call Vane.get();
-    for (i = 0; i < sizeof(lookup); i++) {
-      if (lookup[i] == wind) {
-       compass[i]++;
-       return;
-      }
+    post startRead();
+  }
+
+  event void Vane.readDone(error_t error, uint16_t value)
+  {
+    if (error == SUCCESS) {
+      /* Convert the adc value (0...4095) to a compass heading
+       * (0...COMPASS_COUNT - 1).
+       */
+      value = (value + ADC_OFFSET) / ADC_PER_HEADING;
+      while (value >= COMPASS_COUNT)
+       value -= COMPASS_COUNT;
+      compass[value]++;
     }
   }
 
@@ -213,10 +223,12 @@ implementation {
 
       /* m_data's left, avg and right fields are currently represented in
        * compass positions.  We must now convert those fields into units of
-       * angular degrees.
+       * angular degrees.  The order of calculations is to maximize precision
+       * using integer arithmetic.  Note that using a 16-bit unsigned field
+       * for calculations, the largest value of COMPASS_COUNT is 37.
        */
-      m_data->left = 1800U / COMPASS_COUNT * m_data->left / 10;
-      m_data->right = 1800U / COMPASS_COUNT * m_data->right / 10;
+      m_data->left = 1800U * m_data->left / COMPASS_COUNT / 10;
+      m_data->right = 1800U * m_data->right / COMPASS_COUNT / 10;
     }
 
     m_data = 0;