Attiny85 multiple Interrupts

Hi everyone!
I am working on a little project that envolves an Attiny85.
For an encoder two interrupts are needed. The Attiny of course only has one interrupt
but, as far as I know, it can be configured to multiple pins.
I started with this sketch:

int led = 3;

void setup() {                
  pinMode(led, OUTPUT);    
  GIMSK=_BV(PCIE);
  PCMSK =_BV(PCINT2);
}

void loop() {}

ISR(PCINT0_vect){
  digitalWrite(led, HIGH); 
  delay(8000);    
  digitalWrite(led, LOW);
}

This sketch works fine by reacting to a change of pin 2.
Now if I set PCMSK to any other pin (eg. PCINT1) it will not work the same way.
The debug led will light up continuously if the pin is LOW.
If I set PCMSK to more than one pin, I get nearly random blinking.
What am I doing wrong?

Sorry if I asked a similar question on Letsmakerobots but this is more of a microcontroller specific issue:

What sort of encoder?

If it is just a manually-operated encoder, or generating fewer than 1000 transitions per second, you neither need, nor should be using interrupts.

Care to explain your actual purpose? That would enable us to suggest the proper way to to perform it.


Oh, and another little detail I just noted. "delay()" is never used in interrupt code anyway.

I want to build a quadrature encoder into a servo. With the gear ratio etc. I have about 1500 ticks per revolution. This is difficult to do without interrupts. The whole setup already works on an Arduino nano, I just want to convert it to the Attiny: https://www.youtube.com/watch?v=z9YZjmV9NNE

Why not just tap off the potentiometer that the servo is already using for positional feedback? Why go to the hassle of using an encoder when the servo already has hardware built in?

The ATtiny85 has a 10-bit ADC just like the Arduino.

Jiggy-Ninja: Why not just tap off the potentiometer that the servo is already using for positional feedback?

Ok, I should have said that it's a continuous servo. If you take a look at the video I linked in my previous post, you can see that the servo is spinning and is still able to measure the angle. I dont know of a continuous rotation poti with an acceptable resolution and price. So trust me, this already is the easiest solution, I just need to get those interrupts working.

Any pin can cause an interrupt on a Tiny85.

Your PCINT0_vect interrupt needs to look at the bits in GIFR to see which pin caused the interrupt.

Now if I set PCMSK to any other pin (eg. PCINT1) it will not work the same way.
The debug led will light up continuously if the pin is LOW.
If I set PCMSK to more than one pin, I get nearly random blinking.
What am I doing wrong?

Are the pins set as inputs? Are they floating…?

fungus: Are the pins set as inputs? Are they floating...?

Actually, the pins are not set to anything. That could be part of the problem. And what exactly does floating mean? Do I have to enable the pullup resistors?

Wingman:

fungus: Are the pins set as inputs? Are they floating...?

Actually, the pins are not set to anything. That could be part of the problem. And what exactly does floating mean? Do I have to enable the pullup resistors?

It means they'll dance to the beat of your local radio station if you don't connect anything to them or enable the pullups .

XD OK, this is the new version with the pin set to input, the pullup enabled and without delays:

int led = 3;
boolean ledstate;

void setup() {                
  pinMode(led, OUTPUT);    
  pinMode(1, INPUT);
  digitalWrite(1, HIGH);
  GIMSK=_BV(PCIE);
  PCMSK =_BV(PCINT1);
}

void loop() {
  digitalWrite(led, ledstate);
}

ISR(PCINT0_vect){
  ledstate=!ledstate;
}

Now the interrupt is not being triggered at all. Any ideas?

Wingman: The Attiny of course only has one interrupt but, as far as I know, it can be configured to multiple pins.

Not quite. ATtiny85 has one "external" interrupt and six pin change interrupts (if the reset pin is needed, then five of the six are available). The external interrupt is more flexible since it has level- and edge-triggered options, but often a pin change interrupt can be made to work similarly with just a little bit of code.

But why does this external interrupt work exclusively on pin 2? I must be doing something wrong.

