Go Down

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

Danois90

Ugh.  I am just so tired of answering questions that are trivial to answer with Google.  @Danois90, do some research.  Nick Gammon's website is a great place to start.
And yet you answer anyway.. Please gimme some links instead of referring to Google as a reference :)
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!!

DKWatson

OP's ISR is text book, timestamp, set flag, get out. Test the flag and deal with it elsewhere. The flag is only set in the ISR and only cleared by whatever function processes it.
Live as if you were to die tomorrow. Learn as if you were to live forever. - Mahatma Gandhi

Danois90

OP's ISR is text book, timestamp, set flag, get out. Test the flag and deal with it elsewhere. The flag is only set in the ISR and only cleared by whatever function processes it.
The ISR does not respect the flag it sets, that ain't "text book" coding to me since the timestamp and flag may be changed during "processing elsewhere".
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!!

DKWatson

Don't know where you learned your coding but the function of an ISR is to acknowledge an event and get out, full stop. By disrupting global interrupts any longer than that you negatively impact the deterministic behaviour of a bare metal, real-time processor.
Live as if you were to die tomorrow. Learn as if you were to live forever. - Mahatma Gandhi

holmes4

Try matt black paint on the shaft!

I can't see why you are playing around with the code !

Mark

Danois90

Don't know where you learned your coding but the function of an ISR is to acknowledge an event and get out, full stop. By disrupting global interrupts any longer than that you negatively impact the deterministic behaviour of a bare metal, real-time processor.
The interrupt handler for timer0 overflow is just nothing like that, yet it works splendid :)
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!!

DKWatson

FYI @Danois90, Arduino is a development/hobby platform. In the real world, a.k.a. commercial systems, we don't have functions like setup and loop and millis or any other 'behind-the-scenes' libraries that detract from the purpose of the processor. All of the 'nice to have' features that make Arduino such an attractive learning experience are not relevant in a bare-metal production system. As stated, the OP's ISR is exactly as it should be. 0210 here, Goodnight.
Live as if you were to die tomorrow. Learn as if you were to live forever. - Mahatma Gandhi

Robin2

Thanks for all the inputs.

I guess I made a mistake by presenting the problem in the way I did in my Original Post - but in the interests of transparency I thought I should explain the project. The issue I have been hoping to get ideas about is how to detect the aberrant values among the data as presented in Reply #4.

At the moment I have been ignoring values that are less than 50% of the previous value. And I was wondering if there is a better idea.

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

DaleScott

I didn't see any posts with this so:

An Alpha beta filter can be used to make a running average.

Inside a loop.

    ...

  EstimateCurrent = Alpha*EstimateLast + Beta*measured_value

  EstimateLast = EstimateCurrent

   ...

where Alpha is defined as a number between 0 and 1 and Beta = Alpha -1.

An Alpha near 1 has a long time constant (Beta will be small, using less sample value).

If you start with a good number, and use an Alpha close to 1, the EstimateCurrent will not be perturbed much by the bad measurements.

Then test to see if new measured value is within a certain "acceptable region" of the EstimateCurrent.

Hope that's helpful.

westfw

Quote
Code: [Select]
8123 7990 7957 8011 3876 8001 7997

What is a clever way to detect and ignore the 3876?
Keep track of expected deviation (perhaps doing those calculations NOT in the ISR), and discard times that exceed the deviation.  Each time you discard a time, increase the expected deviation - if your "base" time has actually changed, you'll pick it up eventually.  For your example, you might calculate a running average of the accepted values (need not be perfect up-to-date), and set the expected deviation to (avg>>2)
If you're only concerned about "too small" aberrant values, you can have you code calculate a simple lower bound.


This is vaguely simillar to some of the techniques used in TCP implementations to try to measure accurate "Round Trip Time" for purposes of calculating a reasonable retransmission timeout.  You can find scholarly papers on that topic, occasionally containing efficient coding for doing the equivalent of standard deviation calculations...

holmes4

Quote
At the moment I have been ignoring values that are less than 50% of the previous value. And I was wondering if there is a better idea.
Yes there is - Find out whats causing the odd values and get rid of the cause.

If the cause is in software then we need to see the whole code or a complete program which shows the same symptoms. We also need a circuit diagram (not fritzing)  and in this case some good photos of your home brew hardware.

