Unplugging Arduino UNO from USB then plugging back in doesn't start sketch

I have an Arduino UNO R3 that I'm trying to interface with using a C++ program I made. The UNO transmits data, and the program receives the aforementioned data. The program and Arduino run well together without a hitch, but when I unplug the UNO from the USB port then plug it back in, it seems like the sketch won't start (for the rest of this post, I'll call this state, the UNO's "frozen" state.)

Interestingly, hitting the reset button while the UNO is operational doesn't put it in a "frozen" state, which is weird to me because I read here that pressing the reset button is the same as unplugging then plugging back in the UNO.

In order to bring the UNO out of the "frozen" state and back into an operational state, I have to open the Serial monitor via Arduino IDE. Once I open the serial monitor, the sketch starts up again with no problems. The UNO transmits data to my program without any problems after I open then close the serial monitor.

Possibly related: When I upload a sketch onto the UNO, the UNO initially transmits junk data to my program, but when I open the serial monitor in Arduino IDE, the UNO becomes operational and starts transmitting valid data again. The UNO reverts back to transmitting junk data when I upload a sketch, and I must open the serial monitor (then close it) every time I want the UNO to become functional.

This leads me to believe that opening the serial monitor somehow jump starts the UNO (or "initializes" it) and I need to know how to do this in my C++ program.

Does anyone know what the problem may be and/or if it's possible for me to "initialize" the UNO myself in my program?

EDIT: Edited above for clarity.

What you read was for the STK500 msg.
Reset simple re-starts a sketch in almost all cases.

