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

Status
Not open for further replies.

BriComp

Well-known member
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.
Capture.jpg
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:
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?
 
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.
 
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.
 
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
 
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
Capture2 Teensy 3.2.jpg

Compiler error Screen Capture
Capture Snooze Compile Warning.jpg
 
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
 
Status
Not open for further replies.
Back
Top