Serial glitch after deepSleep() on Teensy 3.2 and Teensyduino 1.53

mykle

Well-known member
Hi,

While working on getting my board to sleep and wake up, I've isolated a pretty strange behavior.

After the *second* time teensy wakes from deepSleep(), and after all subsequent wakeups, the first two Serial.println() statements have their output swapped.

I found this while running a simple test script based on the Snooze audio deepSleep_all_wakeups example. I just added some logging to it.
Here's what the output looks like before the first sleep:

Code:
three
two
one
zzz

Then after it wakes up again the first time, I see this (expected) output:

Code:
Good morning
three
two
one
zzz

But after subsequent wakeups, I see this:

Code:
three
Good morning
two
one
zzz

This happens even if I wait a good long time (2 seconds) after wakeup before I print anything.

This could be a bug in Teensy code, or in MacOS 11.2.3, or in Teensyduino, or my code, or who knows what else.

I wonder if this is a known problem, or if there's anything else I can do to help solve it. It's not really an issue for me because I only use it for logging, but I bet it's a problem for someone.

For the record, this is with TeensyDuino 1.53, Arduino 1.8.13, MacOS 11.2.3 , Snooze 6.3.9 .

Code included below:


Code:
/***************************************
  This shows all the wakeups for deepSleep

  Supported Micros: T-LC/3.x/4.0
****************************************/
#include "Bounce2.h"

#include <Snooze.h>
// Load drivers
SnoozeDigital digital;
SnoozeCompare compare;
SnoozeTimer timer;
//SnoozeUSBSerial usb;
#if !defined(__MK64FX512__) && !defined(__IMXRT1062__)
SnoozeTouch touch;
#endif
SnoozeAlarm	alarm;
#if defined(__MKL26Z64__)
// configures the lc's 5v data buffer (OUTPUT, LOW) for low power
Snoozelc5vBuffer  lc5vBuffer;
#endif
/***********************************************************
  Teensy 4.0 does not have a Touch Interface. Always use the
  SnoozeUSBSerial Driver.

  Teensy 3.6/LC can't use Timer Driver with either Touch or
  Compare Drivers and Touch can't be used with Compare.

  Teensy 3.5 does not Touch Interface.

  Teensy LC does not have a rtc so Alarm Driver can't be
  used as of yet.

  Teensy 3.2 can use any Core Drivers together.
***********************************************************/
#if defined(__IMXRT1062__)
SnoozeBlock config_teensy40(usb, digital, alarm);
#elif defined(__MK66FX1M0__)
SnoozeBlock config_teensy36(touch, digital, alarm);
#elif defined(__MK64FX512__)
SnoozeBlock config_teensy35(digital, compare, timer);
#elif defined(__MK20DX256__)
//SnoozeBlock config_teensy32(touch, digital, compare, timer);
//SnoozeBlock config_teensy32(digital, timer);
SnoozeBlock config_teensy32(timer);
#elif defined(__MK20DX128__)
SnoozeBlock config_teensy30(touch, digital, compare, timer);
#elif defined(__MKL26Z64__)
SnoozeBlock config_teensyLC(lc5vBuffer, digital, timer);
#endif

// GUItool reqs:
#include <Audio.h>

// GUItool: begin automatically generated code
//AudioSynthNoisePink      pink1;          //xy=88,242
AudioSynthNoiseWhite      pink1;          //xy=88,242
AudioAmplifier           amp1;           //xy=257,241
//AudioEffectReverb        reverb1;        //xy=440,243
AudioOutputAnalog        dac1;           //xy=628,246
AudioConnection          patchCord1(pink1, amp1);
//AudioConnection          patchCord2(amp1, reverb1);
//AudioConnection          patchCord3(reverb1, dac1);
AudioConnection          patchCord2(amp1, dac1); 
// GUItool: end automatically generated code


// set pin numbers:
const int button1Pin = 0;   // sw1
const int button2Pin = 9;   // sw2
const int led1Pin =  21;    // led1
const int led2Pin =  20;    // led2
const int pulsePin1 = 11;   // j1 tip
const int pulsePin2 = 8;    // j2 tip
const int analogOut = 14;   // j1/j2 ring: 12 bit DAC on Teensy 3.2 !
const int PO_play = 16;     // goes high on PO play (runs to play LED)
const int PO_wake = 17;   // goes low when PO sleeps I think
const int PO_reset = 7;
const int PO_SWCLK = 6;
const int PO_SWDIO = 5;
const int PO_SWO   = 4;
const int IMU_fsync = 1;   // need to ground this on icm-42605
const int IMU_int = 2;

// default time periods:
const int debounceLen = 2;

// Objects:
Bounce btn1 = Bounce();
Bounce btn2 = Bounce();
#define PRESSED(btn)        (btn.read() == LOW)


