Obtaining the average of 10 readings

I’m using the code below to take 10 consecutive readings from a sensor, spaced 10ms apart, and output the average of the readings.
It works fine, except on rare occasions, the sensor fails to provide a reading, but as the divisor is hard coded, it will divide the sum of 9 samples by 10, giving an incorrect output reading.

Is there a better way to either ensure that I have 10 samples, or better still to ensure that the divisor matches the number of samples, ie divide 9 samples by 9, instead of 10.

int sval;
int ival;

 // Read sensor level
  int readSensor2(){
  int i;
  sval = 0;
  ival = 0;
  for (i = 0; i < 10; i++){
    ival = analogRead(analogPin);
    sval = sval + ival;
    delay (10);
  }
  return (sval/10);
}

except on rare occasions, the sensor fails to provide a reading,

I don't see how that would be possible for analogRead(). Please describe the situation in which this happens, and provide some evidence that no "reading" was obtained.

Always post ALL your code, using code tags. The above example fails to provide important information, like how you declared ival and sval.

Perhaps you meant

unsigned int readSensor2(){
  unsigned int sval = 0;
  for (int i = 0; i < 10; i++){
    sval += analogRead(analogPin);
    delay (10);
  }
  return sval / 10;
}

Please describe the situation in which this happens, and provide some evidence that no "reading" was obtained.

Doing the maths has guided me to that conclusion. Usually the readings are around 700 each (10 x 700), and on occasion when an abnormal output reading is noticed, the output reading would be around 630.
Although the output readings are taken every 1 minute, any changes occur slowly, so I can get a good idea what the reading should be by looking at the reading before, and after the abnormal reading.

Code tags added.

how you declared ival and sval.

Added to 1st post

Perhaps you meant

Yes, unsigned int would be more appropriate, and your coding is much cleaner, thanks.

Your evidence suggests that readings are always returned (as expected), but on occasion, one value in ten might be zero instead of 700.

Such abnormal readings can be caused by a faulty connection, or glitches in the source that you are monitoring. Best to print out all readings, wiggle wires, etc. until you find out what the real problem is.

If the problem persists, it is certainly possible to ignore readings that are clearly out of range, using something like the following:

#define min_acceptable 500
unsigned int readSensor2(){
  unsigned int sval = 0, numval = 0, temp = 0;
  for (int i = 0; i < 10; i++){
   temp=analogRead(analogPin);
  if (temp > min_acceptable) {
     numval++;
     sval += temp; 
     }
    delay (10);
  }
  if (numval > 0) return sval / numval;
  return 0;
}

Yes that sounds good. I can adapt that, thanks.

I assume if (numval > 0) return sval / numval;
should be;

 if (numval >= 10) return sval / numval;

Paul

The if condition (numval > 0) is correct.

If readings are ever rejected, there won't be ten of them, and if all are rejected there will be none, in which case you do not want to divide by zero.

Don't reject a bad value, immediately re-read it. Then all the counts are valid. The more often
you get errors, the longer the loop will take to complete.

Just wondering, why take 10 readings? A round value like 8 or 16 means you can get your average with a simple bit shift (2-3 bytes of compiled code) instead of a division (hundreds of bytes, much slower).

jremington - I've had chance today to look through and add your code, and it works great! exactly what I wanted. Thank you.

MarkT - Yes, that would work ok, but I only get bad readings maybe 2 or 3 a week, and dropping the the bad reading so I average 9 instead of 10 is not a big problem and won't significantly affect accuracy.

wvmarie - remember your talking to a newbie!! I had a read up on 'simple bit shifts' earlier, and they are anything but!
I'd prefer to use code which I understand, and bit shifts are out of my comfort zone. But thanks for the suggestion.

One quick question though, what does return 0; actually return. Does it return the number 0 (if 0 is a number??) or does it return null?
(hopefully nothing at all)

what does return 0; actually return

The value "0", in the unlikely event of no valid readings.

pauldreed:
*wvmarie* - remember your talking to a newbie!! I had a read up on 'simple bit shifts' earlier, and they are anything but!
I'd prefer to use code which I understand, and bit shifts are out of my comfort zone. But thanks for the suggestion.

Bits and powers of 2 are at the core of computing, and you'll encounter this more. Choosing your variable type is one such points, choose the wrong type and weird things may happen.

avg = total / 8;
avg = total >> 3;

are the exact same when avg and total are integers, but the second is more efficient.

but the second is more efficient

...and is probably what the compiler will implement when you write the first.

True. Seems to be the case in my very limited testing indeed.
Maybe time to try out the difference between the calculation of val / 8 and val / 10. Should be simple, but I don't have a compiler at hand.