4

I am using an Arduino Uno with the Arduino as ISP sketch to program an ATtiny85.

I followed this tutorial to set up to program the ATtiny, and successfully got it to run Blink and an interrupt-free version of my program.

I then added an interrupt triggered by a button and got it working on the Arduino Uno (with a software debounce in the ISR). Now I want to run that sketch, with appropriate pin changes, on the ATtiny. Which pins correspond to which interrupt IDs for attachInterrupt()?

Or can I not use attachInterrupt()? If I can't, how do I do set up an interrupt on an ATtiny85?

7
  • attiny is kind of a piece of crap. Get arduino-tiny instead. Aug 26, 2014 at 4:26
  • 2
    @IgnacioVazquez-Abrams attiny is kind of a piece of crap. I assume you refer to the device? If that is the case then how does an Arduino core change anything? The "instead" statement is what confuses me.
    – alexan_e
    Aug 26, 2014 at 6:44
  • 1
    No I think Ignacio refers to the attiny library that is referenced by the tutorial.
    – jfpoilpret
    Aug 26, 2014 at 8:03
  • I am indeed talking about the extension module for the IDE. Aug 26, 2014 at 12:43
  • In arduino-tiny you can use the constant EXTERNAL_INTERRUPT_0 for INT0 at physical pin 7
    – Gerben
    Aug 26, 2014 at 15:45

1 Answer 1

5

You can setup interrupts on the Attiny with some different code, but it works the same way. It's important to note that PIN Change Interrupts are triggered at BOTH Rising and Falling Edge

Pins: enter image description here

Using the Arduino-Tiny Cores

Below is a sample code which used a Pin Change Interrupt on PB1 which switches an LED on and off on PB4.

//Includes
#include <avr/io.h>
#include <avr/interrupt.h>

#define INTERRUPTPIN PCINT1 //this is PB1 per the schematic
#define PCINT_VECTOR PCINT0_vect  //this step is not necessary
#define DATADIRECTIONPIN DDB1 //Page 64 of data sheet
#define PORTPIN PB1 //Page 64
#define READPIN PINB1 //page 64
#define LEDPIN 4 //PB4

#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) //OR
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) //AND

/*
 * Alias for the ISR: "PCINT_VECTOR" (Note: There is only one PCINT ISR. 
 * PCINT0 in the name for the ISR was confusing to me at first, 
 * hence the Alias, but it's how the datasheet refers to it)
 */

static volatile byte LEDState; //variable used within ISR must be declared Volatile.

void setup() {
    cli();//disable interrupts during setup
    pinMode(LEDPIN, OUTPUT); //we can use standard arduino style for this as an example
    digitalWrite(LEDPIN, LOW); //set the LED to LOW
    LEDState = 0; //we use 0 for Low state and 1 for High
    PCMSK |= (1 << INTERRUPTPIN); //sbi(PCMSK,INTERRUPTPIN) also works but I think this is more clear // tell pin change mask to listen to pin2 /pb3 //SBI
    GIMSK |= (1 << PCIE);   // enable PCINT interrupt in the general interrupt mask //SBI

    DDRB &= ~(1 << DATADIRECTIONPIN); //cbi(DDRB, DATADIRECTIONPIN);//  set up as input  - pin2 clear bit  - set to zero
    PORTB |= (1<< PORTPIN); //cbi(PORTB, PORTPIN);// disable pull-up. hook up pulldown resistor. - set to zero
    sei(); //last line of setup - enable interrupts after setup

}

void loop() {
  // put your main code here, to run repeatedly:
  //If you connect a debounced pushbutton to PB2 and to VCC you can tap the button and the LED will come on
  //tap the button again and the LED will turn off.

}


//this is the interrupt handler
ISR(PCINT_VECTOR)
{
  //Since the PCINTn triggers on both rising and falling edge let's just looks for rising edge
  //i.e. pin goes to 5v
  byte pinState;
  pinState = (PINB >> READPIN)& 1; //PINB is the register to read the state of the pins
  if (pinState >0) //look at the pin state on the pin PINB register- returns 1 if high
  {
   if (LEDState == 0)
   {
    digitalWrite(LEDPIN,HIGH); //you can use Arduino Code or LowerLevel Code to write to the register
    LEDState = 1; 
    }
   else
   {
    digitalWrite(LEDPIN,LOW);
    LEDState = 0;
    }
  }


}

If you're going to be using the ATTiny85, I highly suggest you read through the data sheet to understand better how to program these chips at a lower level of code....It took me a while for it to start to make sense.

12
  • The ISR should be PCINT0_vect, see the include file iotnx5.h. #define PCINT0_vect _VECTOR(2). Or at least, that is how it is in my distribution.
    – Nick Gammon
    Jul 27, 2015 at 5:43
  • Why use PCINTn, when there is INT0 on PB2?
    – RSM
    Jul 27, 2015 at 8:30
  • @NickGammon you're correct. I had some Alias defined in the code that I forgot to include. (Pun intended).I updated my answer.
    – GisMofx
    Jul 27, 2015 at 10:58
  • @RSM INT0 is the timer 0 interrupt..not the pin change interrupt(PCINTn). AttachInterrupt in Arduino is a Pin Change Interrupt.
    – GisMofx
    Jul 27, 2015 at 11:03
  • 1
    @GisMofx: May I suggest you rework your answer to provide a complete, compilable example? Also move your comments about the mask into it to clarify. You use (1 << INTERRUPTPIN) in some places, but cbi(DDRB, DATADIRECTIONPIN) in others, which is a bit inconsistent. How about DDRB &= ~(1 << DATADIRECTIONPIN) ? You might also want to mention the difference between pin-change interrupts and external interrupts.
    – Nick Gammon
    Jul 27, 2015 at 21:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.