In part 10, we opened up the ATMEGA328P can of worms, looking at bypass caps, serial termination and the ceramic resonator. Now we’ll pull apart the Data Terminal Read (DTR) and RESET spaghetti.
Build An Arduino UNO R3 from Scratch Table of Contents
DTR and RESET Theory
When the 328P on your Arduino gets reset, the bootloader (currently Optiboot, I believe) checks to see if there is a new program waiting to be installed by checking if anything is waiting on the serial line. If a new program is there, the bootloader overwrites the existing sketch with the new sketch and hands control over to it. If no program is waiting, the bootloader drops off and allows the serial connection to run as normal.
The key in that sequence for us is the “when the Arduino gets reset, the bootloader checks” part. It would be annoying if we had to press the reset button manually every time we corrected some little bug in our code and sent it back to the chip. On the UNO R3 (and most current Arduino variants), an “auto-reset” feature has been implemented to take care of this for us.
When we talk to the 328P from our computer, we do it over USB. The USB goes to the 16U2, which translates it into USART, and handles the interaction to the 328P. Part of the USART communications standard allows for something called “flow control” which allowed a computer on one end of a serial connection to start or stop the serial conversation by setting the logic state of a pin called “Data-Terminal-Ready” or DTR (there are other variants on this principle). When DTR is high, it says, “Hey, I’m ready for all the data you can send.” When DTR is low, it says, “WOAH! Gimme a break, I need to process some stuff so hold off on the communication.”
The Arduino designers take advantage of this process, by using the DTR signal to issue a reset from the 16U2 to the 328P. Any time the 16U2 establishes a serial connection, the DTR is brought low, which causes a reset and cues the bootloader. That’s why your sketch always restarts when you open a new serial monitor window!
It’s important though, that we don’t hold the 328P in reset. We just want to pulse the pin very, very briefly, so that the bootloader can listen to SERIAL_Rx and determine if a new sketch is being sent. When the RESET pin on the 328P is low, all the pins (except for the ICSP pins, I believe) are set to a high impedance state, effectively killing the serial pins. So we pulse the Pin 1 on the 328P to issue the reset, not drag it low then drag it high again.
DTR and RESET Circuit
(See how I’m not complaining about the quality of this schematic?)
For the sake of complete-ness, I’ve included the ICSP header connection here, but the essential parts that implement the theory above are…
- The 328P_DTR net coming in from the 16U2 on the left
- The 1K pull down resistor RN2D
- The 100nF capacitor C5
- The 10K pull up resistor RN1D
- The big Reset pushbutton switch
When nothing is happening and your Arduino is powered, C5 is charged to 5V through pull up resistor RN1D, which is also acting to keep the RESET pin from accidentally activating because of noise. Remember, RESET is active low. If you decide to press the big reset button, you connect the RESET pin directly to GND, and initiate a reset. This also discharges C5, but you don’t really care, because the connection to GND is made through the switch. As soon as you release the button, C5 charges back to 5V through the 10K resistor. While this is going on, the DTR line is held HIGH by the 16U2.
Now, let’s actually push a new sketch to our 328P over USB. You click the “Upload” button. After the sketch compiles, the 16U2 receives the code over USB and pulls DTR low. That causes capacitor C5 to rapidly discharge through the 1K pull down RN2D, because the 5V potential on the 16U2 side has disappeared. Immediately though, it starts recharging through the 10K pull up RN1D and after around 5ms, the capacitor, and the RESET pin, are back at 5V. The bootloader then starts a timeout period waiting for something to come across as new sketch code. By my tests, it seems to be about one full second. In that time, the 16U2 starts transmitting the new sketch over the USART to the 328P, then receives some form of acknowledgement, and DTR is returned to high. The bootloader hands control over to the next sketch and you’re good to go.
When the DTR line goes back high, for a brief moment, capacitor C5, which reset to 5V 5ms after DTR was dropped in the first place, will “overcharge” to VCC x 2, 10V, as it will now have 5V potential on the 16U2 side. If you tried applying 10V to any other pin of your Arduino, you’d burn it out in a heart beat. The RESET pin is special because it facilitates something called “High Voltage Programming” and is able to take a voltage of up to 12.5V I think. So for an instant, the pin is at 10V before it immediately begins to discharge through the 10K pullup resistor to the lower 5V potential.
If for some reason, you wanted to disable the autoreset function, you would run a very sharp knife down between the two halves of the solder jumper at “RESET EN”, to cut the trace. By doing so, you would isolate the 328P RESET from the C5 capacitor. If you wanted to re-enable the feature again, you’d just blob a bunch of solder to bridge across the two silver pads.
UPDATE: Based on reader feedback, I’ve added more details on the functioning of the C5 capacitor to the bottom of this post.
New Sketch Upload On A Scope
Here is an example of pushing a simple sketch to the Uno. All the sketch does is write 0x01 5 times over USART so I can easily detect those five pulses.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
void setup() { Serial.begin(9600); Serial.println (0x01); delay(100); Serial.println (0x01); delay(100); Serial.println (0x01); delay(100); Serial.println (0x01); delay(100); Serial.println (0x01); delay(100); } void loop() { } |
- Yellow Trace is being sampled on the 16U2 side of capacitor C5.
- Light Blue Trace is being sampled on the 328P side of capacitor C5.
- Purple Trace is connected to the 328P Serial TX pin.
- Dark Blue Trace is connected to the 328P Serial Rx pin.
This trace is divided into 200ms sections on the horizontal scale, with each trace set to 5V per division. On the left, you can see the DTR signal (16U2) go low, and the barest hint of the low going pulse on the 328P Reset pin below it. About a full second later, you see activity as the 328P receives the sketch across the serial line, and then responds to the 16U2 over the Tx line. DTR is brought high again and you see the start of the five serial pulses about 40ms later.
Let’s zoom in on the start of it…
I’ve zoomed in now to 5.00ms per division and you can see the pulse generated by the low going DTR pin, causing capacitor C5 to discharge through the pulldown resistor, before immediately beginning to charge again. Somewhere around 4ms after the pulse is initiated, C5 is back at 5V, and so is the RESET pin.
Now let’s zoom in on the end of it…
You can see the tail end of the serial acknowledgement on the Tx line before DTR goes high. The barest hint of a >5V pulse is seen on the 328P trace at that moment, that evaporates within one or two milliseconds. Because we’re zoomed in at 2ms per division, we don’t see the 5 serial commands execute yet.
Finally, let’s have a look at what happens when we simply open the serial monitor with our little 5 serial blip sketch already uploaded.
Again, we’re zoomed out to 200ms per division. You can see DTR go low, with the corresponding reset pulse on the 328P reset line. Then 1.4 seconds passes before anything happens! That is the bootloader waiting to see if any new code is coming. It times out, hands control back over to the existing sketch, and our five serial blips are seen immediately after. DTR remains low as long as the serial monitor window is left open.
Wrap Up
That’s a lot to digest, so I’ll cut it off there. In the next segment, we’ll identify components for the 328P subsystem, and publish the KiCad Schematic and BOM.
UPDATE
I received an email from a reader who said that he was getting lost in my description of what happens around the capacitor during the reset sequence, which is a totally valid point, because the capacitor is being used in an unusual way. Below, I’ve added my response to Charles question in the hopes that it might explain things a little more clearly…
Hey Charles! Thanks for writing!
Getting feedback like that is great, because it makes me go back and re-read what I wrote with not only a critical eye, but also the “see if I can reteach this to myself” attitude, because it’s hard for me to remember the specific details of how stuff like this works. After going over the post a few times, and actually thinking, “hell, I must have gotten this all wrong”… I retested everything and can reconfirm that the post is correct. Ok, so going with that premise, let me see if I can clarify.
The tricky part is the functioning of the capacitor. Given no resistance in a circuit a capacitor will charge and discharge in an equal amount of time. If you add resistance, you increase the length of time it takes to charge / discharge. If you unbalance the amount of resistance, for example by putting a large resistance between the cap and the voltage source vs. the resistance between the cap and ground, the cap will charge very slowly, but discharge rapidly. Capacitors 101.
Ok, so we have this circuit…
Assuming we have a blank sketch uploaded to the Arduino, meaning one that makes no use of serial comm., in the running state, you have a logic HIGH on DTR and a logic HIGH on RESET. 5V on both sides of the cap. You’re right to think that the voltage potential across the cap is zero, because the charged particles inside the cap have no place to go: they can’t charge the left side plates in the cap because DTR is pushing them away and they can’t charge the right side plates in the cap because RESET is pushing them away… but the capacitor is still at 5V on both sides… I would characterize that as a steady, but extremely volatile state. Because the cap isn’t technically charged, just held at a voltage potential, any change in voltage will cause it to swing rapidly in voltage level itself. Of course all this while, a ridiculously large amount of current is being thrown away down the well of RN2D, Ohm’s Law says 5V across 1K = 5mA constant loss just to keep that cap in that state.
So now the 16U2 needs to issue a reset… it does so by pulling Pin 13 low… although that’s sort of a misnomer. Pin 13 might not actually be going low, it might be going high impedance and the path to ground is maintained through RN2D. I’m not entirely sure, and honestly that’s sort of minutia, the point being that the 16U2 brings the DTR side of the cap to ground, unbalancing the potential at C5.
C5 has no charged particles to give, because it was held at that steady, but volatile state, so the charge across it drops almost instantly to zero… *BOOM* RESET! … but then starts to build a charge up to 5V on the RESET side through the 10K RN1D. Since there is some sort of programmed timeout within the bootloaders that waits over a full second for something to happen here, and it only takes about 4ms for the cap to charge through RN1D, C5 gets to 5V on the RESET side very quickly.
The sketch is transmitted over serial Rx and Tx between the 16U2 and the 328P, all while DTR is held low, and when it’s ready to stop with the serial talk, DTR is raised, instantly creating 5V potential on both sides of the cap. Now the cap is forced towards that steady, but volatile state, it’s got 5V on DTR and 5V on RESET, but it *also* has 5V charged into the plates on the RESET side. That creates the +10V spike of voltage potential that gets bled into the +5V rail when the RESET sequence is over.
Does that description make more sense? Because it certainly helped me understand it more effectively 🙂 I’ll probably wind up adding this to that page.
– dan