Teensy 3.1 External Interrupt on pin - please provide guidance

Status
Not open for further replies.

RichardFerraro

Well-known member
I have Nunchuck working and ADXL345 accelerometer partially working using TeensyDuino with Teensy 3.1.

I want to generate an interrupt when the signal on a pin changes (e.g., goes low) so that I can access data from the ADXL345.

I know how to do this on Arduino MEGA as pins are dedicated to certain interrupts.
Mega pin 2 (interrupt 0),
attachInterrupt(0, ISR0_ADXL345_WATERMARK, FALLING); // watermark

void ISR0_ADXL345_WATERMARK() {...} // ISR


I don't know how to do this on Teensy 3.1 as I understand any pin can be configured to generate an interrupt.

For example, suppose pin is 23 receives an interrupt signal from the ADXL345.

What does the software look like that would:
configure pin 23 to generate an interrupt?
specify the interrupt handler that will be called when pin 23 changes (e.g., goes low)?

thanks,

Richard
 
Fixed:

#define PinInt1 23

void setup(){

Serial.begin(115200);

pinMode(PinInt1, INPUT); // sets the digital pin as output

attachInterrupt(PinInt1, isrService, FALLING); // interrrupt 1 is data ready
}

void loop()
{
delay(1000);
Serial.println("Running");
}

// watermark generates this interrupt
void isrService()
{
cli();
Serial.println("At ISR0");
sei();
}
 
RichardFerraro,
How are you resolving cli() and sei()? When I put these in my sketch to do not resolve. Thanks
 
I have removed them and have minimized the operations in the interrupt service routines to set a flag.

I query the flag in a timer service routine.

Richard
 
How are you resolving cli() and sei()

Just looking around quickly, looks like they are defined in wiring.h as __enable_irq() and __disable_irq().

__enable_irq() and __disable_irq() are defined in mk20dx128.h

Make sure these files get #include d

TLB
 
How do you implement a more complex interrupt? For example, if pin 15 receives 11001110 then the interrupt is triggered. In my case, attachInterrupt is too simple to detect if an interrupt service should be executed.
 
Im thinking I could use one of the ISR() macros to service the interrupt, but how would I trigger the ISF flag in order to execute the ISR?
 
How do you implement a more complex interrupt? For example, if pin 15 receives 11001110 then the interrupt is triggered. In my case, attachInterrupt is too simple to detect if an interrupt service should be executed.
where pin 15 is not a UART ? (11001110 is a bit-serial flow, complicated with partial match, too few bits, bit rate)
 
Hi Stevech,

I just read through this thread: http://http://forum.pjrc.com/threads/24015-help-with-interrupts-on-t3

It sounds like if I have a serial stream on a data, it is automatically put into a buffer. I then need to parse that buffer for a specific byte. If that byte occurs I need to, for example, quit the process and display an error message. For learning purposes, I would like to execute an ISR when that specific byte is received. Could you please explain how to do this?

where pin 15 is not a UART ? (11001110 is a bit-serial flow, complicated with partial match, too few bits, bit rate)
Are you saying I should initialize that pin as a UART and use that to buffer my incoming message?
 
Last edited:
UART... no. I just didn't understand that you have a bit-stream coming in as serial. Bit streams have to have a framing method, with n bits per frame. In UARTs like the common "serial" ports, the framing is done with a prefix special bit called a start bit. Then the data bits, often 8, then one or more stop bits. The UART hardware can detect the start and stop bits to find the frame start/end. Then the data bits are converted from serial input to a byte of several (e.g., 8) bits, and stored in bytes in memory in a buffer. The application then processes bytes. There are many other ways to do serial data, e.g., CAN bus uses a similar scheme but allows for 2+ devices to compete for using a single "wire" for their transmissions.

So if you put serial data on an I/O bit, and have that I/O bit programmed to interrupt on a high-to-low, or low-to-high, or either state change, the CPU can note the "time" since the last interrupt and thus time-tag the transitions in the data. The list of transition times and state (1 or 0) can be parsed to construct frames and data bits, much as a UART does. This is hard.

So it's key to understand the serial data and how its framed, e.g. asynchronous serial (as in the common serial port), vs. synchronous data with a lead-in set of bits for frame synch, versus other methods.
 
It is work

Fixed:

#define PinInt1 23

void setup(){

Serial.begin(115200);

pinMode(PinInt1, INPUT); // sets the digital pin as output

attachInterrupt(PinInt1, isrService, FALLING); // interrrupt 1 is data ready
}

void loop()
{
delay(1000);
Serial.println("Running");
}

// watermark generates this interrupt
void isrService()
{
cli();
Serial.println("At ISR0");
sei();
}



Thanks so much, it is work
 
I'm using the same above interrupt program.
I have connected one button on pin23 and when I press it very much going to isr but inside isr I have written tone_melody program which should get played but its not playing.
Kindly let me know is there any connection between the tone_melody program and interrupt.
 
I am not sure if anyone can help without seeing the code...

Also not sure about above program who does cli/sei in the interrupt handler. Probably OK in the above case as most likely the Serial.println will hopefully just put stuff into a buffer...
 
Inside interrupt below is not getting played.

for (int thisNote = 12; thisNote < 36; thisNote++) {//0; thisNote < 24; thisNote++) {//
freq123 = 43-(thisNote-12);

tone(9, freq123*55.2369,960);
delay(6); // creates delay of 6 ms

//tone(9, musicTones[thisNote], 40);
//delay(40); // creates delay of 6 ms
}
delay(300);
for (int thisNote = 0; thisNote < 40; thisNote++) {

tone(9, data_play[thisNote]*hz, 960);
delay(40);


//tone(9, musicTones[freqArray[thisNote]], 70);
//delay(70);

}
noTone(9);
}
 
I suggest:
removing all code from the ISR except a global scope flag:

global scope...
boolean globalFiredFlag=false;

inside isr()...
globalFiredFlag=true;

inside loop()...
if (globalFiredFlag) {
[your code above from isr]
globalFiredFlag=false;
}
 
thanks, RichardFerraro...
The above is working fine but need something which again not check the condition as my program can be anywhere at any time, with above I need to be precise that everytime my program should check the condition.

The worst case is, if my program gets stuck and at the same time, interrupt occur than the delay will happen and chances it will not reach the conditioon loop.
 
Last edited:
Using things like delay inside an interrupt handler is probably going to work very well. I would have suggested more or less the same as Richard did above.

An alternate to the above is maybe when the button is pressed it starts up a timer such as Interval timer, lets say every 10ms, and keep a state table, that maybe you can call tone inside the interrupt. Then maybe keep a state number and count of timer interrupts, that have happened, if enough has happened, you start a new tone, when everything is done, you turn off this timer.
 
Using things like delay inside an interrupt handler is probably going to work very well.

@KurtE: Did you mean that using delay inside an interrupt handler would NOT work very well? IIRC using delay inside an interrupt handler is generally a Bad Idea.

@ npashine: You could replace the delay()'s with millis().

- George
 
Status
Not open for further replies.
Back
Top