Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. General Discussion
  3. Pro Mini + RFM95 and two ISR-watched buttons possible?

Pro Mini + RFM95 and two ISR-watched buttons possible?

Scheduled Pinned Locked Moved General Discussion
16 Posts 4 Posters 111 Views 4 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • electrikE Offline
    electrikE Offline
    electrik
    wrote on last edited by
    #4

    Look here for a working example with nrf24:

    https://github.com/rikki78/MySensors

    1 Reply Last reply
    1
    • J Offline
      J Offline
      Joost
      wrote on last edited by
      #5

      Thanks very much! Will start looking into this now!

      1 Reply Last reply
      0
      • J Offline
        J Offline
        Joost
        wrote on last edited by
        #6

        Hi everybody,
        thanks for you help, I got as far as this:

        #include <Arduino.h>
        #include <avr/interrupt.h>
        
        #define MY_RADIO_RFM95
        #include <MySensors.h>
        
        volatile int value = 1000;
        volatile char PinRegLast, ChangedPin, PinRegister;
        volatile unsigned long last_debounce_time=0;
        
        void setup()
        {
        noInterrupts();
        PCICR |= 0b00000011; // Enables Ports B and C Pin Change Interrupts
        PCMSK1 |= 0b00000110; //PCINT9 & PCINT10 = A1 & A2
        PCMSK1 |= 0b00001000; // PCINT11
        PCIFR  = B00000001; // Reset Interruptflag
        interrupts();
        pinMode(A1, INPUT_PULLUP); pinMode(A2, INPUT_PULLUP);
        Serial.begin(38400);
        }
        
        void presentation() {}
        
        void loop()
        {
          //_wokeUpByInterrupt = INVALID_INTERRUPT_NUM;
          Serial.print(value); Serial.print(" : ");Serial.println(PinRegister, BIN);
          sleep(160000);
        }
        
        ISR(PCINT1_vect)
        {
          if ( (long) millis() - last_debounce_time > 30)
          {
            //_wokeUpByInterrupt = 0xFE;
            PinRegister = PINC;
            ChangedPin = PinRegister ^ PinRegLast;
            PinRegLast = PinRegister;
            switch (ChangedPin){
            case (1 << PINC1):
              if (~PinRegister & (1 << PINC1)) value++;
              break;
            case (1 << PINC2):
              if (~PinRegister & (1 << PINC2)) value--;
              break;
            default:
              break;
            }
            last_debounce_time = millis();
        
          }
        }
        
        

        When I have this code without the MySensors parts (e.g. #inclue MySensors.h & sleep(..)) in it running, it kind of works plus/minus some debouncing issues. But when including MySensors and sleeping in loop(), there is rarely a reaction to pin changes and at no time a change of the variable "value", which is working without the MySensors bits in there.

        Is there something special to deal with when using sleep() together with PinChangeInterrupts?

        mfalkviddM 1 Reply Last reply
        0
        • J Joost

          Hi everybody,
          thanks for you help, I got as far as this:

          #include <Arduino.h>
          #include <avr/interrupt.h>
          
          #define MY_RADIO_RFM95
          #include <MySensors.h>
          
          volatile int value = 1000;
          volatile char PinRegLast, ChangedPin, PinRegister;
          volatile unsigned long last_debounce_time=0;
          
          void setup()
          {
          noInterrupts();
          PCICR |= 0b00000011; // Enables Ports B and C Pin Change Interrupts
          PCMSK1 |= 0b00000110; //PCINT9 & PCINT10 = A1 & A2
          PCMSK1 |= 0b00001000; // PCINT11
          PCIFR  = B00000001; // Reset Interruptflag
          interrupts();
          pinMode(A1, INPUT_PULLUP); pinMode(A2, INPUT_PULLUP);
          Serial.begin(38400);
          }
          
          void presentation() {}
          
          void loop()
          {
            //_wokeUpByInterrupt = INVALID_INTERRUPT_NUM;
            Serial.print(value); Serial.print(" : ");Serial.println(PinRegister, BIN);
            sleep(160000);
          }
          
          ISR(PCINT1_vect)
          {
            if ( (long) millis() - last_debounce_time > 30)
            {
              //_wokeUpByInterrupt = 0xFE;
              PinRegister = PINC;
              ChangedPin = PinRegister ^ PinRegLast;
              PinRegLast = PinRegister;
              switch (ChangedPin){
              case (1 << PINC1):
                if (~PinRegister & (1 << PINC1)) value++;
                break;
              case (1 << PINC2):
                if (~PinRegister & (1 << PINC2)) value--;
                break;
              default:
                break;
              }
              last_debounce_time = millis();
          
            }
          }
          
          

          When I have this code without the MySensors parts (e.g. #inclue MySensors.h & sleep(..)) in it running, it kind of works plus/minus some debouncing issues. But when including MySensors and sleeping in loop(), there is rarely a reaction to pin changes and at no time a change of the variable "value", which is working without the MySensors bits in there.

          Is there something special to deal with when using sleep() together with PinChangeInterrupts?

          mfalkviddM Offline
          mfalkviddM Offline
          mfalkvidd
          Mod
          wrote on last edited by
          #7

          @Joost I think you need to use a custom sleep command, like at https://github.com/rikki78/MySensors/blob/master/WallRemote/WallRemote.ino#L142

          J 1 Reply Last reply
          0
          • mfalkviddM mfalkvidd

            @Joost I think you need to use a custom sleep command, like at https://github.com/rikki78/MySensors/blob/master/WallRemote/WallRemote.ino#L142

            J Offline
            J Offline
            Joost
            wrote on last edited by
            #8

            @mfalkvidd Thanks, will try that.
            TBH I had seen that already in there, but hoped it would not be needed anymore (since that sketch is from 2016).
            Would I need to power down my RFM95 radio like it is done with the NRF24?
            Don't want to loose my 9microAmp sleeping current :-)

            Will get back with results tomorrow,

            Joost

            mfalkviddM 1 Reply Last reply
            0
            • J Joost

              @mfalkvidd Thanks, will try that.
              TBH I had seen that already in there, but hoped it would not be needed anymore (since that sketch is from 2016).
              Would I need to power down my RFM95 radio like it is done with the NRF24?
              Don't want to loose my 9microAmp sleeping current :-)

              Will get back with results tomorrow,

              Joost

              mfalkviddM Offline
              mfalkviddM Offline
              mfalkvidd
              Mod
              wrote on last edited by
              #9

              @Joost yes you would need to power down the rfm95 to get low sleeping current. I think the radio will need to be reinitialized when it is powered on again but I have no experience working on this low level.

              J 1 Reply Last reply
              0
              • BearWithBeardB Offline
                BearWithBeardB Offline
                BearWithBeard
                wrote on last edited by
                #10

                A good while ago I have experimented with a multi (touch) button node which used both external and pin change interrupts and did not need to use a custom sleep function. Here is the relevant excerpt of the latest sketch which I used. As far as I remember, it was working fine.

                Note that I was using a NRF24 radio. I'm not familiar with the RFM95, but I don't think that should be a problem. (Is the IRQ pin even needed for a regular sensor node?)

                #include <Arduino.h>
                #include <avr/interrupt.h>
                
                #define MY_RADIO_RF24
                [ other MySensors stuff ]
                #include <MySensors.h>
                
                void sense()
                {
                    // Handle interrupt
                }
                
                ISR(PCINT2_vect)
                {
                    // Handle interrupt
                }
                
                setup () 
                {
                    pinMode(2, INPUT);
                    pinMode(3, INPUT);
                    pinMode(4, INPUT);
                    cli();
                    PCICR |= 0b00000100; // Port D
                    PCMSK2 |= 0b00010000; // PCINT20 (D4)
                    sei();
                    attachInterrupt(0, sense, RISING); // (D2)
                    attachInterrupt(1, sense, RISING); // (D3)
                }
                
                void loop()
                {
                    // Do stuff, send messages
                	
                    sleep(0);
                }
                
                J 1 Reply Last reply
                0
                • mfalkviddM mfalkvidd

                  @Joost yes you would need to power down the rfm95 to get low sleeping current. I think the radio will need to be reinitialized when it is powered on again but I have no experience working on this low level.

                  J Offline
                  J Offline
                  Joost
                  wrote on last edited by
                  #11

                  @mfalkvidd Will look into this tonight or tomorrow; just as a quick note for me and potentially others:
                  Just found this thread with a very professional looking sketch by the author which seems a solid base to start upon:

                  https://forum.mysensors.org/topic/5704/rfm95-sleep-mode/6

                  Seemingly important parts from the sketch ( https://github.com/trlafleur/Soil_Moisture_Sensor_MS_R1.1-RFM95/blob/master/Soil_Moisture_Sensor_MS_R1.1-RFM95.ino ) :

                  void systemSleep()
                  {
                      debug1(PSTR("\n*** Going to Sleep ***\n"));
                      wait (100);
                      // put led's, radio and flash to sleep
                      // Turn off LED's
                      pinMode (MY_DEFAULT_TX_LED_PIN, INPUT);
                      pinMode (MY_DEFAULT_RX_LED_PIN, INPUT);
                      pinMode (MY_DEFAULT_ERR_LED_PIN, INPUT);
                      pinMode (OnBoardLed, INPUT); 
                      
                      // Put Flash to sleep
                      
                  
                      // Put Radio and transport to Sleep
                      transportPowerDown();               // Shut down radio and MySensor transport
                      
                      interrupts();                       // make sure interrupts are on...
                      LowPower.standby();                 // SAMD sleep from LowPower systems
                      
                         //  .... we will wake up from sleeping here if triggered from an interrupt
                      interrupts();                       // make sure interrupts are on...                                      
                  }
                  
                  /* **************** System Wake-up from Sleep ******************* */
                  void systemWakeUp() 
                  {                                          
                      
                  //  re enable LED's if needed
                  //    pinMode (MY_DEFAULT_TX_LED_PIN, OUTPUT);
                  //    pinMode (MY_DEFAULT_RX_LED_PIN, OUTPUT);
                  //    pinMode (MY_DEFAULT_ERR_LED_PIN, OUTPUT);
                  //    pinMode (OnBoardLed, OUTPUT);  
                  
                      // wake up Flash if needed
                  
                      // wake up MySensor transport and Radio from Sleep
                      //transportInit();
                      hwSleep(1);                         // as MySensor had NO sleep or Watch Dog for SAMD, this will
                                                          // wake us up so that we can send and receive messages
                      while (!isTransportReady()) {       // Make sure transport is ready
                      _process(); }
                  
                      interrupts();                       // make sure interrupts are on...
                  }
                  
                  1 Reply Last reply
                  0
                  • BearWithBeardB BearWithBeard

                    A good while ago I have experimented with a multi (touch) button node which used both external and pin change interrupts and did not need to use a custom sleep function. Here is the relevant excerpt of the latest sketch which I used. As far as I remember, it was working fine.

                    Note that I was using a NRF24 radio. I'm not familiar with the RFM95, but I don't think that should be a problem. (Is the IRQ pin even needed for a regular sensor node?)

                    #include <Arduino.h>
                    #include <avr/interrupt.h>
                    
                    #define MY_RADIO_RF24
                    [ other MySensors stuff ]
                    #include <MySensors.h>
                    
                    void sense()
                    {
                        // Handle interrupt
                    }
                    
                    ISR(PCINT2_vect)
                    {
                        // Handle interrupt
                    }
                    
                    setup () 
                    {
                        pinMode(2, INPUT);
                        pinMode(3, INPUT);
                        pinMode(4, INPUT);
                        cli();
                        PCICR |= 0b00000100; // Port D
                        PCMSK2 |= 0b00010000; // PCINT20 (D4)
                        sei();
                        attachInterrupt(0, sense, RISING); // (D2)
                        attachInterrupt(1, sense, RISING); // (D3)
                    }
                    
                    void loop()
                    {
                        // Do stuff, send messages
                    	
                        sleep(0);
                    }
                    
                    J Offline
                    J Offline
                    Joost
                    wrote on last edited by
                    #12

                    @BearWithBeard Thanks; will look into this as well.
                    Seems to me that the main difference is your sleep(0) vs. my sleep(16000), but who knows, perhaps that makes a difference. Btw, I believe Pin2 with the attached IRQ is obligatory for RFM95 radios (at least it's the default in MySensors, and I designed my PCB according to this).

                    1 Reply Last reply
                    0
                    • J Offline
                      J Offline
                      Joost
                      wrote on last edited by
                      #13

                      Well, seems MySensors and the Low-Power lib in its latest revisions don't play nice together, bummer...

                      Getting

                      Compiling .pio/build/pro8MHzatmega328/src/main.cpp.o
                      Linking .pio/build/pro8MHzatmega328/firmware.elf
                      LowPower.cpp.o (symbol from plugin): In function `LowPowerClass::idle(period_t, adc_t, timer2_t, timer1_t, timer0_t, spi_t, usart0_t, twi_t)':
                      (.text+0x0): multiple definition of `__vector_6'
                      .pio/build/pro8MHzatmega328/src/main.cpp.o (symbol from plugin):(.text+0x0): first defined here
                      collect2: error: ld returned 1 exit status
                      *** [.pio/build/pro8MHzatmega328/firmware.elf] Error 1
                      

                      and it looks like I'm not the only one: :confused:
                      Github issue

                      electrikE 1 Reply Last reply
                      0
                      • J Joost

                        Well, seems MySensors and the Low-Power lib in its latest revisions don't play nice together, bummer...

                        Getting

                        Compiling .pio/build/pro8MHzatmega328/src/main.cpp.o
                        Linking .pio/build/pro8MHzatmega328/firmware.elf
                        LowPower.cpp.o (symbol from plugin): In function `LowPowerClass::idle(period_t, adc_t, timer2_t, timer1_t, timer0_t, spi_t, usart0_t, twi_t)':
                        (.text+0x0): multiple definition of `__vector_6'
                        .pio/build/pro8MHzatmega328/src/main.cpp.o (symbol from plugin):(.text+0x0): first defined here
                        collect2: error: ld returned 1 exit status
                        *** [.pio/build/pro8MHzatmega328/firmware.elf] Error 1
                        

                        and it looks like I'm not the only one: :confused:
                        Github issue

                        electrikE Offline
                        electrikE Offline
                        electrik
                        wrote on last edited by
                        #14

                        @Joost I've used mysensors V2 I believe...

                        1 Reply Last reply
                        0
                        • J Offline
                          J Offline
                          Joost
                          wrote on last edited by Joost
                          #15

                          *** Edit: sorry, all below seems to be wrong / misuse of sleep(); see end of linked thread from 2017

                          Some news: I found this comment https://forum.mysensors.org/post/56372 by @DavidZH who possibly described what I seem to be seeing as well (no wakeups via PinChangeInterrupt when using MySensors sleep() function as posted above) and who also posted a workaround (thanks David for posting this in 2017!!):

                          sleep(0xff,0x00, 0xff, 0x00, 0); 
                          

                          Quote: "...As soon as I change any of the parameters, the node will not wake up anymore...."

                          Now indeed my node can be woken via PinChangeInterrupts on Pin A1 and A2 and is down to some unbelievable 1microAmp in between (by means of a cheap Multimeter) with no radio/transport initialization so far.
                          So, with just preliminary testing so far this might be the solution (did not check radio transmission after interrupts for now).
                          Could someone shed some light on what these parameters do to the sleep function? Looked here of course https://www.mysensors.org/download/sensor_api_20#sleeping but couldn't make sense out of 0xFF, 0x00 .
                          Thanks everyone,

                          Joost

                          ********************** End of edit

                          1 Reply Last reply
                          0
                          • J Offline
                            J Offline
                            Joost
                            wrote on last edited by Joost
                            #16

                            PS: one downside will probably be not being able to wake up programmatically and double the node as a e.g. temperature / climate sensor, as I had in mind.

                            Sorry for the confusion above, too little sleep in the last days (at least I hope that explains it :-) )

                            Perhaps @Yveaux can help here on how to combine pin change interrupts and timer wake into a successful sleep() command? So far it looks like that would be possible with Low-Power lib, but this is not compiling in conjunction with MySensors 2.3.2.

                            1 Reply Last reply
                            0
                            Reply
                            • Reply as topic
                            Log in to reply
                            • Oldest to Newest
                            • Newest to Oldest
                            • Most Votes


                            12

                            Online

                            11.7k

                            Users

                            11.2k

                            Topics

                            113.1k

                            Posts


                            Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                            • Login

                            • Don't have an account? Register

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • MySensors
                            • OpenHardware.io
                            • Categories
                            • Recent
                            • Tags
                            • Popular