void setup() {
	Serial.begin(115200); // not needed?  see if it affects sleep?  sleep seems good atm.
	// TODO: also check if Serial+Midi mode affects sleep ...

	    // slight hack:
  // because i changed chips, this pin (imu pin 10) is now "reserved" on the IMU:
  pinMode(IMU_fsync, OUTPUT);
  digitalWrite(IMU_fsync, 1); // ground this pin (teensy signals are "active low" so ground == 1)
  // imu pin 11 is also reserved but I can't get to it from software ...

  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  /********************************************************
    Define digital pins for waking the teensy up. This
    combines pinMode and attachInterrupt in one function.

    Teensy 4.0
    Digtal pins: all pins

    Teensy 3.x
    Digtal pins: 2,4,6,7,9,10,11,13,16,21,22,26,30,33

    Teensy LC
    Digtal pins: 6,9,10,11,13,16,21,22
  ********************************************************/
  //digital.pinMode(button1Pin, INPUT_PULLUP, FALLING);//pin, mode, type
  digital.pinMode(button1Pin, INPUT_PULLUP, FALLING);//pin, mode, type
  digital.pinMode(button2Pin, INPUT_PULLUP, FALLING);//pin, mode, type

	pinMode(button1Pin, INPUT_PULLUP); // sw1
  pinMode(button2Pin, INPUT_PULLUP); // sw2

	btn1.attach(button1Pin);
  btn1.interval(debounceLen);
  btn2.attach(button2Pin);
  btn2.interval(debounceLen);

  /********************************************************
    Teensy LC Does not have a RTC.

    Set RTC alarm wake up in (hours, minutes, seconds).
  ********************************************************/
#if !defined(__MKL26Z64__)
  alarm.setRtcTimer(0, 0, 10);// hour, min, sec
#endif

  /********************************************************
    Teensy 4.0 Set Low Power Timer wake up in Seconds.
    MAX: 131071s

    Teensy 3.x/LC Set Low Power Timer wake up in Milliseconds.
    MAX: 65535ms
  ********************************************************/
#if defined(__IMXRT1062__)
    timer.setTimer(5);// seconds
#else
    timer.setTimer(5000);// milliseconds
#endif

  /********************************************************
    In deeSleep the Compare module works by setting the
    internal 6 bit DAC to a volatge threshold for voltage
    crossing measurements. The internal DAC uses a 64 tap
    resistor ladder network supplied by VOUT33 at 0.0515625v
    per tap (VOUT33/64). Thus the possible threshold voltages
    are 0.0515625*(0-64). Only one compare pin can be used at
    a time.

    parameter "type": LOW & FALLING are the same and have no effect.
    parameter "type": HIGH & RISING are the same and have no effect.

    Teensy 4.0
    Compare pins: 0, 1, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23

    Teensy 3.x
    Compare pins: 11,9,4

    Teensy LC
    Compare pins: 11
  ********************************************************/
  // trigger at threshold values greater than 1.65v
  //(pin, type, threshold(v))
  //compare.pinMode(11, HIGH, 1.65);

  // trigger at threshold values less than 1.65v
  //(pin, type, threshold(v))
  compare.pinMode(PO_wake, HIGH, 3.65);

  /********************************************************
    Values greater than threshold will trigger TSI wakeup.
    Threshold value is in capacitance. Only one pin can be
    used while sleeping.

    Teensy 4.0: No Touch Sense

    Teensy 3.2/3.6
    Touch Sense pins: 0,1,15,16,17,18,19,22,23,25,32,33

    Teensy LC
    Touch Sense pins: 0,1,3,4,15,16,17,18,19,22,23
  ********************************************************/
#if !defined(__MK64FX512__) && !defined(__IMXRT1062__)
  /* touch.pinMode(0, touchRead(0) + 250); // pin, threshold */
#endif

	  // teensy audio setup
  AudioMemory(2);
  dac1.analogReference(EXTERNAL); // 3.3v p2p
  pink1.amplitude(2);
  //reverb1.reverbTime(0.5);
  amp1.gain(0);

}

void loop() {
  int who;
	static elapsedMillis timer;

	  btn1.update();
		btn2.update();
		digitalWrite(led1Pin, PRESSED(btn1));
		digitalWrite(led2Pin, PRESSED(btn2));

	if (timer == 1000) {
		Serial.println("three");
		digitalWrite(led2Pin, HIGH);
		delay(200);
		digitalWrite(led2Pin, LOW);
	} else if (timer == 2000) {
		Serial.println("two");
		digitalWrite(led2Pin, HIGH);
		delay(200);
		digitalWrite(led2Pin, LOW);
	} else if (timer == 3000) {
		Serial.println("one");
		digitalWrite(led2Pin, HIGH);
		delay(200);
		digitalWrite(led2Pin, LOW);
	} else if (timer > 4000){
		Serial.println("zzz");
		/* Serial.flush(); */
		/* digitalWrite(led1Pin, LOW); */
		/* digitalWrite(led2Pin, HIGH); */
		/* delay(100); */
		/* digitalWrite(led2Pin, LOW); */

		delay(10);
		
		/********************************************************
			feed the sleep function its wakeup parameters. Then go
			to deepSleep.
		********************************************************/
#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__)

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


#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

		delay(2000);
		Serial.println("Good morning");
		if (who == button1Pin) { // pin wakeup source is its pin value
			for (int i = 0; i < 1; i++) {
				digitalWrite(led1Pin, HIGH);
				delay(200);
				digitalWrite(led1Pin, LOW);
				delay(200);
			}
		}

		if (who == button2Pin) { // pin wakeup source is its pin value
			for (int i = 0; i < 2; i++) {
				digitalWrite(led1Pin, HIGH);
				delay(200);
				digitalWrite(led1Pin, LOW);
				delay(200);
			}
		}

		if (who == 34) { // compare wakeup value
			for (int i = 0; i < 3; i++) {
				digitalWrite(led1Pin, HIGH);
				delay(200);
				digitalWrite(led1Pin, LOW);
				delay(200);
			}
		}

		if (who == 35) { // rtc wakeup value
			for (int i = 0; i < 4; i++) {
				digitalWrite(led1Pin, HIGH);
				delay(200);
				digitalWrite(led1Pin, LOW);
				delay(200);
			}
		}

		if (who == 36) { // lptmr wakeup value
			for (int i = 0; i < 5; i++) {
				digitalWrite(led1Pin, HIGH);
				delay(200);
				digitalWrite(led1Pin, LOW);
				delay(200);
			}
		}

		if (who == 37) { // tsi wakeup value
			for (int i = 0; i < 6; i++) {
				digitalWrite(led1Pin, HIGH);
				delay(200);
				digitalWrite(led1Pin, LOW);
				delay(200);
			}
		}
		timer = 0;
	}
}
 
The Snooze library has a tendency to cut usb serial off whilst it still has things in it's output buffer
so it helps to flush the buffer before going to sleep.
Code:
//  Use SnoozeUSBSerial when setting up Snooze  
    SnoozeUSBSerial SerialUsb;
    SnoozeBlock config_teensy32(SerialUsb, timer);
