I'm guessing I already know the answer to this but just want to make sure. Interrupts are on pin #2 and #3 on an Arduino Uno. Since pin #2 is not available on the Trinket Pro I'm assuming that I am limited to applications where I only need 1 interrupt line. Is this true, or is there a "configuration" using fuses or something more advanced where I can tell the hardware to use, say pin #3 and pin #4 for the two interrupts.
Thanks, and awesome product as usual!
Kevin
Trinket Pro and Interrupts
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- adafruit_support_bill
- Posts: 88154
- Joined: Sat Feb 07, 2009 10:11 am
Re: Trinket Pro and Interrupts
You can't re-map the external interrupt pins. But don't forget about pin-change interrupts:
http://www.geertlangereis.nl/Electronic ... ge_en.html
http://www.geertlangereis.nl/Electronic ... ge_en.html
- iitgrad
- Posts: 98
- Joined: Sun Dec 30, 2012 6:43 pm
Re: Trinket Pro and Interrupts
Wow, never new this. Awesome!
Thanks Bill
Thanks Bill
- maxem
- Posts: 2
- Joined: Sat May 17, 2014 3:43 am
Re: Trinket Pro and Interrupts
Hello,
Sorry for such a noob question. I see that the Pin-Change interrupts is a way of getting around only having one external interrupt pin. But would that work for a high resolution encoder? Does it have the same speed response as the regular external interrupt pin?
I have the AMT102 encoder used in this encoder library tutorial:
http://www.pjrc.com/teensy/td_libs_Encoder.html
I wish to use it to create a digital protractor with the encoder because it has a resolution of 2048 ppr and with quadrature should be 8192 points for 360degrees.
So I purchased your 3.3v Pro Trinket because of the battery backpack portability but now realize pin 3 is the only external interrupt when I need two external interrupt pins.
Because I want to drive the encoder at such a high ppr for maximum detail I figure there can't be much delay on the interrupt pins. And was just wondering if there would be any real difference with this pin-change interrupts workaround. I don't fully understand the Pin-Change Interrupts tutorial linked by Bill but will keep trying, just thought I'd ask about this method. Would it be slower or cause some delay with the way the encoder library works or would it work the same as regular external interrupt pins?
Just curious cause what I read about that Encoder Library apparently they had to stream line the interrupt code just to not miss any encoder counts for high performance encoders.
Thank you! Any help is very much appreciated!
Max
Sorry for such a noob question. I see that the Pin-Change interrupts is a way of getting around only having one external interrupt pin. But would that work for a high resolution encoder? Does it have the same speed response as the regular external interrupt pin?
I have the AMT102 encoder used in this encoder library tutorial:
http://www.pjrc.com/teensy/td_libs_Encoder.html
I wish to use it to create a digital protractor with the encoder because it has a resolution of 2048 ppr and with quadrature should be 8192 points for 360degrees.
So I purchased your 3.3v Pro Trinket because of the battery backpack portability but now realize pin 3 is the only external interrupt when I need two external interrupt pins.
Because I want to drive the encoder at such a high ppr for maximum detail I figure there can't be much delay on the interrupt pins. And was just wondering if there would be any real difference with this pin-change interrupts workaround. I don't fully understand the Pin-Change Interrupts tutorial linked by Bill but will keep trying, just thought I'd ask about this method. Would it be slower or cause some delay with the way the encoder library works or would it work the same as regular external interrupt pins?
Just curious cause what I read about that Encoder Library apparently they had to stream line the interrupt code just to not miss any encoder counts for high performance encoders.
Thank you! Any help is very much appreciated!
Max
- adafruit_support_bill
- Posts: 88154
- Joined: Sat Feb 07, 2009 10:11 am
Re: Trinket Pro and Interrupts
Pin-change interrupts are just as fast. But they require a little more processing in the interrupt handler. The difference from external interrupts is that you don't know which pin generated the interrupt. You have to read the whole port and compare with the previous reading to determine which pin changed.
- maxem
- Posts: 2
- Joined: Sat May 17, 2014 3:43 am
Re: Trinket Pro and Interrupts
Bill,
Thank you so much for the quick reply! I have been re-reading the page you linked and I think I get what your saying about not knowing which pin generated the interrupt cause your basically only able to watch the entire port for the interrupt and not the individual pins.
Since I only need two interrupt pins I'm thinking of how I can use the existing external interrupt pin #3 and then use the pin-change and just read the whole port and not care which pin it was just only connect one of the pins on that port to the encoder and simply don't use the rest for anything. I read somewhere else about the pin-change being hard to do both rising and falling edge of interrupt for quadrature, from what I understand at least. So I'm thinking I'll use pin #3 and the entire port if possible to keep code simple so it will hopefully work with the existing Encoder library.
Thanks again for your super quick reply!
Max
Thank you so much for the quick reply! I have been re-reading the page you linked and I think I get what your saying about not knowing which pin generated the interrupt cause your basically only able to watch the entire port for the interrupt and not the individual pins.
Since I only need two interrupt pins I'm thinking of how I can use the existing external interrupt pin #3 and then use the pin-change and just read the whole port and not care which pin it was just only connect one of the pins on that port to the encoder and simply don't use the rest for anything. I read somewhere else about the pin-change being hard to do both rising and falling edge of interrupt for quadrature, from what I understand at least. So I'm thinking I'll use pin #3 and the entire port if possible to keep code simple so it will hopefully work with the existing Encoder library.
Thanks again for your super quick reply!
Max
- seanahrens
- Posts: 17
- Joined: Thu May 08, 2014 12:09 am
Re: Trinket Pro and Interrupts
Bill, these pin change interrupts will work to wake the trinket pro from sleep, I'm assuming? That's the use case I have.
- adafruit_support_mike
- Posts: 67485
- Joined: Thu Feb 11, 2010 2:51 pm
Re: Trinket Pro and Interrupts
Yes, with some minor limitations.
The ATmega328P has six sleep modes:
- Idle
- ADC Noise Reduction
- Power-Down
- Power-Save
- Standby
- Extended Standby
Pin-change interrupts are wake-up sources for all six modes, but pin 3 has extra interrupt hardware called INT1.
INT1 is more selective than a pin-change interrupt. You know exactly what pin it is for starters, but you can also detect things like rising edges, falling edges, or specific HIGH/LOW input levels.
All INT1 interrupts are wake-up sources for Idle mode, but only the HIGH/LOW level interrupts are wake-up sources for the other five.
Pin 3 can also trigger general pin-change interrupts, so for that pin you need to pay attention to which interrupt vector you're using, what interrupts you enable, and what sleep mode you're using.
The ATmega328P has six sleep modes:
- Idle
- ADC Noise Reduction
- Power-Down
- Power-Save
- Standby
- Extended Standby
Pin-change interrupts are wake-up sources for all six modes, but pin 3 has extra interrupt hardware called INT1.
INT1 is more selective than a pin-change interrupt. You know exactly what pin it is for starters, but you can also detect things like rising edges, falling edges, or specific HIGH/LOW input levels.
All INT1 interrupts are wake-up sources for Idle mode, but only the HIGH/LOW level interrupts are wake-up sources for the other five.
Pin 3 can also trigger general pin-change interrupts, so for that pin you need to pay attention to which interrupt vector you're using, what interrupts you enable, and what sleep mode you're using.
- seanahrens
- Posts: 17
- Joined: Thu May 08, 2014 12:09 am
Re: Trinket Pro and Interrupts
For future people who read this thread, I want to share what I just did. Successfully put my Pro Trinket to sleep and wake it on a button press to basically any button hooked up to any pin (not just PIN 3). Here's the code. I emailed with Geert, the author of http://www.geertlangereis.nl/Electronic ... ge_en.html, but what was hard about modifying his code is that you need to do datasheet lookups to determine how the Trinket Pins map to the ATMega Pin #'s. The following code (partially grabbed from http://playground.arduino.cc/Main/PinChangeInterrupt and http://www.fiz-ix.com/2012/11/low-power ... dog-timer/) automates this. Simply use the Trinket Pin numbers. Note the interrupts will get called for pin state changes other than just your specific pins, so you need logic to check those when it wakes if it matters (comments shown where this is applicable)
Code: Select all
// Define the pins you'll use for interrupts - CHANGE THESE to match the input pins you are using in your project
#define NAV0_PIN A0
#define NAV1_PIN 5
#define NAV2_PIN 3
void setup(){
enablePinInterupt(NAV0_PIN);
enablePinInterupt(NAV1_PIN);
enablePinInterupt(NAV2_PIN);
...
}
void loop(){
//if device is idle logic
goToSleep();
// do normal device stuff here
}
void enablePinInterupt(byte pin)
{
*digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // enable pin
PCIFR |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
PCICR |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group
}
void goToSleep()
{
// The ATmega328 has five different sleep states.
// See the ATmega 328 datasheet for more information.
// SLEEP_MODE_IDLE -the least power savings
// SLEEP_MODE_ADC
// SLEEP_MODE_PWR_SAVE
// SLEEP_MODE_STANDBY
// SLEEP_MODE_PWR_DOWN -the most power savings
// I am using the deepest sleep mode from which a
// watchdog timer interrupt can wake the ATMega328
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode.
sleep_enable(); // Enable sleep mode.
sleep_mode(); // Enter sleep mode.
// After waking the code continues
// to execute from this point.
sleep_disable(); // Disable sleep mode after waking.
}
ISR (PCINT0_vect) // handle pin change interrupt for D8 to D13 here
{
// if I wired up D8-D13 then I'd need some code here
}
ISR (PCINT1_vect) // handle pin change interrupt for A0 to A5 here // NAV0
{
// check it was NAV0 and nothing else
}
ISR (PCINT2_vect) // handle pin change interrupt for D0 to D7 here // NAV1, NAV2
{
// Check it was NAV1 or NAV2 and nothing else
}
Last edited by seanahrens on Sat Jan 24, 2015 12:33 am, edited 4 times in total.
-
- Posts: 13
- Joined: Fri Jun 06, 2014 4:32 pm
Re: Trinket Pro and Interrupts
This part breaks my build, it says NAV0/1/2 aren't defined. Do I need an extra library or defines for these? I'm using Arduino 1.0.5seanahrens wrote:Simply use the Trinket Pin numbers. Note the interrupts will get called for pin state changes other than just your specific pins, so you need logic to check those when it wakes if it matters (comments shown where this is applicable)
Code: Select all
void setup(){ enablePinInterupt(NAV0_PIN); enablePinInterupt(NAV1_PIN); enablePinInterupt(NAV2_PIN); ... }
- seanahrens
- Posts: 17
- Joined: Thu May 08, 2014 12:09 am
Re: Trinket Pro and Interrupts
Jabrwock,
I'm sorry! I left off the code that defines those pins. I've updated my code sample to include them now. See it in the original code sample. You need to set them to the pins that are appropriate for your project though.
I'm sorry! I left off the code that defines those pins. I've updated my code sample to include them now. See it in the original code sample. You need to set them to the pins that are appropriate for your project though.
- MizeSoundGuy
- Posts: 25
- Joined: Sun Apr 05, 2015 4:09 pm
Re: Trinket Pro and Interrupts
I just gotta say that this thread saved me tons of work. I didn't need to wake from sleep or anything, just react to some buttons in a quick and dirty way.
Worked perfectly with no fuss. Thanks.
--Jeff
Worked perfectly with no fuss. Thanks.
--Jeff
- seanahrens
- Posts: 17
- Joined: Thu May 08, 2014 12:09 am
Re: Trinket Pro and Interrupts
Jeff, great to hear! I'm really glad it helped!
- paulosophy
- Posts: 90
- Joined: Fri Apr 17, 2015 5:40 pm
Re: Trinket Pro and Interrupts
Wow this post was incredibly helpful for me, too! Thanks so much.
- efrag
- Posts: 2
- Joined: Fri Oct 23, 2015 5:59 am
Re: Trinket Pro and Interrupts
Hello, Great post !
I have a question please.
I ' m using trinket with fona to send sms when a button is pressed, all the other time the system should go to sleep.
when I try to compile my program I have an error.:
I search and found that there is a library conflict ( "#include "Adafruit_FONA.h" which is using the SoftwareSerial library)
Here is my code:
Is there any way I can fix the problem?
Thank you very much.
Emmanuel.
I have a question please.
I ' m using trinket with fona to send sms when a button is pressed, all the other time the system should go to sleep.
when I try to compile my program I have an error.:
SoftwareSerial\SoftwareSerial.cpp.o: In function `__vector_3':
C:\Arduino\hardware\arduino\avr\libraries\SoftwareSerial/SoftwareSerial.cpp:227: multiple definition of `__vector_5'
softBall_ver3_trinket_sleep.cpp.o:C:\Arduino/softBall_ver3_trinket_sleep.ino:47: first defined here
collect2.exe: error: ld returned 1 exit status
Error compiling.
I search and found that there is a library conflict ( "#include "Adafruit_FONA.h" which is using the SoftwareSerial library)
Here is my code:
Code: Select all
#include <avr/sleep.h>
#include "Adafruit_FONA.h"
#define FONA_RX 3
#define FONA_TX 4
#define FONA_RST 5
#define NAV2_PIN 6
#include <SoftwareSerial.h>
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
SoftwareSerial *fonaSerial = &fonaSS;
Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
void setup() {
enablePinInterupt(NAV2_PIN);
pinMode(13, OUTPUT);
}
void loop() {
//if device is idle logic
goToSleep();
// do normal device stuff here
}
void enablePinInterupt(byte pin)
{
*digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // enable pin
PCIFR |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
PCICR |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group
}
void goToSleep()
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode.
sleep_enable(); // Enable sleep mode.
sleep_mode(); // Enter sleep mode.
sleep_disable(); // Disable sleep mode after waking.
}
ISR (PCINT2_vect) // handle pin change interrupt for D0 to D7 here // NAV1, NAV2
{
fonaSerial->begin(4800);
if (! fona.begin(*fonaSerial)) {
// Serial.println(F("Couldn't find FONA"));
while (1);
}
char sendto[11] = "6999999999";
char message[12] = "Hello efrag";
// flushSerial();
if (!fona.sendSMS(sendto, message)) {
// Serial.println(F("Failed"));
} else {
// Serial.println(F("Sent!"));
}
}
Thank you very much.
Emmanuel.
Please be positive and constructive with your questions and comments.