Arduino Mega 2560 AttachInterrupt to pin 20 & 21

Hi,
I am using an IR phototransistor and an IR LED as motion detector. When the IR light which shines on the phototransistor is blocked, the transistor causes an open circuit and the voltage at the pin rises.
When the voltage rises, an interrupt routine is executed. For pins 2,3,18 and 19, the setup works as expected. For pins 20 (SDA) and 21 (SCL), it does not.
From looking at the interactive board viewer, these two pins appear to be a little different. Not sure what to make of it other than these pins can't have a low setting?

Is there something different about these two pins that prevents them from being used like the other four.
Is there a way to get the same functionality as the other two pins?
Regards
Cillian

Interactive Board viewer Link

transientch:
Hi,
I am using an IR phototransistor and an IR LED as motion detector. When the IR light which shines on the phototransistor is blocked, the transistor causes an open circuit and the voltage at the pin rises.
When the voltage rises, an interrupt routine is executed. For pins 2,3,18 and 19, the setup works as expected. For pins 20 (SDA) and 21 (SCL), it does not.
From looking at the interactive board viewer, these two pins appear to be a little different. Not sure what to make of it other than these pins can't have a low setting?

Is there something different about these two pins that prevents them from being used like the other four.
Is there a way to get the same functionality as the other two pins?
Regards
Cillian

Interactive Board viewer Link
Arduino Mega 2560 Rev3 — Arduino Official Store

Can't really help much without seeing your sketch. Have you written a simple sketch that just displays the state of those pins to make sure they are actually changing when the IR is blocked?
Also, it sounds like a rather simple application. Is there some reason you need to use interrupts rather than polling?

#define Trans_pin_CL 18
#define Trans_pin_CC 19
#define Trans_pin_CR 20
#define IRMP A14 // Measure Voltage
#define IRMN A15 // Measure Voltage
volatile int Value = 0;
// the setup function runs once when you press reset or power the board

void setup() {
    Serial.begin(9600);
    
    
    pinMode(Trans_pin_CL, INPUT);
    digitalWrite(Trans_pin_CL, HIGH);
    pinMode(Trans_pin_CC, INPUT);
    digitalWrite(Trans_pin_CC, HIGH);
    pinMode(Trans_pin_CR, INPUT);
    digitalWrite(Trans_pin_CR, HIGH);
    
    pinMode(IRMP, INPUT);
    pinMode(IRMN, INPUT);
    
    EIFR = bit(INTF5);  // clear flag for interrupt 0
    EIFR = bit(INTF4);  // clear flag for interrupt 1
    EIFR = bit(INTF3);  // clear flag for interrupt 1
    EIFR = bit(INTF2);  // clear flag for interrupt 1
    EIFR = bit(INTF1);  // clear flag for interrupt 1
    EIFR = bit(INTF0);  // clear flag for interrupt 1

    attachInterrupt(digitalPinToInterrupt(Trans_pin_CL),
        []() {Value = 1; },
        RISING);

    attachInterrupt(digitalPinToInterrupt(Trans_pin_CC),
        []() {Value = 2; },
        RISING);
    
    attachInterrupt(digitalPinToInterrupt(Trans_pin_CR),
        []() {Value = 3; },
        RISING);
}

// the loop function runs over and over again until power down or reset
void loop() {
    
    delay(2*1000);

    Serial.println(Value);

    WhichPin(Value);

    Serial.println(" ");
    Serial.print("IR Pos Pin = ");                     // Display "A3 = " 
    Serial.print(volts(IRMP));                    // Display measured A3 volts
    Serial.println(" volts");

    
    Serial.print("IR Neg Pin = ");                     // Display "A3 = " 
    Serial.print(volts(IRMN));                    // Display measured A3 volts
    Serial.println(" volts");

    Value = 0;
}


float volts(int adPin)                       // Measures volts at adPin 
{                                            // Returns floating point voltage
    return float(analogRead(adPin)) * 5.0 / 1024.0;
}