.
.
.
.
.
// Before going to sleep[ flush the usb serial line and delay a short while after flush.
    SerialUsb.flush();  //
    delay(50);
    config_teensy32 += digital;
    who = Snooze.deepSleep( config_teensy32 );// return module that woke processor
    config_teensy32 -= digital;
.
.
.
.
PS
It makes you code much more readable if you delete all the unnecessary #defines
especially if you want someone else to read and comment on your code.
 
Still glitchy

Hi, thanks for the suggestion. I went ahead and added that to my example, and it improves things, but it does not completely fix the bug.

Before calling usb.flush(), I had correct output after the first sleep, but scrambled output after subsequent sleeps.
Now that I'm calling usb.flush(), I see the exact opposite: output is always scrambled after the first sleep, but correct after subsequent sleeps.
Furthermore, if I watch it run long enough, I still see the scrambling occasionally. Hard to predict exactly when, but I see it on maybe 5% of wakeups. Just often enough to corrupt someone's data, just rarely enough to be hard to debug!

Here's the new, simplified example. Notice that I'm using usb.println() here -- as some of the Snooze examples do -- but I get the same results with Serial.println().

Code:
#include <Snooze.h>

// Load drivers
SnoozeDigital digital;
SnoozeTimer timer;
SnoozeUSBSerial usb;
SnoozeBlock config_teensy32(usb, timer);

// set pin numbers:
const int button1Pin = 0;   // sw1
const int button2Pin = 9;   // sw2
const int led1Pin =  21;    // led1
const int led2Pin =  20;    // led2

void setup() {
  Serial.begin(115200); 

  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);

  digital.pinMode(button1Pin, INPUT_PULLUP, FALLING);//pin, mode, type
  digital.pinMode(button2Pin, INPUT_PULLUP, FALLING);//pin, mode, type

  timer.setTimer(5000);// milliseconds
}

void loop() {
  int who;
  static elapsedMillis clock;

  if (clock == 1000) {
    usb.println("three");
    digitalWrite(led2Pin, HIGH);
    delay(200);
    digitalWrite(led2Pin, LOW);
  } else if (clock == 2000) {
    usb.println("two");
    digitalWrite(led2Pin, HIGH);
    delay(200);
    digitalWrite(led2Pin, LOW);
  } else if (clock == 3000) {
    usb.println("one");
    digitalWrite(led2Pin, HIGH);
    delay(200);
    digitalWrite(led2Pin, LOW);
  } else if (clock > 4000){
    usb.println("zzz");

    delay(10);
    
    /********************************************************
      feed the sleep function its wakeup parameters. Then go
      to deepSleep.
    ********************************************************/

    usb.flush();  
    delay(50);
    config_teensy32 += digital;
    who = Snooze.deepSleep( config_teensy32 );// return module that woke processor
    config_teensy32 -= digital;

    delay(500);
    usb.println("Good morning");
    if (who == button1Pin) { // pin wakeup source is its pin value
      for (int i = 0; i < 1; i++) {
        digitalWrite(led1Pin, HIGH);
        delay(200);
        digitalWrite(led1Pin, LOW);
        delay(200);
      }
    }

    if (who == button2Pin) { // pin wakeup source is its pin value
      for (int i = 0; i < 2; i++) {
        digitalWrite(led1Pin, HIGH);
        delay(200);
        digitalWrite(led1Pin, LOW);
        delay(200);
      }
    }

    if (who == 34) { // compare wakeup value
      for (int i = 0; i < 3; i++) {
        digitalWrite(led1Pin, HIGH);
        delay(200);
        digitalWrite(led1Pin, LOW);
        delay(200);
      }
    }

    if (who == 35) { // rtc wakeup value
      for (int i = 0; i < 4; i++) {
        digitalWrite(led1Pin, HIGH);
        delay(200);
        digitalWrite(led1Pin, LOW);
        delay(200);
      }
    }

    if (who == 36) { // lptmr wakeup value
      for (int i = 0; i < 5; i++) {
        digitalWrite(led1Pin, HIGH);
        delay(200);
        digitalWrite(led1Pin, LOW);
        delay(200);
      }
    }

    if (who == 37) { // tsi wakeup value
      for (int i = 0; i < 6; i++) {
        digitalWrite(led1Pin, HIGH);
        delay(200);
        digitalWrite(led1Pin, LOW);
        delay(200);
      }
    }
    clock = 0;
  }
}
 
I have made changes to your code as shown below. I think it will now work as you expect.
I have annotated the lines I have deleted, changed or added with //*** REB "whatever"
Code:
#include <Snooze.h>

// Load drivers
SnoozeDigital digital;
SnoozeTimer timer;
SnoozeUSBSerial usb;
//SnoozeBlock config_teensy32(usb, timer);
SnoozeBlock config_teensy32(usb, timer, digital);    ///*** REB ADDED / CHANGED

// set pin numbers:
const int button1Pin = 0;   // sw1
const int button2Pin = 9;   // sw2
const int led1Pin =  21;    // led1
const int led2Pin =  20;    // led2

void setup() {
  Serial.begin(115200); 

  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);

  digital.pinMode(button1Pin, INPUT_PULLUP, FALLING);//pin, mode, type
  digital.pinMode(button2Pin, INPUT_PULLUP, FALLING);//pin, mode, type

  timer.setTimer(5000);// milliseconds
}

