X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=tos%2Fplatforms%2Ftmirws%2Fsensors%2FWindVaneReadP.nc;h=765668f6d16d55600cdd384d8192e16b133a4909;hb=c9c913f02451e45b41c74dec562d35f21a2960a5;hp=3b10041ca4437a862b6108acdb1b22776733fd16;hpb=8ad250df7cb573906e00c173e512d539261874de;p=tinyos-2.x.git diff --git a/tos/platforms/tmirws/sensors/WindVaneReadP.nc b/tos/platforms/tmirws/sensors/WindVaneReadP.nc index 3b10041c..765668f6 100644 --- a/tos/platforms/tmirws/sensors/WindVaneReadP.nc +++ b/tos/platforms/tmirws/sensors/WindVaneReadP.nc @@ -28,17 +28,18 @@ */ /** - * Take an instantaneous reading of the wind vane position. + * Take an instantaneous reading of the wind vane position as a 10 bit unsigned + * 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 */ -module WindVaneReadP @safe() +generic module WindVaneReadP(uint16_t count) @safe() { provides interface Read; uses { - interface Get as Count; - interface Read as SubRead; + interface ReadRef; interface GeneralIO as WPower; interface GeneralIO as WDead; interface State; @@ -55,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 @@ -64,12 +65,23 @@ implementation * within the dead zone, of course, but would be even if we did implement * the extra logic. */ - DEAD_BEGIN = 6000, /* 4 12-bit ADC readings; about 120 degrees */ - DEAD_END = 10000, /* 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 */ }; - char m_msg[80]; + uint16_t m_value; + uint16_t m_samples[count]; command error_t Read.read() { @@ -77,7 +89,7 @@ implementation return EBUSY; call WPower.set(); - if (call SubRead.read() == SUCCESS) { + if (call ReadRef.read(m_samples) == SUCCESS) { call State.forceState(S_READ); return SUCCESS; } else { @@ -91,44 +103,57 @@ implementation call WDead.makeInput(); call WPower.clr(); - /* Value is the sum of multiple 12-bit ADC acquisitions, per the attached - * MultiSampleC component. Convert the value to degrees. Note, the values - * 360 and 0 (zero) represent the same angular position. We don't do a - * modulus operation here because we fully expect the client will do - * additional processing that will likely involve a modulus function anyway. - */ - value = (uint16_t)(((uint32_t)(value / call Count.get()) * 360 + 2047) / - 4096); - 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); } - event void SubRead.readDone(error_t error, uint16_t result) + bool badReading(uint16_t* result) { - static uint16_t m_value; + unsigned i; + uint16_t min = result[0]; + uint16_t max = result[0]; - if (error != SUCCESS) { - signalReadDone(error, 0); - return; + 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 ReadRef.readDone(error_t error, uint16_t* result) + { + 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 (result < DEAD_BEGIN || result > DEAD_END) - signalReadDone(SUCCESS, result); - else { - m_value = result; - call WDead.makeOutput(); - if (call SubRead.read() == SUCCESS) - call State.forceState(S_CHECK); - else - signalReadDone(FAIL, 0); - } - break; - case S_CHECK: - signalReadDone(SUCCESS, (result > DEAD_THRESH) ? 0 : m_value); - break; + 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; + } } } }