Pages: [1] 2 3   Go Down
Author Topic: How to create 3th interrupt  (Read 5173 times)
0 Members and 1 Guest are viewing this topic.
Oppuurs, Belgium
Offline Offline
Jr. Member
**
Karma: 0
Posts: 94
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi all,

can someone post some code on how to create a 3th interrupt (and evt more) with the possibility to set RISING or FALLING?

I went through the datasheet of the 328 but i'm not getting it.  :-[

Thanks in advance,
EriSan500
« Last Edit: December 04, 2009, 04:20:25 am by erisan500 » Logged

Spokane, Washington
Offline Offline
God Member
*****
Karma: 1
Posts: 686
My name is Bob, and I'm an addict.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

3rd*

And I don't believe there is a 3rd interrupt available on the 328.  If you want more interrupts, you'll need to upgrade. I know for sure the 1280 (Arduino Mega) has like 5 or 6 interrupts?

What are you trying to do with the interrupts exactly? There may be a way to utilize just 1 interrupt to handle multiple buttons.

For example.. if that's what you're doing.. using multiple buttons, you can use an analog input pin, set resistors on each of the buttons, and use analog-read to get button pushes. This way, you only use 1 pin for like.. 3 buttons or how many ever you're using, and anytime one of those 3 buttons is pushed, it interrupts, but only using 1 arduino pin.

http://www.nuelectronics.com/estore/index.php?main_page=product_info&cPath=1&products_id=2

Here's an example of a shield using that, it only uses analog pin 0 to read all the buttons.
Logged

Oppuurs, Belgium
Offline Offline
Jr. Member
**
Karma: 0
Posts: 94
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

CaptainObvious,

have a look at http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1257584961 it explains why i (we) need 3 interrupts.

EriSan500
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 637
Posts: 34599
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Use the pin change interrupt:-
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1193225679
Logged

Oppuurs, Belgium
Offline Offline
Jr. Member
**
Karma: 0
Posts: 94
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok, i guess you are reffering to this piece of code:

Code:
#include <avr/interrupt.h>  
#include <avr/io.h>

#define LEFT false
#define RIGHT true

int mPin1 = 5; // H-bridge leg 1
int mPin2 = 6; // H-bridge leg 2
int mEnable = 7;

boolean volatile mDirection = RIGHT;
int volatile mSpeed = 200;

ISR( PCINT1_vect )
{
 if( ( ( PINC & _BV( PC4 ) ) && mDirection == LEFT ) ||
     ( ( PINC & _BV( PC5 ) ) && mDirection == RIGHT ) )
     switch_direction();
}

void setup() {
 pinMode( mPin1, OUTPUT );
 pinMode( mPin2, OUTPUT );
 pinMode( mEnable, OUTPUT );
 
 //make analog pins 5 and 6 into pin change interrupts  
 PCICR |= (1 << PCIE1);
 PCMSK1 |= (1 << PCINT12);
 PCMSK1 |= (1 << PCINT13);  
 
 digitalWrite( mEnable, HIGH );
 set_motor();
}

void loop() {  
}

void set_motor()
{
 boolean speedPin = ( mDirection ) ? mPin1 : mPin2;
 boolean unusedPin = ( mDirection ) ? mPin2 : mPin1;

 analogWrite( unusedPin, 0 );
 analogWrite( speedPin, mSpeed );  
}

void switch_direction()
{
 mDirection = !mDirection;  
 set_motor();
}

Can someone explain the following pieces:

Code:
ISR( PCINT1_vect )
{
 if( ( ( PINC & _BV( PC4 ) ) && mDirection == LEFT ) ||
     ( ( PINC & _BV( PC5 ) ) && mDirection == RIGHT ) )
     switch_direction();
}
especialy the "PCINT1_vect" and "PINC & _BV(PC4)"