void loop() {
  int who;
  static elapsedMillis clock;
  int iWokeUpAt;        //**** REB ADDED ****
  int usbWokeUpAt;      //**** REB ADDED ****

  if (clock == 1000) {
    usb.println("three");
    digitalWrite(led2Pin, HIGH);
    delay(200);
    digitalWrite(led2Pin, LOW);
  } else if (clock == 2000) {             
    usb.println("two");
    digitalWrite(led2Pin, HIGH);
    delay(200);
    digitalWrite(led2Pin, LOW);
  } else if (clock == 3000) {           
    usb.println("one");
    digitalWrite(led2Pin, HIGH);
    delay(200);
    digitalWrite(led2Pin, LOW);
  } else if (clock > 4000){
    usb.println("zzz");

    delay(10);
    
    /********************************************************
      feed the sleep function its wakeup parameters. Then go
      to deepSleep.
    ********************************************************/

    usb.flush();  
    delay(50);
//    config_teensy32 += digital;                   //**** REB REMOVED ****
    who = Snooze.deepSleep( config_teensy32 );// return module that woke processor
//    config_teensy32 -= digital;                   //**** REB REMOVED ****
    iWokeUpAt = millis();                           //**** REB ADDED ****
    
    while (!usb && (millis() < iWokeUpAt + 8000));  //**** REB ADDED ****
    usbWokeUpAt = millis();                         //**** REB ADDED ****

    delay(500);

    usb.println("Good morning");
    usb.print("who="); usb.println(who);            //**** REB ADDED ****
    usb.print("Time to wake up usb=");              //**** REB ADDED ****
    usb.print(usbWokeUpAt - iWokeUpAt);             //**** REB ADDED ****
    usb.println("ms");                              //**** REB ADDED ****

    if (who == button1Pin) { // pin wakeup source is its pin value
      for (int i = 0; i < 1; i++) {
        digitalWrite(led1Pin, HIGH);
        delay(200);
        digitalWrite(led1Pin, LOW);
        delay(200);
      }
    }

    if (who == button2Pin) { // pin wakeup source is its pin value
      for (int i = 0; i < 2; i++) {
        digitalWrite(led1Pin, HIGH);
        delay(200);
        digitalWrite(led1Pin, LOW);
        delay(200);
      }
    }

    if (who == 34) { // compare wakeup value
      for (int i = 0; i < 3; i++) {
        digitalWrite(led1Pin, HIGH);
        delay(200);
        digitalWrite(led1Pin, LOW);
        delay(200);
      }
    }

    if (who == 35) { // rtc wakeup value
      for (int i = 0; i < 4; i++) {
        digitalWrite(led1Pin, HIGH);
        delay(200);
        digitalWrite(led1Pin, LOW);
        delay(200);
      }
    }

    if (who == 36) { // lptmr wakeup value
      for (int i = 0; i < 5; i++) {
        digitalWrite(led1Pin, HIGH);
        delay(200);
        digitalWrite(led1Pin, LOW);
        delay(200);
      }
    }

    if (who == 37) { // tsi wakeup value
      for (int i = 0; i < 6; i++) {
        digitalWrite(led1Pin, HIGH);
        delay(200);
        digitalWrite(led1Pin, LOW);
        delay(200);
      }
    }
    clock = 0;
  }
}

When the teensy goes to sleep the usb loses contact with windows, or "whatever".
You have to wait for it to regain contact before you can start writing to usb again.
When I was running the above code it took just under 1.5seconds to start printing again.

When using elaspsedMillis never use == as elapsedMillis do not always increment in ones.
Much better to use >= or <= as appropriate. This may need code to be altered checking from highest to lowest to get the order correct.

EDIT:
NOPE that did not solve it. On what appears to be the second loop it goes screwy.
 
Last edited:
NOPE that did not solve it. On what appears to be the second loop it goes screwy.

Same here.
To put a finer point on it: I have added a call to usb.flush() immediately after every single Serial.println() in this example, and I still see the bug.

And as I said before, I've already tried some pretty long delay times waiting for the Serial port to reconnect, but it doesn't change anything.

I should reiterate that this is not a case of data being lost, but of data being rearranged. To me, that's weirder.

What's a simple way to determine if what we're seeing is really what Teensy is sending? It could just be the Arduino Serial Monitor screwing up.

Also, is there anybody running Teensyduino 1.54 beta who could check if this problem still exists there? If it's fixed in 1.54, then no worries. =)
 
Also, is there anybody running Teensyduino 1.54 beta who could check if this problem still exists there? If it's fixed in 1.54, then no worries. =)
I was running my tests under Teensyduino 1.54b9
 
Ok, managed to do some more sleuthing...
I put in some boolean flags and changed the == to >=.
The boolean flags were to ensure that the loops only ran once per major loop.
All the changes for this iteration are commented:- //**** REB ADDED 2222
Code below--
Code:
#include <Snooze.h>

// Load drivers
SnoozeDigital digital;
SnoozeTimer timer;
SnoozeUSBSerial usb;
//SnoozeBlock config_teensy32(usb, timer);
SnoozeBlock config_teensy32(usb, timer, digital);    ///*** REB ADDED / CHANGED

// set pin numbers:
const int button1Pin = 0;   // sw1
const int button2Pin = 9;   // sw2
const int led1Pin =  21;    // led1
const int led2Pin =  20;    // led2

void setup() {
  Serial.begin(115200); 
  while (!usb){};
  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);

  digital.pinMode(button1Pin, INPUT_PULLUP, FALLING);//pin, mode, type
  digital.pinMode(button2Pin, INPUT_PULLUP, FALLING);//pin, mode, type

  timer.setTimer(5000);// milliseconds
//  usb.println("Setup Done");
}
  bool done1=false;           //**** REB ADDED 2222
  bool done2=false;           //**** REB ADDED 2222
  bool done3=false;           //**** REB ADDED 2222


