Monday, February 27, 2017

Communicating with AVRs via serial (USART). Poorman's isolated RS232 to TTL interface

AVR and serial (RS232) communication

I've been trying to build a new project based on the AVR for about a week and I needed to find a way to communicate with the MCU on the breadboard for debugging purposes. Up until now the projects I worked on were quite small and simple so no communication with the PC was needed, but this has changed. One way of achieving my goal is by using the USART capability of the AVR which has some nice features:

  • Full duplex connection
  • Serial frames with 5 to 9 data bits and 1 - 2 stop bits
  • Sync or Async operation modes
  • High resolution baud rate generator
So far so good, the only thing left is to find a way to interface it with the PC.

First try: disaster

Since my desktop computer has a serial port (RS232) header, I decided to use it instead of an USB RS232 to TTL converter. The main reason for this choice is because I had a few ST232 chips in my parts box that I wanted to put to use. The ST232 is a 5V powered multi-channel RS-232 driver and receiver compatible with MAX232.  By following the datasheet, I built this circuit:
First try at a RS232-to-TTL interface

As you can see, it's made up of the ST232 level converter, a few polarized capacitors used by its charge pumps and the DB9 connector. Note that both the ST232 and the ATMEGA share the same power supply and ground. The +5V power comes from my lab PSU.

I have used the above circuit for a few days without any trouble until one time when the microcontroller simply refused to program. Oddly enough, it was correctly detected by avrdude, it accepted all the commands and received the data sent to it, but upon verification the flash memory was completely filled with nulls. Thinking it was just a bad microcontroller, I replaced it with another one (bought in a different store to eliminate the probability of a bad batch) and then with third one (ATMega 8). Again, everything went well until the MCU simply died between 2 power cycles. This is when I understood that the ST232 circuit was somehow responsible for killing the ATMEGA chips. There were no other components on the breadboard, just the MCU and ST232 circuit. ESD is also excluded since I had ESD protection gloves on at all times.

Here all the voltage levels for the circuit while it's powered on and after the lab power supply is turned off and the ST232 circuit remains plugged in the computer RS232 port:

Measuring some points in the above circuit

As you can see from the picture, the circuit is working normally while it's powered, but when the lab power supply is disconnected (and the RS232 connection is still maintained with the PC), the power rail (VCC) dips to -513 mV (-0,513 volts). If you are unlucky to have other ICs on this rail, they could be destroyed.

According to the Absolute Maximum Ratings table in the datasheet of the ATMega8, voltage on any pin except RESET (with respect to Ground) should be between -0,5V and VCC + 0,5V and voltage on the VCC pin 1.8V to 5.5V. Clearly, the -0,513 volts that is leaked by the ST232 IC is out of spec for the MCU, thing that lead to it being destroyed after a few power cycles. While AVRs are pretty tolerant, there are some other ICs out there that are much more sensitive so if you are using such a RS232 to TTL converter chip (be it ST232 or MAX232), make sure to first disconnect the RS232 plug from the PC and only after that turn off power to the circuit.

A solution

In order to communicate with the AVR without risking to destroy it, I made an inexpensive RS232 to TTL interface using only common parts. The interface is galvanically isolated so the AVR will have great protection against power surges or current leaks. One drawback of using cheap components is that transfer speeds will not be too big, but it should be enough for debugging some simple projects.

  • Principle of operation: voltage level conversion with PC817C (or CT817C, EL817C, etc.) optocoupler / optoisolator
  • Operating voltage (TTL side): 3V to 5V (one resistor value needs to be changed for switching the level)
  • Operating voltage (RS232 / PC side): same as the serial port DTR / RTS lines (it harvests power from these lines)
  • Maximum data rate: 4800 Baud half-duplex

  • It needs the software to set the RTS line to logic 0 (which provides +10V) and the DTR line to logic 1 (which provides -10V). The circuit will not work if these lines are not configured correctly. Not all software can toggle these lines. For Linux one can use GTKTerm and for Windows RealTerm.
