Feed on
Posts
Comments

Learn how to use the Pin Change Interrupt on the ATtiny85 to wake up the microcontroller from sleep. Using the Pin Change Interrupt you can use any of the ATtiny’s 6 pins however remember that all 6 will trigger the same interrupt vector PCINT0.

Download the sketch: insideGadgets_pin_change_v1

14 Responses to “How to use the Pin Change Interrupt on ATtiny85”

  1. Matt says:

    Hi Alex

    Thanks for your video tutorial! I am currently using an ATTiny85 to control an LED for a costume i have built (the terminator) I have designed the circuit to power up at 1/4 brightness and flash at a slow rate (as it does in T2 when Arnold is impaled & manages to re-route alt power) I then have the LED flashing at 2-3 times the rate and then stopping and coming on full brightness – like it does in the movie! That works fine and I am happy with that but I want to interrupt the circuit like what you have done via a micro switch to power the LED down say over 5secs? If i reset the ATTiny85 it just turns straight off which is NOT what I am after! Can this pin interrupt idea work? I was thinking i was almost going to have to do a capacitor type circuit to power the LED once the ATtiny85 was turned off but surely this can be achieved via the interrupt? If it works I can put pictures up!

    Thanks Matt

    • Alex says:

      Hi Matt,

      Yes it’s possible. From reading what you’ve said when the button is pressed you would like the LED to stay lit for over 5 seconds.

      From the example code above, copy both the #define and the setup code (change the pinmode as suits) to your own code.

      Then copy the interrupt part but in it, add what you would like it to do when interrupted, such as:
      ISR(PCINT0_vect) {
      digitalWrite(pinLed,HIGH);
      delay(5000);
      }

      After it does what you made it do in the interrupt, it will return back to where it got interrupted from.

      Alex.

  2. richard says:

    Hi,
    Is it also possible to execute differtent codes for falling or rising?
    e.g. if pin turns high: blink once.
    if pin turns low: blink twice?
    thans for your great tutorial.
    regards Richard

    • Alex says:

      Hi Richard,
      Yes you can execute different code if it goes high or low, all you need to do is when the interrupt occurs check whether the pin reads high or low.

      Example:
      ISR(PCINT0_vect) {
      if (PINB & (1<

  3. Richard says:

    Hi Alex,
    Thanks a lot for your reply! It really helped me a lot.
    Although i dont exacly understand what you mean with this:
    if (PINB & (1<
    i think there's something missing?
    I have accomplished it with digitalread:
    ISR(PCINT0_vect) {
    val = digitalRead(1); // read input value and store it in val
    if (val == LOW) {
    etc.

    That brings me to the next question.
    As i have read, it is possible to assign multiple pins as interrupt ( wakeup ) pins.
    Is it possible to:
    Use multiple interrupt pins at the same time, but execute different codes while waking up from different pins?
    E.g. If pin 0 changes
    ISR(PCINT0_vect) { // <- 0
    … pin 0 code
    }
    And if pin 1 changes
    ISR(PCINT1_vect) { // <- 1
    … pin 1 code
    }

    What i want is to have multiple input pins, while changing, read state ( low or high ) and execute different commands. So input pin 0 changes led 3 pin 1 changes led 4.

    I hope you'll understand my question and you can help me.

    Regards Richard

    • Alex says:

      Hi Richard, looks like wordpress stripped out the missing part but yes what you did was what I intended to say.

      In terms of having 1 different interrupt per pin, the ATtiny doesn’t support that, it has 1 interrupt for a couple of pins. The exception is the INT0 pin, this interrupt is dedicated to a special pin on the ATtiny. Another exception is if you choose an ATtiny84 or similar, you can have a maximum of 3 pin related interrupts.

      So the way to solve this as it is now is to check each pin’s state once the interrupt for all pins is triggered.

  4. Emmanuel says:

    Hi, great tutorial, many thanks.
    I’m trying to built what Richard (December 18, 2012 at 10:00 am) did, I mean to know if pin goes high or low and execute different code in each case but obviously I’m doing something wrong. Can you please help ? Thanks.
    Here is the code:

    int val =0;
    void setup(){
    pinMode(pinLed,OUTPUT);
    pinMode(1,INPUT);
    sbi(GIMSK,PCIE); // Turn on Pin Change interrupt
    sbi(PCMSK,PCINT1); // Which pins are affected by the interrupt
    }
    void loop(){
    system_sleep();
    }
    // From http://interface.khm.de/index.php/lab/experiments/sleep_watchdog_battery/
    void system_sleep() {
    cbi(ADCSRA,ADEN); // Switch Analog to Digital converter OFF
    set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode
    sleep_mode(); // System sleeps here
    sbi(ADCSRA,ADEN); // Switch Analog to Digital converter ON
    }
    ISR(PCINT0_vect) {
    val = digitalRead(1); // read input value and store it in val
    if (val == LOW) {
    digitalWrite(pinLed,HIGH);
    delay(1500);
    digitalWrite(pinLed,LOW);
    }
    else {
    digitalWrite(pinLed,HIGH);
    delay(1500);
    digitalWrite(pinLed,LOW);
    delay(1500);
    digitalWrite(pinLed,HIGH);
    delay(1500);
    digitalWrite(pinLed,LOW);
    }
    }

  5. Robert says:

    Hi – I can get your example to work, but if I use an internal pull-up resistor on the interrupt pin, then there is a significant current draw if that pin is grounded – the system sleeps but current flows through that pin to ground. If the pin is taken to VCC and left there, it’s not a problem – the current is negligible. If the pin is left to float, then there’s also a current draw.
    I would like to arrange it so that the pin can be taken to either VCC or ground and left there while the system sleeps, with the interrupt occurring if there’s then a change. How can I do this?
    Thank you

    • Alex says:

      Hi Robert,

      I don’t know if there is a perfect solution to take both VCC and GND to draw no current. The internal pull-up is 20-50K but if you disable that and use an external 1M resistor either as a pull up or pull down, then you current should only 5uA. You can keep going up in resistance but at some point it might become unstable/noisy.

  6. Robert says:

    Thanks I have only just seen your reply. I did solve it another way: if the interrupt takes the pin high then the first thing that happens after the interrupt is to write that pin high. The next interrupt takes it low, so then I write it low. I.e. The interrupts toggle the pin assignation. I’d post the code but it’s on another computer. I know it works though 🙂

  7. sasi says:

    how can in rest the counter using interrupt in attiny85

  8. beachlab says:

    Thank you, Alex! Your ten years old tutorial saved my day (and batteries)! Now I finally understand sleep mode and will use this knowledge extensively. Shoutout from Sweden!

  9. Andrés says:

    Hi Alex, I have a problem, do you know if the interruption can block the upload of a new code? Because now I can’t upload the new code to my attiny, and it says that I need to check if it is the correct chip or check conections. In the case it is true, is there any way to overcome this incovenient?

    • Alex says:

      Hi Andres, you should still be able to upload code because the ATtiny has a dedicated reset pin, once it goes low the chip will be ready to be re-programmed. If you have connections hooked up to SCK, MOSI, MISO in your circuit, then that could cause a problem

Leave a Reply to Richard