ArduinoLowPower icon indicating copy to clipboard operation
ArduinoLowPower copied to clipboard

Serial not working after wakeup

Open tatulea opened this issue 6 years ago • 32 comments

Hi,

I am using a button to put Arduino in sleep mode and wake it up, but the Serial is not working anymore after it is waking up. What should I do?

#include "ArduinoLowPower.h"

volatile bool just_wakeup = true;

// Pin used to trigger a wakeup
const int pin = 0;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(pin, INPUT_PULLUP);
}

void loop() {
  if (just_wakeup) {
    just_wakeup = false;
    delay(3000);
    Serial.begin(115200);
  }
  digitalWrite(LED_BUILTIN, HIGH);
  delay(500);
  digitalWrite(LED_BUILTIN, LOW);
  delay(500);
  Serial.println("test");

  if (digitalRead(pin) == LOW) {
    Serial.end();
    delay(500);
    LowPower.attachInterruptWakeup(pin, wakeup_handler, FALLING );
    LowPower.deepSleep();
  }
}

void wakeup_handler() {
  just_wakeup = true;
  detachInterrupt(pin);
}

tatulea avatar Sep 24 '18 12:09 tatulea

Hi @tatulea, wakeup/standby with the USB connected is super tricky since it depends on the operating system/USB controller the board is connected to. Would you mind sharing your PC or Mac configuration (both software and hardware) so I can try reproducing it? Thanks

facchinm avatar Sep 24 '18 12:09 facchinm

Hi,

I am using Windows 10 and Arduino IDE. The PC is a HP EliteDesk 800 with intel I5-6500.

tatulea avatar Sep 24 '18 12:09 tatulea

Hello,

I have the same problem with MKR WiFi1010 (and MKR1000) - Win10

grezco avatar Sep 29 '18 18:09 grezco

Hello,

I also have the same problem with the Arduino WiFi MKR 1010 and MacBook Pro running OS X Yosemite.

sashkaw avatar Sep 29 '18 21:09 sashkaw

@tatulea @grezco @durasno can you take a look at https://github.com/arduino-libraries/ArduinoLowPower/pull/8 ? Let me know if the proposed behaviour could work for you.

facchinm avatar Oct 01 '18 09:10 facchinm

Hi @facchinm,

For me, it's the same problem. At the wake up, the com port is present but even after closed serial monitors and reopened after a successful resume, I don't have serial print event.

grezco avatar Oct 01 '18 11:10 grezco

@grezco which operating system/PC are you using?

facchinm avatar Oct 01 '18 11:10 facchinm

Windows 7 and Windows 10

grezco avatar Oct 01 '18 12:10 grezco

@tatulea @grezco @durasno can you take a look at #8 ? Let me know if the proposed behaviour could work for you.

Hi @facchinm,

The below script (based on the TimedWakeup example) seems to be working relatively well (after brief testing with Arduino WiFi MKR 1010, MacBook Pro + OS X Yosemite) with the changes from #8. The added delay is from a LowPowerLab/LowPower SAMD21 example sketch.


void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  // Uncomment this function if you wish to attach function dummy when RTC wakes up the chip
  LowPower.attachInterruptWakeup(RTC_ALARM_WAKEUP, dummy, CHANGE);
}

void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(500);
  digitalWrite(LED_BUILTIN, LOW);
  delay(500);
  
  while(!SerialUSB);
  delay(1000); 
  SerialUSB.println("Just woke up!");
  
  // Triggers a 2000 ms sleep (the device will be woken up only by the registered wakeup sources and by internal RTC)
  // The power consumption of the chip will drop consistently
  LowPower.sleep(2000);
}

void dummy() {
  // This function will be called once on device wakeup
  // You can do some little operations here (like changing variables which will be used in the loop)
  // Remember to avoid calling delay() and long running functions since this functions executes in interrupt context
}

sashkaw avatar Oct 06 '18 01:10 sashkaw

Hi @durasno,

The same script testing with WiFi MKR 1010 and Windows10 with the changes from #8 Don't work for me.

grezco avatar Oct 06 '18 05:10 grezco

Hi @grezco,

