Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

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.
 
I suggest you add code to the interrupt handler to verify that pin 3 (Which I assume is (INT0)/ PD2 on the ATMEGA328P) is still low at between 100 and 500 mS after the interrupt has occurred. If it not still low then take no action. You have still not given any details of the transmitter and monitor and how it is connected to your block diagram.

Les.

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.

DoorBell2.jpg


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.
 
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.

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.
 
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.
 
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. I will have to study this one for a bit.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top