Thanks for the helpful replies which I will act on.
As suggested, I will post the full code here in case anyone has the opportunity to look and can spot any errors.
I built the sketch modularly to try to ensure everything worked before bringing it together, but I will start to strip back to basics, checking and testing as I go (again!!)
At the moment I am foxed. This is the biggest thing I have attempted so far, and it will not beat me!
The interrupts all seem to fire correctly when I expect them to, but I am getting unexpected ones in the interim when nothing has been activated.
Thanks for the help so far. Any further suggestions gratefully received.
[code]
//Initialisation ==============================================
//for battery voltage ============
#define VBATPIN A9
float measuredvbat;
int healthCheck;
// For the RTC ===========
#include "Wire.h"
#include "RTClibExtended.h"
#define RTCwakePin 1
volatile bool clockAlarm = false;
RTC_DS3231 RTC;
// For Sleep mode ===========
#include "LowPower.h"
// For the sensor =============
#define sensorWakePin 0
int waterLevel;
volatile bool sensorAlarm = false;
volatile int valA;
int waterLevelSent;
// For LoRa ============
#include <SPI.h>
#include <LoRa.h>
#define RFM95_CS 8
#define RFM95_RST 4
#define RFM95_INT 7
void setup() {
// For the RTC ====================================================
pinMode(RTCwakePin, INPUT_PULLUP);
//Initialize communication with the clock
Wire.begin();
RTC.begin();
// dECIDE IF TO LEAVE THE BELOW OR REMOVE - NEED TO SET RTC SEPERATELY IF REMOVED
//RTC.adjust(DateTime(__DATE__, __TIME__)); //set RTC date and time to COMPILE time
//Set SQW pin to OFF
RTC.writeSqwPinMode(DS3231_OFF);
initiateAlarm(); //call fn to clear and set alarms
//Set alarm1 every day at 09:00 - minutes first then hour, 0 for secs no account of daylight saving time
//RTC.setAlarm(ALM1_MATCH_HOURS, 0, 0, 09, 0);
//Set alarm1 at 1 min past the hour past the minute REMOVE IN FINAL
RTC.setAlarm(ALM1_MATCH_MINUTES, 0, 01, 0, 0);///REMOVE IN FINAL
// For the Water Sensor ====================================
pinMode(sensorWakePin, INPUT_PULLUP);
// For LoRa ===============================
LoRa.setPins(RFM95_CS, RFM95_RST, RFM95_INT);
//433E6 or 868E6
// Change sync word (0xF3)ranges from 0-0xFF
//LoRa.setSyncWord(0xF3);
while (!LoRa.begin(868E6))
{
;
}
LoRa.setTxPower(20);
LoRa.enableCrc(); //prevent bad packets
//Set Spreading Factor to 12 for more robust, yet slowest signal
//LoRa.setSpreadingFactor(12);
//Set coding rate for best signal immunity - range 5 - 8 - default 5 8 doubles TX time!!
//LoRa.setCodingRate4(8);
//LoRa.setSignalBandwidth();
}
void RTCWakeUp() {
clockAlarm = true;
}
void sensorWakeUp() {
valA = digitalRead(sensorWakePin);
sensorAlarm = true;
}
void loop() {
USBDevice.attach();//remove in final
// rtc interrupt response
if (clockAlarm) {
clockAlarm = !clockAlarm; //reset flag
initiateAlarm();
measuredvbat = analogRead(VBATPIN);
measuredvbat *= 2; // we divided by 2, so multiply back
measuredvbat *= 3.3; // Multiply by 3.3V, our reference voltage
measuredvbat /= 1024; // convert to voltage
if (measuredvbat >= 3.4) {
healthCheck = 2;
}
else {
healthCheck = 3;
}
LORATXHealth();
}
// sensor interrupt response
if (sensorAlarm) {
sensorAlarm = !sensorAlarm;// reset flag
sensorDebounce();
//only send packet via Lora if there has been a change to water level since last packet sent
if ((waterLevel) != (waterLevelSent)) {
LORATXSensor();
}
}
// once dealt with interrupts, can go back to sleep
goToSleep();
}
void goToSleep() {
noInterrupts();
attachInterrupt(digitalPinToInterrupt(sensorWakePin), sensorWakeUp, CHANGE);
attachInterrupt(digitalPinToInterrupt(RTCwakePin), RTCWakeUp, FALLING);
//LoRa sleep???
interrupts();
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
//Disable external pin interrupts on wake up
detachInterrupt(digitalPinToInterrupt(RTCwakePin));
detachInterrupt(digitalPinToInterrupt(sensorWakePin));
}
void initiateAlarm() {
//clear any pending alarms and reset
RTC.armAlarm(1, false);
RTC.clearAlarm(1);
RTC.alarmInterrupt(1, false);
RTC.armAlarm(2, false);
RTC.clearAlarm(2);
RTC.alarmInterrupt(2, false);
RTC.alarmInterrupt(1, true);//reset
}
void sensorDebounce() {
//not really debounce. Just checking if water level is the same 3 secs later and only take action if so.
delay(3000);
int valB = digitalRead(sensorWakePin);
if ((valA) != (valB)) {//tried surrounding this with 'noInterrupts' to preserve the volatile 'valA' but no effect
goToSleep();
}
else {
waterLevel = !valB;
}
}
void LORATXHealth() {
noInterrupts();
LoRa.beginPacket();
LoRa.print(healthCheck);//state of battery, 3 = OK, 4 = re-charge
LoRa.endPacket();
//LORASLEEP?? if so need to wake on interrupt
//what about an acknowledgement or re-send?
interrupts();
}
void LORATXSensor() {
noInterrupts();
LoRa.beginPacket();
LoRa.print(waterLevel);
LoRa.endPacket();
waterLevelSent = waterLevel;
//LORASLEEP?? if so need to wake on interrupt
//what about an acknowledgement or re-send?
interrupts();
}
[/code]