Poorman's isolated RS232 to TTL interface

The circuit is pretty simple. The positive part of the Tx RS232 signal from the PC passes through D1 then fed into the led of U1 via the resistor R1. The led sees about 5 mA of current. On the output side, optocoupler U1 is wired as common collector so the signal will be the same polarity as the one in the RS232 port, but at TTL voltage. R2 is chosen with a low value in order to improve the rise / fall time of the waveform and decrease the phototransistor switching time. The signal is then fed into an inverting, common emitter buffer comprised of Q1 and load resistor R4.

On the transmitter side, the signal is fed into the led of U2 via the resistor R5 (which can be changed to work with 2 different voltage levels, see the schematic). On the output of U2, the voltages used for the signals are harvested from the RTS (+10V), DTR (-10V) lines, so the software must toggle the lines accordingly. The phototransistor and the PNP transistor Q2 are arranged in a cascode configuration to get an improved rise and fall time. The cascode configuration is great for a circuit like this because the phototransistor does not see the load resistor R7, it only sees the internal resistance of Q2, which is quite small.

Here's an example transmission on the screen of an old scope:

Sending a letter via GTKTerminal

The waveforms above were created by continually sending the "V" character at a rate of 4800 bps, 8 data bits, 1 stop bit, no parity. The power supply on the TTL side is 5 Volts and the scope is set to 5V / div & 0,5 mS / div for the timebase. The first picture shows the TTL output (that goes to the MCU's Rx pin) and the second one the RS232 output (that goes to the PC's Rx pin).

The voltage levels on the RS232 side are not perfect (e.g. +-12V) because the control lines can only supply 10V a few mA of current and there is also a voltage drop across the diodes. But this shouldn't matter since for RS232 the space (0 or ON) condition is indicated by +3 to +12V and a mark (1 or OFF) condition anything from -3 to -12V.  Judging from the oscillogram above, the circuit should work just fine (not to mention that modern RS232 transceivers are forgiving, with some sensitive enough to work with +-2V signals).

So what speed can this be used at?

First, it should be noted that PC817C (and equivalents) are quite slow (with maximum Tr / Tf of around 18 μs with RL of 100R depending on the manufacturer and sample). To be sure that the circuit works reliably I'll use the worst case scenario for the rise and fall times (e.g. 18 μs) for both optocouplers, but just as an exercise, let's calculate the speed for each of them:

For U1, speed is dictated by the load resistor R2, so the slowest time will be 18 μs (as per the datasheet).

For U2, the phototransistor only sees the input resistance of Q2. Considering that the led of U2 is powered with around 5,5 mA of current and with a failsafe value of 135% CTR for CT817C (taking into account temperature and aging of the device and substracting them from the 200% CTR that the manufacturer claims), Ic will be at

Ic = 1,35 * 5,5 = 7,42 mA. 

To calculate the internal resistance Re of Q2, we use the following formula:

Re = 25 mV / Ic (in mA) = 25 / 7,42 = 3,36 Ohms

This low resistance will ensure good switching time, but I want to be on the safe side so I'll consider it equal with the time above (18 μs), not to mention that the datasheet doesn't show the timing values for load resistors less than 100R. The minimum bit time should be kept to 1/10 of the baud rate so we can calculate it like this:

Mbt = 18 μs * 10 = 180 μs

To work reliably, the circuit must work at a baud rate that has a bigger bit time than the one calculated above. Knowing that the bit time for an arbitrary baud rate can be calculated by dividing 1 second to the baud rate, the following table can be devised:

Baud rate Bit width (μs) Max rise/fall time (μs)
1200 833 83,3
2400 416 41,6
4800 208 20,8
9600 104 10,4
19200 52 5,2
38400 26 2,6
57600 17 1,7
115200 8 0,8

Since the fastest speed with a bigger bit width than 180 uS is 4800 baud, this will be the max rate at which this circuit circuit is considered reliable. Higher speeds would be attainable by using fast optoisolators like 6N137, but much of the schematic would need modification.

1 comment: