ISR within ISR - possible crash due to non-global ISR executable

I have two interrupt pins on my Mega 2560 used for tracking the position and displacement of my motor encoder. I added a button-triggered interrupt for capturing RGB values of fluids (using the TCS230 sensor). When I pressed the button, I was able to successfully capture RGB values without interrupt the other timers in my loop() (even though the RGB values were completely off, didn't matter).

I have now been writing a procedure layout using the MD_TCS320.h library for the color sensor. I tested it on another, brand new Mega 2560 (using delay(250) as my timer, no button-triggering ISR). Everything went well, and the RGB values were on the dime (credit to the guy who made the library).

The MD_TCS320.h library uses another library, FreqCounter.h, which uses its own interrupt to output on pin 47 (which really isn't a specific interrupt pin as noted in the documentation for Mega 2560.) It also mentions that "Pins Unusable with analogWrite()" are 9,10,44,45,46. I am using all of them for other purposes (LCD particularly).

So....the problem. When I combine all of these functions with my original Mega 2560, and press the button for the ISR routine of "snap-shooting" an RGB value (which seems to me to be an interrupt within an interrupt), my Serial monitor freezes and so does my LCD....I don't think the Arduino can handle that much. (For the record, I commented out all Serial.print() functions and the result was still the same.)

I also have a temperature monitoring system that continuously runs in the loop() function...so that's another load.

Any ideas as to why this happens? Should I explicitly attach an interrupt to pin 47? Or is there too much going on?

I assume a code problem but without code that's all I can assume...

But an interrupt for a button is just overkill / bad program design :wink:

I'd have to provide the entire library for you then at that point. In terms of the code I wrote (and the wiring I did) I don't see anything wrong (I will continue to check over it all now, nonetheless.)

The reason why I'm using a button for an interrupt is because the main portion of the system is to use PID looping to regulate temperature. The secondary control is fraction collection - using a stepper motor with an ISR-controlled encoder to rotate a 12 or 20 vial carousel. The third minor control is display to the LCD.

The fourth and final control (which, with regards to how this system will be used by customers) is the fluid detector...which doesn't actually do anything until a user requests to find out what fluid is in a vial. So, they press a button and the color sensor would capture the frequencies and output a fluid based on the readings.

When separate from the rest, the button ISR works well. When combined...a disaster.

For what I just described, how would I get my color sensor to work (based on user input) without the button ISR functionality?

lennon-pledge:
I'd have to provide the entire library for you then at that point.

A link is the least you could do :wink:

lennon-pledge:
In terms of the code I wrote (and the wiring I did) I don't see anything wrong (I will continue to check over it all now, nonetheless.)

Then that's that then. That just leaves, PEBKEC, the Russians and the CIA MI5 I guess...

lennon-pledge:
The reason why I'm using a button for an interrupt is because the main portion of the system is to use PID looping to regulate temperature. The secondary control is fraction collection - using a stepper motor with an ISR-controlled encoder to rotate a 12 or 20 vial carousel. The third minor control is display to the LCD.

So? The button is still a very very slow process compared to the rest :slight_smile:

Right (insert daft-looking "I'm-an-imbecile" yellow face here)! Here's the link for the MD_TCS230.h and FreqCounter.h libraries, respectively:

The .cpp and .h in MD_TCS230 are in the src folder. Look in the util folder in FreqCounter for the bit operations performed on the ATMega2560 chip.

Looks like I'm part of MI7 :grinning: , cause nothing in the code/hardware seems out of place (again, it all worked in separate components...fusing them together didn't change the code, and the hardware was just 8 extra pins to attach...all of which are accounted for.)

And just cause I'm new to this and want to keep pressing, why is the button a slow process? Any alternative suggestions for non-timer-based trigger operations for color sensor? Grazie

Here's my colorSnap() function (the ISR from the button).

void colorSnap()
{
    buttonTime = millis();
    if (buttonTime - lastButtonTime > 1500) {
        // noInterrupts();
        char *fluid;
        // Serial.println("There");
        strcpy(fluid, colorMatcher());
        lcd.setCursor(13,1);
        lcd.print("   ");
        lcd.setCursor(13,1);
        if (fluid == "Saline") lcd.print("Sal");
        else if (fluid == "Blood") lcd.print("Blo");
        else lcd.print("Unk");
        lastButtonTime = buttonTime;
        // Serial.println("and back again");
        // interrupts();
}

So prevent debouncing with the timer. Then I run this method inside the ISR called colorMatcher() which goes through the whole finite-state machine of reading and obtaining an rgb value. What gets returned is the char string either Saline, Blood, White or Black (which is just unknown). Then print to LCD. Straightforward, and I don't know if this helps at all.

The milis() function is frozen inside an ISR, the value it returns never changes.

Printing from serial inside an ISR is not a good idea because you can jam up the system because the buffer can never empty and LCD printing takes a long time.

In short the code is simply a disaster as your concept of an interrupt seems flawed. You do not want to use an interrupt but you want to implement these functions as a state machine.

why is the button a slow process

The switch is NOT a slow process. The human that presses the switch is ssslllooowww compared to how quickly an Arduino COULD read the switch.

The Arduino could read the state of the switch, if there is no blocking code, hundreds of thousands of times while the user taps the switch.

Given that, if you are a few nanoseconds late reading the switch the lumbering slow human will still be fat-fingering the switch.

  • Grumpy_Mike - I figured the code just created a paradox of ideas...interrupt with a state machine. Originally I wanted to use a constantly analyzed if statement in my main loop - has the state of the button changed?. And if it has, run the code you see in the ISR. If that's the best way to check this condition of a human taking a color sample then I'll write it. I just figured always running the if statement would be unnecessary. Although I didn't know the millis() could freeze up in the ISR. Note taken. I was also thinking of interfacing the color snapshots through a LabView button...when it's clicked, a signal via SPI is sent to a buffer in the Mega...if it can act as a slave.

  • PaulS- Something I figured as well, but didn't think it was all too important because of the millis() delay to prevent debouncing. Seeing as all of that in an ISR is terrible, I'm scratching it all.