You neglected to include the sketch so nobody can tell if it was an issue in there or not. (use CODe TAGS ( </> )
Nor did you mention the serial settings you are using at both ends so that too makes it a little awkward to diagnose.

1 Like

Reset simply re-starts a sketch in almost all cases

Okay, so that explains why the Arduino, if already in an operational state, will remain operational after pressing the reset button. However, I don't understand why the button doesn't fix the Arduino if the UNO is in the "frozen" state.

Nor did you mention the serial settings you are using at both ends so that too makes it a little awkward to diagnose.

I'm using a baud rate of 19200, but I don't see how the serial settings would affect the Arduino's operation if the UNO and my program were working fine after opening (then closing) the serial monitor.

I'm pretty certain there is nothing wrong with the sketch, but here it is:

//DataBit will contain bit coming from digital IO (value should be either 0 or 1)
int DataBit;

//'DataWord' contains the 24 bit (3 byte) word comprised of DataBits
//'DataWordLength' is a constant that stores how many total entries 'DataWord' contains
//'DataWordSize' is used to keep track of the current size and index of the 'DataWord' array
int DataWord[24];
int DataWordLength = 24;
int DataWordSize;

//Use Arduino's digital pin input 4 for data
int DataPin = 4;


void initializeDataWord()
{
  for (int DataWordIndex = 0 ; DataWordIndex < DataWordLength ; DataWordIndex++)
  {
    DataWord[DataWordIndex] = -1;
  }

  DataWordSize = 0;
}


void setup()
{
  //Set up Serial port for printing to console.
  Serial.begin(19200);

  //Tell Arduino to prepare to read data from Data Pin
  pinMode(DataPin, INPUT);


  //BEGIN Initialize variables
  
  initializeDataWord();

  DataWordSize = 0;
  
  //END Initialize variables

}


void loop()
{

  DataBit = digitalRead(DataPin);

  DataWord[DataWordSize] = DataBit;
  DataWordSize++;



  if (DataWordSize == DataWordLength)
  {
    //Send word to program
    for (int DataWordIndex = 0 ; DataWordIndex < DataWordLength ; DataWordIndex++)
    {
        if (DataWord[DataWordIndex] == 0)
          Serial.write('0');
        else if (DataWord[DataWordIndex] == 1)
          Serial.write('1');
        else
          Serial.write('n'); //n is flag used to indicate to program that word from IO was not properly received

    }
  
    Serial.write('e'); //indicate to program that current word has finished sending using e as flag

    initializeDataWord();
  }

}

Here is my C++ program:

#include <stdio.h>;
#include <iostream>;
#include <Windows.h>;

using namespace std;

char readbuf[26];
char pause;
unsigned long int nobytesread;
int wordlength = 25;

int main() {
	//initialize readbuf
	memset(readbuf, 0, sizeof(readbuf));
	
	//connect to Arduino
	HANDLE m_hCommPort = ::CreateFile("COM4", GENERIC_READ , 0, 0, OPEN_EXISTING, NULL, 0);

	//check if connection successful
	if (m_hCommPort == INVALID_HANDLE_VALUE)
	{
		DWORD err = GetLastError();
		printf("\nHandle creation error code: %x\n", err);
		cout << "Press any key to continue...";
		cin >> pause;
	}

	while (1)
	{
		ReadFile(m_hCommPort, readbuf, wordlength, &nobytesread, NULL);
		printf("%s\n", readbuf);
		memset(readbuf, 0, sizeof(readbuf));
		
		cout << "Press 's' then enter to stop. Otherwise, press any other key then enter to continue...";
		cin >> pause;
		
		if (pause == 's')
		{
			CloseHandle(m_hCommPort);
			exit(1);
		}
	}
}

More out of curiosity what sensor is it reading ?

Sketch compiles and loads fine (as expected)

Also the sketch calls a 24 bit word but the C calls a 26 bit, header and terminator ?

More out of curiosity what sensor is it reading ?
I have the UNO hooked up to a control panel. The only thing the control panel is transmitting to the UNO is its current configuration (position of knobs and switches).

Also the sketch calls a 24 bit word but the C calls a 26 bit, header and terminator ?
The word is 24 chars long, then there is the char 'e' at the end which signifies the end of the word, then finally there is the null terminator for a total of 26 elements.

When you press reset, you reset the 328 micro and not the USB micro (16U2 on a real Arduino). So your connection with the PC is not lost.

When you unplug, the connection is lost and your PC has lost the serial port. Your handle is no longer valid or points to something that is no longer valid, even after reconnecting.

Sketches do restart; try the simple blink :wink:

1 Like

Sketches do restart; try the simple blink :wink:
Yup. Blink works even after disconnecting the UNO.

When you unplug, the connection is lost and your PC has lost the serial port. Your handle is no longer valid or points to something that is no longer valid, even after reconnecting.

Here's what happens: I unplug the UNO from USB, then I reconnect it. The UNO stops transmitting data. I start my C++ program, I look at the TX LED, and there are no signs of the UNO transmitting data. After opening the serial monitor, the UNO's TX LED starts flashing again when it should, and I can view the data on my C++ program.

It seems to me that the action of opening the Serial Monitor on Arduino IDE somehow re-establishes the connection between the UNO and the computer. My objective is to establish a connection between the UNO and my computer WITHOUT needing to open the Serial Monitor in the Arduino IDE. I am looking at the github here to try and see what piece of code I need, but I can't track down what's happening.

Can anyone help me figure out what I need to do in my C++ program so that, when the program starts, it can communicate with a freshly reconnected UNO?

stefan55:
Here's what happens: I unplug the UNO from USB, then I reconnect it. The UNO stops transmitting data. I start my C++ program, I look at the TX LED, and there are no signs of the UNO transmitting data. After opening the serial monitor, the UNO's TX LED starts flashing again when it should, and I can view the data on my C++ program.

Damn ( :wink: ), you're right. Never noticed that.

stefan55:
It seems to me that the action of opening the Serial Monitor on Arduino IDE somehow re-establishes the connection between the UNO and the computer. My objective is to establish a connection between the UNO and my computer WITHOUT needing to open the Serial Monitor in the Arduino IDE. I am looking at the github here to try and see what piece of code I need, but I can't track down what's happening.

Opening the serial monitor activates the DTR line that goes from the 16U2 to the 328P micro. So if your code closes the connection at the moment that it no longer sees the Arduino and next tries to open it again, it should work.

I have tried your scenario and after I lost the communication pressed the reset button; even that does not work. So it looks like there is also something happening at the 16U2 level.

Your reading in the C++ application should actually fail in some way if the Arduino is not connected; does ReadFile return something (maybe -1)? Check that. If you can find something that indicates that the connection is lost, you can close the handle and try to open it again.

PS1
My initial test was done with a Nano that uses a different USB-to-TTL converter and it does not show the behaviour that you described.

PS2
The TX and RX leds are driven by the 16U2 on the Uno; another indication that it's actually the 16U2 that is causing the issue.

1 Like

Here's my theory:

Your program is opening the serial port wrong. (this suspicion is supported by the fact that the baud rate doesn't seem to be specified anywhere!)

It's doing it sufficiently wrong that the 16u2 (which is running a program that makes it act as a serial adapter) barfs; the firmware on the 16u2 was written by and for arduino, and hence should not be assumed to be particularly robust. Since the TX and RX lights on uno are driven by the 16u2, not directly from the serial lines, if you hose the 16u2, the serial activity lights won't work either (I'll bet if you hooked a TTL serial adapter up to the arduino's TX pin, you'd find that data was still coming out).

1 Like

I would like to clarify that this whole time, the Arduino UNO had been powered by the USB cable.

I found out that if I keep the UNO hooked up to an external power supply (9v battery), then disconnect and reconnect the USB cable, the TX led turns on when it should.

This is in contrast to its earlier behavior without the external power supply: upon reconnecting the USB cable, the TX led does not turn on when I expect it to, and this can be remedied by opening the serial monitor in the Arduino IDE.

However, in both cases (with and without the external power supply) once I disconnect the UNO and reconnect it, I cannot read whatever the UNO is transmitting unless I open up the serial monitor (to "connect" the UNO) first, then close it (to free the serial port so that my program can access the UNO).

I hope the above information can help guide us to the root problem.

Your program is opening the serial port wrong. (this suspicion is supported by the fact that the baud rate doesn't seem to be specified anywhere!)
Do you know where I could go about opening the serial port correctly? And if I am opening the serial port wrong, how is my C++ program correctly reading the UNO's output (after opening then closing the serial monitor)?

Your reading in the C++ application should actually fail in some way if the Arduino is not connected; does ReadFile return something (maybe -1)? Check that. If you can find something that indicates that the connection is lost, you can close the handle and try to open it again.
My program just pauses at the "ReadFile()" line when I disconnect the UNO because the function is waiting for something to read, so no error or exception is thrown.

Alright, so I added a simple line of code. Right after reading the value of the data bit coming into the UNO from the control panel, I do digitalWrite(8, DataBit). I hooked up the output of pin 8 to an oscilloscope, and I do indeed see the word displayed on the scope, even after powering cycling the UNO (I did this both with and without the power supply). This suggests that the sketch is, in fact, running once the UNO powers on. All I need now is to know how to get my C++ program to read from the UNO without needing to open the serial monitor on the Arduino IDE everytime the UNO powers off.

First result in google -> first link on page:

Looks like they explain it here (first part of page looks like what you've got, then they go into setting baud rate with a DCB. )

My guess is that without specifying the baud rate, it defaults to whatever it had before - but while some dedicated serial adapters have a default, the f/w on the 16u2 does not.

Looks like they explain it here (first part of page looks like what you've got, then they go into setting baud rate with a DCB. )

Looking at the link you gave me as well as here, it seems the DCB has many members that I can change other than BaudRate such as ByteSize and StopBits. Would anyone know how I should set the members of the DCB so I can communicate with the UNO? I looked at the Arduino IDE github again, but I still can't figure out what the Serial Monitor is doing code-wise to establish a connection with the UNO.

I would do what they recommend here Serial Communication in Windows | CodeGuru, namely: "I have found it easier to get the current DCB struct and then set those members that we are interested in changing. The following code gets the current DCB and sets some of the fields:"

But anyway:

It's 8 bit, 1 stop bit, no parity. DTR control should be enabled, but the rest of the weird shit shouldn't.

1 Like

I have the same problem. Arduino UNO works while the code is uploaded recently but when unplugged it forgets the code. Plugging it back and it seems the Arduino is empty, no flashing lights no nothing.

Any help please?

It's literally impossible for the Uno to "forget" the code is was running when power cycled, and in any case this would be a completely different problem than previously discussed in this thread.
You should start a new topic, and include additional information as described in the How to Use this forum sticky post.

1 Like

Wow - many thanks for this (old) thread, which solved my dilemma. Special thanks to sterretje for his insights. I wasted a bunch of time misinterpreting the lack of blinking Tx LED on an UNO as indicating the processor wasn't sending data. Of course on the processor's Tx pin (which is what I needed to connect to), the data was there all the time. Thanks, guys!

1 Like