]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
Update WindVaneC to use newer underlying code.
authorsmckown <smckown@4bc1554a-c7f2-4f65-a403-e0be01f0239c>
Wed, 4 Nov 2009 03:55:06 +0000 (03:55 +0000)
committerR. Steve McKown <rsmckown@gmail.com>
Tue, 1 Dec 2009 03:01:46 +0000 (20:01 -0700)
Wind directions are returned as sectors; use the sector count available by
call Sectors.get() to convert to degrees.  Doing this saves some memory.

tos/platforms/tmirws/sensors/WindVane.h
tos/platforms/tmirws/sensors/WindVaneC.nc
tos/platforms/tmirws/sensors/WindVaneP.nc

index 20afde750e17203abb35a48f4cf8b0a93f1e5367..70c51ef61d7e06d7b2e290a634b16354bf848320 100644 (file)
@@ -36,7 +36,8 @@
 #ifndef WIND_VANE_H
 #define WIND_VANE_H
 
-#define WINDVANE_NO_HEADING    255
+#define WINDVANE_OVERFLOW      255
+#define WINDVANE_NO_HEADING    254
 
 /* Units are degrees/2, so 90 degrees is 45 units.  This allows a full
  * circle of degrees to be represented in a single byte.  Resolution reduction
index 883021f72e61977ebc0df79f1428b649c91d5a3e..7da5c9a63bba12824f68dac4f752a312569ad5e9 100644 (file)
  */
  
 /**
- * WindVane sensor
+ * WindVane sensor.  The compass is a number of sectors, 0...(sectors - 1).
+ * sectors must be a power of 2.  Sector zero is North, and sectors/2 is South.
+ * Like any compass, the heading increases as one traverses the compass
+ * clockwise.  The number of sectors are contrained by the uint8_t data members
+ * of wind_vane_t to 128.
  * 
  * @author R. Steve McKown <rsmckown@gmail.com>
  */
  
 #include "WindVane.h"
 
