Snooze: Calling a function on a pin interrupt?

Status
Not open for further replies.

DaveB

Member
I'm missing something basic here. The attachInterrupt feature lets you specify a function to call when the interrupt is triggered:
Code:
pinMode(21, INPUT_PULLUP);
attachInterrupt(21, [B]ISR_Function[/B], FALLING);

The Snooze library combines attachInterrupt into one line with pinMode, but it doesn't let you define a function to call:
Code:
digital.pinMode(21, INPUT_PULLUP, FALLING);

Can someone tell me what I'm missing?
 
Last edited:
I'm missing something basic here. The attachInterrupt feature lets you specify a function to call when the interrupt is triggered:
Code:
pinMode(21, INPUT_PULLUP);
attachInterrupt(21, [B]ISR_Function[/B], FALLING);

The Snooze library combines attachInterrupt into one line with pinMode, but it doesn't let you define a function to call:
Code:
digital.pinMode(21, INPUT_PULLUP, FALLING);

Can someone tell me what I'm missing?

That the Snooze library is about waking up? When pin 21 sees a falling edge during sleep, wake the processor - I presume.
 
That's correct. The Snooze code is working perfectly. I just need the Teensy to process a function as soon as the interrupt occurs, rather than wait its turn in the loop.

As this code snippet shows, I'm following Duff's example code to process wakeup calls, where ISRs aren't treated like ISRs.

Edit: My first example was generic and used pin 21. My actual code uses pin 22. Sorry for any confusion around that.