If it helps I wait for the led to flash and then repeatedly try to open the serial monitor until text displays. Past that I unfortunately don't have much advice to offer.

sashkaw avatar Oct 06 '18 23:10 sashkaw

Hi @facchinm With the script above, with arduino/ArduinoCore-samd#361 if I send a char by serial monitor, I freeze IDE (Wndows 10).

grezco avatar Oct 13 '18 10:10 grezco

You may want to take a look at this: https://github.com/arduino-libraries/ArduinoLowPower/pull/9

polygamma avatar Oct 13 '18 22:10 polygamma

Hi @polygamma, Nothing better with #9 for me. After wake up, in all case, I need to unplug / reconnected USB of MKR WiFi1010 device to be abble to see the serial message.

grezco avatar Oct 14 '18 12:10 grezco

@grezco with the following example, you never see the second message?

#include "ArduinoLowPower.h" // https://www.arduino.cc/en/Reference/ArduinoLowPower
#include "RTCZero.h" // https://www.arduino.cc/en/Reference/RTC

/*
 * initial setup, will be run once at the start of the whole routine
 */
void setup() {
  // init serial connection
  Serial.begin(9600);
  while (!Serial) {}
  RTCZero().begin(false);
}

/*
 * will be run forever, after initial setup() call
 */
void loop() {
  Serial.println("I am being printed, because the device has not been sleeping, yet");
  
  // deep sleep of 5 seconds
  LowPower.sleep(1000 * 5);
  
  Serial.println("I am never being printed, because of a deadlock");
}

Notice the RTCZero().begin(false); call, if you want to avoid that one, install the latest RTCZero version from the master branch, found here including this commit.

Running that snippet, having my commits included, yields the wanted output of:

I am being printed, because the device has not been sleeping, yet I am never being printed, because of a deadlock I am being printed, because the device has not been sleeping, yet I am never being printed, because of a deadlock ...

at least for me...

polygamma avatar Oct 14 '18 12:10 polygamma

@polygamma, No I never see the second message.

grezco avatar Oct 14 '18 14:10 grezco

Since you wrote in https://github.com/arduino-libraries/ArduinoLowPower/issues/7#issuecomment-425667428 that you are using Windows 10, I tried the snippet with my fixes on Win10, too. Sorry, have to confirm, that my changes do not help, if you are using Win 10. Anyway: When using Arch Linux, and probably any Linux distribution, it does indeed fix the problems.

polygamma avatar Oct 14 '18 15:10 polygamma

@polygamma, thanks for the time spent trying to solve my problem.

Until I find a solution, I use

  USBDevice.detach();
  LowPower.sleep(1000 * 5);
  USBDevice.attach();

and reopen the serial monitor when the port appear.

grezco avatar Oct 14 '18 17:10 grezco

@grezco @polygamma @durasno thank you all for testing on different platforms; being able to reproduce the behaviour is crucial to get a solution. @grezco are you testing with https://github.com/arduino-libraries/ArduinoLowPower/pull/8 applied? Because it implements (almost) the same solution you are using; I'd hate to insert OS-specific code based on the machine you are working with (these kind of solution never work in the real world)

facchinm avatar Oct 15 '18 07:10 facchinm

Hi @facchinm As previously said, #8 don't work (for me) with Windows10 and MKR1000. With Arduino SAMD core - Pull Request #361, the serial port don't disappear in the device manager of Windows 10. But after wake up, in all case, I'm not abble to see the serial message (unless I unplugged / reconnects USB).

grezco avatar Oct 15 '18 15:10 grezco

@grezco so what did you mean with

Until I find a solution, I use ...

if you are unable to see the serial message? Does adding the extra lines change the behaviour over #8 or not?

facchinm avatar Oct 15 '18 15:10 facchinm

@facchinm, #8 don't change the behaviour when I use (or not) USBDevice.detach(); With, or without #8, I need to unplug / reconnected USB of MKR WiFi1010 device or use USBDevice.detach to be able to see the serial message after the wake up.

#include ArduinoLowPower.h" // https://www.arduino.cc/en/Reference/ArduinoLowPower
#include "RTCZero.h" // https://www.arduino.cc/en/Reference/RTC

