Trinket Pro and Interrupts

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
iitgrad
 
Posts: 98
Joined: Sun Dec 30, 2012 6:43 pm

Trinket Pro and Interrupts

Post by iitgrad »

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

User avatar
adafruit_support_bill
 
Posts: 88154
Joined: Sat Feb 07, 2009 10:11 am

Re: Trinket Pro and Interrupts

Post by adafruit_support_bill »

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

User avatar
iitgrad
 
Posts: 98
Joined: Sun Dec 30, 2012 6:43 pm

Re: Trinket Pro and Interrupts

Post by iitgrad »

Wow, never new this. Awesome!

Thanks Bill

User avatar
maxem
 
Posts: 2
Joined: Sat May 17, 2014 3:43 am

Re: Trinket Pro and Interrupts

Post by maxem »

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

User avatar
adafruit_support_bill
 
Posts: 88154
Joined: Sat Feb 07, 2009 10:11 am

Re: Trinket Pro and Interrupts

Post by adafruit_support_bill »

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.

User avatar
maxem
 
Posts: 2
Joined: Sat May 17, 2014 3:43 am

Re: Trinket Pro and Interrupts

Post by maxem »

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

User avatar
seanahrens
 
Posts: 17
Joined: Thu May 08, 2014 12:09 am

Re: Trinket Pro and Interrupts

Post by seanahrens »

Bill, these pin change interrupts will work to wake the trinket pro from sleep, I'm assuming? That's the use case I have.

User avatar
adafruit_support_mike
 
Posts: 67485
Joined: Thu Feb 11, 2010 2:51 pm

Re: Trinket Pro and Interrupts

Post by adafruit_support_mike »

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.

User avatar
seanahrens
 
Posts: 17
Joined: Thu May 08, 2014 12:09 am

Re: Trinket Pro and Interrupts

Post by seanahrens »

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.

Jabrwock
 
Posts: 13
Joined: Fri Jun 06, 2014 4:32 pm

Re: Trinket Pro and Interrupts

Post by Jabrwock »

seanahrens 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); 
  ...
}
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.5

User avatar
seanahrens
 
Posts: 17
Joined: Thu May 08, 2014 12:09 am

Re: Trinket Pro and Interrupts

Post by seanahrens »

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.

User avatar
MizeSoundGuy
 
Posts: 25
Joined: Sun Apr 05, 2015 4:09 pm

Re: Trinket Pro and Interrupts

Post by MizeSoundGuy »

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

User avatar
seanahrens
 
Posts: 17
Joined: Thu May 08, 2014 12:09 am

Re: Trinket Pro and Interrupts

Post by seanahrens »

Jeff, great to hear! I'm really glad it helped!

User avatar
paulosophy
 
Posts: 90
Joined: Fri Apr 17, 2015 5:40 pm

Re: Trinket Pro and Interrupts

Post by paulosophy »

Wow this post was incredibly helpful for me, too! Thanks so much.

User avatar
efrag
 
Posts: 2
Joined: Fri Oct 23, 2015 5:59 am

Re: Trinket Pro and Interrupts

Post by efrag »

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.:
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!"));
  }
}

Is there any way I can fix the problem?

Thank you very much.
Emmanuel.

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino”