Go Down

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

bidouilleelec

Hello Robin2

Code: [Select]
void revDetectorISR() {
    isrMicros = micros();
    newIsrMicros = true;
}


How can you be sure that isrMicros is not written by revDetectorISR() while you are executing
Code: [Select]
revMicros[revIndex] = isrMicros;

in getIsrData() ?

Regards,
bidouilleelec

Robin2

Code: [Select]
4  53499560  Diff 11848      
5  53507368  Diff 7808        
6  53511432  Diff 4064        
7  53523328  Diff 11896    


Interesting.  Do you always get two anomalous values in a row?  I notice that they sum to about the "correct" value...

Probably. Most times the small number is much smaller - for example 11,000  and 848 - and yes they usually sum to the correct value. However the low value does not always come after the large value.

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

Robin2

How can you be sure that isrMicros is not written by revDetectorISR() while you are executing
Because of
Code: [Select]
noInterrupts();

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

holmes4

If they are paired then it is a hardware problem!

Something like an extra "bright spot" on the shaft.

Mark

Robin2

If they are paired then it is a hardware problem!
That is my belief also. But I have not been able to find the cause. And I have a few different motor/sensor/Arduino devices that all behave the same.

There is only one pulse per revolution so the problem is not simply due to a bright spot.

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

bidouilleelec

Quote
Because of


noInterrupts();
Oups...   :smiley-confuse:  ::)
Thanks

bidouilleelec

holmes4

How about a small cap between the interrupt pin and ground (hardware debounce)

Mark

Danois90

As for the software end of things you could try this approach, just for the fun of it:

Code: [Select]
volatile unsigned long isrMicros;
volatile byte isrInternal = 0, isrCount;
volatile bool isrUpdated = false;

unsigned long lastMicros = 0, revMicros;

void loop()
{
  //Test if there is new data from ISR
  if (isrUpdated)
  {
    //Yes, isrCount is the number of interrupts that has occurred
    //in the period since last update, so we calculate micros per
    //revolution as:
    revMicros = (isrMicros - lastMicros) / isrCount;

    //Store isrMicros for next update
    lastMicros = isrMicros;

    //Allow the ISR to update data again
    isrUpdated = false;

    //From here it's just the usual business..
    Serial.print("revMicros = ");
    Serial.println(revMicros);
    //delay(100);
  }

}

void revDetectorISR()
{
  //Increment the interrupt internal counter to count how many
  //times the interrupt has happened
  isrInternal++;

  //If isrUpdated is true, the loop() has not yet handled the data
  //so the handler must not alter the data = exit / return
  if (isrUpdated) return;

  //If the loop() has handled the data (isrUpdated = false), then
  //add new data:

  //Microseconds as in you own ISR
  isrMicros = micros();

  //Transfer the counter to loop()
  isrCount = isrInternal;

  //Reset the counter to zero: Any value XOR itself = 0, the XOR
  //instruction is just faster than an assignment like: isrInternal = 0
  isrInternal ^= isrInternal;
 
  //Set isrUpdated to true to tell loop() there is new data
  isrUpdated = true;
}


This should ensure than nothing is missed, the low values might be caused by "a half dot registred" after interrupt attach.

For the hardware side of things you could try to stabilize the power supply of the sensor with a small cap - if it is not already done on a breakout board.

@Coding Badly: Please do not refer time critical code executed with interrupts disabled as a "critical sections" - because it is not. I critical section / mutex is a mechanism used in multi-threading environments and not in a single threaded Arduino. Since an interrupt (AFAIK) cannot halt an instruction and resume it again, you can protect variables shared between ISR's and the main loop without disabling interrupts. Disabling interrupts may cause sensor data to be (partially) lost, so if your code depends on data from an ISR it may not be a good idea to disable interrupts periodically.
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!!

lastchancename

You mentioned the dislike of a moving average - agreed.
But you could implement a low-overhead moving-margin filter to ignore values outside the desired range...?
Experienced responders have a nose for laziness, (they were beginners once)... Sure, there are trolls, chest-beaters, and pretenders - but the help you'll get here is about as good as it gets - if you try to help youself!.

Robin2

As for the software end of things you could try this approach, just for the fun of it:
I don't understand the code in your ISR

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

demkat1

You mentioned the dislike of a moving average - agreed.
But you could implement a low-overhead moving-margin filter to ignore values outside the desired range...?
+1

Danois90

I don't understand the code in your ISR

...R
I have added explanatory comments to the code :)
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

I have added explanatory comments to the code :)
Thanks for that. However I don't understand the purpose of counting the interrupts and dividing by the count.


Separately I did try a version of my code that prevented the value being saved if the previous value had not yet been read but (as expected) it made no difference. Even with a much faster motor there is oodles of time between pulses to do a PID calculation and collect wireless data. In the project I am working on at the moment there won't be any need for PID.

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

Coding Badly


What is the cost of ignoring one good value?

In other words, if you are given a simple solution that reliably ignores the bad values but also ignores one good value when a bad value is ignored, would you be pleased?  (e.g. values 5, 6, and 7 from post #28 would be ignored)


Robin2

What is the cost of ignoring one good value?
I don't think it would matter - what have you in mind?

And if it "knows" that values are being ignored it could substitute the most recent good value

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

Go Up