Hi everyone,
I am using a regular Moteino to create a two button remote. There is an "up" button and a "down" button.
I successfully attached an interrupt on D3 and used the enable interrupts library to enable another interrupt on D5 for each of the buttons. This worked reliably to trigger the Moteino to send out a message.
Then I introduced the "OneButton" library to detect single / double / long clicks to change the message sent out by the remote. This also worked reliably and it appears to use some simple millis() calculations to "debounce" and determine what type of click.
Now, lastly, I am trying to use the LowerPower library to put the Moteino and radio to sleep. It should wake upon a button press and then detect single/double/long click and send the message as it was doing before. However, this is where I am running into issues.
In the code below I removed the functions for the double and long click just to simplify the troubleshooting process. It should now only look for single clicks.
The Moteino successfully wakes up upon pressing either button. I know this works because of the quick LED flash I added in after it wakes up. However, the only way I can get the single click functions to call is if I quickly release and press the button again during the time that the LED is flashed on/off. If I remove this LED flash code, then everything happens too fast and I can't release and press again fast enough. Holding the button down will not trigger the single click to flash.
It is almost like I have to press the button once to trigger the interrupt, and then press it again quickly to get it to register the button press. This was not an issue before I tried putting the Moteino to sleep. When I was only using the interrupt to test the button click it worked perfectly.
I'm assuming this is some kind of timing issue or millis() problem after the Moteino wakes up? Any help would be appreciated! Thank you
#define EI_NOTEXTERNAL
#include <EnableInterrupt.h>
#include <LowPower.h>
#include <OneButton.h>
#include <RFM69.h>
#include <SPI.h>
// Setup a new OneButton on pin D5 (UP BUTTON) --> true parameter enables the pullup resistor on this pin
OneButton button1(5, true);
// Setup a new OneButton on pin D3 (DOWN BUTTON) --> true parameter enables the pullup resistor on this pin
OneButton button2(3, true);
#define UPPIN 5
#define DOWNPIN 3
// Addresses for this node. CHANGE THESE FOR EACH NODE!
#define NETWORKID 0 // Must be the same for all nodes
#define MYNODEID 2 // My node ID
#define TONODEID 1 // Destination node ID
// RFM69 frequency
#define FREQUENCY RF69_915MHZ
// AES encryption (or not):
#define ENCRYPT true // 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
// Packet sent/received indicator LED (optional):
#define LED 4 // LED positive pin
//#define GND 8 // LED ground pin
// Create a library object for our RFM69HCW module:
RFM69 radio;
int sendlength = 1;
char message[] = "1";
volatile bool newbutton = false;
/*--------------------------------------------------------------------------------------------------------------------------------------------------------------*/
void setup() {
pinMode(LED,OUTPUT);
digitalWrite(LED,LOW);
// link the button 1 functions.
button1.attachClick(click1); //single click
// link the button 2 functions.
button2.attachClick(click2); //single click
//Initialize the RFM69HCW:
radio.initialize(FREQUENCY, MYNODEID, NETWORKID);
// Turn on encryption if set to true above
if (ENCRYPT)
radio.encrypt(ENCRYPTKEY);
}
/*--------------------------------------------------------------------------------------------------------------------------------------------------------------*/
void upinterrupt(){
newbutton = true;
}
/*--------------------------------------------------------------------------------------------------------------------------------------------------------------*/
void downinterrupt(){
newbutton = true;
}
/*--------------------------------------------------------------------------------------------------------------------------------------------------------------*/
void loop()
{
digitalWrite(LED,LOW); //make sure the LED is off before going to sleep indefinitely.
//These interrupts will wake the module when it is powered down to save battery
enableInterrupt(UPPIN, upinterrupt, FALLING); //enables interrupt on UPPIN and calls upinterrupt
attachInterrupt(digitalPinToInterrupt(DOWNPIN), downinterrupt, FALLING); //enables interrupt on DOWNPIN and calls downinterrupt
radio.sleep(); //Put the RFM69 to sleep
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); //Put Moteino to power down sleep. Will wake on interrupt and run the next line of code after ISR
//First line to run after the ISR that wakes the module:
disableInterrupt(UPPIN);
detachInterrupt(DOWNPIN); //Prevents interrupts being called again until everything is complete
digitalWrite(LED,HIGH);
delay(100);
digitalWrite(LED,LOW);
delay(250);
if(newbutton){ //ISR that wakes up module will set this to true
button1.tick(); //check button1 (UP) for click, double click, hold
button2.tick(); //check button1 (UP) for click, double click, hold //checking to see what button was pressed and if click/doubleclick/hold
}
} // loop
/*--------------------------------------------------------------------------------------------------------------------------------------------------------------*/
//UP BUTTON PRESSED
void click1() {
message[0] = '1';
if (radio.sendWithRetry(TONODEID, message, sendlength)){
digitalWrite(LED,LOW);
delay(150);
digitalWrite(LED,HIGH); //ack received, quick confirm flash
delay(250);
digitalWrite(LED,LOW);
delay(150);
digitalWrite(LED,HIGH);
delay(250);
digitalWrite(LED,LOW);
}
else{ //no ack received, assume receiver did not get message. Slow flash.
digitalWrite(LED,HIGH);
delay(1000);
digitalWrite(LED,LOW);
}
newbutton = false;
}
/*--------------------------------------------------------------------------------------------------------------------------------------------------------------*/
// DOWN BUTTON PRESSED
void click2() {
message[0] = '3';
if (radio.sendWithRetry(TONODEID, message, sendlength)){
digitalWrite(LED,LOW);
delay(150);
digitalWrite(LED,HIGH); //ack received, quick confirm flash
delay(250);
digitalWrite(LED,LOW);
delay(150);
digitalWrite(LED,HIGH);
delay(250);
digitalWrite(LED,LOW);
}
else{ //no ack received, assume receiver did not get message. Slow flash.
digitalWrite(LED,HIGH);
delay(1000);
digitalWrite(LED,LOW);
}
newbutton = false;
}
// click2