DoorBell goes off Unpredictibly

Status
Not open for further replies.
The internal pull-up resistor on an Arduino input is something like 20,000 Ohms.

That makes the inputs extremely sensitive to input noise (including static and nearby radio transmitters, mobile phones etc.)if there are anything other than fairly short wires connected. That's why I suggested an extra resistor to reduce its sensitivity to interference.

Also, rather than relying on there being an interrupt, check the input pin and verify it stays low for eg. 20mS minimum before considering it a valid switch activation.
 

My Code change appears to have corrected the unpredictable doorbell ringing. However, another question comes up. That is, what may have caused the processor to wake up when the bell switch was not pressed?

I have modified Figure B and the raw code follows. Suggested changes have not be done yet.
Please suggest.



Code:
// --------------------------------------------------------
//  Set Board to Arduino Pro or Pro Mimi
//  Set Processor to ATmega328P (3.3V, 8 MHz)
//  Set COM port
// --------------------------------------------------------

#include <RFM69.h>
#include <LowPower.h>

// RFM69 frequency, uncomment the frequency of your module:
//#define FREQUENCY   RF69_433MHZ
#define FREQUENCY     RF69_915MHZ

// AES encryption (or not):
#define ENCRYPT       true // Set to "true" to use encryption
//#define ENCRYPT       false // Set to "true" to use encryption
#define ENCRYPTKEY    "TOPSECRETPASSWRD" // Use the same 16-byte key on all nodes

// Use ACKnowledge when sending messages (or not):
#define USEACK        true // Request ACKs or not

// Create a library object for our RFM69HCW module:
RFM69 radio;

//----------------------------------------------------------------
const byte interruptPin = 3;

// Addresses for this node. CHANGE THESE FOR EACH NODE!
int networkID = 144;  // Must be the same for all nodes
int thisNodeID = 4;  // This node ID - Set in setup
int toNodeID = 1;  // Destination node ID

byte ledPin = 9;

char switchStateOPEN[] = "144-4-SO";
char switchStateCLOSED[] = "144-4-SC";

volatile bool interruptReceived = false;

byte sensorMode = LOW;

void setup ()
{
  pinMode (interruptPin, INPUT_PULLUP);
  attachInterrupt (digitalPinToInterrupt(interruptPin), handleInterrupt, CHANGE );  
  
  pinMode (ledPin, OUTPUT);  

  // Isolated relay output
  pinMode (A0, OUTPUT);
  digitalWrite (A0, LOW);

  if (digitalRead(interruptPin) == LOW)
  {
    digitalWrite (ledPin, LOW);
  }
  else
  {
    digitalWrite (ledPin, HIGH);
  }
  
  // Switch Mode Pin
  pinMode (8, INPUT_PULLUP);
  if (digitalRead (8) == LOW)
  {
    // swap sensor action
     sensorMode = HIGH;
  }
    
  // Initialize the RFM69HCW:
  radio.initialize(FREQUENCY, thisNodeID, networkID);
  //radio.initialize(FREQUENCY, myNodeID, NETWORKID);
  radio.setHighPower(); // Always use this for RFM69HCW
  // Turn on encryption if desired:
  if (ENCRYPT) radio.encrypt(ENCRYPTKEY);

}  //End setup()


void loop ()
{
  if (interruptReceived == true)
  {
    sendSwitchState();
    interruptReceived == false;
  }

  //  Check again
  if (interruptReceived == true)
  {
    sendSwitchState();
    interruptReceived == false;
  }
  
  radio.sleep();  
  //LowPower.powerDown(SLEEP_2S, ADC_OFF, BOD_OFF);
  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
  // do nothing
}

void handleInterrupt ()
{
  interruptReceived = true;
}

void sendSwitchState()
{
  if (digitalRead(interruptPin) == sensorMode)
  //if (digitalRead(interruptPin) == LOW)
  {
    // Switch Closed
    digitalWrite(ledPin,LOW);
    if (radio.sendWithRetry(toNodeID, switchStateCLOSED, strlen(switchStateCLOSED)+1))    
    {  }  // ACK received!
    else
    {  }  // No ACK received
    delay (1000);
  }
  else
  {
    // Switch Open
    digitalWrite(ledPin,HIGH);
    if (radio.sendWithRetry(toNodeID, switchStateOPEN, strlen(switchStateOPEN)+1))
    {  }  // ACK received!        
    else
    {  }  // No ACK received
    digitalWrite (A0, HIGH);
    delay (1000);
    digitalWrite (A0, LOW);
  }  
}  // End void sendSwitchState()
 