Code:
void loop() {  
  who = Snooze.deepSleep( config_teensy32 );  // return module that woke processor
  if (who == 16) { 
    rainfallGetSample();     //  <---- This was previously in an ISR request, where it incremented a counter. 
  }
  if (who == 22) { 
    windSpeed_GetSample();   //  <---- This was previously in an ISR request, where it incremented a counter. 
  }
  if (who == 35) { // process counters
    // 3 second events  
    // Set RTC alarm wake up in (hours, minutes, seconds).
    alarm.setRtcTimer(0, 0, 3);// hour, min, sec 
    blinker();
    Counter30sec  += 1; Counter5min   += 1; Counter20min  += 1; Counter60min  += 1; uptimeSeconds += 3;
    uptimeUpdate();
 
Last edited:
just an assumption - but not using the same pin #21 snooze uses to wake should work normally.

Using the snooze pin will replace the call to ISR_Function.

If you control start of Sleep but need the same pin - perhaps digital.pinMode(21, INPUT_PULLUP, FALLING); before sleep and the attachInterrupt() on waking would work?
 
Thanks defragster, I'm trying your suggestion. I'm afraid my generic example in the first post may have confused things. I'm actually using pin 22, not 21.
If adding the attachInterrupt line doesn't work, I'll post all the code (600+ lines at this point).
 
Well, no luck adding attachInterrupt. Here's a stripped down version of the code. I attempted to remove anything that requires an Adafruit driver. If anyone has any ideas about this Snooze/Interrupt challenge I'm facing, it would obviously be greatly appreciated. Happy to share too if anyone finds this project of interest.

Code:
/* Teensy 3.2 weather station */
String VERSION_NUMBER = "0.0910";

#include <Wire.h>
#include <TimeLib.h>            // For RTC   
#include <Snooze.h>
#include <FreqMeasure.h>

// CREATE TIMERS
elapsedMillis master;
elapsedMillis windSpeedDebounce;  // ---- To do

// CREATE OBJECTS
SnoozeDigital   digital;
SnoozeAlarm     alarm;  
SnoozeBlock     config_teensy32(digital, alarm);

// PIN DEFINES
#define XBEE_SLEEP_CONTROL 4
#define COLLECTING_DATA_INDICATOR 5    
#define LED_PIN 13
#define RAIN_INPUT 16
#define WIND_SPEED_INPUT 22

// MISC DEFINES
#define ARRAY_SIZE 200

// REPORTING LEVEL DEFINES (These tell the RPi what color to use for console messages )  
#define OH_NO         "0"
#define REQUEST_DATA  "2"
#define SENSOR_DATA   "3"
#define RAIN_DATA     "3"
#define WIND_DATA     "3"
#define GOOD_TO_KNOW  "5"
#define NO_CHANGE     "7"
#define MISC_DATA     "8"
#define XBEE_CONNECT  "8"
#define LOW_PRIORITY  "9"

// Variables
String Node = "Backyard"; 
String datastring; 
String messageType, reportingLevel, sensorName, sensorModel, sensorInfo, data01, data02, data03, future1, future2, comment;
boolean       newData         = false;
boolean       recvInProgress  = false;
boolean       restarted        = true;
unsigned int  masterTime      = 3000; // 3 second timer 
unsigned int  pingCount       = 0;
unsigned long externalTime;
int           who;
float         seaLevelPressure;

// RTC VARIABLES
int RTCTime[6];                       // ------ To do

// SERIAL2 VARIABLES
double        freqsum       = 0;      // frequency counter summing
int           freqcount     = 0;
int           incomingByte  = 0;      // incoming serial data
String        serial2InData;

// WIND SPEED VARIABLES
int           windSpeedRotations = 0;
int           windSpeedSampleCount = 0;
float         windSpeedArray[ARRAY_SIZE];

// RAINFALL VARIABLES
int           rainfallTipCount = 0;

//timer counters 
unsigned int  Counter30sec  = 10, Counter5min   = 100, Counter20min  = 400, Counter60min  = 1200;   
unsigned int  uptimeSeconds = 0, uptimeMinutes, uptimeDays, uptimeHours;

void setup(){
  //Serial.begin(19200);
  Serial2.begin(9600, SERIAL_8N1);
  FreqMeasure.begin();
  delay(1000);                                  // Give Serial2 a moment to collect itself. 
  pinMode(LED_PIN, OUTPUT);           
  pinMode(XBEE_SLEEP_CONTROL, INPUT);           // This gets set to OUTPUT when XBee needs to be turned on. Otherwise it floats.
  pinMode(COLLECTING_DATA_INDICATOR,  OUTPUT);  // Visual indicator that sensors are being read.
  
// RTC initialize
  setSyncProvider(getTeensy3Time);              // Use RTC
  externalTime = 278631501;                     // Fake epoch time for testing
  Teensy3Clock.set(externalTime);               
  setTime(externalTime);                        // Set the RTC

// RAINFALL INITIALIZE
  digital.pinMode(16, INPUT_PULLDOWN, RISING);  // Rainfall 
  // attachInterrupt(digitalPinToInterrupt(16), rainfallGetSample, RISING);

// WIND SPEED INITIALIZE
  digital.pinMode(22, INPUT_PULLDOWN, RISING);  // Wind speed 
  // attachInterrupt(digitalPinToInterrupt(22), windSpeedGetSample, RISING);
  
// RESTART MESSAGE
  xbeeMeshNetworkSync();
  messageType    = "Diagnostics";
  reportingLevel = OH_NO;
  comment        = "Weather station " + VERSION_NUMBER + " has restarted.";  
  sendMessageToPi();
  restarted = false;
  alarm.setRtcTimer(0, 0, 3);   // Set RTC alarm for 3 seconds. 
  xbeeSleep();
}
void loop() {  
  who = Snooze.deepSleep( config_teensy32 );    // return module that woke processor
  if (who == 16) { 
    rainfallGetSample();
  }
  if (who == 22) { 
    windSpeedGetSample();
  }
  if (who == 35) { // process counters
    // 3 second events  
    alarm.setRtcTimer(0, 0, 3);                 // Set RTC alarm for 3 seconds. 
    Counter30sec  += 1; Counter5min   += 1; Counter20min  += 1; Counter60min  += 1; uptimeSeconds += 3;
    uptimeUpdate();

    if (Counter30sec >= 10){
      windSpeedSave();   
      Counter30sec = 0;
    }
    if ((Counter5min >= 100) || (Counter20min >= 400) || (Counter60min >= 1200)){  
      externalTime = now();
      xbeeMeshNetworkSync();
      if (Counter5min >= 100){
        sendPing();
        pingCount += 1;
        xminuteUpdate(5);
        uptimeSendToPi();
        Counter5min = 0;
      }  
      if (Counter20min >= 400){
        xminuteUpdate(20);
        requestDataFromPi("SeaLevelPressure");
        windSpeedProcessData();
        rainfallProcessData();
        Counter20min = 0;
      }  
      if (Counter60min >= 1200){
        xminuteUpdate(60);
        requestDataFromPi("CurrentTime");   
        Counter60min = 0;
      }  
    }
    xbeeSleep();
  }
} 

// FUNCTIONS
void xminuteUpdate(int minutes){
  messageType    = "Diagnostics";
  reportingLevel = LOW_PRIORITY;
  comment        = String(minutes) + " minute update";  
  sendMessageToPi();
}
void showCounters(){
  messageType    = "Diagnostics";
  reportingLevel = GOOD_TO_KNOW;
  comment        = "Counters 30sec: " + String(Counter30sec) + " 5min: " + String(Counter5min) + " 20min: " + String(Counter20min) + " 60min: " + String(Counter60min);
  sendMessageToPi();
}
void xbeeSleep(){
  pinMode(XBEE_SLEEP_CONTROL, INPUT);  // This is set to output when the xbee is awake, but all other time it's an input so it can float.
}
void xbeeMeshNetworkSync(){                       // Ensures that xbee is connected to its mesh network.
  pinMode(XBEE_SLEEP_CONTROL, OUTPUT);            // This is set to output when the xbee is awake, but all other time it's an input so it can float.
  digitalWrite(XBEE_SLEEP_CONTROL, LOW);          // turn on the xbee
  float frequency = 0;
  while ( frequency <= 1.99 || frequency >= 2.10) {
    if (FreqMeasure.available()) {
      freqsum = freqsum + FreqMeasure.read();
      freqcount = freqcount + 1;
      if (freqcount > 10) {  // Used to be "4" but that caused the bug where it didn't connect once per hour at the :05 minute mark (?!)
        frequency = FreqMeasure.countToFrequency(freqsum / freqcount);
        freqsum = 0;
        freqcount = 0;
      }
    }
  }
  messageType    = "Diagnostics";
  reportingLevel = MISC_DATA;
  comment        = "Connected to XBee network. Associate pin frequency: " + String(frequency) + "Hz";  
  sendMessageToPi();
}   
float rounder(float roundme){  // Round float to the nearest .5
  roundme = roundme * 2;
  roundme = round(roundme);
  roundme = roundme / 2;
  return roundme;
}
void uptimeUpdate(){
  if (uptimeSeconds >= 60) { uptimeSeconds  = 0; uptimeMinutes += 1; }
  if (uptimeMinutes >= 60) { uptimeMinutes  = 0; uptimeHours   += 1; }
  if (uptimeHours >= 24)   { uptimeHours    = 0; uptimeDays    += 1; }
}
void uptimeSendToPi(){
  // SensorType = "Uptime";
  String uptimeDays_string = ""; 
  String uptimeHours_string = ""; 
  String uptimeMinutes_string = "";
  if (uptimeMinutes < 10)  { uptimeMinutes_string = "0" + String(uptimeMinutes); } else { uptimeMinutes_string = String(uptimeMinutes); }
  if (uptimeHours   < 10)  { uptimeHours_string =   "0" + String(uptimeHours);   } else { uptimeHours_string =   String(uptimeHours); }
  if (uptimeDays >= 10 && uptimeDays < 100 ){ uptimeDays_string = "0" + String(uptimeDays); }
  if (uptimeDays < 10)     { uptimeDays_string = "00" + String(uptimeDays);  }
  messageType    = "Diagnostics";
  reportingLevel = GOOD_TO_KNOW;
  comment        = "Uptime:  " + String(uptimeDays_string) + ":" + String(uptimeHours_string) + ":" + String(uptimeMinutes_string);
  sendMessageToPi();
}
void sendMessageToPi(){
  datastring =  "<" + messageType + "|" + reportingLevel + "|" + Node + "|" + sensorName + "|" + sensorModel + "|" + sensorInfo + "|" + data01 + "|" + data02 + "|" + data03 + "|" + future1 + "|" + future2 + "|" + comment + ">";
  Serial2.println(datastring);
  Serial2.flush();
  // clears out variables.  Don't comment out (again)
  messageType = ""; reportingLevel = ""; sensorName = ""; sensorModel = ""; sensorInfo = ""; data01 = ""; data02 = ""; data03 = ""; future1 = ""; future2 = ""; comment = "";
}
void sendPing(){
  messageType    = "Diagnostics";
  sensorName     = "ping";
  data01         = String(pingCount);
  reportingLevel = MISC_DATA;
  comment        = Node + " " + sensorName + " " + data01;
  sendMessageToPi();
}
void requestDataFromPi(String RequestData){
  messageType     = "RequestData";
  reportingLevel  = REQUEST_DATA;
  comment         = RequestData;
  sendMessageToPi();
  readFromSerial(); 
}
void readFromSerial() {
  delay(500);
  char startMarker = '<';
  char endMarker = '>';
  while (Serial2.available() > 0) {
    incomingByte = Serial2.read();
    if (recvInProgress == true) {
      if (incomingByte != endMarker) {
        serial2InData = (serial2InData + (char)incomingByte);
      }
      else {
        serial2InData = (serial2InData + "\n");  // terminate the string
        recvInProgress = false;
        newData = true;
      }
    }
    else if (incomingByte == startMarker) {
      recvInProgress = true;
    }      
  }
  if (newData == true){ 
    String sa[7];   // Create temporary array
    int r=0, t=0;
    String superdata;
    for (unsigned int i=0; i < serial2InData.length(); i++) { 
      if(serial2InData.charAt(i) == ',') { 
        sa[t] = serial2InData.substring(r, i); 
        r=(i+1); 
        t++; 
      }
    }
    if (sa[0] == "SeaLevelPressure"){
      messageType    = "DataConfirmed";
      reportingLevel = REQUEST_DATA;
      data01         = sa[1];
      comment        = sa[0];
      sendMessageToPi();
      seaLevelPressure = sa[1].toInt();
    }
    if (sa[0] == "CurrentTime") {  
      messageType    = "DataConfirmed";
      reportingLevel = REQUEST_DATA;
      for (int i=0; i<t; i++) { 
        superdata = superdata + sa[i] + ",";
      }
      comment        = superdata;
      sendMessageToPi();
    }                                                     
    newData = false;
    serial2InData = "";
    superdata = "";
  }
}


// WINDSPEED 
void windSpeedGetSample() { // USES INTERUPT: This function is triggered by an interupt on the windspeed input pin
  windSpeedRotations += 1; 
}
void windSpeedSave(){
  windSpeedArray[windSpeedSampleCount] = windSpeedRotations; 
  windSpeedSampleCount += 1;
  windSpeedRotations = 0;
  if (windSpeedSampleCount >= ARRAY_SIZE){
    windSpeedSampleCount = 0;
  }
}
void windSpeedProcessData() {
  float windSpeedMax = 0, windSpeedAvg = 0, windSpeedMin = 100, windspeedMPH;
  if (windSpeedSampleCount > 0) { 
    for (int j = 1; j < windSpeedSampleCount; j++) {
      windspeedMPH = (windSpeedArray[j] * (2.25/30));  // Convert pulses to MPH
      if (windspeedMPH >= windSpeedMax){ windSpeedMax = windspeedMPH; }
      if (windspeedMPH <= windSpeedMin){ windSpeedMin = windspeedMPH; }
      windSpeedAvg = windSpeedAvg + windspeedMPH;
    }
    windSpeedAvg = windSpeedAvg / (windSpeedSampleCount-1);
    messageType    = "SensorData";
    reportingLevel = SENSOR_DATA;
    sensorName     = "WindSpeed";
    sensorModel    = "Davis 6410";
    data01         = String(windSpeedMax);
    data02         = String(windSpeedAvg);
    data03         = String(windSpeedMin);
    comment        = "Max, Avg, Min";
    sendMessageToPi();
  }
    /*
    else {
      messageType    = "Diagnostics";
      reportingLevel = NO_CHANGE;
      comment        = "No wind activity since last transmission."; 
      sendMessageToPi();      
    }
    */
    windSpeedSampleCount = 0;
}

// RAINFALL
void rainfallGetSample() { // USES INTERUPT: This function is triggered by an interupt on the 'rain' input pin 
  rainfallTipCount += 1;
  // if (rainSensorDebounce >= 500) { rain_tip_count += 1; rainSensorDebounce = 0; }  // ------ To do.
}
void rainfallProcessData() { 
  float rainfallAmount = rainfallTipCount * .01;
  messageType    = "SensorData";
  sensorName     = "Rainfall";
  sensorModel    = "Davis 6466";
  reportingLevel = RAIN_DATA;
  data01         = String(rainfallAmount);
  data02         = String(rainfallTipCount);
  comment        = "Amount, RainfallTipCount";
  sendMessageToPi();
  rainfallTipCount = 0;
}

time_t getTeensy3Time()
{
  return Teensy3Clock.get();
}
 
So this is sleeping most often? - in that case the CPU not awake for normal pins interrupts? Even if it was set to wake the Teensy - it wouldn't detect RISING?

How long is the pin held high on interrupt? Maybe a quick read could catch it high?
 
I just need the Teensy to process a function as soon as the interrupt occurs, rather than wait its turn in the loop
Why? It will only take a microsecond or so longer to "wait its turn" than a directly attached function.

Pete
 
As it's currently written, it wakes up one of three ways:
1) An interrupt pin that's triggered every time a few drops of rain are collected by the rain sensor.
2) An interrupt pin that's triggered for every rotation of an anemometer (wind speed gauge).
3) A 3 second alarm that does all the other housekeeping, accumulating sensor data, doing some minor processing, then sending it out the Serial2 port.