Wingman: But why does this external interrupt work exclusively on pin 2?

That's the way the chip is wired. Can't change it.

The Mega328 has 2 "special" interrupt pins.

(You can't change those, either...)

Wingman: But why does this external interrupt work exclusively on pin 2?

Sorry, I meant the pin change interrupt. Those are available on any pin and if it is triggered, the attiny just has to check which pins are high to know what pin caused the interrupt. Is there a difference between declaring external interrupts and pin change interrupts? Because I thought I was already doing that. The Atmel datasheet says that the external interrupt is triggered by INT0. The PCMSK register controls which pins contribute to the pin change interrupt. PCMSK =_BV(PCINT1); should set the pin change interrupt to INT1 GIMSK =_BV(PCIE) enables the pin change interrupts, not the external interrupt ISR(PCINT0_vect){} should be called by a pin change interrupt This works perfectly for pin 2 but not for any other pin. And I can't find a line in the datasheet that says pin 2 is in some way wired to an external interrupt.

Wingman:

Wingman: But why does this external interrupt work exclusively on pin 2?

Sorry, I meant the pin change interrupt. Those are available on any pin and if it is triggered, the attiny just has to check which pins are high to know what pin caused the interrupt. Is there a difference between declaring external interrupts and pin change interrupts? Because I thought I was already doing that. The Atmel datasheet says that the external interrupt is triggered by INT0. The PCMSK register controls which pins contribute to the pin change interrupt. PCMSK =_BV(PCINT1); should set the pin change interrupt to INT1 GIMSK =_BV(PCIE) enables the pin change interrupts, not the external interrupt ISR(PCINT0_vect){} should be called by a pin change interrupt This works perfectly for pin 2 but not for any other pin. And I can't find a line in the datasheet that says pin 2 is in some way wired to an external interrupt.

Sounds like you've got it figured out, it should work for any pin. I'd sure take delay() out of the ISR though. Just set a flag in the ISR and check it in loop().

I tried to put resistor between pin 1 and GND. It is working perfectly, even with a mean delay in it.. Seems that this was the only problem.

// 10k Ohm resistor between INT1 and GND
int led = 0;

void setup() {                
  pinMode(led, OUTPUT); 
  pinMode(1, INPUT);   
  GIMSK=_BV(PCIE);
  PCMSK =_BV(PCINT1);
}

void loop() {}

ISR(PCINT0_vect){
  digitalWrite(led, HIGH); 
  delay(8000);    
  digitalWrite(led, LOW);
}

Wingman: I tried to put resistor between pin 1 and GND. It is working perfectly, even with a mean delay in it.. Seems that this was the only problem.

SOP is to put a 10K pullup resistor on pin 1, which is the reset pin. The resistor goes between pin 1 and the supply voltage. Between pin 1 and pin 8 in other words.

delay() depends on interrupts to work correctly. I do not see how it could in an ISR where interrupts are disabled by default upon entry to the ISR.

I don't think we are talking about the same pins here. What I did is wire a resistor between the interrupt pin(Pin 1 not Reset) and GND. This is basically a pull-down resistor. It does not work with a pull-up resistor, which could also be enabled via software. In this video they also use a pull-down resistor: https://www.youtube.com/watch?v=0aAwKT0YWJU

It took me like 5 hours to find this one comment in code attached to a YT video. Nobody else apparently has ever used pin change interrupts on this chip. It is no problem to use two 5ct resistors but at least I need to know that they are necessary. :)

Sorry about that, got the physical and logical pins confused. The pull-down resistor seems odd but hard to comment without seeing the schematic. I've used PC interrupts and they work fine. If you have a minimal sketch and schematic, post them and I'll have a look and will wire it up if necessary. Explain what the sketch is supposed to do and what it actually does.

I have posted some Multiple interrupt sketches for the ATTiny85 on the forum elsewhere. Using the PinChange Interrupt Library makes it very easy.

http://forum.arduino.cc/index.php?topic=65706.msg1756727#msg1756727

Have a look at the OWRain1.ino attachment for an example where interrupts on two pins are used.