and this:
Code:
//make analog pins 5 and 6 into pin change interrupts  
 PCICR |= (1 << PCIE1);
 PCMSK1 |= (1 << PCINT12);
 PCMSK1 |= (1 << PCINT13);
i figured out i have to look in the datasheet to find out that analog pin 5 = PCINT12 and 6 = PCINT13. Can i also assign digital pins in this way?


Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 175
---
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code sample for setting interrupts on some other pins.

Refer to Section 12 - External Interrupts in  the data sheet
In addition, here's a pin map. http://arduino.cc/en/Hacking/PinMapping168

Code:
//make analog pins 5 and 6 into pin change interrupts
//this corresponds to PCINT1_vect  
 PCICR |= (1 << PCIE1);
 PCMSK1 |= (1 << PCINT12);
 PCMSK1 |= (1 << PCINT13);
 
//pin change interrupt on digital pin 9
//this corresponds to PCINT0_vect
 PCICR |= (1 << PCIE0);
 PCMSK0 |= (1 << PCINT1);
 
//pin change interrupt on digital pin 4
//this corresponds to PCINT2_vect
 PCICR |= (1 << PCIE2);
 PCMSK2 |= (1 << PCINT20);

You will notice that I have given examples which use each of the corresponding masks and pin change interrupt enable bits.


Now, that you've configured the board for interrupts, we may now tell it what to do when an interrupt occurs. In your posted code example, we simply had one interrupt service routine run, but now that we have the board configured for interrupts on 3 pins, lets setup 3 different interrupt service routines.

Code:
 ISR_0 ( PCINT0_vect )
{
      //do something
}
 
 ISR_1 ( PCINT1_vect )
{
      //do something else
}

 ISR_2 ( PCINT2_vect )
{
      //do something different
}
Logged

Oppuurs, Belgium
Offline Offline
Jr. Member
**
Karma: 0
Posts: 94
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks FusiveResonance for the wonderfull explanation.  smiley-wink

Still need to try this, was a bit bussy with real life (family and things).

Can this be modified to have FALLING or RISING interupts, or do I simply check inside the ISR the pins for HIGH or LOW?

Greetings,
EriSan500
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 175
---
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Can this be modified to have FALLING or RISING interupts, or do I simply check inside the ISR the pins for HIGH or LOW?

No, this is strictly for pin CHANGE interrupts.

Yes, you will have to implement your own system of detecting rising vs falling.

Mind you, remember to keep your interrupt service routine short, as when in a heavy ISR block, you run the risk of missing another interrupt. Depending on the device you have hooked up on this pin, consider debouncing.

Finally, turn off interrupts when you're inside an ISR, as you shouldn't allow an interrupt while you're already servicing one.

Code:

#define atomic(off) PCICR = 0x07 //sets the pin change interrupt control register to B00000111
#define atomic(on) PCICR = 0x00 //sets the pin change interrupt control register to B00000000


Now in your ISR you may write something like:

Code:
ISR ( PCINT1_vect)
{
   atomic(on); //masks all interrupts. ie. sets the interrupt mask

   //some code

   atomic(off); //resets the interrupt control registers to enable interrupts
}

Be warned, depending on whether or not you are actually using all 3 pin change interrupt capabilities, you might need to modify the hex values in the atomic(on) define statement above. Please see section 12.2.4 in the atmel data sheet for more details.

Some good reading, although doesn't have anything on pin change interrupts, but I believe that you will need to include the headers that they include in their code snippet. http://gonium.net/md/2006/12/20/handling-external-interrupts-with-arduino/

Good luck. Let me know if you have issues, as I haven't tested the above code.
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 210
Posts: 13039
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Finally, turn off interrupts when you're inside an ISR, as you shouldn't allow an interrupt while you're already servicing one.
This is not necessary.  The processor automatically handles it for you.
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 175
---
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
This is not necessary.  The processor automatically handles it for you.

Wow. never knew that. Thanks.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 55
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am getting this error with your code
Code:

