Arduino Automatic Reset

As mentioned in my previous article, I am planning to publish a long-form article on UART. I am doing a series of shorter articles to lay the groundwork. This is one of these “short” articles; this one about how Arduino uses UART. Of course, I still went way too deep in this topic for something that was meant to be a short segue. Anyway, on to the actual content!

I have an Arduino Leonardo. It features an ATmega32U4 microcontroller, which can do USB directly. This is great, but I actually want to play around with “real” UART. It so happens that the older Arduino Uno does “real” UART, so I got a cheap clone from AliExpress for less than 4€. Its design looks somewhat similar to the Arduino Uno R3 SMD.

The first large difference is that this board has a USB-C connector instead of a USB-B one, which is nice. Surprisingly, it cannot power the board. The USB-B variant from the same seller can.

“Arduino” Uno

This section is not necessary to follow the rest of the explanations.

Since this is a clone, I thought it would be useful to take a look at how similar it really is to the original. There are some significant differences, but they should not matter for the casual user.

The Arduino Uno is built around the ATmega328P microcontroller. This clone uses the same chip, as using a different microcontroller would be a huge difference with the original, making this board not really a clone.

However, the original Arduino Uno actually features a second microcontroller. Depending on revisions, that would be the ATmega8U2 or the ATmega16U2. The Arduino Uno uses it as a UART-to-USB adapter (with the proper firmware). This is surprising, since there are dedicated chips for that, but the actual reason is to avoid needing a custom driver:

“Which is when we realized there was this thing called CDC (communications device class) protocol, which was embedded into operating systems. It’s the reason you don’t need a driver for a USB serial port. We found that you could develop a firmware for some simple Atmel processors that worked just the same as FTDI chips, but would liberate us from needing a driver.” (source)

USB CDC is the standard way to expose a UART-like interface through USB. Since it is part of the core specification of USB, it should work out-of-the-box on any operating system with proper USB support. However, dedicated UART-to-USB adapter chips were designed without USB CDC and instead require some specific software (a “driver”) to be installed by the user to work.

Nowadays, I would expect the drivers to be installed automatically, but it was definitely not the case at the time the Arduino Uno was designed. So, to make things simpler for users, they used a microcontroller and wrote a firmware to make it talk USB CDC.

The clone has replaced it with a dedicated UART-to-USB adapter (a CH340G). Also note that, while the Arduino Uno has two ICSP connectors, one to program the ATmega328P, and one to program the ATmega8U2/ATmega16U2, this clone has a single ICSP connector.

The IC right next to the USB connector is the UART adapter. Unfortunately, there does not seem to be any marking on it. The title of the listing suggests that this is a CH340G.

“Real” UART on the Uno

Like before, we connect GND to GND, TX to RX and RX to TX. We’ll also power the board by connecting VCC to 5V. They are conveniently labelled on the board, so this is quite easy.

This time, I used an FT232RL as the UART-to-USB adapter. It will come in handy later, but a CH340G-2 would still work.

Unfortunately, the firmware which is shipped with this board does not send anything through UART. We could write some firmware and upload it, using AVRDUDE. But that process itself uses UART, so we’ll just use that as an example.

Let’s try running a basic command to request information on the target microcontroller.

This fails. The reason is that the board is currently running some user firmware (in my case, that just makes the “L” LED blink slowly), which does not understand AVRDUDE. There is a short period where the microcontroller is able to understand AVRDUDE: right after it starts.

Note: There is no magic. The thing that makes the microcontroller understand AVRDUDE is just another firmware called the “bootloader”. The microcontroller loads that bootloader first. The bootloader listens for commands from UART for a short while and, if no commands are received, it just starts the user firmware from flash memory.

We need to press the reset button (the only button on the board, next to the USB-B port) right before running AVRDUDE. When we do so, we get a proper report:

It works! This is what you had to do for the earliest boards from Arduino, but they quickly improved the process so that the user would not have to fiddle with the reset button to upload a firmware.

Automatic reset

“It turned out that if you put a capacitor between the reset pin of the microcontroller and one of the serial port pins,” he explains, “it would reset the board automatically whenever you opened the port.” This small tweak became a vital and very popular aspect of the UNO’s useability. (source)

Depending on your background, this sounds either obvious or completely opaque over multiple levels. I was in the latter camp until very recently.

The first thing you need to understand this is that, in addition to GND, TX and RX, UART1 defines a number of additional pins. Although they are obsolete, they are still supported. In particular, DTR and RTS will have a very predictable behavior:

  • By default, they will be electrically high (e.g. at 3.3V)
  • When the UART device gets opened, they are automatically set to electrically low (0V)

