ATtiny85 attachInterrupt

In the following code, the fading of the LED works fine. When /LOCK goes low, the LED goes out, as it should. However, It doesn't seem as if the interrupt to blink the LED is working. I am a bit confused as to the proper designation for the INT0 pin. It is digital pin 2 (physical pin 7), but examples I see of attachInterrupt all use the "0" designator, indicating INT0. Which is correct?

BTW, I have this breadboarded up for testing. It is not connected to the rubidium yet. I am simulating the inputs with alligator clips to 5V or GND, as appropriate.

I'm using 1.6.0 RC1.

// Use an ATtiny85 to control an LED based on inputs from an FE-5680A rubidium frequency reference.
//
// To support ATtiny in the Arduino IDE, I used the following with 1.6.0 RC1:
// http://www.leonardomiliani.com/en/2014/aggiornato-il-core-attiny-per-lide-1-5-8-di-arduino/
//
// I found the LED fade routine on the Arduino Forum.
//
// December 2014 by Joseph Gray W5JG
//
// Inputs:
//    Pin INT0 (physical pin 7) = PPS from rubidium. 1 uS pulse. May need a pulse stretcher to reliably see this
//              every time. This pin may need a pulldown resistor to keep the input from floating. 10 K should work.
//    Pin 3 (physical pin 2) = /LOCK from rubidium.  Goes LOW when locked. Use the internal pullup resistor.
// Outputs:
//    Pin 1 (physical pin 6) = PWM to LED. Don't forget a current limiting resistor. 1 K or so is good.
//
// This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

const byte ppsPin = 0;					// INT0 pin.
const byte lockPin = 3;					// Digital I/O pin.
const byte ledPin = 1;					// One of two PWM pins on the ATtiny85.
const int period = 3000;                // Three second fade interval.

boolean isr = false;					// Flag to tell us if the ISR is enabled.
int value;                              // Value to PWM LED with.
long time = 0;                          // Holds milliseconds since program start.

void setup() {
    pinMode(ppsPin, INPUT);             // PPS from rubidium.
    pinMode(lockPin, INPUT_PULLUP);     // /LOCK from rubidium.
    pinMode(ledPin, OUTPUT);            // PWM to LED.
}

void loop() {
    while(digitalRead(lockPin) == HIGH){                    // Fade LED in/out while the rubidium is warming up.
		if (isr == true){
			detachInterrupt(ppsPin);						// Disable ISR if we don't have lock. Fade LED instead of blink.
		}
        time = millis();                                    // Get the current time since program start.
        value = 128 + 127 * cos(2 * PI / period * time);    // Using cosine gives smoother fade.
                                                            // Circular function does fade in/out.
        analogWrite(ledPin, value);                         // Sets PWM value from 0 to 255.
    }

// Rubidium has lock, so stop fading LED.

    digitalWrite(ledPin, LOW);                              // Turn LED off.

	if (isr == false){										// Setup ISR to detect PPS.
		attachInterrupt(ppsPin, blinkLED, RISING);			// Interrupt on rising edge of PPS.
		isr = true;											// Set flag so we know we have enabled the ISR.
	}
}

void blinkLED() {
	digitalWrite(ledPin, HIGH);								// Turn the LED on.
	delayMicroseconds(500000);								// This is usable inside the ISR.
	digitalWrite(ledPin, LOW);								// Turn the LED off.
}
	delayMicroseconds(500000);								// This is usable inside the ISR.

Usable, but stupid. An ISR is supposed to be FAST. delayAnything() is NOT.

If all you were going to do was call me stupid, and not help, why did you bother replying? Did it make you feel superior?

The reason I put the delay in there was to make sure I could see the LED blink. I'll make it work "better" later. I'm just trying to get the damn ISR working. Is that OK with you?

Also, the ISR does nothing but blink the LED. Once the LOCK goes low, there is no other code that is run. I tried doing the PPS thing in a loop, but it isn't fast enough to catch each PPS. So, I thought I'd try the ISR because it might catch all of them.

This is why I always hesitate to post, asking for help on forums. There is always someone like you.

Joe

1 Like

The reason I put the delay in there was to make sure I could see the LED blink. I'll make it work "better" later. I'm just trying to get the damn ISR working. Is that OK with you?

No. You should do it right from the beginning.

OK, to avoid any more comments on my "stupid" demo code, I changed it to the following. It still seems that the ISR is not working.

const byte ppsPin = 0; // INT0 pin.
const byte lockPin = 3; // Digital I/O pin.
const byte ledPin = 1; // One of two PWM pins on the ATtiny85.
const int period = 3000;                // Three second fade interval.

volatile boolean pps = false;           // Flag to tell use that the PPS went high.
boolean isr = false; // Flag to tell us if the ISR is enabled.
int value;                              // Value to PWM LED with.
long time = 0;                          // Holds milliseconds since program start.

void setup() {
    pinMode(ppsPin, INPUT);             // PPS from rubidium.
    pinMode(lockPin, INPUT_PULLUP);     // /LOCK from rubidium.
    pinMode(ledPin, OUTPUT);            // PWM to LED.
}

void loop() {
    while(digitalRead(lockPin) == HIGH){                    // Fade LED in/out while the rubidium is warming up.
 if (isr == true){
 detachInterrupt(ppsPin); // Disable ISR if we don't have lock. Fade LED instead of blink.
 }
        time = millis();                                    // Get the current time since program start.
        value = 128 + 127 * cos(2 * PI / period * time);    // Using cosine gives smoother fade.
                                                            // Circular function does fade in/out.
        analogWrite(ledPin, value);                         // Sets PWM value from 0 to 255.
    }

// Rubidium has lock, so stop fading LED.

    if(isr == true){
        if(pps == true){
            pps = false;                                    // Reset flag.
            digitalWrite(ledPin, HIGH);                     // Turn LED on.
            delay(200);
        }
    }

    digitalWrite(ledPin, LOW);                              // Turn LED off.

 if (isr == false){ // Setup ISR to detect PPS.
 attachInterrupt(ppsPin, blinkLED, RISING); // Interrupt on rising edge of PPS.
 isr = true; // Set flag so we know we have enabled the ISR.
 }
}

void blinkLED() {
    pps = true;                                             // Just set a flag to indicate PPS, then return from ISR.
}

PaulS:
No. You should do it right from the beginning.

OK, I get it. I should stop feeding the Troll.

If anyone else would like to offer some help or suggestions, please do.

It is digital pin 2 (physical pin 7), but examples I see of attachInterrupt all use the "0" designator, indicating INT0. Which is correct?

Zero for INT0.

const byte ppsPin = 0;					// INT0 pin.

I have always seen physical pin 7 / PB2 / INT0 assigned pin number 2 not pin number 0.

void loop() {
...
			detachInterrupt(ppsPin);
...
attachInterrupt(ppsPin, blinkLED, RISING);
}

...nearly always creates a race condition (nasty bug). Unless you have a reason to be doing that, attachInterrupt should be called once in setup and detachInterrupt should never be called.


Until you are more experienced with interrupts I suggest you first try building your code without them. Once you have that (polling) working then try using interrupts.