]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
Work in process to support Davis instruments aerovane (wind vane).
authorsmckown <smckown@4bc1554a-c7f2-4f65-a403-e0be01f0239c>
Mon, 2 Nov 2009 20:43:22 +0000 (20:43 +0000)
committerR. Steve McKown <rsmckown@gmail.com>
Tue, 1 Dec 2009 03:01:44 +0000 (20:01 -0700)
tos/platforms/tmirws/sensors/WindVaneAdcC.nc
tos/platforms/tmirws/sensors/WindVaneAdcP.nc
tos/platforms/tmirws/sensors/WindVaneC.nc
tos/platforms/tmirws/sensors/WindVaneP.nc

index 472f9ec7b2e50e519fd752e33a64c44128668b96..a659995b7672bab3389d16d7a44ed9799084df24 100644 (file)
  */
  
 /**
- * Reads the ADC pin connected to the LiPoly battery.  The connection is made
- * via a resistor divider where the battery voltage is 3x that read by the ADC.
- * Therefore, BattV = ADC / 4096 * 1.5 * 3.
+ * Reads the ADC pin connected to the Davis Instruments anemometer.  The
+ * connection is made via a resistor divider.  The voltage seen by the ADC
+ * is related to VREF, the maximum voltage presented to the ADC.
+ * 0V or VREF means North
+ * VREF*1/4 means East
+ * VREF*2/4 means South
+ * VREF*3/4 means West
+ *
+ * We assume a 12-bit ADC, so VREF reads as 4095 and 0V reads as 0.
  * 
  * @author R. Steve McKown <rsmckown@gmail.com>
  */
  
-generic configuration BatteryAdcC() {
+generic configuration WindVaneAdcC() {
   provides interface Read<uint16_t>;
   provides interface ReadStream<uint16_t>;
 
@@ -49,13 +55,13 @@ implementation {
   components new AdcReadStreamClientC();
   ReadStream = AdcReadStreamClientC;
 
-  components BatteryAdcP;
-  AdcReadClientC.AdcConfigure -> BatteryAdcP;
-  AdcReadStreamClientC.AdcConfigure -> BatteryAdcP;
+  components WindVaneAdcP;
+  AdcReadClientC.AdcConfigure -> WindVaneAdcP;
+  AdcReadStreamClientC.AdcConfigure -> WindVaneAdcP;
 
   components new AdcReadNowClientC();
   Resource = AdcReadNowClientC;
   ReadNow = AdcReadNowClientC;
   
-  AdcReadNowClientC.AdcConfigure -> BatteryAdcP;
+  AdcReadNowClientC.AdcConfigure -> WindVaneAdcP;
 }
index a80362bad34021a7db41aea82dacd40b86718b44..b4e920548f8fad9033361f9b099ee767a18b46eb 100644 (file)
  */
  
 /**
- * Battery ADC reading.
+ * Reads the ADC pin connected to the Davis Instruments anemometer.  The
+ * connection is made via a resistor divider.  The voltage seen by the ADC
+ * is related to VREF, the maximum voltage presented to the ADC.
+ * 0V or VREF means North
+ * VREF*1/4 means East
+ * VREF*2/4 means South
+ * VREF*3/4 means West
+ *
+ * We assume a 12-bit ADC, so VREF reads as 4095 and 0V reads as 0.
  * 
  * @author R. Steve McKown <rsmckown@gmail.com>
  */
  
 #include "Msp430Adc12.h"
 
-module BatteryAdcP {
+module WindVaneAdcP {
   provides interface AdcConfigure<const msp430adc12_channel_config_t*>;
 }
 implementation {
@@ -43,7 +51,7 @@ implementation {
    * jumping around.  The external reference of 2.50V seems stable.
    */
   const msp430adc12_channel_config_t config = {
-      inch: INPUT_CHANNEL_A0,
+      inch: INPUT_CHANNEL_A0, // A2
 #if 0 /* internal references unstable */
       sref: REFERENCE_VREFplus_AVss,
       ref2_5v: REFVOLT_LEVEL_1_5, /* REFVOLT_LEVEL_2_5, */
index 1ce247fac65f795c57e5680419146df21b5fdbef..2c317596ee7d2e63a9779adbd8b9226294d06af6 100644 (file)
@@ -45,6 +45,6 @@ implementation {
   components SoftwareRtcC as RtcC;
   WindVaneP.Second -> RtcC;
 
-  components HalWindVaneC;
-  WindVaneP.Vane -> HalWindVaneC.AsyncGet;
+  components new WindVaneAdcC();
+  WindVaneP.Vane -> WindVaneAdcC.Read;
 }
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;