Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 2 1 2 LastLast
Results 1 to 25 of 33

Thread: Snooze: Calling a function on a pin interrupt?

  1. #1
    Junior Member DaveB's Avatar
    Join Date
    Jul 2015
    Location
    Kansas City, MO, USA
    Posts
    17

    Snooze: Calling a function on a pin interrupt?

    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, ISR_Function, 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 by DaveB; 08-29-2020 at 04:47 PM.

  2. #2
    Senior Member
    Join Date
    Jul 2020
    Posts
    472
    Quote Originally Posted by DaveB View Post
    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, ISR_Function, 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.

  3. #3
    Junior Member DaveB's Avatar
    Join Date
    Jul 2015
    Location
    Kansas City, MO, USA
    Posts
    17
    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 by DaveB; 08-29-2020 at 07:56 PM. Reason: Clarity

  4. #4
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    12,701
    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?

  5. #5
    Junior Member DaveB's Avatar
    Join Date
    Jul 2015
    Location
    Kansas City, MO, USA
    Posts
    17
    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).

  6. #6
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    12,701
    Good luck. Yes, not using same pin should work normally it 'seems'.

  7. #7
    Junior Member DaveB's Avatar
    Join Date
    Jul 2015
    Location
    Kansas City, MO, USA
    Posts
    17
    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();
    }

  8. #8
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    12,701
    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?

  9. #9
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,489
    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

  10. #10
    Junior Member DaveB's Avatar
    Join Date
    Jul 2015
    Location
    Kansas City, MO, USA
    Posts
    17
    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.

    Click image for larger version. 

Name:	PythonExample.jpg 
Views:	12 
Size:	160.6 KB 
ID:	21528

  11. #11
    Junior Member DaveB's Avatar
    Join Date
    Jul 2015
    Location
    Kansas City, MO, USA
    Posts
    17
    Quote Originally Posted by el_supremo View Post
    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.

  12. #12
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,489
    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

  13. #13
    Junior Member DaveB's Avatar
    Join Date
    Jul 2015
    Location
    Kansas City, MO, USA
    Posts
    17
    Quote Originally Posted by defragster View Post
    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.

  14. #14
    Junior Member DaveB's Avatar
    Join Date
    Jul 2015
    Location
    Kansas City, MO, USA
    Posts
    17
    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 
      attachInterrupt(digitalPinToInterrupt(16), rainfallGetSample, RISING);
    
    // WIND SPEED INITIALIZE
      digital.pinMode(22, INPUT_PULLDOWN, RISING);  // Wind speed 
      attachInterrupt(digitalPinToInterrupt(22), windSpeedGetSample, RISING);
    
    ...
    
    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. 
        ...
    And the ISRs:
    Code:
    void windSpeedGetSample() { 
      windSpeedRotations += 1; 
    }
    void rainfallGetSample() { 
      rainfallTipCount += 1;
    }

  15. #15
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    12,701
    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

  16. #16
    Junior Member DaveB's Avatar
    Join Date
    Jul 2015
    Location
    Kansas City, MO, USA
    Posts
    17
    Quote Originally Posted by defragster View Post
    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?

  17. #17
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    12,701
    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()?

  18. #18
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,489
    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

  19. #19
    Junior Member DaveB's Avatar
    Join Date
    Jul 2015
    Location
    Kansas City, MO, USA
    Posts
    17
    Quote Originally Posted by defragster View Post
    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.

  20. #20
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    12,701
    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.

  21. #21
    Junior Member DaveB's Avatar
    Join Date
    Jul 2015
    Location
    Kansas City, MO, USA
    Posts
    17
    Quote Originally Posted by el_supremo View Post
    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?

  22. #22
    Junior Member DaveB's Avatar
    Join Date
    Jul 2015
    Location
    Kansas City, MO, USA
    Posts
    17
    Quote Originally Posted by defragster View Post
    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.

  23. #23
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    12,701
    @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?

  24. #24
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    12,701
    Quote Originally Posted by DaveB View Post
    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);

  25. #25
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,489
    I missed this: both windSpeedRotations and rainfallTipCount must be declared volatile if they are modified in an interrupt.

    Pete
    Last edited by el_supremo; 08-30-2020 at 04:54 PM.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •