arendst / Tasmota

Alternative firmware for ESP8266 and ESP32 based devices with easy configuration using webUI, OTA updates, automation using timers or rules, expandability and entirely local control over MQTT, HTTP, Serial or KNX. Full documentation at
https://tasmota.github.io/docs
GNU General Public License v3.0
21.97k stars 4.77k forks source link

How to Take Median Value for Ultrasonic Sensor HC-SR04 #3727

Closed asking23 closed 5 years ago

asking23 commented 6 years ago

Hi,

I have been using Tasmota 6.2.0 and its working great... But when i interface JSN-SR04T it works great until in between it switch from 82CM to Directly 92CM or 62CM randomely inbetween. I know its Module issue. But for Ultrasonics continous measurement we use Median Value to Get Stable Reading.

How we can implement median reading with Tasmota firmware ? for Sensor Readings... from last 10 values it will consider the Median Value and Provide output. So output will be stable...

Please consider it as addon / Enchancement if already not implemented.

ascillato commented 6 years ago

What should be better, median or average in this case?

asking23 commented 6 years ago

For intermittent fluctuations in value, Median is best. Level measurement applications Ultrasonic sensors use Median Value. Stable output is available with median value.

gerardovf commented 5 years ago

_P128_HCSR04_M.txt I use this in EspEasy to calculate median with a HC-SR04 ultrasonic sensor...

andrethomas commented 5 years ago

Will explore the option to set in the driver or user_config.h which method is required - ordered some sensors which arrived today so maybe over the weekend, I will look at adding it to Tasmota.

This is why we have not yet closed this issue - pending development ;)

andrethomas commented 5 years ago

I've implemented a rolling buffer of 5 samples, then sort them and pick sample no 3 as the used value... so in theory, this should work but I still get some random values from time to time.

andrethomas commented 5 years ago

Actually, if one looks at the existing code it already does what is requested.

  /* Send ping and get delay */
  duration = Sr04GetSamples(9, 250);
uint16_t Sr04GetSamples(uint8_t it, uint16_t max_cm_distance)
{
  uint16_t uS[it];
  uint16_t last;
  uint8_t j;
  uint8_t i = 0;
  uint16_t t;
  uS[0] = 0;

  while (i < it) {
    t = micros();
    last = Sr04Ping(max_cm_distance);

    if (last != 0) {
      if (i > 0) {
        for (j = i; j > 0 && uS[j - 1] < last; j--) {
          uS[j] = uS[j - 1];
        }
      } else {
        j = 0;
      }
      uS[j] = last;
      i++;
    } else {
      it--;
    }
    if (i < it && micros() - t < PING_MEDIAN_DELAY) {
      delay((PING_MEDIAN_DELAY + t - micros()) / 1000);
    }
  }

  return (uS[1]); // Return the ping distance from the 2nd highest reading
}

It's just that it returns the second highest reading and not the midpoint/median.

Changing this does not solve erratic readings from time to time so most likely has to do with the hardware rather than the software approach.

Any takers on this?

andrethomas commented 5 years ago

I've explored a number of different approaches to try and solve this problem but due to the lack of consistent data from the sensor you would need many multitudes of readings to get an average - using median did not yield any useful results from my testing.

I suggest development time rather be spent on more accurate sensors such as VL53L0X Time-of-Flight sensors.

@arendst @ascillato I'm not willing to invest more development time in this cheap module and propose we shelf this one in view that there are better and smaller sensors out there.

arendst commented 5 years ago

Agree.

ascillato commented 5 years ago

Agree