void loop() {
  
  int who;
  static elapsedMillis clock;
  int iWokeUpAt;        //**** REB ADDED ****
  int usbWokeUpAt;      //**** REB ADDED ****
  
  if ((done3==false) && (clock >= 1000)) {                 //**** REB ALTERED 2222
      done3=true;
      usb.println("three");
      digitalWrite(led2Pin, HIGH);
      delay(200);
      digitalWrite(led2Pin, LOW);
  } else if ((done2==false) && (clock >= 2000)) {          //**** REB ALTERED 2222
      done2=true;
      usb.println("two");
      digitalWrite(led2Pin, HIGH);
      delay(200);
      digitalWrite(led2Pin, LOW);
  } else if ((done1==false) && (clock >= 3000)) {          //**** REB ALTERED 2222
      done1=true;
      usb.println("one");
      digitalWrite(led2Pin, HIGH);
      delay(200);
      digitalWrite(led2Pin, LOW);
  } else if (clock > 4000){
      usb.println("zzz");
      done1=false;                          //**** REB ADDED 2222
      done2=false;                          //**** REB ADDED 2222
      done3=false;                          //**** REB ADDED 2222
  

      delay(10);
    
    /********************************************************
      feed the sleep function its wakeup parameters. Then go
      to deepSleep.
    ********************************************************/

      usb.flush();  
      delay(500);
//    config_teensy32 += digital;                   //**** REB REMOVED ****
      who = Snooze.deepSleep( config_teensy32 );// return module that woke processor
//    config_teensy32 -= digital;                   //**** REB REMOVED ****
      iWokeUpAt = millis();                           //**** REB ADDED ****
    
      while (!usb && (millis() < iWokeUpAt + 8000));  //**** REB ADDED ****
      usbWokeUpAt = millis();                         //**** REB ADDED ****

      delay(500);

      usb.println("Good morning");
      usb.print("who="); usb.println(who);            //**** REB ADDED ****
      usb.print("Time to wake up usb=");              //**** REB ADDED ****
      usb.print(usbWokeUpAt - iWokeUpAt);             //**** REB ADDED ****
      usb.println("ms");                              //**** REB ADDED ****

      if (who == button1Pin) { // pin wakeup source is its pin value
          for (int i = 0; i < 1; i++) {
              digitalWrite(led1Pin, HIGH);
              delay(200);
              digitalWrite(led1Pin, LOW);
              delay(200);
          }
       }

      if (who == button2Pin) { // pin wakeup source is its pin value
          for (int i = 0; i < 2; i++) {
              digitalWrite(led1Pin, HIGH);
              delay(200);
              digitalWrite(led1Pin, LOW);
              delay(200);
          } 
      }

      if (who == 34) { // compare wakeup value
          for (int i = 0; i < 3; i++) {
              digitalWrite(led1Pin, HIGH);
              delay(200);
              digitalWrite(led1Pin, LOW);
              delay(200);
          }
      }

      if (who == 35) { // rtc wakeup value
          for (int i = 0; i < 4; i++) {
              digitalWrite(led1Pin, HIGH);
              delay(200);
              digitalWrite(led1Pin, LOW);
              delay(200);
          }
      }

      if (who == 36) { // lptmr wakeup value
          for (int i = 0; i < 5; i++) {
              digitalWrite(led1Pin, HIGH);
              delay(200);
              digitalWrite(led1Pin, LOW);
              delay(200);
          }
      }

      if (who == 37) { // tsi wakeup value
          for (int i = 0; i < 6; i++) {
              digitalWrite(led1Pin, HIGH);
              delay(200);
              digitalWrite(led1Pin, LOW);
              delay(200);
          }
      }
      clock = 0;
    }
}
RESULT - no change in output, still screws up on second go round.
 
...still sleuthing.
This time I added some code to get some history. Basically I kept an array of printed out data and recorded Millis() for the occurrence.
All the added code is commented as //**** REB ADDED 3333
Code:
#include <Snooze.h>

// Load drivers
SnoozeDigital digital;
SnoozeTimer timer;
SnoozeUSBSerial usb;
//SnoozeBlock config_teensy32(usb, timer);
SnoozeBlock config_teensy32(usb, timer, digital);    ///*** REB ADDED / CHANGED
const int maxHistorySize = 40;                      //**** REB ADDED 3333

struct hData                                        //**** REB ADDED 3333
{                                                   //**** REB ADDED 3333
    char text[25];                                  //**** REB ADDED 3333
    unsigned long time;                             //**** REB ADDED 3333
};                                                  //**** REB ADDED 3333
hData history[maxHistorySize];                                 //**** REB ADDED 3333
int idx = 0;                                        //**** REB ADDED 3333

// set pin numbers:
const int button1Pin = 0;   // sw1
const int button2Pin = 9;   // sw2
const int led1Pin =  21;    // led1
const int led2Pin =  20;    // led2

void setup() {
  Serial.begin(115200); 
  while (!usb){};
  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);

  digital.pinMode(button1Pin, INPUT_PULLUP, FALLING);//pin, mode, type
  digital.pinMode(button2Pin, INPUT_PULLUP, FALLING);//pin, mode, type

  timer.setTimer(5000);// milliseconds
//  usb.println("Setup Done");
}
  bool done1=false;           //**** REB ADDED 2222
  bool done2=false;           //**** REB ADDED 2222
  bool done3=false;           //**** REB ADDED 2222


