From 108ff439d63ddb1413efe5e9830392bab56e001b Mon Sep 17 00:00:00 2001 From: smckown Date: Mon, 2 Nov 2009 20:43:22 +0000 Subject: [PATCH] Work in process to support Davis instruments aerovane (wind vane). --- tos/platforms/tmirws/sensors/WindVaneAdcC.nc | 22 +++++---- tos/platforms/tmirws/sensors/WindVaneAdcP.nc | 14 ++++-- tos/platforms/tmirws/sensors/WindVaneC.nc | 4 +- tos/platforms/tmirws/sensors/WindVaneP.nc | 48 ++++++++++++-------- 4 files changed, 57 insertions(+), 31 deletions(-) diff --git a/tos/platforms/tmirws/sensors/WindVaneAdcC.nc b/tos/platforms/tmirws/sensors/WindVaneAdcC.nc index 472f9ec7..a659995b 100644 --- a/tos/platforms/tmirws/sensors/WindVaneAdcC.nc +++ b/tos/platforms/tmirws/sensors/WindVaneAdcC.nc @@ -28,14 +28,20 @@ */ /** - * 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 */ -generic configuration BatteryAdcC() { +generic configuration WindVaneAdcC() { provides interface Read; provides interface ReadStream; @@ -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; } diff --git a/tos/platforms/tmirws/sensors/WindVaneAdcP.nc b/tos/platforms/tmirws/sensors/WindVaneAdcP.nc index a80362ba..b4e92054 100644 --- a/tos/platforms/tmirws/sensors/WindVaneAdcP.nc +++ b/tos/platforms/tmirws/sensors/WindVaneAdcP.nc @@ -28,14 +28,22 @@ */ /** - * 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 */ #include "Msp430Adc12.h" -module BatteryAdcP { +module WindVaneAdcP { provides interface AdcConfigure; } 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, */ diff --git a/tos/platforms/tmirws/sensors/WindVaneC.nc b/tos/platforms/tmirws/sensors/WindVaneC.nc index 1ce247fa..2c317596 100644 --- a/tos/platforms/tmirws/sensors/WindVaneC.nc +++ b/tos/platforms/tmirws/sensors/WindVaneC.nc @@ -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; } diff --git a/tos/platforms/tmirws/sensors/WindVaneP.nc b/tos/platforms/tmirws/sensors/WindVaneP.nc index a6976e95..4042470e 100644 --- a/tos/platforms/tmirws/sensors/WindVaneP.nc +++ b/tos/platforms/tmirws/sensors/WindVaneP.nc @@ -39,11 +39,17 @@ module WindVaneP { provides interface ReadRef; uses { interface Tick as Second; - interface AsyncGet as Vane; + interface Read 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; -- 2.39.2