Go Down

Topic: Averaging Digital input. (Read 620 times) previous topic - next topic

urthlight

I have a digital input that is 0 volts when dry and 5 volts when wet. I have it showing in my software. Every now and then I get a false wet or dry. I think what I want to do is average the input after a hundred samples or so. What would be the proper way of doing this?

Shpaget

Write the values in an array, sum them all up and divide by the number of measurements. Round the result.

UKHeliBob

#2
Feb 04, 2013, 11:18 pm Last Edit: Feb 04, 2013, 11:20 pm by UKHeliBob Reason: 1
The best thing would be to find out why the false readings happen and eliminate the problem.

No need to average the readings.  If you cannot prevent the false readings then you could, perhaps, take 100 readings, adding each to a running total and if the total is not zero or 100 then discard that set, otherwise regard the set as valid and record/display the value as wet or dry as appropriate.  How often are the readings taken ?
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Arrch

You could also utilize a debounce to ensure that the reading is only valid if it's been that way for X # of milli/microseconds.

billroy

Another simple filter for a isolated spikes is to require a data value change to be presented for two or three readings before believing it.

"Tell me once, tell me twice; what you tell me three times I believe is true."

(Edit: You could say this is a way to implement Arrch's proposal.)

-br

urthlight

#5
Feb 05, 2013, 02:32 pm Last Edit: Feb 05, 2013, 02:42 pm by urthlight Reason: 1
This is one of the final hurdles before taking this to Beta test. So time is of the essence.
Quote
Write the values in an array, sum them all up and divide by the number of measurements. Round the result.

This looks like a good avenue and the least to learn.


Quote
The best thing would be to find out why the false readings happen and eliminate the problem.

I have only seen one false bit of data, and I may have caused it. However I don't want this device kicking out over a bit of noise.
Quote

No need to average the readings.  If you cannot prevent the false readings then you could, perhaps, take 100 readings, adding each to a running total and if the total is not zero or 100 then discard that set, otherwise regard the set as valid and record/display the value as wet or dry as appropriate.

The logic is to check if the tank is wet before filling ( not empty ) If wet redirect to manual drain, so the culling process would not need to be so severe. This is mainly a safety to prevent overflow.
Quote

How often are the readings taken ?

Right now in the main loop. I am only using it for filling but I might want it in other states also like  draining, abort fill and such.

Quote
You could also utilize a debounce to ensure that the reading is only valid if it's been that way for X # of milli/microseconds.

This is where I started and soon got frustrated.
Creative juices running low at this time.

Quote
Another simple filter for a isolated spikes is to require a data value change to be presented for two or three readings before believing it.

"Tell me once, tell me twice; what you tell me three times I believe is true."

(Edit: You could say this is a way to implement Arrch's proposal.)


This is a viable approach but more like tell me 50 times that you are wet I will act.
And I guess it would work pretty much the same if dry

urthlight

Any code snippets would be greatly appreciated as it has been a long project burning the candle at work and at home and I now am having trouble braining anymore.

Arrch

There is a debounce example that you should take a look at. It pretty much does exactly what you need, you just have to define the interval.

Riva

This is untested code but maybe something like this? The last 16 times (unsigned int) through the loop must match for reading to count as high or low. You could maybe use unsigned long if the loop is tight so you need 32 matching readings or byte for only 8 readings.

Code: [Select]
unsigned int readBits = 0;

void loop(){
  readBits = readBits << 1;
  if (digitalRead(WetDry) == HIGH) {
    bitSet(readBits,0);
  }
  // Do other stuff

  switch (readBits) {
    case 0xFFFF:
    // Set
      break;
    case 0x0:
    // Clear
      break;
    case default:
    // Not valid (do nothing)
      break;
  }
}

UKHeliBob

Untested code, but you will see the idea
Code: [Select]
int levelTotal = 0;
for (int level = 0;level <= 99;level++)
{
 //code here to get sensorReading (0 or 1)
 levelTotal = levelTotal + sensorReading;
}
if {levelTotal != 100)
{
  Serial.println("The tank is not wet");
}

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Go Up