void loop() {
  
  int who;
  static elapsedMillis clock;
  int iWokeUpAt;        //**** REB ADDED ****
  int usbWokeUpAt;      //**** REB ADDED ****
  
    if ((done3==false) && (clock >= 1000)) {                 //**** REB ALTERED 2222
        done3=true;
        strncpy(history[idx].text, "three", 10);            //**** REB ADDED 3333
        history[idx].time = millis();                       //**** REB ADDED 3333
        ++idx;                                              //**** REB ADDED 3333
        usb.println("three");
        digitalWrite(led2Pin, HIGH);
        delay(200);
        digitalWrite(led2Pin, LOW);
    } else if ((done2==false) && (clock >= 2000)) {          //**** REB ALTERED 2222
      done2=true;
        strncpy(history[idx].text, "two", 10);                //**** REB ADDED 3333
        history[idx].time = millis();                         //**** REB ADDED 3333
        ++idx;                                                //**** REB ADDED 3333
        usb.println("two");
        digitalWrite(led2Pin, HIGH);
        delay(200);
        digitalWrite(led2Pin, LOW);
  } else if ((done1==false) && (clock >= 3000)) {          //**** REB ALTERED 2222
        done1=true;
        strncpy(history[idx].text, "one", 10);                //**** REB ADDED 3333
        history[idx].time = millis();                         //**** REB ADDED 3333
        ++idx;                                                //**** REB ADDED 3333
        usb.println("one");
        digitalWrite(led2Pin, HIGH);
        delay(200);
        digitalWrite(led2Pin, LOW);
  } else if (clock > 4000){
        strncpy(history[idx].text, "zzz", 10);                //**** REB ADDED 3333
        history[idx].time = millis();                         //**** REB ADDED 3333
        ++idx;                                                //**** REB ADDED 3333
        usb.println("zzz");
        done1=false;                          //**** REB ADDED 2222
        done2=false;                          //**** REB ADDED 2222
        done3=false;                          //**** REB ADDED 2222
  

        delay(10);
    
    /********************************************************
      feed the sleep function its wakeup parameters. Then go
      to deepSleep.
    ********************************************************/

        usb.flush();  
        delay(500);
//      config_teensy32 += digital;                   //**** REB REMOVED ****
        who = Snooze.deepSleep( config_teensy32 );// return module that woke processor
//      config_teensy32 -= digital;                   //**** REB REMOVED ****
        iWokeUpAt = millis();                           //**** REB ADDED ****
    
        while (!usb && (millis() < iWokeUpAt + 8000));  //**** REB ADDED ****
        usbWokeUpAt = millis();                         //**** REB ADDED ****

        delay(500);

        strncpy(history[idx].text, "Good morning", 25);       //**** REB ADDED 3333
        history[idx].time = millis();                         //**** REB ADDED 3333
        ++idx;                                                //**** REB ADDED 3333
        usb.println("Good morning");
        usb.print("who="); usb.println(who);            //**** REB ADDED ****
        usb.print("Time to wake up usb=");              //**** REB ADDED ****
        usb.print(usbWokeUpAt - iWokeUpAt);             //**** REB ADDED ****
        usb.println("ms");                              //**** REB ADDED ****

        if (who == button1Pin) { // pin wakeup source is its pin value
            for (int i = 0; i < 1; i++) {
                digitalWrite(led1Pin, HIGH);
                delay(200);
                digitalWrite(led1Pin, LOW);
                delay(200);
            }
        }

        if (who == button2Pin) { // pin wakeup source is its pin value
            for (int i = 0; i < 2; i++) {
                digitalWrite(led1Pin, HIGH);
                delay(200);
                digitalWrite(led1Pin, LOW);
                delay(200);
            } 
        }

        if (who == 34) { // compare wakeup value
            for (int i = 0; i < 3; i++) {
                digitalWrite(led1Pin, HIGH);
                delay(200);
                digitalWrite(led1Pin, LOW);
                delay(200);
            }
        }

        if (who == 35) { // rtc wakeup value
            for (int i = 0; i < 4; i++) {
                digitalWrite(led1Pin, HIGH);
                delay(200);
                digitalWrite(led1Pin, LOW);
                delay(200);
            }
        }

        if (who == 36) { // lptmr wakeup value
            for (int i = 0; i < 5; i++) {
                digitalWrite(led1Pin, HIGH);
                delay(200);
                digitalWrite(led1Pin, LOW);
                delay(200);
            }
        }

        if (who == 37) { // tsi wakeup value
            for (int i = 0; i < 6; i++) {
                digitalWrite(led1Pin, HIGH);
                delay(200);
                digitalWrite(led1Pin, LOW);
                delay(200);
            }
        }
        clock = 0;
    }
    if (idx >= maxHistorySize-2)                                                //**** REB ADDED 3333
    {
        usb.println("------------- HISTORY --------------------");              //**** REB ADDED 3333

        for (int n = 0; n < idx; ++n)                                           //**** REB ADDED 3333
        {                                                                       //**** REB ADDED 3333
            usb.print(history[n].time);                                         //**** REB ADDED 3333
            usb.print(" - ");                                                   //**** REB ADDED 3333
            usb.println(history[n].text);                                       //**** REB ADDED 3333
        }                                                                       //**** REB ADDED 3333
        usb.println(idx);                                                       //**** REB ADDED 3333
        usb.println("---------- END OF HISTORY ----------------");              //**** REB ADDED 3333
        idx = 0;                                                                //**** REB ADDED 3333
        while (1);                                                              //**** REB ADDED 3333
    }
}
The output is screwed up as before but the history printout at the end indicates that all the events occurred when they should have, it is just the usb serial printout which gets screwed up and printed out of order on the second loop round.
 
...continued, you know what
After looking at history above, I modified the code in Message #7 to print out Millis() every time there was any "print out".
Code is below. Changes this time are annotated //**** REB ADDED 2.5
Code:
#include <Snooze.h>

// Load drivers
SnoozeDigital digital;
SnoozeTimer timer;
SnoozeUSBSerial usb;
//SnoozeBlock config_teensy32(usb, timer);
SnoozeBlock config_teensy32(usb, timer, digital);    ///*** REB ADDED / CHANGED

// set pin numbers:
const int button1Pin = 0;   // sw1
const int button2Pin = 9;   // sw2
const int led1Pin =  21;    // led1
const int led2Pin =  20;    // led2

  int loopCounter=0;                      //**** REB ADDED 2.5

void setup() {
  Serial.begin(115200); 
  while (!usb){};
  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);

  digital.pinMode(button1Pin, INPUT_PULLUP, FALLING);//pin, mode, type
  digital.pinMode(button2Pin, INPUT_PULLUP, FALLING);//pin, mode, type

  timer.setTimer(5000);// milliseconds
