Complicated sleep problems with Teensy 3.2 (Snooze not snoozing)

Status
Not open for further replies.

mykle

Well-known member
(Reposting, because i posted in the wrong place before. Oops.)

Hello! I'm working on a project that embeds a Teensy 3.2 which is doing quite a lot .. it's running Teensy Audio, sending MIDI over USB, providing some debug over USB serial, and talking to an IMU/accelerometer chip over I2c. All of that works, amazingly.

But now I'm trying to implement power savings using the Snooze library, and it's not really working as it's supposed to. I want to sleep when a pin goes low, then wake on the spin rising and/or any button press. Depending on the configs I've tried, the sleep() method either doesn't go to sleep properly or doesn't wake up properly. For debugging purposes I have managed to get it to wake on one button press, but only by disabling that button for the rest of the app. The pin that Snooze.digital is configured to listen to on RISING is going high, but still no wakeup. I also tried a 3000ms Snooze.timer() for wakeup, and that didn't work either. Something is screwy.

I wonder if the things I'm trying to do are even allowed:

-- I need to wake up on any button press, so I'm running SnoozeDigital.pinmode() on the same two pins that are already attached to the Bounce2 library. Is that allowed? When I do that, it seems that Snooze always detects a button press and wakes immediately. Do I need to somehow detach Bounce2 and attach Snooze before sleeping, and then switch back on wakeup?

-- I am using the digital, usbserial and audio drivers. usbserial is supposed to let the teensy play well with USB serial during sleep & wake. But actually serial output from the teensy hangs after wake. (Although the computer does detect a USB serial device.) Do I need to reset the serial port somehow after sleeping? Does the fact that I'm also sending USB MIDI events mean that I need to do something different here, or is that also managed by usbserial ?

-- The IMU chip is generating interrupts when new data arrives. Do I need to disable interrupts before sleep? Teensy Audio uses interrupts too, and maybe Bounce2 does, I'm not sure. Does Snooze use interrupts in some way that might be incompatible with my situation?

-- The pin I'm trying to be woken by, PO_wake, puts out 2.5v, not the full 3.3v. When the teensy is awake & the pin is high, the Teensy reads it as logic-high, no problem ... is there some reason why that would behave differently during sleep? I suppose I could read the pin in ADC mode instead, but can I trigger Snooze with an analog pin?

Here's the relevant bits of not-working sleep code so far, extracted from a much larger file:

Code:
// in outer block:
SnoozeDigital s_digital;
SnoozeUSBSerial s_usbserial;
SnoozeAudio s_audio;
SnoozeBlock s_config(s_digital, s_usbserial, s_audio);

Bounce btn1 = Bounce();

// in setup(): 

  pinMode(button1Pin, INPUT_PULLUP); // sw1
  s_digital.pinMode(button1Pin, INPUT_PULLUP, RISING);  // wake on btn 1 press
  pinMode(PO_wake, INPUT);
  s_digital.pinMode(PO_wake, INPUT, RISING);  // wake on PO_wake pin voltage

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

// in main loop:

  sleepPinState = digitalRead(PO_wake);
  sleepState = sleepPinState;
  if (sleepState) { 
    // do misc ...
  } else {
    // sleep until PO_wake goes high or btn1 is pressed:
    Serial.println("zzzzz.");
    delay(1);
    Snooze.sleep(s_config);
    Serial.println("good morning!");
    awakeTime = 0;
  }

Much obliged for any advice,
-mykle-
 
Okay, after a lot of trial & error I have it working. Here are some things I wish had been more obvious to me when I started. Note this is only applicable to Teensy 3.2 .

1) The AudioOutputAnalog object of Teensy Audio is incompatible with Snooze.sleep(). It sets up DMA channels to the DAC which cause the Snooze library's sleep() command to wake up immediately. I think this is because audio DMA uses interrupts, as you'd expect, but AudioNoInterrupts() does not suppress those interrupts, as you might not expect. Snooze.deepSleep() doesn't have this problem, so I just started using that instead.

2) However, the SnoozeDigital driver can wake from sleep() on any pin, but can only use certain pins to wake from deepSleep(). So a SnoozeDigital config that works fine for sleep() may not work for deepSleep(). The same is true for SnoozeCompare. (The deepSleep_all_wakeups example documents the specific pin options.) I was wrong to blame TeensyAudio for this one.

3) The conflict between Bounce and SnoozeDigital on the same pin can be handled by attaching the SnoozeDigital driver to the SnoozeBlock right before sleep, and detaching it right after. This is done with overloaded + and - operators. However it seems like you're not allowed to have an empty SnoozeBlock, so you need to configure at least one other driver besides SnoozeDigital in the block, even if you don't use it.

4) The Snooze docs suggest that it's necessary to add the SnoozeUsb and SnoozeAudio drivers when using Serial and TeensyAudio with Snooze, but the examples indicate they're only necessary for Teensy 4.0. I took them out and am having no problems with either subsystem so far.

5) It seems necessary in my USB serial setup (Teensy 3.2 through a no-name USB hub to USB-C port on M1 Mac Mini) to delay(10) between the last Serial.println and sleep, if I want the line to reach the Serial Monitor. Calling Serial.flush() has no effect. YMMV.
 
Status
Not open for further replies.
Back
Top