void WhichPin(int Value) {

    if (Value == 1) {
        Serial.println(" ");
        Serial.println("CL Trans Pin Triggered");
        Serial.println(" ");
    }
    else if (Value == 2) {
        Serial.println(" ");
        Serial.println("CC Trans Pin Triggered");
        Serial.println(" ");
    }

    else if (Value == 3) {
        Serial.println(" ");
        Serial.println("CR Trans Pin Triggered");
        Serial.println(" ");

    }
    else {
        Serial.println(" ");
        Serial.println("No Trans Pin Triggered");
        Serial.println(" ");
    }

    
    
}

I hope this code snippet helps (for my sake.... :slight_smile: ). I've also attached a fritizing drawings for what the board looks like. I only did it it for one IR_LED/Phototransistor pair though (and it was of the pins I am having trouble with!)
As regards to question about polling vs interrupts, this sketch is to help me understand the functionality of another project that needs interrupts.

Any other thoughts or suggestions are greatly appreciated!
Regards
Cillian

photoTrans_IR_LED_CircuitSchematic.pdf (565 KB)

photoTrans_IR_LED_board layout.pdf (715 KB)

The following code enables the internal pull-up resistor for these inputs. Is that what you intended?

  pinMode(Trans_pin_CL, INPUT);
  digitalWrite(Trans_pin_CL, HIGH);
  pinMode(Trans_pin_CC, INPUT);
  digitalWrite(Trans_pin_CC, HIGH);
  pinMode(Trans_pin_CR, INPUT);
  digitalWrite(Trans_pin_CR, HIGH);

The other issue I see is that value is declared int which is a multi-byte variable. You will need to disables interrupts when reading this variable from loop().

I still don't understand why you are using interrupts. You should just poll the inputs.

Thank you for the quick reply again!

To answer your last comment first. I am trying to understand how interrupts work on the MEGA 2560. There is a large sketch that I am working with that uses interrupts and I am just trying to learn how they work. I then spotted this discrepancy between how I thought the external interrupt pins worked on the MEGA 2560 and how they actually work.


My response to your first comment
Trans_pin_CL (pin 18) and Trans_pin_CC (pin 19) are set High, otherwise there is no voltage at those pins at all. I want the voltage set high on those pins.
Trans_pin_CR (pin 20) is constantly HIGH. I can't set pin 20 to LOW. The interactive board viewer appears to indicate that those pins on the MEGA 2560 are fixed to 5V with 10kOhm resistors?

The setup works perfectly for pin 18 and pin 19 ( 2 & 3 as well ).
It is pin 20 (and 21) that do not function as I expected.

My goal is to try and understand why pins 20 & 21 do not function like the other pins.
A stretch goal may be to try and get them to function like the other pins.


I have updated my code to reflect your detachinterrupts() comment also.
It's weird, it worked without doing that....

/*
 Name:		IR_Sensor.ino
 Created:	10/26/2020 9:15:22 AM
 Author:	cilli
*/






#define Trans_pin_CL 18
#define Trans_pin_CC 19
#define Trans_pin_CR 20
#define IRMP A14 // Measure Voltage
#define IRMN A15 // Measure Voltage
volatile int Value = 0;
// the setup function runs once when you press reset or power the board

void setup() {
    Serial.begin(9600);
    
    
    pinMode(Trans_pin_CL, INPUT);
    digitalWrite(Trans_pin_CL, HIGH);
    pinMode(Trans_pin_CC, INPUT);
    digitalWrite(Trans_pin_CC, HIGH);
    pinMode(Trans_pin_CR, INPUT);
    digitalWrite(Trans_pin_CR, LOW);
    
    pinMode(IRMP, INPUT);
    pinMode(IRMN, INPUT);
    
    EIFR = bit(INTF5);  // clear flag for interrupt 5
    EIFR = bit(INTF4);  // clear flag for interrupt 4
    EIFR = bit(INTF3);  // clear flag for interrupt 3
    EIFR = bit(INTF2);  // clear flag for interrupt 2
    EIFR = bit(INTF1);  // clear flag for interrupt 1
    EIFR = bit(INTF0);  // clear flag for interrupt 0

    attachInterrupt(digitalPinToInterrupt(Trans_pin_CL),
        []() {Value = 1; },
        RISING);

    attachInterrupt(digitalPinToInterrupt(Trans_pin_CC),
        []() {Value = 2; },
        RISING);

    attachInterrupt(digitalPinToInterrupt(Trans_pin_CR),
        []() {Value = 3; },
        RISING);

}