I have no idea about how to to deal with interrupts in "C". I find assembler easier to understand. Probably some other members will be able to help you with your "C" code.

Les.
 
I have no idea about how to to deal with interrupts in "C". I find assembler easier to understand. Probably some other members will be able to help you with your "C" code.

Les.

It's even easier in C, at least on a PIC, here's an example:

Code:
void __interrupt() INTERRUPT_InterruptManager (void)
{
    // interrupt handler
    if(PIE0bits.IOCIE == 1 && PIR0bits.IOCIF == 1)
    {
        if(IOCCFbits.IOCCF3 == 1)
        { 
            IOCCFbits.IOCCF3 = 0;
            if (CNT_IN == 0)
            {
                InputCnt++;
                INPUT_FLAG=true;
            }
            else if (CNT_IN == 1)
            {

            }
        }
        else if(IOCCFbits.IOCCF4 == 1)
        { 
            IOCCFbits.IOCCF4 = 0; 
            if (SER_IN == 1)
            {
                Delay_ms(100);
                if (SER_IN == 1)
                {
                    NEW_SERIAL_FLAG=true;
                    //disable interrupt on change for serial input - positive
                    IOCCPbits.IOCCP4 = 0;
                    // reset RX usart
                    RC1STAbits.SPEN = 1;
                    RC1STAbits.CREN = 0;
                    RC1STAbits.CREN = 1;
                }
            }
            else if (SER_IN == 0)
            {
                //Delay_ms(100);
                //if (SER_IN == 0)
                //{
                    //NEW_SERIAL_FLAG=false;
                //}
            }
        }
    }
    if(INTCONbits.PEIE == 1)
    {
        if(PIE3bits.TX1IE == 1 && PIR3bits.TX1IF == 1)
        {
            if(sizeof(eusart1TxBuffer) > eusart1TxBufferRemaining)
            {
                TX1REG = eusart1TxBuffer[eusart1TxTail++];
                if(sizeof(eusart1TxBuffer) <= eusart1TxTail)
                {
                    eusart1TxTail = 0;
                }
                eusart1TxBufferRemaining++;
            }
            else
            {
                PIE3bits.TX1IE = 0;
            }
        } 
        else if(PIE3bits.RC1IE == 1 && PIR3bits.RC1IF == 1)
        {
            if(1 == RC1STAbits.OERR)
            {
                // EUSART1 error - restart

                RC1STAbits.CREN = 0;
                RC1STAbits.CREN = 1;
            }

            // buffer overruns are ignored
            char c = RC1REG;
            eusart1RxBuffer[eusart1RxHead++] = c;
            if (c == CR)
            {
                SERIAL_FLAG=true;
            }
            //eusart1RxBuffer[eusart1RxHead++] = RC1REG;
            if(sizeof(eusart1RxBuffer) <= eusart1RxHead)
            {
                eusart1RxHead = 0;
            }
            eusart1RxCount++;
        } 
        else
        {
            //Unhandled Interrupt
        }
    }      
    else
    {
        //Unhandled Interrupt
    }
}

[/code}

The first line is what makes it an interrupt routine, Arduino is similar, and there's no messing about siting the routine at the correct address, or saving/restoring registers.

Most of that routine was created automatically from within MPLABX.
 

Thanks. Very interesting.

So far, I have determined that the unpredictable doorbell ringing was due to the processor waking up when no interrupt has occurred. My code change seems to have fixed that. However, something was causing the processor to wake up anyway once in a while.

Still, the switch line from the Arduino to the switch is 25 to 30 feet of #18 wire.

Maybe add a 1K resistor from pin 3 to ground?
 
Maybe add a 1K resistor from pin 3 to ground?
That would short out the bellpush.
Put it from pin 3 to the +3.3V so the input is held high when the bellpush is not pressed.

If it still triggers erratically, you could add a small capacitor from pin 3 to ground/0V, to bypass RF interference. Try 10nF or 100nF, a ceramic or plastic film type.
 

Yes. Pin 3 to +3.3V. I don't know what I was thinking.
 

Thanks. I will have to study this one for a bit.
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…