The three second alarm wakes the Teensy for milliseconds and none of the other routines are very long, so it's sleeping most of the time. It's solar-powered, so I'm committed to the process. :)

Everything worked great until I tried add the pin interrupts back in. It kinda works if the pins aren't triggered more than once every few seconds.
Before I added in the Snooze code, the pin interrupts worked as you would expect. They ran their little subroutines and got back to the loop. That's what I'm trying to get back to.
For grins, here's a screenshot of the data that the Teensy is sending to a RaspberryPi running a Python script.

PythonExample.jpg
 
Why? It will only take a microsecond or so longer to "wait its turn" than a directly attached function.

Pete

Unfortunately there is a fair amount of blocking going on between sensor response time and XBee connections. A 10mph wind will create about five pulses per second, which means pulses will be consistently missed.
 
Everything worked great until I tried add the pin interrupts back in.
In what way does it fail?

It kinda works if the pins aren't triggered more than once every few seconds
What happens in this case?

Post your code which uses the attachinterrupts.

Pete
 
So this is sleeping most often? - in that case the CPU not awake for normal pins interrupts? Even if it was set to wake the Teensy - it wouldn't detect RISING?

How long is the pin held high on interrupt? Maybe a quick read could catch it high?

I missed a couple of these questions earlier.
- The only pin interrupts I'm using are tied to Snooze all other external connections are either I2C or not time sensitive (e.g. power management, a potentiometer for measuring wind direction).
- Pin interrupts are using the 'who' variable in a polling configuration but, with everything else happening in the loop, they haven't been reliable.
- Regarding the length of time a pin is held high, these are both connected to reed switches. I haven't put them on a scope, but an educated guess would be that the switches are closed for at least a few milliseconds. Long enough if it wasn't for everything else that's going on.
 
