From c9c913f02451e45b41c74dec562d35f21a2960a5 Mon Sep 17 00:00:00 2001 From: smckown Date: Mon, 9 Nov 2009 19:31:00 +0000 Subject: [PATCH] Address possible dead zone discontinuities when reading in WindVaneReadP. --- tos/platforms/tmirws/sensors/WindVaneReadC.nc | 3 - tos/platforms/tmirws/sensors/WindVaneReadP.nc | 97 +++++++++++-------- 2 files changed, 57 insertions(+), 43 deletions(-) diff --git a/tos/platforms/tmirws/sensors/WindVaneReadC.nc b/tos/platforms/tmirws/sensors/WindVaneReadC.nc index 732db264..98c1bfeb 100644 --- a/tos/platforms/tmirws/sensors/WindVaneReadC.nc +++ b/tos/platforms/tmirws/sensors/WindVaneReadC.nc @@ -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; } diff --git a/tos/platforms/tmirws/sensors/WindVaneReadP.nc b/tos/platforms/tmirws/sensors/WindVaneReadP.nc index 4bbb1e38..765668f6 100644 --- a/tos/platforms/tmirws/sensors/WindVaneReadP.nc +++ b/tos/platforms/tmirws/sensors/WindVaneReadP.nc @@ -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 */ @@ -41,7 +42,6 @@ generic module WindVaneReadP(uint16_t count) @safe() interface ReadRef; interface GeneralIO as WPower; interface GeneralIO as WDead; - interface Average; 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; + } } } } -- 2.39.2