Arduino Yun and Interrupts problems

Hi, this is my post on this forum and I hope to write in the right section. I'm using Arduino YUN to intercept remote temperature sensor (433Mhz) with standard receiver module to create a weather station. I use attachInterrupt(1, ext_int_1, CHANGE); Data pin of receiver module is on pin 2 of Arduino YUN but I don't receive any type of data. This is code that I use

volatile word pulse;

OregonDecoderV2 orscV2;
OregonDecoderV3 orscV3;

void ext_int_1(void) {
    static word last;
    pulse = micros() - last;
    last += pulse;
}


void setup () {
   Serial.begin(115200);
   while (!Serial);
   attachInterrupt(1, ext_int_1, CHANGE);
   Serial.println("Ready");
}

void loop () {
    static int i = 0;
    cli();
    word p = pulse;
    
    pulse = 0;
    sei();
   
    if (p != 0) {
        if (orscV2.nextPulse(p))
            reportSerial("OSV2", orscV2);   //Print data
        if (orscV3.nextPulse(p))
            reportSerial("OSV3", orscV3);   //Print data     
    }
}

I also tested this code on Arduino UNO R3 on pin 3 and works properly.

I also changed interrupts without success on pin 3 (INT 0).

Where I wrong? Which pin I should use ?

Greeting and thank you in advance.

Hi, welcome to the forum.

Do you see the message "Ready" on the serial monitor ? I think you have the pins and interrupts as they are for attachInterrupt on a Leonardo/Yun.

Do you use Arduino IDE 1.5.8 ?

You could make a minimal test sketch. Just set a flag in the interrupt_routine, and print that flag to the serial monitor, and toggle the pin with a resistor and a button.

Hi Peter, thank you for your response. I see message "ready" on serial monitor and I use IDE 1.5.8 version and I also upgrade image at last version. I will test and I will post the result, but I think that problem is the interrupt change don't work on external events.

Hi,
I have used this sketch for interrupt test :

int pbIn = 1;                  // Interrupt 1 is on DIGITAL PIN 2 ON YUN/LEONARDO!
int ledOut = 8;                // The output LED pin
volatile int state = LOW;      // The input state toggle
 
void setup()
{   
    Serial.begin(115200);  
    // Set up the digital pin 2 to an Interrupt and Pin 4 to an Output
    pinMode(ledOut, OUTPUT);
    //Attach the interrupt to the input pin and monitor for ANY Change
    attachInterrupt(pbIn, stateChange, CHANGE);
    while (!Serial);
    
    Serial.println("Ready");
    Serial.print("state:");
    Serial.println(state);
}
void loop()                    
{
    //Simulate a long running process or complex task
    Serial.print("state:");
    Serial.println(state);
    digitalWrite(ledOut, state); 
    
}
 
void stateChange()
{
    state = !state;
 
}

and it’s work. Then where is problem into first sketch ? Do anyone can test the first sketch on Arduino YUN ?

Thanks

I can't test it right now on my Leonardo. So I'm looking at the first sketch, and I still don't see a problem.

Could you use a wire to the input (instead of the receiver), and use the first sketch and test with 5V and GND. The ATmega32U4 (Yun) has other input voltage levels than the ATmega328P (Uno).

Or try adding a small delay at the end of the loop: delay(1); Perhaps the disabling of the interrupt has some influence on micros(), since that is updated in an interrupt routine and the Arduino has almost no time to breath between the disabled interrupts. Since you only check if "pulse" is not zero, the compiler might optimize that a lot.

You could avoid disabling the interrupts, by using a byte as flag, and still use the 16-bit word for the timing value. Since writing the flag can not be interrupted, you can rely on that. You could even increment the flag to detect too much interrupts.

For me, it seems better to do the calculation in the loop(). So the interrupt routine only captures the micros() value.

// speude code written just now, not tested // The interrupt routine should set pulse just once. It therefor disables writing pulse again by incrementing the flag. // A new value should be set in pulse only after the main loop tells it is okay by decrementing the flag. ISR : if flag == 0, pulse = micros(); flag++ else flag = error (for example negative value or value 100) loop() : if flag == 1, copy pulse to start-micros or end-micro; flag--; calculate diff; else if flag !=0 : missed an interrupt, start all over again. reset flag: flag = 0

The compiler makes many decisions while optimizing, perhaps it generated other code for the ATmega32U4 than for the ATmega328P.

Do you know the pulseIn() function ? and the frequency and timing library at the teensy website ?

ADDED: Now that I'm thinking about that pseud code, it might perhaps be better to use an 'index' for a 'flag'. The Interrupt routine could fill two values in an array and update 'index'. When 'index' is 2, it does nothing. In the loop(), the values are read, and 'index' is made zero to fill the array again.