The attachInterrupts are in the code I posted a little bit ago, they're just commented out. Here are the changes I made when attempting to use them.

Code:
// RAINFALL INITIALIZE
  digital.pinMode(16, INPUT_PULLDOWN, RISING);  // Rainfall 
  [COLOR="#FF0000"]attachInterrupt(digitalPinToInterrupt(16), rainfallGetSample, RISING);[/COLOR]

// WIND SPEED INITIALIZE
  digital.pinMode(22, INPUT_PULLDOWN, RISING);  // Wind speed 
  [COLOR="#FF0000"]attachInterrupt(digitalPinToInterrupt(22), windSpeedGetSample, RISING);[/COLOR]

...

void loop() {  
  who = Snooze.deepSleep( config_teensy32 );    // return module that woke processor
[COLOR="#D3D3D3"]  /*
  if (who == 16) { 
    rainfallGetSample();
  }
  if (who == 22) { 
    windSpeedGetSample();
  }
  */[/COLOR]
  if (who == 35) { // process counters
    // 3 second events  
    alarm.setRtcTimer(0, 0, 3);                 // Set RTC alarm for 3 seconds. 
    ...
And the ISRs:
Code:
void windSpeedGetSample() { 
  windSpeedRotations += 1; 
}
void rainfallGetSample() { 
  rainfallTipCount += 1;
}
 
Not sure how interrupts are handled with/during snooze ... do they wake also? If not then the wake will race to get the MCU awake - and may not be ready to capture pin events?
Wonder what CHANGE would do rather than Rising? Would require only counting when falling - i.e LOW==digitalReadFast(pin#)?

About to ask - but code comment above says this is on a T_3.2
 
Not sure how interrupts are handled with/during snooze ... do they wake also? If not then the wake will race to get the MCU awake - and may not be ready to capture pin events?
Wonder what CHANGE would do rather than Rising? Would require only counting when falling - i.e LOW==digitalReadFast(pin#)?

About to ask - but code comment above says this is on a T_3.2

CHANGE will capture both rising and falling. It's usually what I use before I realize I need to take a step back and rethink what I'm doing. :)
And yeah, the big questions for me really, are whether Snooze supports 'traditional' ISRs and if it does, how?
 
Glancing at the code to get 'who' of PIN# returned they should work with:
Code:
// RAINFALL INITIALIZE
  digital.pinMode(16, INPUT_PULLDOWN, RISING);  // Rainfall 
// WIND SPEED INITIALIZE
  digital.pinMode(22, INPUT_PULLDOWN, RISING);  // Wind speed

Using attachInterrupt() will bypass the snooze processing done in SnoozeDigital. It not only sets MODE and records the TYPE desired , but creates a list for detection during snooze and wake.

> It may only trigger on the first 'source' pin found if multiple trigger at the same time? :: \libraries\Snooze\src\hal\TEENSY_32\hal.c :: wakeup_isr( void ) {
> and it may go unnoticed if it fires while awake?

Is that what led to using attachInterrupt()?
 
Code:
// RAINFALL INITIALIZE
  digital.pinMode(16, INPUT_PULLDOWN, RISING);  // Rainfall 
  attachInterrupt(digitalPinToInterrupt(16), rainfallGetSample, RISING);

// WIND SPEED INITIALIZE
  digital.pinMode(22, INPUT_PULLDOWN, RISING);  // Wind speed 
  attachInterrupt(digitalPinToInterrupt(22), windSpeedGetSample, RISING);
The Snooze code will interfere with the attached interrupt. You should change both occurrences of digital.pinMode to just pinMode.

Pete
 
Glancing at the code to get 'who' of PIN# returned they should work with:
Code:
// RAINFALL INITIALIZE
  digital.pinMode(16, INPUT_PULLDOWN, RISING);  // Rainfall 
// WIND SPEED INITIALIZE
  digital.pinMode(22, INPUT_PULLDOWN, RISING);  // Wind speed

Using attachInterrupt() will bypass the snooze processing done in SnoozeDigital. It not only sets MODE and records the TYPE desired , but creates a list for detection during snooze and wake.

> It may only trigger on the first 'source' pin found if multiple trigger at the same time? :: \libraries\Snooze\src\hal\TEENSY_32\hal.c :: wakeup_isr( void ) {
> and it may go unnoticed if it fires while awake?

Is that what led to using attachInterrupt()?

Well, before I added Snooze, attachInterrupt was used to make sure I didn't miss any external triggers while reading, for example, the barometric pressure sensor. Some of those sensors can take a 100ms to respond. My history is in pre-Arduino AVR assembler, so using interrupts like that has been the norm for me. Seems like it's not that popular these days?

I suppose I could try to rewrite everything into a 'scheduler' to be non-blocking, but man I'd really rather not try to tackle that.

If that piece you wrote about bypassing the snooze processing is correct, I'll be over the moon. I'll give it a shot when my wife isn't reminding me that Saturday night is movie night. :)
 
During Snooze it seems it will wake on indicated interrupts with needed : digital.pinMode(22, INPUT_PULLDOWN, RISING);

Though when awake - the : attachInterrupt( 22, windSpeedGetSample, RISING);

Would need to be in place to capture those events?

So back to this idea in p#4:
If you control start of Sleep ... - perhaps digital.pinMode(22, INPUT_PULLUP, RISING); before sleep and the attachInterrupt() on waking would work?

There will be intervals between coming awake and going snooze where other events could be missed.

Indeed this is no longer a normal processing task when going in&out of snooze.
 
Code:
// RAINFALL INITIALIZE
  digital.pinMode(16, INPUT_PULLDOWN, RISING);  // Rainfall 
  attachInterrupt(digitalPinToInterrupt(16), rainfallGetSample, RISING);

// WIND SPEED INITIALIZE
  digital.pinMode(22, INPUT_PULLDOWN, RISING);  // Wind speed 
  attachInterrupt(digitalPinToInterrupt(22), windSpeedGetSample, RISING);
The Snooze code will interfere with the attached interrupt. You should change both occurrences of digital.pinMode to just pinMode.

Pete

I'll try that too, thanks, though I thought I needed to specify digital.pinMode to trigger Snooze's wake up. Have I got that wrong?
 
During Snooze it seems it will wake on indicated interrupts with needed : digital.pinMode(22, INPUT_PULLDOWN, RISING);

Though when awake - the : attachInterrupt( 22, windSpeedGetSample, RISING);

Would need to be in place to capture those events?

So back to this idea in p#4:
If you control start of Sleep ... - perhaps digital.pinMode(22, INPUT_PULLUP, RISING); before sleep and the attachInterrupt() on waking would work?

There will be intervals between coming awake and going snooze where other events could be missed.

Indeed this is no longer a normal processing task when going in&out of snooze.

Hmmm. I tried that earlier, specifying both lines, and the results were the same. Yeah, Snooze has been a life saver so far, allowing me to run quite a few things on solar power. Hopefully it's just my inexperience with it, and not something that wasn't part of the design. I guess I could run an extension cord into the back yard. :)
 
@duff or a real user of snooze might know.

Try it and see - it may wake on any pin interrupt? But if the SnoozeDigital element is used - it parses all interrupts it seems before giving sketch control - only reporting ones registered?
 
Hmmm. I tried that earlier, specifying both lines, and the results were the same. Yeah, Snooze has been a life saver so far, allowing me to run quite a few things on solar power. Hopefully it's just my inexperience with it, and not something that wasn't part of the design. I guess I could run an extension cord into the back yard. :)

Tried something like this?
Code:
void loop() {  

  digital.pinMode(16, INPUT_PULLDOWN, RISING);  // Rainfall 
  digital.pinMode(22, INPUT_PULLDOWN, RISING);  // Wind speed 

  who = Snooze.deepSleep( config_teensy32 );    // return module that woke processor

  attachInterrupt(digitalPinToInterrupt(16), rainfallGetSample, RISING);
  attachInterrupt(digitalPinToInterrupt(22), windSpeedGetSample, RISING);
 
I missed this: both windSpeedRotations and rainfallTipCount must be declared volatile if they are modified in an interrupt.

Pete
 
Last edited:
Status
Not open for further replies.
Back
Top