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.
  • J Offline
    J Offline
    Joost
    wrote on last edited by
    #1

    Hi everyone,

    as connecting a RFM95 radio uses Arduino digital pin 2, I am wondering if it is possible to use another pin besides pin 3 to get two ISR watched buttons connected to one node? I am looking into building general MySensor based remotes for controlling music, lights and other connected DIY hardware via MyController. In this scenario, only having a single button per battery powered node would be kind of inefficient.

    Thanks everyone for any clues,

    Joost

    Arduino ref regarding ISRs

    BearWithBeardB 1 Reply Last reply
    0
    • J Joost

      Hi everyone,

      as connecting a RFM95 radio uses Arduino digital pin 2, I am wondering if it is possible to use another pin besides pin 3 to get two ISR watched buttons connected to one node? I am looking into building general MySensor based remotes for controlling music, lights and other connected DIY hardware via MyController. In this scenario, only having a single button per battery powered node would be kind of inefficient.

      Thanks everyone for any clues,

      Joost

      Arduino ref regarding ISRs

      BearWithBeardB Offline
      BearWithBeardB Offline
      BearWithBeard
      wrote on last edited by BearWithBeard
      #2

      Hi Joost,

      the Arduino Reference article you linked explains how to setup external interrupts, of which the Pro Mini has only two: INT0 on D2 and INT1 on D3. But there are many more interrupt vectors available - for a complete list see page 74 of the megaAVR datasheet - including pin change interrupts which enable you to use (almost) any pin as an interrupt.

      Keep in mind though that pin change interrupts are lower priority than external interrupts and they will always call an interrupt on both the rising and falling edge. Since a button press usually changes the signal twice (closing and opening, plus possibly bouncing), you'll get two interrupts per click and and have to handle that in your ISR.

      Here are two resources that should help you setting up pin change interrupts:

      • https://thewanderingengineer.com/2014/08/11/arduino-pin-change-interrupts/
      • https://playground.arduino.cc/Main/PinChangeInterrupt/

      There are also dedicated libraries available which make pin change interrupts easier to use, but unfortunately I can't recommend any of these, as I have never used one.

      Nick Gammons excellent interrupts introduction is also always worth reading:
      http://www.gammon.com.au/interrupts

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

        Thanks very much for pointing me the way and linking all those docs/references!

        I'll try to make up a working example and leave it here as reference,
        bye,

        Joost

        1 Reply Last reply
        1
        • 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


                                  11

                                  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