Arduino Micro reboots on serial disconnect at 1200 baud

Hello, I'm using an Arduino Micro in a project. Due to integration with legacy equipment, the USB serial port needs to run at 1200 baud. Everything works correctly. The problem is that when the host closes the serial port, the Micro reboots. The same thing happens if the host sets DTR low. (I'm using the terminal built into Visual Studio/Visual Micro which allows independent DTR/RTS selection.)

This only seems to happen at 1200 baud. While I haven't checked all other speeds, the problem is NOT exhibited at 9600 baud.

I believe that 1200 baud is "magically" connected to the boot loader process. The Micro seems to use a CATERIN loader instead of the AverDude loader that seems common on other Arduinos.

Among the things I've tried based on searches regarding this problem is to tie the reset lines to Vcc with a stiff pull-up such as 120 ohms. This seems to have no effect.

The code I'm running to illustrate the problem is:

void setup() {
 
    // initialize digital pin 13 as an output.
  pinMode(13, OUTPUT);

  Serial.begin(1200, SERIAL_8N2);

  delay(2000);

  while (!Serial) {
      ; // wait for serial port to connect. 
  }

  Serial.println("Hello Computer");

}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for a second
  digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);              // wait for a second
}

The problem can be repeated by closing either the USB connection or dropping DTR while the program is running (LED blinking). The Arduino Micro immediately reboots.

Any help or advice to work around this problem is appreciated.

Thank you!

Are you saying your PC USB serial can only run at 1200 BAUD? And what might that pc be?

Fair question. It's not the PC. It's what the device needs. The Arduino is interfacing with the Winkeyer by K1EL. Winkeyer needs 1200 baud, and all the software that uses Winkeyer expects that speed. I wish it were otherwise. It's definitely made life complicated when using an Arduino with the Winkeyer chip.

FWIW, the newer Winkeyer 3 supports 9600 baud, but none of the software, including the utilities written by K1EL support this higher speed yet. So while it's available, it's not yet a viable option due to lack of support.

Hope that helps. :slight_smile:

This is the same problem you asked about a month ago (although on a different platform.)

You might actually be able to fix it easily on an Arduino Micro, though. Not without breaking the automatic upload, though. (Perhaps double-tap reset for each upload is not too bad?)

