Go Down

Topic: PCINT with reed sensor - repeatedly calling interrupt handler (Read 128 times) previous topic - next topic

jackman_fam

I have a cool project for a home bar that I built. I'm currently doing door alarms when the refrigerator gets left open. I want to use interrupts because I am going to have several sensors tied into an Uno. I've spent all evening on a problem that I just can't seem to figure out and hoping one of you have any thoughts.

Diagram:
D7 - Reed switch for fridge 1 - http://www.ebay.com/itm/1-Magnetic-Door-Window-Contact-Reed-Switch-Alarm-Security-Ademco-Honeywell-Bosch/160743056070  (closed loop when magnets close)
D6 - Reed switch for fridge 2
10k pulldown resistor  (doesn't seem to make a difference as far as I can tell thus far)

Problem:
I get constantly repeating output when magnets are apart (simulating fridge door open). It appears the interrupt keeps recurring and I only want it to trigger on a RISING or a FALLING state.

Code: [Select]
#define BevCenter 6   //digital pin for beverage center door sensor; corresponds to PCINT22
#define WineFridge 7  //digital pin for wine fridge door sensor; corresponds to PCINT23
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

  int BevCenterState = 0;
  int WineFridgeState = 0;
  volatile long unsigned eventTime, prevEventTime;
  volatile byte changedBits, portDpast, portDstatus = 0b00000000;
  volatile boolean fridgeEvent = false;

void setup() {
  Serial.begin(9600);
  Serial.println(">>>> Arduino Test Program <<<<");
  Serial.println();
  pinMode(BevCenter, INPUT);
  pinMode(WineFridge, INPUT);

  //enable interrupts for refigerators
  sbi (PCICR, PCIE2); //enable Pin Change Interrupt 2 where D0 - D7 reside
  sbi (PCMSK2, PCINT22); //for digital input 6
  sbi (PCMSK2, PCINT23); //for digital input 7
}
 
void loop() {
  //REFRIGERATOR DOOR ALARMS
  if (fridgeEvent && (eventTime-prevEventTime > 100)) {                 //checking if a fridge event occurred
    fridgeEvent = 0;                 //reset flag for event trigger
    prevEventTime = eventTime;
    if (changedBits & 0b10000000) {  //do byte level compares to see which one
      //digital pin 7 triggered
      Serial.print(changedBits, BIN); Serial.println(" Wine fridge door opened or closed.");
    } else if (changedBits & 0b01000000) {
      //digital pin 6 triggered
      Serial.print(changedBits, BIN); Serial.println(" Beverage center fridge door opened or closed.");
    }   
  }
  }

ISR (PCINT2_vect) { //If any interrupt happens on the pins flagged for PCINT2 bus
  portDpast = portDstatus;
  portDstatus = PIND; //grab the current value of digital pins 0-7
  changedBits = portDpast ^ portDstatus;
  eventTime = millis();
  fridgeEvent = 1; //setting a flag so the main loop knows a button was pressed. Which one, we don't know yet
}


I greatly appreciate the input! I'm just learning and want to do so much more. :)

DrDiettrich

Most probably you configured the interrupts for level, not edge trigger.

Why do you think that you need interrupts? Polling the digital pins in loop() costs not really much more than testing a flag, set by an ISR.

cattledog

The inputs from the reed switches maybe floating when the magnets are apart. Please provide a schematic of how the magnetic switches and pin 6 and 7 inputs are wired. How was the pulldown resistor connected? Have you tried configuring pin 6 and 7 as INPUT_PULLUP?

jackman_fam

Thank you for the response, DrDiettrich. I wanted to use interrupts to have a better chance of not missing a rising or falling event. I intent to have several sensors connected including a radio, so I'm concerned about it being glitchy. I have read that interrupts aren't fail safe either, but it would allow an event to happen while doing other work.

If I'm missing something, I appreciate the input. I'm thinking about the core architectural design and didn't think a simple looping code segment that would do work occasionally would make sense.

jackman_fam

I will document this tonight (GMT-8) and also try the PULLUP. I did do that, but in the test I did I wasn't able to get it to trigger the reed sensor at all.  I will try again and post results.

Is there a way to measure scientifically a floating value problem? I have a nice handheld Fluke, but I don't have an o-scope.

Thanks!

jackman_fam

I just modeled out the current schematic. The resistor is a 10k.

I'm going to start experimenting again.

Shawn

cattledog

The input to pin 6 is floating (not connected to anything) when the reed switch is open.

Use INPUT_PULLUP on pin 6 with one side of the reed switch connected to pin6 and the other side to ground. You don't need the external resistor or the connection to 5v.

When the switch is closed, pin 6 will see ground and be low. When the switch is open, pin 6 will see the 5v of the internal pullup and will be high.

jackman_fam

I tried another reed switch using the internal pull-up resistor and I can't get anything out of it at all. I didn't use the 10k resistor in that reed switch configuration. I effectively just connected it from 5V to the arduino pin.

In the reed switch as I documented above (without using the internal pull-up), whenever the reed switch is triggered (when magnet is pulled away thus closing the circuit) the interrupt just keeps repeating constantly. Here is my output...

Code: [Select]
1100000 Beverage center fridge door opened or closed.
1100000 Beverage center fridge door opened or closed.
1100000 Beverage center fridge door opened or closed.
1100000 Beverage center fridge door opened or closed.
1100010 Beverage center fridge door opened or closed.
1100000 Beverage center fridge door opened or closed.
1000000 Beverage center fridge door opened or closed.
1000000 Beverage center fridge door opened or closed.
1000000 Beverage center fridge door opened or closed.
1000000 Beverage center fridge door opened or closed.

and so on...

jackman_fam

You nailed it! :)

The input to pin 6 is floating (not connected to anything) when the reed switch is open.

Use INPUT_PULLUP on pin 6 with one side of the reed switch connected to pin6 and the other side to ground. You don't need the external resistor or the connection to 5v.
One of the switches works perfectly. One only interrupts on the rising edge, so I am going to check over everything again.

Thank you very much!

DrDiettrich

Is there a way to measure scientifically a floating value problem? I have a nice handheld Fluke, but I don't have an o-scope.
You can use the attached circuit (don't know how to inline the image).

Connect the sensor/module as you would use it, but disconnect the unknown signal from any Arduino pin. Power up everything, then measure the voltage in active and non-active state of the module/sensor. Short pulses require to connect a scope instead of the DMM.

Then you may observe the following (approximate) voltages:
0: the output is driven LOW
U1: the output is driven HIGH
U1 / 2: the output is floating, requires an pull up/down resistor

Go Up