Mirror with some correction
Dependencies: mbed FastIO FastPWM USBDevice
Diff: main.cpp
- Revision:
- 69:cc5039284fac
- Parent:
- 67:c39e66c4e000
- Child:
- 70:9f58735a1732
--- a/main.cpp Sun Nov 27 23:20:51 2016 +0000 +++ b/main.cpp Wed Dec 28 23:32:38 2016 +0000 @@ -1968,7 +1968,7 @@ // logical state OFF to ON) toggles the current night mode state. if (cfg.nightMode.flags & 0x01) { - // toggle switch - when the button changes state, change + // on/off switch - when the button changes state, change // night mode to match the new state setNightMode(bs->logState); } @@ -3102,6 +3102,7 @@ switch (cfg.plunger.sensorType) { case PlungerType_TSL1410RS: + // TSL1410R, serial mode (all pixels read in one file) // pins are: SI, CLOCK, AO plungerSensor = new PlungerSensorTSL1410R( wirePinName(cfg.plunger.sensorPin[0]), @@ -3111,6 +3112,7 @@ break; case PlungerType_TSL1410RP: + // TSL1410R, parallel mode (each half-sensor's pixels read separately) // pins are: SI, CLOCK, AO1, AO2 plungerSensor = new PlungerSensorTSL1410R( wirePinName(cfg.plunger.sensorPin[0]), @@ -3119,7 +3121,8 @@ wirePinName(cfg.plunger.sensorPin[3])); break; - case PlungerType_TSL1412RS: + case PlungerType_TSL1412SS: + // TSL1412S, serial mode // pins are: SI, CLOCK, AO1, AO2 plungerSensor = new PlungerSensorTSL1412R( wirePinName(cfg.plunger.sensorPin[0]), @@ -3128,7 +3131,8 @@ NC); break; - case PlungerType_TSL1412RP: + case PlungerType_TSL1412SP: + // TSL1412S, parallel mode // pins are: SI, CLOCK, AO1, AO2 plungerSensor = new PlungerSensorTSL1412R( wirePinName(cfg.plunger.sensorPin[0]), @@ -3228,18 +3232,26 @@ PlungerReading r; if (plungerSensor->read(r)) { + // filter the raw sensor reading + applyPreFilter(r); + // Pull the previous reading from the history const PlungerReading &prv = nthHist(0); - // If the new reading is within 2ms of the previous reading, + // If the new reading is within 1ms of the previous reading, // ignore it. We require a minimum time between samples to // ensure that we have a usable amount of precision in the // denominator (the time interval) for calculating the plunger - // velocity. (The CCD sensor can't take readings faster than - // this anyway, but other sensor types, such as potentiometers, - // can, so we have to throttle the rate artifically in case - // we're using a fast sensor like that.) - if (uint32_t(r.t - prv.t) < 2000UL) + // velocity. The CCD sensor hardware takes about 2.5ms to + // read, so it will never be affected by this, but other sensor + // types don't all have the same hardware cycle time, so we need + // to throttle them artificially. E.g., the potentiometer only + // needs one ADC sample per reading, which only takes about 15us. + // We don't need to check which sensor type we have here; we + // just ignore readings until the minimum interval has passed, + // so if the sensor is already slower than this, we'll end up + // using all of its readings. + if (uint32_t(r.t - prv.t) < 1000UL) return; // check for calibration mode @@ -3534,8 +3546,8 @@ hist[histIdx++] = r; histIdx %= countof(hist); - // figure the filtered value - zf = applyFilter(); + // apply the post-processing filter + zf = applyPostFilter(); } } @@ -3573,6 +3585,7 @@ if (plungerSensor->read(r)) { // got a reading - use it as the initial zero point + applyPreFilter(r); cfg.plunger.cal.zero = r.pos; // use it as the starting point for the settling watch @@ -3611,9 +3624,91 @@ private: - // Figure the next filtered value. This applies the hysteresis - // filter to the last raw z value and returns the filtered result. - int applyFilter() +#if 1 + // Disable all filtering + void applyPreFilter(PlungerReading &r) { } + int applyPostFilter() { return z; } +#elif 1 + // Apply pre-processing filter. This filter is applied to the raw + // value coming off the sensor, before calibration or fire-event + // processing. + void applyPreFilter(PlungerReading &r) + { + // get the previous raw reading + PlungerReading prv = pre.raw; + + // the new reading is the previous raw reading next time, no + // matter how we end up filtering it + pre.raw = r; + + // If it's too big an excursion from the previous raw reading, + // ignore it and repeat the previous reported reading. This + // filters out anomalous spikes where we suddenly jump to a + // level that's too far away to be possible. Real plungers + // take about 60ms to travel the full distance when released, + // so assuming constant acceleration, the maximum realistic + // speed is about 2.200 distance units (on our 0..0xffff scale) + // per microsecond. + // + // On the other hand, if the new reading is too *close* to the + // previous reading, use the previous reported reading. This + // filters out jitter around a stationary position. + const float maxDist = 2.184f*uint32_t(r.t - prv.t); + const int minDist = 256; + const int delta = abs(r.pos - prv.pos); + if (maxDist > minDist && delta > maxDist) + { + // too big an excursion - discard this reading by reporting + // the last reported reading instead + r.pos = pre.reported; + } + else if (delta < minDist) + { + // too close to the prior reading - apply hysteresis + r.pos = pre.reported; + } + else + { + // the reading is in range - keep it, and remember it as + // the last reported reading + pre.reported = r.pos; + } + } + + // pre-filter data + struct PreFilterData { + PreFilterData() + : reported(0) + { + raw.t = 0; + raw.pos = 0; + } + PlungerReading raw; // previous raw sensor reading + int reported; // previous reported reading + } pre; + + + // Apply the post-processing filter. This filter is applied after + // the fire-event processing. In the past, this used hysteresis to + // try to smooth out jittering readings for a stationary plunger. + // We've switched to a different approach that massages the readings + // coming off the sensor before + int applyPostFilter() + { + return z; + } +#else + // Apply pre-processing filter. This filter is applied to the raw + // value coming off the sensor, before calibration or fire-event + // processing. + void applyPreFilter(PlungerReading &r) + { + } + + // Figure the next post-processing filtered value. This applies a + // hysteresis filter to the last raw z value and returns the + // filtered result. + int applyPostFilter() { if (firing <= 1) { @@ -3649,7 +3744,7 @@ } else { - // we're diretionless - return the new average, with the + // we're directionless - return the new average, with the // new sample included filterSum += z; ++filterN; @@ -3665,6 +3760,7 @@ return z; } } +#endif void initFilter() {