-configuration WindVaneC {
-  provides interface ReadRef<wind_vane_t>;
+generic configuration WindVaneC(uint8_t sectors) {
+  provides {
+    interface Get<uint8_t> as Sectors;
+    interface ReadRef<wind_vane_t>;
+  }
 }
 implementation {
-  components WindVaneP;
+  components new WindVaneP(sectors);
+  Sectors = WindVaneP;
   ReadRef = WindVaneP;
 
   components SoftwareRtcC as RtcC;
   WindVaneP.Second -> RtcC;
 
-  components new WindVaneAdcC();
-  WindVaneP.Vane -> WindVaneAdcC.Read;
-
-  components HalWindVaneC;
-  WindVaneP.WPower -> HalWindVaneC;
+  components WindVaneReadC;
+  WindVaneP.Vane -> WindVaneReadC.Read;
 }
index f9907c8eee4b9a20c5f22c88744b1885d1b9cd56..ef1543c42d9f4ff8b2086f1843ff453a3b79b832 100644 (file)
  */
  
 /**
- * WindVane sensor
+ * WindVane sensor.  The compass is a number of sectors, 0...(sectors - 1).
+ * sectors must be a power of 2.  Sector zero is North, and sectors/2 is South.
+ * Like any compass, the heading increases as one traverses the compass
+ * clockwise.  The number of sectors are contrained by the uint8_t data members
+ * of wind_vane_t to 128.
  * 
  * @author R. Steve McKown <rsmckown@gmail.com>
  */
  
 #include "WindVane.h"
 
-module WindVaneP {
-  provides interface ReadRef<wind_vane_t>;
+generic module WindVaneP(uint8_t sectors) {
+  provides {
+    interface Get<uint8_t> as Sectors;
+    interface ReadRef<wind_vane_t>;
+  }
   uses {
-    interface Tick as Second;
     interface Read<uint16_t> as Vane;
-    interface GeneralIO as WPower;
+    interface Tick as Second;
   }
 }
 implementation {
-  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,
-  };
-
+  uint16_t m_compass[sectors];
+  bool m_overflow;
   wind_vane_t* m_data;
-  /* compass[0] = North, 0 degrees,
-   * compass(COMPASS_COUNT/2) = South, 180 degrees.
-   */
-  uint16_t compass[COMPASS_COUNT];
 
 
   /*** Support functions ***/
 
 
-  /* return the number of positions clockwise along the compass from start
-   * to end.
+  /* Convert a sector number into a degree heading.  We use the degree value
+   * that is in the center of the sector to represent that sector.  For example,
+   * with 32 sectors, each sector is 11.25 degrees.  Sector 4 represents all
+   * degree headings between 39.375 and 50.624 and is represented on the whole
+   * the degree heading of 45 degrees.
    */
+  uint16_t sectorToDegree(uint8_t sector)
+  {
+    return (360.0 / sectors) * sector;
+  }
+
+  /* Convert a degree heading into a sector */
+  uint16_t degreeToSector(uint16_t degree)
+  {
+    return ((degree * sectors + 180) / 360) % 32;
+  }
+
+  /* Return the # of sectors clockwise along the compass from start to end.  */
   uint8_t distance(uint8_t start, uint8_t end)
   {
-    return (end > start) ? end - start : (end + COMPASS_COUNT) - start;
+    return (end > start) ? end - start : (end + sectors) - start;
   }
 
-  /* circularly examine compass, starting with pos+1, for the next compass
+  /* circularly examine compass, starting with pos + 1, for the next compass
    * position having a value of zero.
    */
-  uint8_t nextNonZero(uint16_t* tc, uint8_t pos)
+  uint8_t nextNonZero(uint16_t* compass, uint8_t pos)
   {
     do {
-      pos = (pos + 1) % COMPASS_COUNT;
-    } while (tc[pos] == 0);
+      pos = (pos + 1) % sectors;
+    } while (compass[pos] == 0);
     return pos;
   }
 
-  bool isCompassEmpty(uint16_t* tc)
+  bool isCompassEmpty(uint16_t* compass)
   {
     int i;
 
-    for (i = 0; i < COMPASS_COUNT; i++) {
-      if (tc[i])
+    for (i = 0; i < sectors; i++) {
+      if (compass[i])
        break;
     }
-    return (i == COMPASS_COUNT) ? TRUE : FALSE;
+    return (i == sectors) ? TRUE : FALSE;
   }
 
   /* Reduce all compass headings equally until a compass heading has a value
    * of zero.
    */
-  void minimizeCompass(uint16_t* tc)
+  void minimizeCompass(uint16_t* compass)
   {
     uint8_t min = 255;
     int i;
 
-    for (i = 0; i < COMPASS_COUNT; i++) {
-      if (tc[i] < min)
-       min = tc[i];
+    for (i = 0; i < sectors; i++) {
+      if (compass[i] < min)
+       min = compass[i];
     }
     if (min > 0) {
-      for (i = 0; i < COMPASS_COUNT; i++)
-       tc[i] -= min;
+      for (i = 0; i < sectors; i++)
+       compass[i] -= min;
     }
   }
 
-  /* Locate the arc in which the compass[] has been constrained, defining
+  /* Locate the arc in which the m_compass[] has been constrained, defining
    * that arc in m_data's left and right fields.  The compass arc is always
    * defined clockwise, from left to right.
    */
-  void findArc(uint16_t* tc)
+  void findArc(uint16_t* compass)
   {
     uint8_t begin;
     uint8_t save = 255;
     uint8_t dist = 0;
 
-    begin = m_data->left = nextNonZero(tc, COMPASS_COUNT - 1);
+    begin = m_data->left = nextNonZero(compass, sectors - 1);
     do {
       uint8_t d;
 
-      m_data->right = nextNonZero(tc, m_data->left);
+      m_data->right = nextNonZero(compass, m_data->left);
       d = distance(m_data->left, m_data->right);
       if (d > dist) {
        dist = d;
@@ -133,39 +144,37 @@ implementation {
       m_data->left = m_data->right;
     } while (m_data->left != begin);
     m_data->right = save;
-    m_data->left = (save + dist) % COMPASS_COUNT;
+    m_data->left = (save + dist) % sectors;
   }
 
-  void calcAvg(uint16_t* tc)
+  void calcAvg(uint16_t* compass)
   {
     /* Find the average compass heading */
     uint32_t sum = 0;
     uint32_t count = 0;
     uint32_t tmp = (m_data->right >= m_data->left) ? m_data->right :
-       m_data->right + COMPASS_COUNT;
+       m_data->right + sectors;
     int i;
 
     for (i = m_data->left; i <= tmp; i++) {
-      uint8_t p = i % COMPASS_COUNT;
+      uint8_t p = i % sectors;
 
-      sum += tc[p] * i;
-      count += tc[p];
+      sum += compass[p] * i;
+      count += compass[p];
     }
-    /* Reduce the sum by whole compass arcs, since only the remaining
-     * partial arc is of relevance.
-     */
-    tmp = COMPASS_COUNT * count;
-    while (sum >= tmp)
-      sum -= tmp;
-    m_data->avg = (sum == 0) ? 0 : (1800 / COMPASS_COUNT) * sum / count / 10;
+    m_data->avg = ((sum + count - 1) / count) % sectors;
   }
 
 
   /*** Method implementations ***/
 
+  command uint8_t Sectors.get()
+  {
+    return sectors;
+  }
+
   task void startRead()
   {
-    call WPower.set();
     call Vane.read();
   }
 
@@ -176,15 +185,9 @@ implementation {
 
   event void Vane.readDone(error_t error, uint16_t value)
   {
-    //call WPower.clr();
     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]++;
+      if (++m_compass[degreeToSector(value)] == 0)
+       m_overflow = TRUE;
     }
   }
 
@@ -205,36 +208,35 @@ implementation {
 
   task void readCompass()
   {
-    uint16_t tc[COMPASS_COUNT];
+    bool overflow;
+    uint16_t compass[sectors];
     wind_vane_t* data = m_data;
 
     atomic {
-      memcpy(tc, compass, sizeof(compass));
-      memset(compass, 0, sizeof(compass));
+      overflow = m_overflow;
+      m_overflow = FALSE;
+      if (!overflow)
+       memcpy(compass, m_compass, sizeof(m_compass));
+      memset(m_compass, 0, sizeof(m_compass));
     }
 
-    minimizeCompass(tc);
-    if (isCompassEmpty(tc)) {
-      /* If there were no readings in the compass, or each compass heading has
-       * a number of readings equal to all other compass headings, we have an
-       * indeterminate wind direction.
-       */
-      m_data->left = m_data->avg = m_data->right = WINDVANE_NO_HEADING;
-    } else {
-      findArc(tc);
-      calcAvg(tc);
-
-      /* 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.  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 * m_data->left / COMPASS_COUNT / 10;
-      m_data->right = 1800U * m_data->right / COMPASS_COUNT / 10;
-    }
+    if (overflow)
+      m_data->left = m_data->avg = m_data->right = WINDVANE_OVERFLOW;
+    else {
+      minimizeCompass(compass);
+      if (isCompassEmpty(compass)) {
+       /* If there were no readings in the compass, or each compass heading has
+        * a number of readings equal to all other compass headings, we have an
+        * indeterminate wind direction.
+        */
+       m_data->left = m_data->avg = m_data->right = WINDVANE_NO_HEADING;
+      } else {
+       findArc(compass);
+       calcAvg(compass);
+      }
 
-    m_data = 0;
-    signal ReadRef.readDone(SUCCESS, data);
+      m_data = 0;
+      signal ReadRef.readDone(SUCCESS, data);
+    }
   }
 }