Go Down

Topic: Any clever ideas for excluding aberrant values produced by an ISR? (Read 3048 times) previous topic - next topic

Robin2

Have you by chance tried to set your ISR to trigger on FALLING instead of RISING?
Yes, tried that.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Danois90

This is an efficient and low memory approach of using an average to dismiss readings / values which deviate by more than average / 8. The caveat is that the base of calculations has to be initialized to a constant value or set by performing some readings in setup():

Code: [Select]
#define SHIFT_DIVISOR 3 //Equal to value / 8
#define AVERAGE_DEFAULT 11500 //The usual average reading
unsigned long goodReadings = AVERAGE_DEFAULT << SHIFT_DIVISOR;

void initGoodReadings()
{
  //Initialize to actual readings
  uint8_t readings = 1;
  goodReadings = getInterval(); //getInterval() must be created
  while (readings < (1 << SHIFT_DIVISOR))
  {
    unsigned int interval = getInterval();
    unsigned int average = goodReadings / readings;
    unsigned int margin = average >> SHIFT_DIVISOR;
    if ((interval > (average - margin)) && ((interval < (average + margin))))
    {
      goodReadings += interval;
      readings++;
    }
  }
}

bool isGoodReading(unsigned int interval)
{
  //Interval is supposed to be previousReading - currentReading
  unsigned int average = (goodReadings >> SHIFT_DIVISOR); //Average reading
  unsigned int margin = (average >> SHIFT_DIVISOR); //Allowed margin = Average / 8
  if ((interval > (average - margin)) && ((interval < (average + margin))))
  {
    //Good reading, subtract the average and add new reading
    //in order to allow the average to rise and fall
    goodReadings = goodReadings - average + interval;
    return true;
  }
  return false;
}


Should be pretty obvious how this works ;)
Instead of mocking what's wrong, teach what's right! ;)
When you get help, remember to thank the helper and give some karma!
Please, do NOT send me any private messages!!

Robin2

Initial tests suggest that the idea proposed by @arduarn in Reply #71 is both simple and effective - if an interval is less than the previous interval by more than X then replace the interval with the higher of the 2 previous intervals. Setting X at 25% of the previous interval seems to work nicely.

The "correct" interval can change at any time as the user alters the motor speed - but it won't change significantly from one rev to the next.

...R

PS ... even simpler - when an aberrant value is found in position N just replace it with the N-2 value. It is possible that the N-1 value is a "small" aberration that slipped under the radar but the N-2 value will always be OK.
That won't help because next time round the N-1 value (which may have been too low) will be in the N-2 position
Two or three hours spent thinking and reading documentation solves most programming problems.

bidouilleelec

Hello Robin2

You didn't show your harware schematic.

Have you tried to put a schmitt trigger between the QRE1113 and Arduino ?

Regards,
bidouilleelec

Robin2

Have you tried to but a scmitt trigger between the QRE1113 and Arduino ?
I did think of that a long time ago but I don't have space for one..

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

bidouilleelec

I did think of that a long time ago but I don't have space for one..

...R
Could you send photos and schematic of your realization?

Regards,
bidouilleelec

Robin2

Could you send photos and schematic of your realization?

I now consider that I have a satisfactory solution (see Reply #77) and I don't plan to prolong this.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

6v6gt

Edit: Just crossed with your "closure request"

You have go a long thread here. I guess some of this has has already been alluded to and may have missed it and you seem to have managed to avoid producing a wiring diagram up until now.

I'd look at hardware first to clean up the signal. I guess you have the sensor wired in a normal open collector configuration with the emitter at ground. Maybe make the pullup resistor stronger.
You've probably done the usual stuff to suppress noise from the motor (flywheel diode etc.)
I don't believe a capacitor would help with the sensor because of the range frequencies (period; 100,000 µsecs to 4,000 µsecs) . A capacitor value chosen to eliminate spurious readings at the lower frequencies would risk masking valid readings at higher frequencies.

At the software level, I believe you are wrong to rule out a moving type average solution. You can get an approximation by doing something like this:

newMovingAverage = oldMovingAverage * ( numberOfSamples-1 / numberOfSamples ) +  ( newValue / numberOfSamples)

which you can simplify with the number of samples fixed chosen depending on the acceleration/deceleration of the motor. Then start excluding out of range values as soon as you've read at least your chosen numberOfSamples.  If that is too computationally expensive, maybe simply hold the last few values in an array.


Robin2

You have go a long thread here. I guess some of this has has already been alluded to and may have missed it and you seem to have managed to avoid producing a wiring diagram up until now.
See Replies #68 and #69

If somebody else is prepared to do the experimenting and come up with a suitable circuit for more reliably detecting RPM with a QRE1113 reflective optical sensor I will certainly consider using that circuit.

But I am not prepared to waste any more of my own time on experiments.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

bidouilleelec

I now consider that I have a satisfactory solution (see Reply #77) and I don't plan to prolong this.

...R
I'm happy if you are happy.

Regards,
bidouilleelec

6v6gt

I know the OP has more or less given up on this, but I think that the topic could still be interesting

I didn't know about these QRE1113 devices until I saw this thread. I have an application which detects paper lying on a mat (in my mail box) and would probably have used these instead of the existing method (bouncing  modulated  IR beams from the base to the top and back to a TSOP device) and maybe these would have been better, so I have been now looking in some detail.

The data sheet is rather thin, but I believe that to use these QRE1113 devices optimally,  you have to modulate the power to the LED (say at 38 kHz) and use a small capacitor in series with the input pin on the Arduino. This would minimise the effect of ambient light. But, more importantly, the sketch would not then detect a single pulse, but bursts of a 38kHz signal and would be thus much less sensitive to the odd noise spike in such a burst.

Robin2

But, more importantly, the sketch would not then detect a single pulse, but bursts of a 38kHz signal and would be thus much less sensitive to the odd noise spike in such a burst.
I have not noticed any reference to modulation in the datasheet, but maybe someone with a lot more knowledge of electronics would infer that.

My sense is that using a pulsed signal would greatly reduce the precision of the timing because you would have to wait for several pulses to be sure that you had a solid detection.

I am using the simple circuit in this Sparkfun analogue circuit.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Go Up