Arduino pro mini, rfm69 with 2 Reed switches on interrupts?



  • Hi,

    I am trying to build my first sensor using an arduino pro mini (3v), an rfm69hw and two Reed switches on sundbergh84s easypcb.

    Its purpose is to let me know whether there is mail in my mailbox. One Reed switch sends a message when the mailman has opened the little hatch in my mailbox ->there is mail in the mail box.

    The other switch sends a message when the big hatch has been opened -> mail has been collected by somebody in the family, the mailbox is empty.

    To conserve battery power I planned on connecting each switch to an interrupt pin, but I realised that the rfm69hw also needs an interrupt pin...

    Am I out of luck or does somebody have an idea how I can make my mailbox smart?


  • Mod

    @kiesel other pins can be used for interrupts. I have not had a need to use it myself, but see the last posts in https://forum.mysensors.org/post/103080



  • @mfalkvidd thanks, I read the thread and will try to figure out how to use this with sleep().

    If anybody has any sketches with NodeManager and sleep I'd be grateful l for a link 🙂



  • I adapted code I found online and except for a few hickups it seems to work. Thanks to anticimex for making this code available:

    /*
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2019 Sensnology AB
     * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * DESCRIPTION
     *
     * Interrupt driven binary switch example with dual interrupts
     * Author: Patrick 'Anticimex' Fallberg
     * Connect one button or door/window reed switch between
     * digital I/O pin 3 (BUTTON_PIN below) and GND and the other
     * one in similar fashion on digital I/O pin 2.
     * This example is designed to fit Arduino Nano/Pro Mini
     *
     */
    
    
    // Enable debug prints to serial monitor
    //#define MY_DEBUG
    
    // Enable and select radio type attached
    #define MY_RADIO_RFM69
    #define MY_IS_RFM69HW
    #define MY_RFM69_NEW_DRIVER
    
    #define MY_NODE_ID 2
    
    #include <MySensors.h>
    
    #define SKETCH_NAME "Briefkasten"
    #define SKETCH_MAJOR_VER "1"
    #define SKETCH_MINOR_VER "0"
    
    #define PRIMARY_CHILD_ID 3
    #define SECONDARY_CHILD_ID 4
    
    #define PRIMARY_BUTTON_PIN 3   // Arduino Digital I/O pin for button/reed switch
    #define SECONDARY_BUTTON_PIN 8 // Arduino Digital I/O pin for button/reed switch
    
    
    volatile static uint8_t valueSecondary=2;
    
    // Change to V_LIGHT if you use S_LIGHT in presentation below
    MyMessage msg(PRIMARY_CHILD_ID, V_TRIPPED);
    MyMessage msg2(SECONDARY_CHILD_ID, V_TRIPPED);
    
    void pciSetup(byte pin)
    {
        *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin));  // enable pin
        PCIFR  |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
        PCICR  |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group
    }
    
    ISR (PCINT0_vect) // handle pin change interrupt for D8 to D13 here
     {    
        //delayMicroseconds(2);
        valueSecondary = digitalRead(SECONDARY_BUTTON_PIN); // ISRs need to finish very fast or the arduino crashes. 
     }
    
    void setup()
    {
      // Setup the buttons
      pinMode(PRIMARY_BUTTON_PIN, INPUT_PULLUP);
      pinMode(SECONDARY_BUTTON_PIN, INPUT_PULLUP);
      pciSetup(SECONDARY_BUTTON_PIN);
    }
    
    void presentation()
    {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo(SKETCH_NAME, SKETCH_MAJOR_VER "." SKETCH_MINOR_VER);
    
      // Register binary input sensor to sensor_node (they will be created as child devices)
      // You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage.
      // If S_LIGHT is used, remember to update variable type you send in. See "msg" above.
      present(PRIMARY_CHILD_ID, S_DOOR);
      present(SECONDARY_CHILD_ID, S_DOOR);
    }
    
    // Loop will iterate on changes on the BUTTON_PINs
    void loop()
    {
      uint8_t valuePrimary;
      static uint8_t lastValuePrimary=2;
      static uint8_t lastValueSecondary=2;
    
      // Short delay to allow buttons to properly settle
      delay(5);
    
      Serial.println("Woken up");
      valuePrimary = digitalRead(PRIMARY_BUTTON_PIN);
    
      //Serial.print("Primary value: ");
      //Serial.println(value);
    
      if (valuePrimary != lastValuePrimary) {
        // Value has changed from last transmission, send the updated value
        Serial.print("Primary:");
        Serial.println(valuePrimary);
        send(msg.set(valuePrimary));
        lastValuePrimary = valuePrimary;
      }
    
      if (valueSecondary != lastValueSecondary) {
          // Value has changed from last transmission, send the updated value
          Serial.print("Secondary:");
          Serial.println(valueSecondary);
          send(msg2.set(valueSecondary));
          lastValueSecondary = valueSecondary;
      }
    
    
    
      // Sleep until something happens with the sensor
      //sleep(PRIMARY_BUTTON_PIN-2, CHANGE, SECONDARY_BUTTON_PIN-2, CHANGE, 0);
      sleep(PRIMARY_BUTTON_PIN-2, CHANGE, 0);
    }
    

    If anybody has some improvements I'd like to hear them! This is my first time adapting/writing C-code, so a lot could probably be better.

    I noticed that sometimes the reed switch "Ignores" a change, can that happen because I moved the magnet too quickly or should I buy better switches?

    Also, I tried "FALLING" in the sleep function, but it the arduino woke up on HIGH and LOW, shouldn't it only wake up on LOW?



  • This post is deleted!


  • @kiesel

    Found on here:
    Quote:

    Commented by Manoraj Gnanadhas (Atmel)
    2015-01-20 06:23:36 GMT
    [Recipients: Nick Gammon]

    Hello Nick,

    Our design team has confirmed that “Note-3 mentioned under Table 10-1” is a datasheet bug. So you can use any type of interrupt (Rising edge/ Falling edge / Low level / Any logical change) to wake up from sleep mode. Sorry for the inconvenience caused.

    Best Regards,
    Manoraj Gnanadhas

    Not responding to reed relay:
    PRIMARY_BUTTON_PIN interrupt is active only in sleep. if you're (un)lucky enough to move magnet when cpu is awake it will ignore it.

    More likely is that relay bounce longer than wake up time + 5ms in your loop.
    Do away with pin reading, serial print and delay, shorter your loop, longer battery life.
    In ISR (PCINT0_vect) set flag, then in a loop check for that flag.
    If it's set it's secondary buttton pin that avoke your cpu,
    if it's not set it's primary button .

    I'm reusing your variables:

    #include <avr/sleep.h>
    #define DEBUG  // coment out when ready to go into the box 
    #ifndef DEBUG //disable serial in production compile, potentially saves few uA in sleep mode
         #define MY_DISABLED_SERIAL
    #endif
    ISR (PCINT0_vect) // handle pin change interrupt for D8 to D13 here
     {    
        //delayMicroseconds(2);
        valueSecondary = true; // ISRs need to finish very fast or the arduino crashes. 
    void loop()
    {
       // Sleep until something happens with the sensor
      //sleep(PRIMARY_BUTTON_PIN-2, CHANGE, SECONDARY_BUTTON_PIN-2, CHANGE, 0);
      sleep_bod_disable();//disable BOD  - saves~ 15uA
      sleep(PRIMARY_BUTTON_PIN-2, CHANGE, 0);
    
      #ifdef DEBUG   //get rid of unnecessary slow downs when ready    
      Serial.println("Woken up");
      #endif
      
    
      if (valueSecondary == true){
             valueSecondary = false;
             #ifdef DEBUG     //get rid of unnecessary slow downs when ready    
             Serial.print("Secondary:");
             #endif
             send(msg2.set(1)); //box emptied/mail in the box
      }
      else{
          #ifdef DEBUG   //get rid of unnecessary slow downs when ready    
           Serial.print("Primary:");
          #endif
          send(msg.set(1));//mail in the box/box emptied
      }
    }
    

    Unless you really need to know if box was opened then closed, then check pin states in my if/else after 10-50ms delay, experiment until you get no bounce errors. BUT it will increase battery drain SIGNIFICANTLY.
    You will have 2 messages sent per event, one per door opening and one per door closing.



  • @Sasquatch that's a great idea, thank you very much!

    I'll try that code out tomorrow. Thanks again!



  • Just a thought.
    I would personally go for one child ID/sensor.
    "There is uncollected mail" indicator.
    Set it to true when small door is tripped, and set to false when big door in open.


Log in to reply
 

Suggested Topics

  • 1
  • 198
  • 2
  • 1
  • 1
  • 6

49
Online

11.4k
Users

11.1k
Topics

112.6k
Posts