error: '__vector_3' was not declared in this scope
Logged

Oppuurs, Belgium
Offline Offline
Jr. Member
**
Karma: 0
Posts: 94
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I gave it a try too, and i'm also getting an error:

Code:
#include <avr/interrupt.h>  
#include <avr/io.h>


void setup() {
//pin change interrupt on digital pin 5
//this corresponds to PCINT0_vect  
 PCICR |= (1 << PCIE0);
 PCMSK0 |= (1 << PCINT21);

//pin change interrupt on digital pin 6
//this corresponds to PCINT1_vect
 PCICR |= (1 << PCIE1);
 PCMSK1 |= (1 << PCINT22);

//pin change interrupt on digital pin 7
//this corresponds to PCINT2_vect
 PCICR |= (1 << PCIE2);
 PCMSK2 |= (1 << PCINT23);
}

[glow]ISR_0( PCINT0_vect )[/glow]
{
      //do something
}

ISR_1( PCINT1_vect )
{
      //do something else
}

ISR_2( PCINT2_vect )
{
      //do something different
}

void loop()
{

}

error pointing to highlighted line:
Code:
error: expected constructor, destructor, or type conversion before '(' token

Any idea what i might be doing wrong?

Greetings,
EriSan500
Logged

Oppuurs, Belgium
Offline Offline
Jr. Member
**
Karma: 0
Posts: 94
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok, made some progress (dunno if this is correct though).

I changed
Code:
ISR_0( PCINT0_vect )
{
      //do something
}
ISR_1( PCINT1_vect )
{
      //do something
}
ISR_2( PCINT2_vect )
{
      //do something
}
to
Code:
ISR( PCINT0_vect )
{
      //do something
}
ISR( PCINT1_vect )
{
      //do something
}
ISR( PCINT2_vect )
{
      //do something
}

and it compiled without errors.
Will test this as soon as my new arduino's arrive.

Do i use DigitalRead(pin) inside the ISR to check if the port is HIGH or LOW ? Or is there a better way?

All i need to happen inside the ISR is to increase a counter.

Greetings,
EriSan500
« Last Edit: December 07, 2009, 08:33:45 am by erisan500 » Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 175
---
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes you may use digitalRead inside the ISR, but if you're finding it too slow you might have to ready the binary data directly from the register.

Don't forget to declare any variables used by the ISR as volatile.

Also, at the end of your setup() method, you'll want to call sei(). This will set the global interrupt enable bit. In case you ever want to reset the bit, (thereby turning off interrupts), you may use cli().
« Last Edit: December 07, 2009, 10:22:47 am by FusiveResonance » Logged

Oppuurs, Belgium
Offline Offline
Jr. Member
**
Karma: 0
Posts: 94
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I finally got my 2nd arduino and got a chance to test this.

And yes, it does not work as expexted. See below code, if you spot the mistake I made, please let me know.

Code:
#include <avr/interrupt.h>  
#include <avr/io.h>


void setup() {
  pinMode(5, INPUT);
  Serial.begin(9600);

//pin change interrupt on digital pin 5
//this corresponds to PCINT0_vect  
 PCICR |= (1 << PCIE0);
 PCMSK0 |= (1 << PCINT21);

//pin change interrupt on digital pin 6
//this corresponds to PCINT1_vect
 PCICR |= (1 << PCIE1);
 PCMSK1 |= (1 << PCINT22);

//pin change interrupt on digital pin 7
//this corresponds to PCINT2_vect
 PCICR |= (1 << PCIE2);
 PCMSK2 |= (1 << PCINT23);
}

ISR( PCINT0_vect )
{
      //do something
Serial.println("interrupt on 5");
}

ISR( PCINT1_vect )
{
      //do something else
}

ISR( PCINT2_vect )
{
      //do something different
}

void loop()
{

}
 
Logged

Pages: [1] 2 3   Go Up
Jump to: