Restarting serial port when restarting PC

Hi everyone,

I've got an Arduino Micro Pro (ATmega32U4) working as a PC Keyboard. It works perfectly but I have to unplug it and plug it again to my PC everytime I turn off my PC and turn it on the next day or it won't work.

I assume the serial port is not re-initializing but I can't figure out how to do it (or even if it's possible).

Has anyone faced this problem with any Micro Pro or Leonardo?

Thank you so much for your help.

Are you running Windows 10 ? I would assume the enumeration fails to recognize your arduino as a keyboard or mouse and just assigns a Serial profile (but I'm not using a PC so I don't know...)

May be you can have a look at the device manager after the PC has rebooted and see how it sees the COM port? USB COM or HID device?

You could explore NicoHood HID stuff to see what's going at USB level when you reconnect.

J-M-L:
Are you running Windows 10 ? I would assume the enumeration fails to recognize your arduino as a keyboard or mouse and just assigns a Serial profile (but I'm not using a PC so I don't know...)

May be you can have a look at the device manager after the PC has rebooted and see how it sees the COM port? USB COM or HID device?

You could explore NicoHood HID stuff to see what's going at USB level when you reconnect.

Thank you for your help! I have just tried reproducing the problem and now it works... Which make me think that maybe it's not a problem with the PC itself but the fact that there's a bug in my code which occurs if it keeps running for a long period of time (all night long).

I will try to see tomorrow morning what you just pointed out just in case.

PD: Do you know if there's a way to tell when does the PC turn off? Checking if the serial port is "not available" maybe? I'm asking that because when the PC turns off it stills keeps power over the USB port and the Arduino is ON.

Other peripherals like my commercial mouse and keyboard can tell when and they turn off the LED backlight, for example.

Thank you!

PD: Do you know if there's a way to tell when does the PC turn off? Checking if the serial port is "not available" maybe? I'm asking that because when the PC turns off it stills keeps power over the USB port and the Arduino is ON.

would be worth checking what if (Serial) {..} says when the PC is off

I think there is also a flag related to USB host that you can access. From top of memory I think it's the ADDEN bit of UDADDR register that would be set if your USB chip has been assigned an address by the host.. so may be something like if (UDADDR & _BV(ADDEN)) {...}

Never tested that though :slight_smile: let us know what you find out

J-M-L:
would be worth checking what if (Serial) {..} says when the PC is off

I think there is also a flag related to USB host that you can access. From top of memory I think it's the ADDEN bit of UDADDR register that would be set if your USB chip has been assigned an address by the host.. so may be something like if (UDADDR & _BV(ADDEN)) {...}

Never tested that though :slight_smile: let us know what you find out

This is great, thank you so much. I am going to try that and come back to say if it works!

if(Serial) will not work to my knowledge; once the Arduino has detected that Serial is there, it does not seem to refresh it. It's definitely the case when using an external power supply and connecting / disconnecting the USB.

Something like this should be able to prove it

const byte ledPin = LED_BUILTIN;

void setup()
{
  Serial.begin(57600);
  while (!Serial);

  // switch on led
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);
}

void loop()
{

  // switch led off when serial disappears
  if (!Serial)
  {
    digitalWrite(ledPin, LOW);
  }
}

Also note that, if I recall correctly, you will need to open a serial port (e.g. Serial monitor).

J-M-L:
would be worth checking what

if (Serial) {..}

says when the PC is off

I think there is also a flag related to USB host that you can access. From top of memory I think it's the ADDEN bit of UDADDR register that would be set if your USB chip has been assigned an address by the host.. so may be something like

if (UDADDR & _BV(ADDEN)) {...}

Never tested that though :slight_smile: let us know what you find out

Hi again!

I tried using if(Serial){} but it doesn't work in my application since it returns true if you open the serial console (and only the first time, after that it will be always true no matter what).

