Investigation: Why does an Arduino clone not work as a USB-Serial
embedded ch340 arduino troubleshootingBackground #
A few months ago, I was experimenting with an old PHOTO-PLAY Arcade Machine (only available in german, use translator). Even back in the 90s, when the first revision was released, the machine had a capacitve CRT touchscreen. This was a bit of a novelty, and it was actually the only input on the machine, so all of the games were designed to work with the touchscreen only. The hardware inside is based around a standard PC system with 486 processor, which means that all of the peripherals (coin counter, touchscreen, CRT) are using standard PC interfaces (RS232, ISA and VGA respectively). So I wanted to replace the 486 with a more modern computer, with the plan to play a wider selection of games or use it to play music. For this project, I wanted to use the original peripherals as far as I could, so I had to find a way to attach the touchscreen ISA card and write a "driver" for modern windows:
Digging through the drivers and reference manuals, I found out that the card exposed a simple serial interface, which is used for all communication. Even better: As I was looking through the datasheets for the chips on the card, I identified one of the chips as a Serial-to-ISA bridge, which was hooked up via serial to the main controller. This means that I could power the card externally, and simply hook up a serial adapter to the RX / TX lines of the main controller to talk to it, ignoring the ISA bus entirely. Conveniently, there is even a jumper on the card that allows me to disconnect the ISA bridge and have a breakout to attach my serial adapter.
The "Arduino-as-serial hack" #
Since the card was using 5V logic levels already, I didn't need any kind of level shifter and could use a 5V USB-Serial adapter directly. However, I did not have one at hand at the moment. Luckily, there is a well-known "trick" that I learned a while ago while I was doing something with Arduinos: Most Arduino board already have a USB-serial onboard that can be used directly to talk to other devices by disabling the microcontroller. With the big Arduinos (like the Uno), the ATMega Microcontroller can be removed entirely so that it does not interfere. But I only had a few Arduino Nano clones lying around, where the microcontroller was soldered on. In this case, it is still possible to bridge the GND
and RESET
pins to effectively disable the microcontroller.
I found out about this years ago by googling, and even now, there are many results for use arduino as usb to serial that show the same trick of bridging RST
to GND
. Now, I don't want to blame anyone who posted this trick, since it actually works just fine for most cases. I used knockoff Nanos as serial adapters multiple times - mostly to connect to other ATMegas, but also with other hardware (e.g. an old CASIO graphing calculator).
So, I just used the same method to communicate with my MicroTouch card. And at first, it seemed to work: When I touched the screen, I would receive a stream of touch coordinates in my serial terminal. But when I tried to send a command, nothing happened, even though the card should have sent a confirmation.
At first, I assumed that something was wrong with my serial settings, so I tried to change a few parameters that were not clearly specified in the documentation, which had no effect. At some point, I decided to probe the serial lines with my oscilloscope so that I could compare the signals transmitted by the card with those I send from the USB serial. As I was probing the TX line of my USB serial, I saw the following:
Pay attention to the cursors that I placed at the low and high levels respectively. The high-level voltage is at
The serial lines on the MicroTouch card are driven by an 8-Bit Microcontroller C501G-LN
, which specifies the following for the input voltage range:
With
At this point, I assumed that the USB-serial-converter chip on my clone Arduino was the culprit. The main difference between a real and clone arduino is in the serial converter: Real Arduinos use a FT232RL
, while most clones use the cheaper CH340G
. Other than that, they are mostly the same, using the same Atmega328P
microcontroller. So, I pulled up the datasheet for the CH340
series as well, which shows the following output levels:
Hm, the datasheet only shows up to 0.5V as the maximum output voltage for a low logic level. So, either the CH340 chip on my board is faulty, or there is something else on the Arduino interfering with it.
Deconstructing the Arduino Nano Clone #
Since my Arduino Nano is a clone, we don't know how well it would match the original Nano schematic. So, I decided to follow the traces on the actual board to create a partial schematic.
(Note: On these photos, I removed the reset button and the actual CH340G chip so that we can see the traces better)
From these pictures, we can trace the lines between the exposed TX / RX pins and the CH340G chip, and derive the following partial schematic, which contains all components that are hooked up to the TX / RX lines:
At this point, it is clear that there are two possible error sources: Either the microcontroller itself, or the status indicator LEDs. So, I desoldered the ATMega from the board:
I then repeated the measurement procedure again, sending a B
character at 9600 Baud, 8N1 using PuTTY and measuring the resulting signal with my oscilloscope:
As you can see, there is no noticeable difference here. This mostly rules out the ATMega as the root cause and only leaves the LEDs. I removed the current-limiting resistors to break the circuit (since it would be a pain to re-solder the LEDs in the correct orientation), and tested again:
Aha! Now we get a clean signal, with the low voltage level going down to almost 0V. I also resoldered the ATMega to the board, and still received a clear signal with it being present (again, with a bridge between RST and GND):
This rules out the ATMega entirely, and shows that the indicator LEDs must cause the issue.
Analysis #
If we look back at the schematic, this behavior is actually quite logical: When we consider only the circuit segment between the CH340G output and the 5V source for the LED, we can see that it resembles a voltage divider with the LED in the middle. If we assume that no current flows through the ATMega, both of the 1k resistors should have exactly the same voltage dropping across them when the CH340 pulls the line low. Now, there is one 1k resistor between the output pin and the CH340G terminals. So, even if the CH340G produces a perfect 0V for a low signal, the voltage at the output will be 0V + the voltage drop
Interestingly enough, this value of 1.4V is barely below the low level voltage limit of an Atmega328P (
So, basically this Arduino Nano clone circuit is not even guaranteed to work as an Arduino. I can only assume that the value in the Datasheet already has a large safety margin applied to it, so that even voltages beyond that point will read as low
almost all of the time.
Ultimately, the indicator LED circuitry is clearly at fault here. However, a real Arduino Nano also has indicator LEDs - so I decided to look into its schematic to see how the circuit is implemented there:
Here, we can clearly see that the LEDs are decoupled from the actual RX and TX lines. Instead, they are attached to the CBUS0
and CBUS1
pins of the FT232RL. These pins are configurable, here they are configured as dedicated RX / TX LED drive pins (which is explicitly supported by the FT232RL).
On the actual RX / TX lines, there is only a single 1k resistor respectively, to prevent damage when the ATMega and FT232RL both actively drive the chip at different levels (which will happen if Pin 0 and 1 are used as output). This means that the "Arduino as USB-Serial" hack should actually work well on a genuine Arduino (or a clone with FTDI Chip).
When we compare the schematics of the original with the clone, we get an idea how the non-optimal circuit for the Nano imitation might have been created:
- Someone wanted to build a cheaper Arduino clone, and noticed that CH340G are cheaper than genuine FT232RL while doing essentially the same job
- The CH340G does not have dedicated LED drive pins, so using the RXD / TXD pins is the only option
- It would be ideal to use some sort of decoupling device (e.g. a small MOSFET or LED driver), but that would increase costs. To keep it simple, the LEDs are directly hooked up to the Arduino outputs
- The circuit is tested, and it works in most of the cases, since the low level is barely inside of the safe range of the Atmega328P almost all times. It's good enough to ship.
Conclusion #
Ultimately, I fixed my issue with the MicroTouch card by digging through a large number of boxes and drawers to find an old FTDI-based USB serial cable. I could finally send data to the card, and my improvised touch driver for it actually works fine now - maybe I'll do a post about it in the future.
As for the Arduino Nano, the conclusion is two-fold:
-
On a technical level: The circuit of at least some Arduino clones is faulty and can lead to issues with serial communication, especially when trying to use the board as a serial adapter for devices that are less tolerant than the ATMega. The problem can be solved easily by breaking the connection to the RX Indicator LED.
-
On a more general note, this shows again that cutting corners can have consequences. I hackishly used the Arduino as a USB serial, even though I knew that issues may arise. However, I had used this method successfully in the past, so I kind of forgot about the potential for errors. Additionally, the designer(s) of the Nano clone cheaped out with their UART indicator LEDs - they probably knew that the implementation was not really spec compliant, but it is cheap and worked well enough to be shipped. But when both hacks combined, issues finally arose.
Comments
If you have any questions or comments, please feel free to reach out to me by sending an email to blog(at)krisnet.de.