Go Down

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


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.
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.

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.

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.

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.

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.

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


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.


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.


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) {
  // Do other stuff

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


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