Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 9 of 9

Thread: Having problems with time it takes Snooze to wake up on digital pin

  1. #1
    Senior Member
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    115

    Having problems with time it takes Snooze to wake up on digital pin

    I am trying to use the Snooze utility, waking up from DeepSleep on a pin going LOW and on a timer.
    The pin going LOW indicates that there is a message being collected by UART radio.
    The pin (AUX) goes LOW 5ms before the radio starts putting the data on it's TX pin, teensy's RX pin.
    Below is a logic analyser trace. (10 from Hobby Components- fantastic value for money )
    The teensy puts pin 13 (led) HIGH as soon as Teensy wakes up. Looking at the trace indicates
    that it takes Teensy 20ms to Wakeup. Is this to be expected...seems very long.
    Unfortunately the information being sent to Teensy on Serial1 is long gone by the time that Teensy wakes up.
    I need it to wake up and be in a state to receive Serial1 data in <=5ms. Is that unreasonable?
    I have included the code below. It's rather long but I don't know how to cut it down much more
    and still be able to show the problem I am having. Bye the way I am using a Teensy 4.0.
    CLICK on Logic Analyser Trace to Expand.
    Click image for larger version. 

Name:	Capture.jpg 
Views:	15 
Size:	44.1 KB 
ID:	22379
    Code:
    /*
     * LoRa E32-TTL-100
     * Receive fixed transmission message on channel.
     * https://www.mischianti.org
     *
     * E32-TTL-100----- Arduino UNO or esp8266
     * M0         ----- 3.3v (To config) GND (To send) 2 (To dinamically manage)
     * M1         ----- 3.3v (To config) GND (To send) 3 (To dinamically manage)
     * TX         ----- RX PIN 1 (PullUP)
     * RX         ----- TX PIN 0 (PullUP & Voltage divider)
     * AUX        ----- Connected (4 if you connect)
     * VCC        ----- 3.3v/5v
     * GND        ----- GND
     *
     */
    
    #include <TimeLib.h>
    #include "Arduino.h"
    //#include "LoRa_E32.h"
    #include "EBYTE.h"
    #include <Wire.h>
    #include "Adafruit_MCP9808.h"
    
    // Load Snooze drivers
    #include <Snooze.h>
    
    SnoozeDigital   snoozeDigital;
    SnoozeTimer     snoozeTimer;
    SnoozeUSBSerial SerialUsb;
    
    #if defined(__IMXRT1062__)
    SnoozeBlock config_teensy40(SerialUsb, snoozeDigital, snoozeTimer ); //alarm);
    #elif defined(__MK64FX512__)
    #elif defined(__MK66FX1M0__)
    SnoozeBlock config_teensy36(SerialUsb, snoozeDigital, snoozeTimer);
    SnoozeBlock config_teensy35(SerialUsb, snoozeDigital, snoozeTimer);
    #elif defined(__MK20DX256__)
    SnoozeBlock config_teensy32(SerialUsb, snoozeDigital, snoozeTimer);
    #elif defined(__MK20DX128__)
    SnoozeBlock config_teensy30(SerialUsb, snoozeDigital, snoozeTimer);
    #elif defined(__MKL26Z64__)
    SnoozeBlock config_teensyLC(SerialUsb, snoozeDigital, snoozeTimer);
    #endif
    
    #define SerialUsb Serial
    /*------------------------------------------------------------------------
     * Parameter Setup
     -------------------------------------------------------------------------*/
    //  Oled 128X64 Display
    
    //  Radio Parameters
    
    #define PIN_M0 2
    #define PIN_M1 3
    #define PIN_AX 4
    #define auxPin PIN_AX
    #define FREQUENCY_868
    
    MODE_TYPE radioMode;
    #define RadioSerial Serial1
    EBYTE Radio(&RadioSerial, PIN_M0, PIN_M1, PIN_AX);
    
    //LoRa_E32 radio(&radioSerial, PIN_AX, PIN_M0, PIN_M1);
    
    /*------------------------------------------------------------------------
     * Radio Addresses etc
     --------------------------------------------------------------------------*/
    const byte cprlbHomeADRH   = 0x00;
    const byte cprlbHomeADRL   = 0x03;
    const byte cprlbHomeCHAN   = 0x04;
    
    const byte masterADRH      = 0x00;
    const byte masterADRL      = 0x01;
    const byte masterCHAN      = 0x04;
    
    const bool asleep = true;
    const bool awake = false;
    
    #pragma pack(push,1)
    
    typedef struct addrType{
      byte H;
      byte L;
      byte Chan;
    } addrType;
    
    addrType addr;
    
    /***************************************************************************
     *                          SLAVE Data Types                               *
     ***************************************************************************/
    typedef struct SlaveToMasterReplyType{
        byte      replyFrom;
        byte      replyWhat;
        uint16_t  data;
    } SlaveToMasterReplyType;
    
    SlaveToMasterReplyType slaveToMasterReply;
    const int sizeOfSlaveToMasterReplyType = sizeof(SlaveToMasterReplyType);
    
    typedef union SlaveToMasterReplyUnion{
        SlaveToMasterReplyType data;
        uint8_t                buf[sizeOfSlaveToMasterReplyType];
    } SlaveToMasterReplyUnion;
    
    SlaveToMasterReplyUnion slaveToMasterReceive;
    
    typedef struct SlaveToMasterTransmitDataType{
        addrType               addr;
        SlaveToMasterReplyType message;
    } SlaveToMasterTransmitDataType;
    
    const int sizeOfSlaveToMasterTransmitDataType = sizeof(SlaveToMasterTransmitDataType);
    
    typedef union SlaveToMasterTransmitReplyUnion{
        SlaveToMasterTransmitDataType data;
        uint8_t                       buf[sizeOfSlaveToMasterTransmitDataType];
    } SlaveToMasterTransmitReplyUnion; // slaveToMasterData;
    
    SlaveToMasterTransmitReplyUnion slaveToMasterTransmit;
    
    /***************************************************************************
     *                           MASTER Data Types                             *
     ***************************************************************************/
    typedef struct MasterToSlaveCommandType{
        byte          command;
        unsigned long time;
        uint16_t      temperature;
     } MasterToSlaveCommandType;
     
    MasterToSlaveCommandType masterToSlaveCommand;
    
    const int sizeOfMasterToSlaveCommandType = sizeof(MasterToSlaveCommandType);
    
    typedef union MasterToSlaveCommandUnion{
        MasterToSlaveCommandType data;
        uint8_t                  buf[sizeOfMasterToSlaveCommandType];
    } MasterToSlaveCommandUnion;
    
    MasterToSlaveCommandUnion masterToSlaveReceive;
    
    typedef struct MasterToSlaveTransmitDataType{
        addrType                  addr;
        MasterToSlaveCommandType  message;
    } MasterToSlaveTransmitDataType;
    
    const int sizeOfMasterToSlaveTransmitDataType = sizeof(MasterToSlaveTransmitDataType);
    
    typedef union MasterToSlaveTransmitUnion{
        MasterToSlaveTransmitDataType data;
        uint8_t                       buf[sizeOfMasterToSlaveTransmitDataType];
    } MasterToSlaveTransmitUnion;
    
    MasterToSlaveTransmitUnion masterToSlaveTransmit;
    
    #pragma pack(pop)
    
    unsigned long waitTilRadioTxBufferEmpty;   // if (Use millis() >= waitTilRadioTxBufferEmpty) so as not to overload radio comms
    
    /*------------------------------------------------------------------------
     * Setup Radio - function is called once at startup of the sketch
     -------------------------------------------------------------------------*/
    void SetupRadio( addrType a, byte wakeUp, /*uint8_t pwrStatus, */bool sleep ){
        RadioSerial.begin(9600);
        Radio.init();
        Radio.SetAddressH(0); //a.H                 );   //Set up Satallite/Master Home Address and Channel Data
        Radio.SetAddressL(3); //          a.L                 );
        Radio.SetChannel(4); //           a.Chan              );
        Radio.SetAirDataRate(       ADR_2400            );
        Radio.SetUARTBaudRate(      UDR_9600            );
        Radio.SetParityBit(         PB_8N1              );
        // SET OPTIONS
        Radio.SetWORTIming(         wakeUp              );               //OPT_WAKEUP250;
        Radio.SetTransmissionMode(  OPT_FixedModeENABLE );
        Radio.SetPullupMode(        OPT_IOOPENDRAIN     );
        Radio.SetFECMode(           OPT_FECENABLE       );
        Radio.SetTransmitPower(     OPT_TP20            );
        
        Radio.SaveParameters(PERMANENT);
        if (sleep) {
            radioMode = MODE_POWERDOWN;
        }
        else
        {
            radioMode = MODE_WAKEUP; // Should only send when they are asleep though there may mbe times when comms take place after they are awake;radio.setMode(MODE_0_NORMAL);  or should it be 
        };
        Radio.SetMode(radioMode);
        ClearRadioSerialInputBuffer();
    }  //SetupRasio
    
    
    /*------------------------------------------------------------------------
     * ***********************************************************************
     *                             SLAVE ROUTINES                            *
     * ***********************************************************************
     -------------------------------------------------------------------------*/
    /*------------------------------------------------------------------------
     * Setup Snooze - send to sleep to save current
     -------------------------------------------------------------------------*/
    void SetupSnooze(){
    #if defined(__IMXRT1062__)
        snoozeTimer.setTimer(60);// seconds
    #else
        snoozeTimer.setTimer(60000);// milliseconds
    #endif
        snoozeDigital.pinMode(PIN_AX, INPUT_PULLUP, LOW);//pin, mode, type
    };   // SetupSnooze  
    
    
    /*------------------------------------------------------------------------
     * SLAVE:  System Setup - for Slave
     -------------------------------------------------------------------------*/
    
    void setup()  // SLAVE
    {
    int led = 13;
    
      pinMode(led, OUTPUT);
      digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
    
        SetupSnooze();
        SetupRadio(addr, OPT_WAKEUP250, asleep);
    }  //  SLAVE  setup()
    
    /*------------------------------------------------------------------------
     * SLAVE:  loop -  the main program loop - for Slave
     -------------------------------------------------------------------------*/
    void loop()   // SLAVE
    {
    
      char str[20];
      int who;
      int n;
      
      /********************************************************
        feed the sleep function its wakeup parameters. Then go
        to deepSleep.
      ********************************************************/
    delay(1000);
    digitalWrite(13,LOW);
    SerialUsb.println("I am about to go to sleep");
    SerialUsb.flush();  //
    delay(500);
    
    #if defined(__IMXRT1062__)
        who = Snooze.deepSleep( config_teensy40 );// return module that woke processor
    #elif defined(__MK66FX1M0__)
        who = Snooze.deepSleep( config_teensy36 );// return module that woke processor
    #elif defined(__MK64FX512__)
        who = Snooze.deepSleep( config_teensy35 );// return module that woke processor
    #elif defined(__MK20DX256__)
        who = Snooze.deepSleep( config_teensy32 );// return module that woke processor
    #elif defined(__MK20DX128__)
        who = Snooze.deepSleep( config_teensy30 );// return module that woke processor
    #elif defined(__MKL26Z64__)
        who = Snooze.deepSleep( config_teensyLC );// return module that woke processor
    #endif
    
    unsigned long wakeupTime0 = millis();
    
    if (!RadioSerial) 
        Serial1.begin(9600);
     
    wakeupTime0 = millis() - wakeupTime0;
    
        if (who== PIN_AX) {
           if (AuxHigh()) digitalWrite(13,HIGH);
           if (RadioSerial.available() >= 1){
              n=RadioSerial.available();
              RadioSerial.readBytes(masterToSlaveReceive.buf, sizeOfMasterToSlaveCommandType );
              masterToSlaveCommand = masterToSlaveReceive.data;
           }  //(radio.available() > 1)
        }
    
    unsigned long    wakeUpTime = millis() +8000;
        
        while ( !SerialUsb && (millis() < wakeUpTime)){
        };
    
    unsigned long SerialUsbUpTime = millis();
    SerialUsb.print( "Time to wake up RadioSerial "); SerialUsb.println( wakeupTime0 );
    SerialUsb.print( "Time to wake up SerialUsb "); SerialUsb.println( SerialUsbUpTime - wakeUpTime - 8000 );
    SerialUsb.print("I have woken up.  Who=");  SerialUsb.println(who);
    
    }  //  SLAVE  loop()
    void ClearRadioSerialInputBuffer(){
        byte b;
        while(RadioSerial.available()) {
            b = RadioSerial.read();
        }
    };  // ClearRadioSerialInputBuffer
    
    
    bool AuxLow(){
      return (digitalRead(auxPin)==LOW);
    };
    bool AuxHigh(){
      return (digitalRead(auxPin)==HIGH);
    };
    Last edited by BriComp; 11-10-2020 at 09:39 PM.

  2. #2
    Senior Member
    Join Date
    Aug 2019
    Location
    southwest USA
    Posts
    123
    the logic anal display does not show that clear on my display. are you timing from when the aux pin goes
    on the rcvr or from when you begin or end the serial stream into the transmitter? which teensy?

  3. #3
    Senior Member
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    115
    You can enlarge the Logic Analyser trace by double clicking on it.
    When the UART Radio detects an incoming radio message it puts AUX low. This is the trigger to wake Teensy.
    5ms after AUX goes low the data is sent from it's serial TX port to Teensy's Serial1 RX port. I am only sending
    7 bytes of data which is LONG GONE by the time teensy wakes up. 20ms to wake up.

  4. #4
    Senior Member
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    115
    Oops forgot to say, I am using a Teensy 4.0

  5. #5
    Senior Member
    Join Date
    Aug 2019
    Location
    southwest USA
    Posts
    123
    Quote Originally Posted by BriComp View Post
    Oops forgot to say, I am using a Teensy 4.0
    if (who== PIN_AX) {
    if (AuxHigh()) digitalWrite(13,HIGH);

    if you you change above to be digitalWrite(13,HIGH); leaving off the if auxhi does it help?

  6. #6
    Senior Member
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    115
    That's a thought, though I don't think it will account for the long delay.
    I will have a look tomorrow. Thanks for looking.
    I tried snooze without SerialUsb and it just went haywire.
    I had set it up for either a 1min snooze or wake on PIN state (message received, to be collected ).
    If I left out SerialUsb snooze reduced the 1 nin to about 1-2 seconds.

  7. #7
    Senior Member
    Join Date
    Aug 2019
    Location
    southwest USA
    Posts
    123
    i agree that it would be hard for that to cause 20ms. i also agree that 20ms is a long time - especially on T4
    you may have to break down and write a super simple code that does nothing other than wait for digital pin
    to go low, wake and activate led for short time, and watch on your logic analyzer while you feed it with a low
    freq sq wave from a signal generator or another teensy or even a pwm pin in the same teensy in order to
    differentiate whether the problem is somehow being induced by an interaction with something in the ebyte.h
    or one of the other lib files - ie use no libs other than snooze

    i have used ebyte products with teensylc and no problems re logic levels - the ebyte talks and listens to 3.3
    volts just fine - i have never listened to the aux pin - always just the data pin

    i have done hibernate testing with t4 with no problems found but cannot remember if i did a digital wakeup -
    may have only done timer wake up

    if your teensy/ebyte are in a battery powered app you might want to look and see if teensylc could get the
    job done - it is the low hibernate current king

  8. #8
    Senior Member
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    115
    Tried
    Code:
    digitalWrite(13,HIGH);
    without the
    Code:
    if (AuxHigh()) d...
    and it made <0.2ms difference.
    I changed the Teensy 4.0 for a Teensy 3.2 and this solved the problem. I have put a Logic Analyser image below. The time to
    respond to the AUX pin change reduced to 496us. Now that will work for me.
    I have noticed that when compiling for the Teensy 4.0 that the compiler produces a warning for the snooze code that
    IRQ_NUMBER_t IRQ_CMP; may be used uninitialized in this function. I have put an image of that below as well.
    When using the Teensy 4.0 program occasionally I have seen the Snooze library report the out of snooze event as -1.
    So I think the Snooze Library needs some work.

    Logic Analyser Screen Capture
    Click image for larger version. 

Name:	Capture2 Teensy 3.2.jpg 
Views:	6 
Size:	42.3 KB 
ID:	22385

    Compiler error Screen Capture
    Click image for larger version. 

Name:	Capture Snooze Compile Warning.jpg 
Views:	8 
Size:	34.5 KB 
ID:	22386

  9. #9
    Senior Member
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    115
    I found that I had been using LOW as in below
    Code:
        snoozeDigital.pinMode(PIN_AX, INPUT_PULLUP, LOW);
    instead of FALLING as below.
    Code:
        snoozeDigital.pinMode(PIN_AX, INPUT_PULLUP, FALLING);
    I also bought some LCs but they do not wake up from a pin input. See-https://forum.pjrc.com/threads/64460-LC-draws-more-current-than-3-1-in-Snooze-modes-does-not-work-on-digital

Posting Permissions

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