I got it working when I used the code:
USBDevice.wakeupHost();
UDCON |= (1 << RMWKUP);
Do you mean pressing a key on a real keyboard or using Keyboard.print() or Keyboard.write() an Arduino emulated keyboard?
Which message do you see in the Utility App "Console" when sleeping/waking up?
The sequence on the Mac should look like this (only some relevant entries):
01.07.13 21:07:28,000 kernel[0]: hibernate_setup(0) took 0 ms
01.07.13 21:07:46,000 kernel[0]: sleep
01.07.13 21:07:46,000 kernel[0]: Wake reason: EHC1
01.07.13 21:08:48,000 kernel[0]: Previous Sleep Cause: 5
01.07.13 21:08:48,000 kernel[0]: The USB device HubDevice (Port 1 of Hub at 0xfd000000) may have caused a wake by issuing a remote wakeup (2)
01.07.13 21:08:48,000 kernel[0]: The USB device Arduino Leonardo (Port 2 of Hub at 0xfd100000) may have caused a wake by issuing a remote wakeup (3)
As you can see in the log it takes up to 18 seconds before the computer really goes to sleep and puts the USB bus in suspend mode. You should wait this time before you wake it up again. Depending on how much RAM you have and the speed of your HDD, it may even take longer.
When a computer is in a Sleep Mode (S3 state), the USB bus is suspended and the devices are no longer polled by the host. In this state it is not possible to send any data to the usb host (e.g. keyboard reports) except the remote wakeup.
In the Microsoft article KB841858 I found an answer why different behaviour can be observed on different computers:
When a USB device is enabled to wake the computer, the default behavior permits the computer to enter the S1 system power state for standby. Standby is not the S3 system power state. The S1 system power state is a "lighter" system power state than S3. The S1 system power state typically conserves less power than the S3 system power state.
So we are talking about different system standby states and it depends on your operating system, the attached peripherals (on the mainboard and via cable) and some settings which of these states is entered and if the USB bus stays in D0 state or enters D3 state. D0 and D3 can be distinguished by checking UDINT & (1<<SUSPI), but unfortunately SUSPI is cleared in the Arduino USB_GEN ISR.
I can try to handle the Power-State cases differently, but first I have to find a computer which uses S1 state.
Still trying and learning...
Michael
harryharry:
I got it working when I used the code:
USBDevice.wakeupHost();
UDCON |= (1 << RMWKUP);
Did you wait at least 20s after going to standby and before calling USBDevice.wakeupHost()?
Which operating system are you using?
Can you please reboot your computer and plug-out and plug-in your Arduino and try again? I've seen that the HID descriptor is cached by the operating system and maybe it didn't recognize the USB_CONFIG_REMOTE_WAKEUP flag in the configuration.
Michael
Do you mean pressing a key on a real keyboard or using Keyboard.print() or Keyboard.write() an Arduino emulated keyboard?
A real keyboard. I was just testing if the wake-up press got "swallowed" or not.
harryharry:
I got it working when I used the code:
USBDevice.wakeupHost();
UDCON |= (1 << RMWKUP);
I don't understand, why you need this last line.
I made an updated version which handles the SUSPEND mode (at least it acknowledges SUSPEND). Install it like the previous version by replacing the original files in your Arduino installation path (see attachment USBWakup2.zip).
I also added a diagnostic sketch to show the state changes via a blink code of the internal LED (see attachment USBWakup-130702g.zip):
Meaning of the blink codes:
1x remote wakeup enabled from the PC
2x remote wakeup disabled from the PC
3x USB host signals SUSPEND state
4x USB host signals end of SUSPEND state (wakeup)
9x USB wakeup rejected because
10x USB wakeup accepted
When the Leonardo is starting (after the bootloader blinks), you should see [3x], 1x, 4x blink.
When the PC goes to standby, you should see 3x blink
When the PC wakes up, you should see 10x blink followed by 4x blink
Currently I don't understand the initial 3x blink which I see on Mac OSX.
What blink codes do you get?
Michael
USBWakeup-130702g.zip (1.19 KB)
USBWakeup2.zip (10.1 KB)
Still looking for testers...
Here it works for
- Mac OSX (on a MacBook Pro)
- Windows 7 (on a MacBook Pro)
- Windows 8 (on a Wetab)
Any comments if it is working or not and what blink codes you get are welcome.
In the pull request #1488 I added also a feature to send your computer to sleep mode or shut it down. When you are interested, you can get the code from there.
You can use it in the following way:
Keyboard.systemControl(SYSTEM_CONTROL_POWER_DOWN);
or
Keyboard.systemControl(SYSTEM_CONTROL_SLEEP);
There are some more commands defined in USBAPI.h, but most of the do nothing on my Mac:
#define SYSTEM_CONTROL_POWER_DOWN 1
#define SYSTEM_CONTROL_SLEEP 2
#define SYSTEM_CONTROL_WAKEUP 3
#define SYSTEM_CONTROL_COLD_RESTART 4
#define SYSTEM_CONTROL_WARM_RESTART 5
#define SYSTEM_CONTROL_DOCK 6
#define SYSTEM_CONTROL_UNDOCK 7
#define SYSTEM_CONTROL_SPEAKER_MUTE 8
#define SYSTEM_CONTROL_HIBERNATE 9
#define SYSTEM_CONTROL_DISPLAY_INVERT 10
#define SYSTEM_CONTROL_DISPLAY_INTERNAL 11
#define SYSTEM_CONTROL_DISPLAY_EXTERNAL 12
#define SYSTEM_CONTROL_DISPLAY_BOTH 13
#define SYSTEM_CONTROL_DISPLAY_DUAL 14
#define SYSTEM_CONTROL_DISPLAY_TOGGLE_INT_EXT 15
#define SYSTEM_CONTROL_DISPLAY_SWAP 16
Michael
Dear Michael "Mike T",
dear "harryharry",
thanks for this USB hack that saves us the Day, try to waking an old MBP 15" in a multimedia setup on a museum installation.
The command "USBDevice.wakeupHost();" itself works but the second command is useful for a strange rarely situation:
- the MBP is in sleep status
- the Arduino Leonardo is double powered (connected via USB and 12V supply)
- if the AC wall current fall down for few minutes
- and then the AC wall current return
- the Arduino try to wake the MBP with "USBDevice...etc" itself, but FAIL
- if we add the second command it never fails !
Thanks again
Greetings from Italy
M.
sorry for this very late reply.
exchanged the 4 files in the current arduino 105 ide.
HID.cpp
USBAPI.h
USBCore.cpp
USBCore.h
put the
USBDevice.wakeupHost();
UDCON |= (1 << RMWKUP);
into my code.
works fine on my mac 10.8.
thank you so much.
when will this find its way into the official builds?
wolf2:
when will this find its way into the official builds?
There needs to be some cleanup, especially for the second line (UDCON |= (1 << RMWKUP)) which should not be necessary in a normal suspend/wakeup scenario.
The USB state machine must conform to the USB standard and to my understanding this second line violates the USB standard because it send a wakeup even when the bus is not in idle state or at least the Arduino USB state machine doesn't know the bus is in idle state.
I mean the following sentence in chapter 7.1.7.7. "Resume" of the USB 2.0 spec:
"A device with remote wakeup capability may not generate resume signaling unless the bus has been continuously in the Idle state for 5 ms (TWTRSM)."
And chapter 9.1.1.6 "Suspended":
"If a USB device is capable of remote wakeup signaling, the device must support the ability of the host to enable and disable this capability. When the device is reset, remote wakeup signaling must be disabled."
And chapter 9.4.5 "Get Status":
"The Remote Wakeup field indicates whether the device is currently enabled to request remote wakeup. The default mode for devices that support remote wakeup is disabled."
Unfortunately I don't have much time at the moment for this clarification. Anybody else with some USB know-how?
Michael
Hi I dont was hoping this might be the answer to my problems ...still am.
However when I replaced the 3 files you'd attached I started getting compile errors...not with those new scripts but with CDC.cpp
Arduino: 1.0.6 (Mac OS X), Board: "Arduino Leonardo"
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/CDC.cpp:117: error: prototype for 'void Serial_::begin(long unsigned int)' does not match any in class 'Serial_'
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/USBAPI.h:34: error: candidate is: void Serial_::begin(uint16_t)
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/CDC.cpp:122: error: prototype for 'void Serial_::begin(long unsigned int, byte)' does not match any in class 'Serial_'
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/USBAPI.h:34: error: candidate is: void Serial_::begin(uint16_t)
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/CDC.cpp: In member function 'virtual int Serial_::available()':
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/CDC.cpp:133: error: 'peek_buffer' was not declared in this scope
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/CDC.cpp: In member function 'virtual int Serial_::peek()':
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/CDC.cpp:141: error: 'peek_buffer' was not declared in this scope
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/CDC.cpp:143: error: 'peek_buffer' was not declared in this scope
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/CDC.cpp: In member function 'virtual int Serial_::read()':
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/CDC.cpp:148: error: 'peek_buffer' was not declared in this scope
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/CDC.cpp: At global scope:
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/CDC.cpp:166: error: prototype for 'size_t Serial_::write(const uint8_t*, size_t)' does not match any in class 'Serial_'
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/Print.h:49: error: candidates are: size_t Print::write(const char*)
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/Print.h:53: error: virtual size_t Print::write(const uint8_t*, size_t)
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/Print.h:54: error: size_t Print::write(const char*, size_t)
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/CDC.cpp:161: error: virtual size_t Serial_::write(uint8_t)
Im not sure if its something to do with the way I copied the files across...something I should have done with them differently. Something to do with the fact I was running a newer version of arduino (10.0.6) (on mac osx 10.8.3)
Or something else...
If you have any thoughts I'd be delighted to hear them.
dave_j:
However when I replaced the 3 files you'd attached I started getting compile errors...not with those new scripts but with CDC.cppIm not sure if its something to do with the way I copied the files across...something I should have done with them differently. Something to do with the fact I was running a newer version of arduino (10.0.6) (on mac osx 10.8.3)
Or something else...
When I also replaced the CDC.ccp with the one from Arduino/hardware/arduino/cores/arduino at master · nospam2000/Arduino · GitHub the build errors stopped and it works. Wakes the sleeping mac (10.8) just like I hoped it might. I still don't quite understand what the problem was but hopefully this is helpful info for someone.
Hi Guys,
Been trying a lot to make this work but still no luck.
Hoping you could assist.
Using Arduino IDE1.06.
I've replaced the 3 files Michael posted in USBWakeup2.zip, but got the same errors as dave posted.
Replaced the CDC.cpp from the link dave shared which worked for him, but getting now other errors in CDC file:
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:13: error: stray '\302' in program
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:13: error: stray '\267' in program
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:13: error: stray '\302' in program
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:13: error: stray '\267' in program
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:284:46: error: exponent has no digits
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:344:40: error: too many decimal points in number
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:353:64: error: too many decimal points in number
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:362:48: error: too many decimal points in number
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:461:31: error: invalid digit "9" in octal constant
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:470:31: error: invalid digit "8" in octal constant
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:551:31: error: invalid digit "9" in octal constant
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:560:31: error: invalid digit "8" in octal constant
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:623:32: error: too many decimal points in number
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:632:32: error: too many decimal points in number
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:677:32: error: too many decimal points in number
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:686:32: error: too many decimal points in number
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:695:32: error: too many decimal points in number
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:704:32: error: too many decimal points in number
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:713:32: error: too many decimal points in number
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:902: error: stray '#' in program
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:906: error: stray '#' in program
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:910: error: stray '#' in program
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:919: error: stray '#' in program
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:923: error: stray '#' in program
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:932: error: stray '#' in program
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:936: error: stray '#' in program
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:940: error: stray '#' in program
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:944: error: stray '#' in program
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:948: error: stray '#' in program
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:1041: error: stray '#' in program
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:1808: error: stray '#' in program
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:1812: error: stray '#' in program
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:5: error: expected unqualified-id before '<' token
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:902: error: expected unqualified-id before '<' token
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:902: error: expected unqualified-id before '<' token
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:906: error: expected unqualified-id before '<' token
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:906: error: expected unqualified-id before '<' token
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:910: error: expected unqualified-id before '<' token
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:910: error: expected unqualified-id before '<' token
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:932: error: expected unqualified-id before numeric constant
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino\CDC.cpp:977: error: expected unqualified-id before '<' token
Uninstalled 1.0.6 and installed 1.0.5 (which was the recent one while this post posted)
Replaced again the 3 files and now it's compiled successfully.
But, no wake up. it reaches the code (put LED on in part of code USBDevice.wakeupHost())
Tried to add 'UDCON |= (1 << RMWKUP)' but not helping.
Arduino is loaded with keyboard & mouse library.
Any suggestions?
Many thanks!
Roi
roidan:
But, no wake up. it reaches the code (put LED on in part of code USBDevice.wakeupHost())
It is really hard to guess why it is not working with too little information.
The compile errors look a bit like you saved the cpp files as HTML instead of raw cpp files. Have a look at the content of the files in an ASCII editor.
Can you please describe your scenario in detail? Which operating system are you using, what kind of hardware (notebook, desktop, Mac, PC, Tablet), when do you connect and start the Arduino, is USB wakeup enabled in your BIOS and Operating System settings, ...
Can you wakeup your PC with a USB keyboard or mouse on the same USB port in the same scenario?
Do you have any "unknown" USB devices in your system configuration? Do you see the two Arduino HID mice and the Arduino HID keyboard in you system configuration?
USB wakeup is needs many components work together and is a bit complicated. The following preconditions must be met:
- The Arduino Leonardo must be connected to the PC before the PC goes to sleep mode. When Arduino or the PC loose power, wakeup will fail
- The Arduino (and all USB HUBs between the PC and the Arduino) must be powered when the PC goes to standby mode. You will see this when the Arduino Leonardo power LEDs still lights when in standby mode.
- Other power modes than the "standby" mode (S3) like hibernate (S4 or S5) might also work, but this depends on many factors
When it doesn't work try it without a USB hub between the PC and the Arduino. Notebook USB ports may internally be connected via a USB HUB, so try a different USB port.
I have attached an updated version of the test sketch. You might have to fiddle with the include lines (I can't test it with 1.0.5 right now).
What blink codes do you see?
1. When starting the Leonardo
2. when you activate sleep mode (wait up to 40 seconds after activating it, OSX needs 40 seconds on my Mac and 10 seconds on Windows 7)
3. When you resume from sleep mode (by connecting pin 2 to GND for a second)
4. When the operating system reacts to the resume signal
I've ported the code to Arduino 1.5.8, but Arduino V1.0.5 and V1.0.6 required the outdated (and insecure) Java 6 version on the Mac, therefore I can't use these versions at the moment. When I have it running with 1.0.6, I will attach the new files.
Michael
USBWakeup-141221d.zip (1.72 KB)
Hi,
in the attachment of this post you will find the port to Arduino 1.0.6. I've also adapted the test sketch so it hopefully compiles now without any changes.
The .h and .cpp files from the archive "cores_arduino_106.zip" need to be copied to the Arduino installation directory.
For 1.0.6 this could be for example "C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino" on Windows
or "/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/" on Mac OSX.
Please make a backup copy of the original files or even better of the whole ".../cores/arduino" folder, so you can switch back.
Let me know the blink codes you see and anything which can be useful for diagnostics (see also my previous posting).
To send the PC to standby mode using the USBWakeup sketch, connect pin 4 to GND (for a short time), to wake it up connect pin 3 to GND (for a short time).
Before you can use wakeup, you have to wait until you get 2x blinks which signals that the USB bus was set to suspend mode.
Michael
USBWakeup-141222a.zip (1.74 KB)
cores_arduino_106.zip (16.3 KB)
Hi,
here the port for Arduino 1.5.8. See also the previous two posts for the sketch and description.
Michael
Arduino_1.5.8_UsbCoreWithWakeup.zip (16.6 KB)
Hi!
just to inform that the modified USB library works fine also with the latest IDE... I've just published a project that makes use of it to wake up a PC at a given time:
Which is the better way to wake up host from S3 suspend:
Keyboard.systemControl(SYSTEM_CONTROL_WAKEUP);
or
USBDevice.wakeupHost();
What is the difference?
bam80:
Which is the better way to wake up host from S3 suspend:
When the USB bus is suspended, the only signal which can be send is wakeupHost().
When the USB bus is not suspended, wakeupHost() will fail, you will notice by checking its return code.
Probably the best way would be:
if(!USBDevice.wakeupHost()) {
Keyboard.systemControl(SYSTEM_CONTROL_WAKEUP);
}
It should also not hurt to send both. One of it will be ignored.
Michael
Mike, thank you for the explanation.
As I understand, Keyboard.systemControl() is not for S3 suspend, but rather for S1. Am I right?
If your code incorporated to Arduino, should we update Documentation as well?
I'm not that confident with the power levels S1 to S5. Microsoft describes their interpretation here:
I haven't found reasonable information which of these system power modes maps to which device mode D0 to D4 for the USB ports. This might even change between operating systems versions or different operating systems.
Actually it doesn't matter, the only relevant points which matter are:
- is the USB bus suspended
- has the operating system enabled the USB wakep feature before suspending the USB bus
Both is handled in wakeupHost():
&& (_usbSuspendState & (1<<SUSPI))
&& (_usbCurrentStatus & FEATURE_REMOTE_WAKEUP_ENABLED))
From a usability perspective, it would be good to provide an extra function on top of the systemControl() and wakeupHost() function or replace the wakeUp function:
bool Wakeup() {
if(USBDevice.wakeupHost()) {
return true;
} else {
return (Keyboard.systemControl(SYSTEM_CONTROL_WAKEUP) == 1);
}
}
In my tests I've never used SYSTEM_CONTROL_WAKEUP.
Michael