Find your core directory (probably ...packages/arduino/hardware/avr/1.8.3/cores/arduino ) and edit CDC.h. Find the occurrence of 1200 and change it to some other value (600? Unless you want to change other IDE components to get auto-reset working, it doesn't matter what you set it to, because nothing is prepared to use it.)

Thanks for the suggestion. I'll check it out when I get back to the shop tomorrow. The problems are related, but are not the same. The Nano Every did not work correctly with a 1200 baud USB input. Switching to the Arduino Micro solved that problem. The current issue is that there's an unintended reboot when the host disconnects from the Micro. Prior to connection, and during connection all is just peachy. The code and Arduino work as expected. But having the Arduino Micro reboot after disconnecting the host may cause problems in some settings. That's why I'm trying to figure out how to fix it.

maybe it is simpler to change boards.txt
micro.upload.use_1200bps_touch=true

1 Like

Thank you Juraj. That looks like it would be an ideal solution, except that it appears that board.txt is targeted at the Arduino Every. I'm using the Arduino Micro.

I found the file on my computer at "C:\Users\username\AppData\Local\arduino15\packages\arduino\hardware\megaavr\1.8.7\boards.txt". I didn't find any other files named "board.txt" when doing a search of my drive. Here's a snip from the file:

nona4809.name=Arduino Nano Every

nona4809.vid.0=0x2341
nona4809.pid.0=0x0058

nona4809.upload.tool=avrdude
nona4809.upload.protocol=jtag2updi
nona4809.upload.maximum_size=49152
nona4809.upload.maximum_data_size=6144
nona4809.upload.speed=115200
nona4809.upload.use_1200bps_touch=true             <======== Highlight added for clarity
nona4809.upload.extra_params=-P{serial.port}

Questions: Would this still work on the Arduino Micro? Am I looking in the right place? Is there an equivalent for the Arduino Micro?

Thank you!

Micro is in boards.txt for the AVR platform, which is bundled with the IDE installation until you install a different version, which is then installed in arduino15.
It would be better for you to define a custom board in the sketchbook folder.

Hi Jurajj, Thanks so much for your help. I think this is on the right track to solve my problem. I took a look at the link, and your Github board examples. But unfortunately I'm hopelessly over my head when it comes to adding a custom board to the Arduino IDE. I'm not conversant in cores and packages etc. and have no idea how to create or modify a similar boards.txt file. At the present time, there is not any hardware subfolder in my sketches folder, so I would have to start from scratch. The likelihood of me making a mistake is 100%.

Is there a way I can force the IDE to create the Arduino Micro boards.txt file in a place where I can modify it?

Any other route that a hardware guy and not-so-talented part-time software developer could take? :smiley:

Thanks again! Your help is appreciated.

This is correct. Opening the virtual serial port with 1200 baud and closing it is the trick to reset the Micro (and Leonardo) into bootloader mode (so it's accepting new sketches for a few seconds). As 1200 baud aren't used on today's computers anymore (the variants that have an USB interface) this usually isn't a problem.

Thanks Westfw! I found the file CDC.h. On my system, I found it under "C:\Users\username\AppData\Local\arduino15\packages\arduino\hardware\megaavr\1.8.7\cores\arduino\CDC.cpp". Also, this could be left over from a previous project when I was using an Arduino Mega. So I'm not sure I'm even looking in the right place. You pointed to ...hardware\avr\1.8.3\cores\ardunio. But that path does not exist on my system.

However there is not any occurrence of "1200" in the file CDC.h. I did find the following code in CDC. cpp. This looks promising, but I'm not completely sure how all these pieces fit together. If I need to modify CDC.cpp I'll need some guidance on to how to proceed to get the change integrated back into my project. BTW, A double-tap reset to upload sketches is perfectly acceptable for my needs.

Thanks again!

Snip from CDC.cpp:

			// auto-reset into the bootloader is triggered when the port, already 
			// open at 1200 bps, is closed.  this is the signal to start the watchdog
			// with a relatively long period so it can finish housekeeping tasks
			// like servicing endpoints before the sketch ends

			uint16_t magic_key_pos = MAGIC_KEY_POS;

// If we don't use the new RAMEND directly, check manually if we have a newer bootloader.
// This is used to keep compatible with the old leonardo bootloaders.
// You are still able to set the magic key position manually to RAMEND-1 to save a few bytes for this check.
#if MAGIC_KEY_POS != (RAMEND-1)
			// For future boards save the key in the inproblematic RAMEND
			// Which is reserved for the main() return value (which will never return)
			if (isLUFAbootloader()) {
				// horray, we got a new bootloader!
				magic_key_pos = (RAMEND-1);
			}
#endif

			// We check DTR state to determine if host port is open (bit 0 of lineState).
			if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0)
			{
#if MAGIC_KEY_POS != (RAMEND-1)
				// Backup ram value if its not a newer bootloader and it hasn't already been saved.
				// This should avoid memory corruption at least a bit, not fully
				if (magic_key_pos != (RAMEND-1) && *(uint16_t *)magic_key_pos != MAGIC_KEY) {
					*(uint16_t *)(RAMEND-1) = *(uint16_t *)magic_key_pos;
				}
#endif

That's for the UNO WiFi (MegaAVR), not the Micro (AVR).
But the AVR code looks similar.

Hi Pylon, Thanks. That's what I suspected. So where else could the hardware folder for the Arduino Micro be located? For what it's worth, I'm using Visual Studio with the Visual Micro support for Arduino as my development environment. Should I temporarily switch to the Arduino 1.8.19 development environment? Would that create the files in the traditional place?

Hi All, After a lot of searching and sleuthing on the internet, I was able to locate both the boards.txt file and the CDC.cpp file. I edited both of them to try and break the 1200 baud auto-reset. Nothing made any difference. However, I was able to break sketch uploading, so I think I was editing the right files. I've put everything back, and sketch uploading works again.

Just as one more try, I put a 10 uf capacitor between the reset pin and ground. This was also a suggested fix. It didn't make a difference either. I looked at the reset line on the scope, and it didn't budge when the auto-reset occurred with USB host disconnect. There was nary a ripple. So the reset isn't happening via the reset line as near as I can tell.

At this point, I'm out of ideas. :slightly_frowning_face:

That's correct, for Arduino Micro and other native USB boards. The arduino core detects the USB message that sets the baudrate, and causes a reset internally.

Modifying CDC.cpp should work, though. Let me see if I can find an 32u4 board and do some experiments.

Modifying CDC.cpp (1200 to 600) did work for me. Setting the port to 1200bps and opening/closing it did not cause the board to reset.
An upload attempt did not work (as expected) without manually tapping the reset button during the upload attempt (double-tap didn't seem to be necessary, but it would visibly put the board into bootloader mode for "a while", and also worked.)

I was used a Leonardo board (but it also worked if I indentified it as a Micro, except for some LED definitions.)

The file I modified was ...packages/arduino/hardware/avr/1.8.4/cores/arduino/CDC.cpp

Thank you Westfw! I really appreciate your help and extra effort to test. I'll double back and retry changing CDC.cpp. I made the same mod as you, but it's possible that I got the wrong file. I used the shotgun approach and changed that file and boards.txt at the same time; seldom the best troubleshooting technique. I'll double back tomorrow and focus on just the CDC.cpp file. However, paths on my system don't quite match your file pointer. This may possibly be due to a quirk using Visual Studio. But I'll dig a bit deeper and try a few things knowing that the approach you suggested will work. I have a busy day tomorrow, so may not make as much progress as I'd like. Life gets in the way sometimes.

Cheers, and thanks again!

If you turn on the verbose option for compilation, then somewhere in the log you'll find the exact path and filename of the CDC.cpp that it's building into the core when you build your sketch.

Thank you for the tip Westfw! I was able to turn on verbose compile and upload. I switched over and used the Arduino IDE instead of Visual Studio. Unfortunately, CDC.cpp never appeared in the debug listing. It appears the path used by the Arduuino-Micro is \program files(x86)\Arduino\hardware\arduino\avr. In ...avr\cores\arduino subdirectory there is a CDC.cpp file, but no corresponding CDC.h. Obviously, there is no CDC library included in the code. Is that supposed to be there?

Just for good measure, I edited that file to change the "1200" to "600", but it made no difference in the reboot situation. Apparently, the Micro does not use this file.

KD6X verbose compile.zip (3.9 KB)

I uploaded the debug compiler output in case that provides any clues as to what's going on. I have to run to an appointment, so I'll study this more later this evening.

Thanks again for all your help!

It appears the path used by the Arduuino-Micro is \program files(x86)\Arduino\hardware\arduino\avr

that seems correct, based on the log file. My path didn't match because I have a newer version of the AVR core installed.

Sigh. That's because:

Compiling core...
Using precompiled core: C:\Users\courtnk\AppData\Local\Temp\arduino_cache_195223\core\core_arduino_avr_micro_0c812875ac70eb4a9b385d8fb077f54c.a

It SHOULD recompile automatically when you've edited CDC.cpp, like:

Compiling core...
Using previously compiled file: C:\Users\billw\AppData\Local\Temp\arduino_build_870691\core\wiring_pulse.S.o
 :
Using previously compiled file: C:\Users\billw\AppData\Local\Temp\arduino_build_870691\core\wiring_shift.c.o
Using previously compiled file: C:\Users\billw\AppData\Local\Temp\arduino_build_870691\core\wiring_pulse.c.o

"C:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega32u4 -DF_CPU=16000000L -DARDUINO=10819 -DARDUINO_AVR_MICRO -DARDUINO_ARCH_AVR -DUSB_VID=0x2341 -DUSB_PID=0x8037 "-DUSB_MANUFACTURER=\"Unknown\"" "-DUSB_PRODUCT=\"Arduino Micro\"" "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino" "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\variants\\micro" "C:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino\\CDC.cpp" -o "C:\\Users\\billw\\AppData\\Local\\Temp\\arduino_build_870691\\core\\CDC.cpp.o"

Using previously compiled file: C:\Users\billw\AppData\Local\Temp\arduino_build_870691\core\HardwareSerial.cpp.o
Using previously compiled file: C:\Users\billw\AppData\Local\Temp\arduino_build_870691\core\HardwareSerial0.cpp.o

Hmm. Are you sure your edit was successful? With the file location under C:\Program Files (x86), you probably need to run your editor "as administrator" in order to have it written successfully.