Go Down

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

#### urthlight

##### Feb 04, 2013, 10:36 pm
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

#1
##### Feb 04, 2013, 11:13 pm
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 pmLast 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

#3
##### Feb 04, 2013, 11:22 pm
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

#4
##### Feb 04, 2013, 11:26 pm
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 pmLast 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

#6
##### Feb 05, 2013, 02:46 pm
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

#7
##### Feb 05, 2013, 03:06 pm
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

#8
##### Feb 05, 2013, 03:30 pm
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;  }}`
Don't PM me for help as I will ignore it.

#### UKHeliBob

#9
##### Feb 05, 2013, 03:31 pm
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