// the loop function runs over and over again until power down or reset
void loop() {
    
    delay(3 * 1000);

    Serial.println(" ");
    Serial.print("IR Pos Pin = ");                     // Display "A3 = " 
    Serial.print(volts(IRMP));                    // Display measured A3 volts
    Serial.println(" volts");

    
    Serial.print("IR Neg Pin = ");                     // Display "A3 = " 
    Serial.print(volts(IRMN));                    // Display measured A3 volts
    Serial.println(" volts");

    detachInterrupt(digitalPinToInterrupt(Trans_pin_CL));
    detachInterrupt(digitalPinToInterrupt(Trans_pin_CC));
    detachInterrupt(digitalPinToInterrupt(Trans_pin_CR));

    WhichPin(Value);
    Serial.println(Value);
    delay(1 * 1000);
    Value = 0;

    attachInterrupt(digitalPinToInterrupt(Trans_pin_CL),
        []() {Value = 1; },
        RISING);
    attachInterrupt(digitalPinToInterrupt(Trans_pin_CC),
        []() {Value = 2; },
        RISING);
    attachInterrupt(digitalPinToInterrupt(Trans_pin_CR),
        []() {Value = 3; },
        RISING);
}


float volts(int adPin)                       // Measures volts at adPin 
{                                            // Returns floating point voltage
    return float(analogRead(adPin)) * 5.0 / 1024.0;
}

void WhichPin(int Value) {


    if (Value == 1) {

        Serial.println(" ");
        Serial.println("CL Trans Pin Triggered");
        Serial.println(" ");

    }
    else if (Value == 2) {
        
        Serial.println(" ");
        Serial.println("CC Trans Pin Triggered");
        Serial.println(" ");
    }

    else if (Value == 3) {
        
        Serial.println(" ");
        Serial.println("CR Trans Pin Triggered");
        Serial.println(" ");

    }
    else {
        Serial.println(" ");
        Serial.println("No Trans Pin Triggered");
        Serial.println(" ");
    }

    
    
}

Again, thanks for taking your own personal time to help.
It is very much appreciated.
And if you don't have time to respond to this post, no offense taken!!

Regards
Cillian

When you do a digitalWrite(pin, HIGH) to a pin declared as input it turns on the internal pullup resistor. It would be more readable in your code to use pinMode(pin, INPUT_PULLUP) and remove the digitalWrite(pin, HIGH) lines.

The following link may answer your question about pins 20 and 21:
digital pin 20 and 21 won't work as digital inputs on Mega R3

ToddL1962:
When you do a digitalWrite(pin, HIGH) to a pin declared as input it turns on the internal pullup resistor.

... but not on every processor... so you should avoid it for portability reasons also

aarg:
... but not on every processor... so you should avoid it for portability reasons also

Good point and I'm not convinced OP knew that is what s/he was doing.

I believe that you are focusing on the correct issue with the internal pullups of 10K on the SDA and SCL pins which are also interrupt pins.

You are using a RISING interrupt on pins which are pulled HIGH either by the 50K internal pullup or the 10K i2c pullup. Can you confirm with a multimeter that the IR sensors are indeed pulling the pins LOW.

I have updated my code to reflect your detachinterrupts() comment also.
It's weird, it worked without doing that....

You misunderstand and should not be attaching and detaching an interrupt in loop(). To make protected readings you bracket the reading with noInterrupts() and interrupts().
In your case, with value = 1,2,3 your best approach is to declare it as a byte and not worry about the problem that can arise with mutibyte values being read from an interrupt.

Ok. Thank you for all the replies.

I got it to work. between the phototransistor emitter and ground was a 10kOhm resistor. I replaced it with 330ohm. I have yet to prove to myself why this works but the explanations in that other post seem reasonable.


Is the message also, use pinmode(pin, INPUT_PULLUP) instead of digitalwrite(pin, HIGH) where possible?


For Cattledog's comments

I do not have a multimeter at hand. I am using the analog pins to measure the voltage only...
I have a multimeter arriving Tuesday.

For the detachinterrupt() comment, I will play around with what you suggested.

Thank you everybody

Regards
Cillian

Regards
Cillian