But the data values you gave are odd as the "false values" are not in pairs!

Mark

bidouilleelec

Hello Robin2

Quote
Any clever ideas for excluding aberrant values produced by an ISR?
Are you sure that   aberrant values are produced inside the ISR, not in the loop?

Quote
The code in loop() figures out the time interval between pulses.
Can't we see the loop?

Quote
I believe I have stated the case with sufficient clarity.
As long as we don't see the loop, we are in complete obscurity.

Regards,
bidouilleelec




Robin2

Are you sure that   aberrant values are produced inside the ISR, not in the loop?
Yes

Quote
Can't we see the loop?
That's going to require too much explanation and I am too lazy.

The only issue I wanted to get ideas about is how to detect an aberrant value in a stream of values of the type I posted in Reply #4


I agree that it would be nice to eliminate the problem rather than stick a band-aid on it but I have been unable to do that and unless somebody else has identical hardware to carry out tests I don't see any change in the situation.


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

Robin2

I eventually remembered that I had a much simpler program that just collects the results from 20 pulses and displays the results. This is an example of the output
Code: [Select]
===============         
PWM Val 200       
0  53452064  Diff 0       
1  53463976  Diff 11912       
2  53475856  Diff 11880       
3  53487712  Diff 11856       
4  53499560  Diff 11848       
5  53507368  Diff 7808       
6  53511432  Diff 4064       
7  53523328  Diff 11896       
8  53535200  Diff 11872       
9  53547040  Diff 11840       
10  53558864  Diff 11824       
11  53570720  Diff 11856       
12  53582592  Diff 11872       
13  53594464  Diff 11872       
14  53606296  Diff 11832       
15  53618128  Diff 11832       
16  53629968  Diff 11840       
17  53641840  Diff 11872       
18  53653720  Diff 11880       
19  53665568  Diff 11848


You will see there are inconsistent values on lines 5 and 6.

And this is the code that produced the data.
Code: [Select]
// python-build-start
// action, upload
// board, arduino:avr:lilypad:cpu=atmega328
// port, /dev/ttyUSB0
// ide, 1.6.3
// python-build-end

// arduino:avr:uno
// arduino:avr:lilypad:cpu=atmega328



#define ledPin A5
#define fwdPin 9
#define revPin 10

const byte potPin = A1;
int potVal;
int pwmVal;

const byte numVals = 20;
unsigned long revMicros[numVals];
byte revIndex = 0;
bool arrayFull = false;

volatile unsigned long isrMicros;
volatile bool newIsrMicros = false;



void setup() {
    Serial.begin(500000);
    Serial.println("RevPotTestB.ino");
    pinMode(ledPin, OUTPUT);
    pinMode (fwdPin, OUTPUT);
    pinMode (revPin, OUTPUT);
    for (byte n = 0; n < 3; n++) {
        digitalWrite(ledPin, LOW);
        delay(300);
        digitalWrite(ledPin, HIGH);
        delay(300);
    }

    attachInterrupt(0, revDetectorISR, RISING);
}

//==========

void loop() {
    readPot();
    getIsrData();
    if (arrayFull == true) {
        showData();
        delay(1000);
        revIndex = 0;
        arrayFull = false;
    }
}

//===========

 void readPot() {
     potVal = analogRead(potPin);
     pwmVal = potVal >> 2;

    digitalWrite(revPin,LOW);
    analogWrite(fwdPin, pwmVal);

 }

//===========

void getIsrData() {
    if (newIsrMicros == true and arrayFull == false) {
        noInterrupts();
            revMicros[revIndex] = isrMicros;
            newIsrMicros = false;
        interrupts();
        revIndex ++;
        if (revIndex >= numVals) {
            arrayFull = true;
        }
    }
}

//===========

void showData() {
    Serial.println();
    Serial.println("===============");
    Serial.print("PWM Val "); Serial.println(pwmVal);
    unsigned long prevMicros = revMicros[0];
    for (byte n = 0; n < numVals; n++) {
        Serial.print(n);
        Serial.print("  ");
        Serial.print(revMicros[n]);
        Serial.print("  Diff ");
        Serial.println(revMicros[n] - prevMicros);
        prevMicros = revMicros[n];
    }
}

//===========

void revDetectorISR() {
    isrMicros = micros();
    newIsrMicros = true;
}


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

westfw

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

Go Up