void setup() {
  // init serial connection
  Serial.begin(9600);
  while (!Serial) {}
  RTCZero().begin(false);
}

void loop() { 
  Serial.println("I am being printed, because the device has not been sleeping, yet");
  delay(10);
  USBDevice.detach();
  LowPower.sleep(1000 * 5); 
  USBDevice.attach();
  delay(5000);
  digitalWrite(LED_BUILTIN, HIGH);
  delay(500);
  digitalWrite(LED_BUILTIN, LOW);
  delay(500);
  Serial.println("Wake up MCU");
}

grezco avatar Oct 15 '18 17:10 grezco

Hi guys, I had the same problem with MKR1000 and I've solved using the library version on GitHub (the version on Library Manager not works) and adding these lines of code on your project: USBDevice.detach(); LowPower.deepSleep(); USBDevice.attach();

fabik111 avatar Jan 10 '19 08:01 fabik111

Hi. Same problem for me: Serial not working after wakeup . "USBDevice.detach(); LowPower.sleep(); USBDevice.attach();" helped me a lot, But I need to close the sérial monitor and re-open (IDE 1.8.8 , windows 10). And I miss some informations on serial port if I don't do that quickly enough Is there a way do to that automatically? And is that planned to modify the library? Thanks a lot for answers. Patrick

pchatill avatar Mar 20 '19 12:03 pchatill