//  usb.println("Setup Done");
}
  bool done1=false;           //**** REB ADDED 2222
  bool done2=false;           //**** REB ADDED 2222
  bool done3=false;           //**** REB ADDED 2222

void loop() {
  
  int who;
  static elapsedMillis clock;
  int iWokeUpAt;        //**** REB ADDED ****
  int usbWokeUpAt;      //**** REB ADDED ****
  
  if ((done3==false) && (clock >= 1000)) {                 //**** REB ALTERED 2222
      done3=true;
      usb.print(millis());                                 //**** REB ADDED 2.5
      usb.println(" - three");                             //**** REB ALTERED 2.5
      digitalWrite(led2Pin, HIGH);
      delay(200);
      digitalWrite(led2Pin, LOW);
  } else if ((done2==false) && (clock >= 2000)) {          //**** REB ALTERED 2222
      done2=true;
      usb.print(millis());                                 //**** REB ADDED 2.5
      usb.println(" - two");                               //**** REB ALTERED 2.5
      digitalWrite(led2Pin, HIGH);
      delay(200);
      digitalWrite(led2Pin, LOW);
  } else if ((done1==false) && (clock >= 3000)) {          //**** REB ALTERED 2222
      done1=true;
      usb.print(millis());                                 //**** REB ADDED 2.5
      usb.println(" - one");                                                       //**** REB ALTERED 2.5
      digitalWrite(led2Pin, HIGH);
      delay(200);
      digitalWrite(led2Pin, LOW);
  } else if (clock > 4000){
      usb.print(millis());                                 //**** REB ADDED 2.5
      usb.println(" - zzz");                               //**** REB ALTERED 2.5
      done1=false;                          //**** REB ADDED 2222
      done2=false;                          //**** REB ADDED 2222
      done3=false;                          //**** REB ADDED 2222
  

      delay(10);
    
    /********************************************************
      feed the sleep function its wakeup parameters. Then go
      to deepSleep.
    ********************************************************/

      usb.flush();  
      delay(500);
//    config_teensy32 += digital;                   //**** REB REMOVED ****
      who = Snooze.deepSleep( config_teensy32 );// return module that woke processor
//    config_teensy32 -= digital;                   //**** REB REMOVED ****
      iWokeUpAt = millis();                           //**** REB ADDED ****
    
      while (!usb && (millis() < iWokeUpAt + 8000));  //**** REB ADDED ****
      usbWokeUpAt = millis();                         //**** REB ADDED ****

      delay(500);
      usb.print(millis());                                 //**** REB ADDED 2.5
      usb.println(" - Good morning");                      //**** REB ALTERED 2.5
      usb.print("who="); usb.println(who);            //**** REB ADDED ****
      usb.print("Time to wake up usb=");              //**** REB ADDED ****
      usb.print(usbWokeUpAt - iWokeUpAt);             //**** REB ADDED ****
      usb.println("ms");                              //**** REB ADDED ****
      usb.println("loopCounter = ");                  //**** REB ADDED 2.5
      usb.println(loopCounter);                       //**** REB ADDED 2.5

      if (loopCounter==0)                   //**** REB ADDED 2.5
      {                                    //**** REB ADDED 2.5
          delay(20000);                    //**** REB ADDED 2.5
      };                                    //**** REB ADDED 2.5
      
      ++loopCounter;                       //**** REB ADDED 2.5
           
      if (who == button1Pin) { // pin wakeup source is its pin value
          for (int i = 0; i < 1; i++) {
              digitalWrite(led1Pin, HIGH);
              delay(200);
              digitalWrite(led1Pin, LOW);
              delay(200);
          }
       }

      if (who == button2Pin) { // pin wakeup source is its pin value
          for (int i = 0; i < 2; i++) {
              digitalWrite(led1Pin, HIGH);
              delay(200);
              digitalWrite(led1Pin, LOW);
              delay(200);
          } 
      }

      if (who == 34) { // compare wakeup value
          for (int i = 0; i < 3; i++) {
              digitalWrite(led1Pin, HIGH);
              delay(200);
              digitalWrite(led1Pin, LOW);
              delay(200);
          }
      }

      if (who == 35) { // rtc wakeup value
          for (int i = 0; i < 4; i++) {
              digitalWrite(led1Pin, HIGH);
              delay(200);
              digitalWrite(led1Pin, LOW);
              delay(200);
          }
      }

      if (who == 36) { // lptmr wakeup value
          for (int i = 0; i < 5; i++) {
              digitalWrite(led1Pin, HIGH);
              delay(200);
              digitalWrite(led1Pin, LOW);
              delay(200);
          }
      }

      if (who == 37) { // tsi wakeup value
          for (int i = 0; i < 6; i++) {
              digitalWrite(led1Pin, HIGH);
              delay(200);
              digitalWrite(led1Pin, LOW);
              delay(200);
          }
      }
      clock = 0;

    }
}
The resulting printout is still screwed up but shows something very interesting, and worrying.
teensy sleep problem1.jpg
The problems with usb printing occur the first time after a DeepSpleep. Subsequent DeepSleeps do not exhibit the same problem.
The attached pic shows the usb printout and the code beside it.
The printing of "three" is completely out of sequence and the delay which should happen after "Good Morning " etc actually occurs before "three" is printed out and the following printout which should have preceded the printing of "three".

You will notice that I printout the value of loopCounter without saying what it is. So I tidied up the code to say what I was printing and this is the result.
UTTERLY AND COMPETELY SCREWED UP.
THERE IS DEFINITEVELY SOMETHING WRONG WITH usb serial printout when using the Snooze library. This is one of a number of problems which crop up with this library. Can someone confirm these problems will get looked at. The author seems not to be supporting the library any more which is a great pity because it is a potentially very good and useful library.
Anyway here is the completely screwed up print out.
teensy sleep problem2.jpg
 