I need to know when the USB port of the PC is closed (it's still powered though) but not available for communication.

I am currently reading in different forums / old posts and it has a lot to do with what you said (UDADDR & _BV(ADDEN)) but for some reason I can't still make that work using this specific command. But I am getting close I think.

I will come back here to tell you how I did to make it work if I finally can. But first I must learn how do all these parameters work..

If it's not a problem that you need to have a serial port open on the PC, the below should be able to detect when serial comms goes down.

void loop()
{

  // if there is space to write
  if (Serial.availableForWrite() > 0)
  {
    // send something
    Serial.print("A");
    // indicate serial not full
    digitalWrite(ledPin, HIGH);
  }
  else
  {
    // indicate serial is full
    digitalWrite(ledPin, LOW);
  }
}

sterretje:
if(Serial) will not work to my knowledge; once the Arduino has detected that Serial is there, it does not seem to refresh it. It's definitely the case when using an external power supply and connecting / disconnecting the USB.

Something like this should be able to prove it

const byte ledPin = LED_BUILTIN;

void setup()
{
 Serial.begin(57600);
 while (!Serial);

// switch on led
 pinMode(ledPin, OUTPUT);
 digitalWrite(ledPin, HIGH);
}

void loop()
{

// switch led off when serial disappears
 if (!Serial)
 {
   digitalWrite(ledPin, LOW);
 }
}




Also note that, if I recall correctly, you will need to open a serial port (e.g. Serial monitor).

Yes, sorry but I didn't read that. You are right, I can not use if(Serial).

I still haven't found the solution to my problem. If I print (UDADDR & _BV(ADDEN)) to my serial port I get "128", which I assume is the address that has been given to my Arduino. But I can't make that change even pluging it out and in again. It is still "128" and I don't know why...

I'm going to keep reading now.

sterretje:
If it's not a problem that you need to have a serial port open on the PC, the below should be able to detect when serial comms goes down.

void loop()

{

// if there is space to write
  if (Serial.availableForWrite() > 0)
  {
    // send something
    Serial.print("A");
    // indicate serial not full
    digitalWrite(ledPin, HIGH);
  }
  else
  {
    // indicate serial is full
    digitalWrite(ledPin, LOW);
  }
}

Thank you for your reply. I tried that and I can't make it work since Serial in the Leonardo is not the hardware serial but the USB port and I can't use "availableForWrite()" with that one... I get an error.

If i understood well, the challenge is detecting that the Arduino is no longer seen as an HID device possibly because upon booting the PC assumed it was only a serial COM device. So writing to serial could work but keyboard or mouse emulation would not

What the sketch needs to detect is this situation and end/begin again to pose as an HID device probably

(UDADDR & _BV(ADDEN)) Is "128" because the ADDEN bit is set (we mask the UDADDR register). It is not the address just a 1 in that bit

But you should not print it to the PC because you want the serial cable to be connected to that PC when it’s off and booting again with no serial console or you force a COM port otherwise . You don’t want any Serial.begin() in your code

Turn on the a led or something based on that state of that byte

pplg:
Thank you for your reply. I tried that and I can't make it work since Serial in the Leonardo is not the hardware serial but the USB port and I can't use "availableForWrite()" with that one... I get an error.

It does work; possible an error at your side. See Serial.print on Leonardo very slow after disconnection from serial - Interfacing w/ Software on the Computer - Arduino Forum, reply #6.

J-M-L:
(UDADDR & _BV(ADDEN)) Is "128" because the ADDEN bit is set (we mask the UDADDR register). It is not the address just a 1 in that bit

But you should not print it to the PC because you want the serial cable to be connected to that PC when it’s off and booting again with no serial console or you force a COM port otherwise . You don’t want any Serial.begin() in your code

Turn on the a led or something based on that state of that byte

Hi again,

After removing the Serial.begin() in my code and any Serial.print I've been able to solve half of the problem:

1-I connect the arduino to the computer and I can use it normally, it works.
2-But if I suspend the PC it won't detect this event and it won't turn off the backlight (I do that to see if it works or not).
3-If I unplug the arduino while the PC is suspended and plug it again it won't turn on the backlight on until the pc starts again (which is what it should do).

So I still need to make Nº 2 work. I am currently using if(UDADDR & _BV(ADDEN)){} in my code as you suggested.

sterretje:
It does work; possible an error at your side. See Serial.print on Leonardo very slow after disconnection from serial - Interfacing w/ Software on the Computer - Arduino Forum, reply #6.

After searching around the internet I found out that my Arduino AVR Boards library was too old and that's why I am getting the "class Serial_ 'has no member named 'availableForWrite'" error... But when I installed the suggested version (and I tried some others too) then, to my surprise, I get the error 'Keyboard only supported on the Arduino Leonardo'. And I have "Arduino Leonardo" selected!

I have no clue what's happening.

Thank you both.

Neither have I :wink: I think that at the time of the link I was using IDE 1.6.6 on Windows 8.

Now on IDE 1.8.5 with AVR boards 1.6.21 on Windows 10; reasonably sure that I tested with that as well.

I found this discussion on line, may be food for thoughts / exploration?

J-M-L:
I found this discussion on line, may be food for thoughts / exploration?

Thank you for your link! I've been able to make my arduino "detect" when the PC is suspended by adding this code to my program (from that post):

#define USBCON 0E0
#define UDINT 0xD8

void setup(){

USBCON = USBCON | B00010000;

//setup code here!!!!
}

void loop(){

if (UDINT & B00000001){

// USD Disconnected code here

}
else {

//USB Connected code here

}

//LOOP code here

}

But, to be honest I don't exactly know what I am exactly doing here. I tried reading the AT32u4 datasheet but this is too complex for me at the moment... I'd like to know how and why it works since the next step is figuring out how to make the Arduino go to sleep if the PC turns off or is suspended and I guess moving on to writing more code is not a good idea without understanding this first!

There's still one thing that confuses me and it is that if I plug the arduino to a wall charger it behaves like if it was plugged to the PC (turns on the backlight!). How is this possible?

Thanks in advance for your help.

pplg:
Hi everyone,

I've got an Arduino Micro Pro (ATmega32U4) working as a PC Keyboard. It works perfectly but I have to unplug it and plug it again to my PC everytime I turn off my PC and turn it on the next day or it won't work.

I assume the serial port is not re-initializing but I can't figure out how to do it (or even if it's possible).

Has anyone faced this problem with any Micro Pro or Leonardo?

Thank you so much for your help.

Remember, you are not connecting directly serial to serial with a the PC. You are using the USB communication with the PC to carry the serial data. When connected, the USB must establish all the necessary parameters between the PC and the Arduino before any of your serial traffic can be handled.

If you break or make the connection with USB, all the preliminary stuff has to be done all over again.

Paul