Hi @pchatill , it was proposed for inclusion in the IDE (https://github.com/arduino/Arduino/pull/8046). That PR is already included in Beta builds of the IDE but has some problems with non arduino boards (esp8266 and similar) so we decided to postopone the merge in master. Testing it would greatly speedup merge ;)

facchinm avatar Mar 21 '19 08:03 facchinm

Thanks for your response facchinm. I tried with IDE beta 1.8.9. It seems not necessary with this version to add :USBDevice.detach(); USBDevice.attach(); But it's always necessary to close serial monitor and reopen it. The difference is that the serial monitor output is cleared when Arduino sleep. The other difference is that the serial monitor looks active again when arduino wake-up (Autoscroll function active for example) but no data displayed ...

pchatill avatar Mar 21 '19 13:03 pchatill

The beta should be numbered 1.9.0 , please double check if you are using that one :wink: Beside that, are you on Windows?

facchinm avatar Mar 21 '19 13:03 facchinm

Sorry for the mistake: Yes I tried with Arduino 1.9.0-beta. Yes windows 10

pchatill avatar Mar 21 '19 13:03 pchatill

Hi facchim. Do you have any news about the problem? Thanks a lot...

pchatill avatar Jun 09 '19 03:06 pchatill

I have found the following code using the Arduino low power library is a partial solution - at least it gives you a delay to close & reopen the USB serial port, after the SAMD wakes up.

I'm using a 16x2 LCD to see what is happening while the serial port is unavailable - remove if you wish. Also the code is a bit messy with commented out sections where I have been trying other low power libraries.

The method uses the USBDevice.detach() -- LowPower.deepSleep() -- USBDevice.attach() combination, together with a delay while(!Serial) {} to give you time to close & reopen the Serial port.

Note: delay(1000); after restarting the USBDevice is very important. The value of Serial is initially returned as 1, and will drop straight through the while delay - after the one second delay however, the value of Serial changes back to 0 and is captured in the while loop until a new Serial window is opened and the value of Serial changes back to 1.

Still not an ideal solution, but at least you get a working Serial window back without losing any output.

Incidentally, the LowPower.deepSleep(); library command also does a USBDevice.detach() -- USBDevice.attach() internally - without the external USBDevice.detach() -- USBDevice.attach() sequence, this will keep your existing Serial communication open (no need to restart) and can receive commands, but will not display any output to the serial monitor. Perhaps this is because there is no 1 second delay & the serial port not being closed and reopened.

There are lots of funny timing issues going on here - I would appreciate it if anyone can shed more light on this.

// **** INCLUDES *****
#include "ArduinoLowPower.h"
#include <Wire.h>
#include <LiquidCrystal_PCF8574.h>

LiquidCrystal_PCF8574 lcd(0x27);  // set the LCD address to 0x27 for a 16 chars and 2 line display

// External interrupt on pin 0 (use pin 0 to 24, except pin 4 on Arduino Zero)
const int pin = 12;
unsigned char count = 3;

void setup()
{
	// Wait for serial USB port to open
	Serial.begin(9600);
       delay(2000);
	Serial.println("***** ATSAMD21 Standby Mode Example *****");

  lcd.begin(16, 2);               // initialize the lcd
  lcd.setBacklight(HIGH);
  printMessages(1, 0, 0);    //print  Found LCD
  delay(2000);                   //small delay before the screen is cleared
  lcd.home(); lcd.clear();
	
	// ***** IMPORTANT *****
	// Delay is required to allow the USB interface to be active during
	// sketch upload process
	Serial.println("Entering standby mode in:");
	for (count; count > 0; count--)
	{
	  Serial.print(count);	
	  Serial.println(" s");
	  delay(1000);
  }
  // ********************
  // External interrupt on pin (example: press of an active low button)
  // A pullup resistor is used to hold the signal high when no button press
  pinMode(pin, INPUT_PULLUP);
  LowPower.attachInterruptWakeup(pin, blink, LOW);
}

void loop() 
{
	Serial.println("Entering standby mode.");
	Serial.println("Apply low signal to wake the processor.");
	Serial.println("Zzzz...");
  Serial.print("SCB_SCR_SLEEPDEEP_Msk  ");
  Serial.println(SCB_SCR_SLEEPDEEP_Msk, BIN);
  Serial.print("~SCB_SCR_SLEEPDEEP_Msk  ");
  Serial.println(~SCB_SCR_SLEEPDEEP_Msk, BIN);
  //Serial.println(GCLK->CLKCTRL.reg, BIN);
  printMessages(0, 0, 0);
  printMessages(0, 0, 1);
  
	// Detach USB interface
	   USBDevice.detach();
 
  // Enter standby mode
  // LowPower.standby();
  /* This is all LowPower.standby() does
  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
  __DSB();
  __WFI();
  */
  LowPower.deepSleep(5000); 
  //LowPower.idle(IDLE_2);

  lcd.setCursor(0, 0); lcd.print(F("Awake"));
   
  // Attach USB interface
     USBDevice.attach();
  // It appears the Serial is returned as 1 after the attach command
  // However it also appears to revert to 0 after 1 sec of inactivity
  // Thus being trapped in the following while statement until the new 
  // serial monitor is opened. If the following delay is omitted the
  // following while loop will pass straight through, without waiting for
  // the new serial monitor to open!!   
  
     delay(1000); 
  
  // Force delay until the old serial monitor is closed and a new one
  // is opened, changing Serial from 0 back to 1
  int s = Serial;
  lcd.setCursor(8, 0); lcd.print(s);

  while(!Serial) {lcd.setCursor(10, 0); lcd.print(s);s++;}  //Close OLD & open NEW Serial connection 
                                                                                     //during this delay

  lcd.setCursor(8, 1); lcd.print(Serial);
  lcd.setCursor(0, 1); lcd.print(F("Serial"));

  Serial.println("Awake!");
  Serial.println("Serial Communication Restored!");
  Serial.println("Send any character to enter standby mode again");

  // Wait for user response
  // Serial.available is 0 while there are no characters in the USB pipline,
  // causing the while to loop indefinitely.
  // As soon as a character is typed, Serial.available changes to 1 and 
  // characters are read from the USB pipline until it is empty and
  // Serial.available returns to 0 and the second while loop terminates.
  while(!Serial.available());
  while(Serial.available() > 0)
  {
		Serial.read();
	}

}

void blink(void)
{
 
}
/***************************************************************************/
//Print messages to the LCD

  void printMessages(uint8_t messNo, uint8_t messCol, uint8_t messRow ) {
  lcd.setCursor(messCol, messRow);                 //set up cursor possition

  if (messNo == 0)  lcd.print(F("                "));
  if (messNo == 1)  lcd.print(F("Found LCD       "));
}

netless-ww avatar Jan 01 '20 03:01 netless-ww