Wow, thanks for digging into this! It is weirder the closer I look. =)

FWIW: in the original code I didn't use the usbserial component of the Snooze library, and the same sort of error was triggered after every sleep but the first one.
Also, it looks like Snooze's usbserial.flush() is just calling usb_serial_flush_output(), from PJRC's usb_serial support code.
So all in all, I'm not sure that this is entirely an issue with Snooze.

It's maybe something about the interaction between different systems, and I know that's a hard kind of bug to track down.

Do you know if there's any other deep-sleep package for Teensy 3.2 that could be easily swapped in? Then we could isolate if it's specific to Snooze, or if it's just about usb_serial and sleep. (I'm trying to parse what Snooze actually does for deepSleep on Teensy 3.2, but the code is a dense forest of #ifdefs ...)

I'm also still trying to figure out how to test this with Serial1 (hardware uart) instead of Serial, just to confirm it's a USB problem. I don't have anything handy to read it with, but I guess I can rig up a second Teensy just for that.
 
Incidentally, the Snooze HAL for teensy 3.2 seems to have a lot of #ifdefs for doing different things at different clock speeds.
So for the record, I'm testing this at 72mhz.
 
I've just run a test outputting to Serial3 which is then read on a laptop with USB to serial converter.
Program runs fine, with text appearing in the correct order.
One thing I noticed is that the Serial3.Flush() before going to sleep is required otherwise the last characters before Snoozing are lost.

Below is a program that demonstrates the Snooze/USB problem. I hope someone will pick it up and investigate the problem, however I have my doubts. Support for this library seems to be DEAD.

Code:
#include <Snooze.h>

// Load drivers
SnoozeDigital digital;
SnoozeTimer timer;
SnoozeUSBSerial usb;

SnoozeBlock config_teensy32(usb, timer, digital); 

// set pin numbers:
const int button1Pin = 0;   // sw1
const int button2Pin = 9;   // sw2
const int led1Pin =  21;    // led1
const int led2Pin =  20;    // led2

int loopCounter=0; 

void setup() {
  Serial.begin(115200); 

  while (!usb){};
  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);

  digital.pinMode(button1Pin, INPUT_PULLUP, FALLING);//pin, mode, type
  digital.pinMode(button2Pin, INPUT_PULLUP, FALLING);//pin, mode, type

  timer.setTimer(5000);// milliseconds
//  usb.println("Setup Done");
}
  bool done1=false;  
  bool done2=false;  
  bool done3=false;  

void loop() {
  
  int who;
  static elapsedMillis clock;
  int iWokeUpAt;     
  int usbWokeUpAt;   
  
  if ((done3==false) && (clock >= 1000)) { 
      done3=true;
      usb.print(millis());                 
      usb.println(" - three");             

      digitalWrite(led2Pin, HIGH);
      delay(200);
      digitalWrite(led2Pin, LOW);
  } else if ((done2==false) && (clock >= 2000)) {
      done2=true;
      usb.print(millis());                       
      usb.println(" - two");                     

      digitalWrite(led2Pin, HIGH);
      delay(200);
      digitalWrite(led2Pin, LOW);
  } else if ((done1==false) && (clock >= 3000)) {
      done1=true;
      usb.print(millis());                       
      usb.println(" - one");                     

      digitalWrite(led2Pin, HIGH);
      delay(200);
      digitalWrite(led2Pin, LOW);
  } else if (clock > 4000){
      usb.print(millis());                       
      usb.println(" - zzz");                     
      done1=false;                          
      done2=false;                          
      done3=false;                          
  

      delay(10);
    
    /********************************************************
      feed the sleep function its wakeup parameters. Then go
      to deepSleep.
    ********************************************************/

      usb.flush();  
//      delay(50);

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

      iWokeUpAt = millis();           
      
      while (!usb && (millis() < iWokeUpAt + 8000)); 
      usbWokeUpAt = millis();                        

      delay(500);
      usb.print(millis());                           
      usb.println(" - Good morning");                

      usb.print("who="); usb.println(who);           
      usb.print("Time to wake up usb=");             
      usb.print(usbWokeUpAt - iWokeUpAt);            
      usb.println("ms");                             
      usb.print("loopCounter = ");                  
      usb.println(loopCounter);                     

      if (loopCounter==0) delay(10000);                    
      
      ++loopCounter;                       
           
      if (who == button1Pin) { // pin wakeup source is its pin value
          for (int i = 0; i < 1; i++) {
              digitalWrite(led1Pin, HIGH);
              delay(200);
              digitalWrite(led1Pin, LOW);
              delay(200);
          }
       }

      if (who == button2Pin) { // pin wakeup source is its pin value
          for (int i = 0; i < 2; i++) {
              digitalWrite(led1Pin, HIGH);
              delay(200);
              digitalWrite(led1Pin, LOW);
              delay(200);
          } 
      }

      if (who == 34) { // compare wakeup value
          for (int i = 0; i < 3; i++) {
              digitalWrite(led1Pin, HIGH);
              delay(200);
              digitalWrite(led1Pin, LOW);
              delay(200);
          }
      }

      if (who == 35) { // rtc wakeup value
          for (int i = 0; i < 4; i++) {
              digitalWrite(led1Pin, HIGH);
              delay(200);
              digitalWrite(led1Pin, LOW);
              delay(200);
          }
      }

      if (who == 36) { // lptmr wakeup value
          for (int i = 0; i < 5; i++) {
              digitalWrite(led1Pin, HIGH);
              delay(200);
              digitalWrite(led1Pin, LOW);
              delay(200);
          }
      }

      if (who == 37) { // tsi wakeup value
          for (int i = 0; i < 6; i++) {
              digitalWrite(led1Pin, HIGH);
              delay(200);
              digitalWrite(led1Pin, LOW);
              delay(200);
          }
      }
      clock = 0;

    }
}
 
Back
Top