This happens, for instance, when AVRDUDE opens /dev/ttyUSB0 to send a firmware to the board. All we need to do is to make it so that the board resets when DTR or RTS flips to low.

Let’s try connecting DTR to the RES (reset) of the board.

The FT232RL-based adapter I have conveniently exposes DTR as a pin (green wire in picture). With the CH340G-2 board, you’ll have to connect to the RTS hole, which is a bit less convenient.

Unfortunately, this does not work. This brings us to:

The second thing you need to understand is that the “RESET” pin really is a “keep running” pin. If you use it, the microcontroller will turn off when it is low (e.g. 0V), and turn on when it is high (e.g. 3.3V). So, we are successfully turning the microcontroller off, but it never starts again.

The third thing to understand is that a capacitor is the perfect solution for that. In short, it lets the current flow through it for a short time, until it gets full. So, if we put a capacitor between DTR and RES, when DTR goes from electrically high to low, this will make RES low for just a short duration.

You can visualize this with the CircuitJS1 simulation below. The graph on the left shows the electrical level of DTR. The graph on the right shows the electrical level of RES. You can toggle the electrical level of DTR by clicking on the switch and observe the effect on RES. It should drop to low immediately, but very quickly returns to high.

Note: The simulation includes a few additional components that are included in the board, but only the 10 kΩ resistor is really needed to make it work at all.

We will need a capacitor with a high enough value that the RES pin is set to a low electrical value long enough for the microcontroller to notice. The recommendation is to use a 100 nF capacitor, but even 10 nF seems to work. Anything lower, and the microcontroller does not reset.

I got some small clamps also from AliExpress, for 4€, which makes it easy for this kind of testing
The three digits on small components usually give you two digits for the value itself (here, “10”), followed by the number of zeros relative to the base unit (here, “4” 0s). For capacitors, the base unit is the picofarad, thus, “104” means “10 0000 pF”, or 100 nF, or 0.1 µF.

With this setup, no physical action is required when running AVRDUDE! The microcontroller resets automatically right when needed.

UART over USB

The same principle is used when programming the Arduino Uno through USB. After all, the ATMega16U2 is just a bridge between USB (CDC) and the physical UART communication line.

The schematics of the Arduino Uno can be confusing. I want to focus on the resetting of the microcontroller, so I removed everything else:

The first thing is that this is connected to the pin 13 of the ATmega16U2, which is labelled “CTS”, even though it is supposed to be DTR. The thing to remember is that this chip is a microcontroller, not an UART adapter, and this pin can be used for any purpose (this is a GPIO pin). Arduino just decided to write the firmware for this chip to output DTR on this pin.

The Arduino Uno lets you disable the auto-reset feature, by scraping away the solder between the pads labelled “RST EN”. The two pads are labelled  “1” and “2” in the schematics, and a wire shorts them to indicate that they are connected by default. This can be confusing, but the software used to produce the schematics does not have a way to indicate that the pads are soldered together. Instead, this is indicated with an extra wire around the pads.

We then have a 10kΩ resistor labelled “RN1D”. It serves the same purpose as the resistor I have used in the EveryCircuit diagram above. When the capacitor is “blocking” (and when nothing is connected to the RES pin of the board), this resistor ensures that the level of “RESET” is 5V. The 10kΩ value is high enough that the capacitor (or the RES pin of the board) can “override” it easily and set “RESET” to ~0V.

The diode is there to handle the case when the capacitor discharges. Without this diode, when DTR switches from electrically low to high, the charge in the capacitor will cause a suddent voltage spike way above 5V. The diode prevents the voltage from even rising above 5V. This is a shunt diode2.

The other resistor, 1kΩ and labelled “RN2D” sets the “default” voltage of DTR to 0V. This avoids random oscillations when the ATmega16u2 is starting and the GPIO PD7 pin is still floating, which could cause unwanted resets. This can also avoid current flowing back into the microcontroller.

“TP_DTR” is a “test point”: a physical place on the board where you can measure the voltage to check that everything works as expected.

Considering all this, we can see that this is nothing more than what we did with the capacitor earlier.

Conclusion

This is a relatively unimportant feature of the Arduino Uno. However, to properly understand it, I needed to uncover a significant amount of implicit knowledge that is absolutely not obvious for someone like me, who mostly ever dealt with software.

  1. Strictly speaking, this is RS-232 which defines this, but let’s keep that aside for now. ↩︎
  2. Combined with the capacitor and the resistor, it looks like a negative biased clamper with negative bias. ↩︎

Leave a Reply

Your email address will not be published. Required fields are marked *