I decided to write this guide, because there are a few details and nuances that I will probably forget soon and then I will have to rediscover them again. So lets get dirty!
Arduino pro mini
This device probably does not need too much introduction. Small, bare-bones ATmega 328P with a LED and a reset button. Comes in 3V3 flavor, which is important for me, as most electronics I touch these days is 3V3. Also, it is good to work with 3V3 boards exclusively as there is then far less change to fry something up.
With boards that are kind of 3V3, or 3V3 compatible but not fully, sometimes a 5V impulse could happen on a GPIO and something else down that communication line can get's damaged. Increasingly not worth the risk. Especially since the proper tools are accessible and inexpensive (it was not always the case). One such tool is CH341A programmer board.
Blue CH341A board
I own a blue CH341A board, which is a bit different than the more well-known one, the black one. The blue one has a proper way to switch levels between 5V and 3V3 for both the VCC supply pin as well as for GPIO pins, meaning full 3V3 in my dictionary. Exactly what one needs. With the black CH341A board, the mod needs to be done to get everything down to 3V3 properly, as without the mod you risk frying your components with 5V.
This blue magic board probably also does not need to much introduction, in short it is a IC that allows to convert USB to various common serial and parallel interface including UART, I2C and SPI, among the few. It is usually used for flashing BIOS or firmware flash memory chips on the motherboards using the SPI mode but can be used to program Microchip's AVR devices using either SPI again or even UART mode.
Avrdude
Avrdude is the actual piece of software that moves the compiled firmware from the computer, through the programmer - the CH341A in our case - into the microcontroller. Latest version can be downloaded via Homebrew:
brew install avrdude
CH341A support in avrdude
was added around version
7.2. At the time of writing, the version of avrdude obtained via Homebrew
is 8.0 and Ican confirm it supports the CH341A. This can be checked like
the following (might need to escape the question mark like \?
depending
on the shell used):
avrdude -c ? 2>&1 | grep ch341a
Which outputs the following in case of success (and nothing otherwise):
ch341a = CH341A programmer: note AVR F_CPU > 6.8 MHz (ISP)
Let's move on.
Using SPI mode
Now with the support for CH341A on avrdude confirmed, it can be used to flash the chip (or the fuses) directly via SPI mode:
avrdude -v -e -D -p mega328p -c ch341a -U flash:w:firmware.hex:i
The support here is important because it is relevant only for this SPI mode, not the UART mode which is more complex to setup in this case and we get back to it later. For the completeness, here is the connection table:
CH341A | Arduino | Connection Purpose |
---|---|---|
GND | GND | Common ground reference |
VCC | VCC | Power supply for Arduino |
SCK | 13 | SPI Clock |
MOSI | 11 | Master Out Slave In data |
MISO | 12 | Master In Slave Out data |
CS0 | RST | Chip/Slave Select, Reset |
Note that for this to work, the mode jumper on on blue CH341A board should be set to SPI/I2C and the D1 LED should be glowing red, but there might be different variants.
Using UART mode
UART mode is getting to the core of the Arduino pro mini. The point of this product is that there is no onboard USB connector nor USB-UART converter. Instead, there is a small piece of software, called bootloader in the ATmega328P, that right at the start of the boot process waits for the data that come over UART and writes them into the flash memory. This way the program get's into the microcontroller. Here's the pinout, and the main reason I wrote this article:
CH341A | Arduino | Connection Purpose |
---|---|---|
GND | GND | Common ground reference |
VCC | VCC | Power supply for Arduino |
TXD | RXD | Serial data connection |
RXD | TXD | Serial data connection |
MOSI | DTR | Automatic reset |
By looking into the CH341A datasheet, we can see that the pin 20 serves as a MODEM liaison output signal, data terminal ready, low-level active or DTR in short, when using 4.3.Asynchronous serial interface pins. The same pin serves as MOSI for the SPI mode. I mean, the Arduino can be programmed even without this pin, but then manual reset pressing is required just after the avrdude command is issued.
MacOS driver
To to get to the avrdude command itself, one next hurdle have to be cleared. Unfortunately, as things currently stands, Mac needs to install a driver for this serial converted to be able to talk with UART mode.
For me, the SPI mode worked straight away on Mac but when I enabled UART
mode by switching a jumper, nothing happened. I could not see the device
listed in /dev/*
and the D2 LED, which according to mentions around the
internet, should be glowing blue, no LED was lit. At first I thought I have
a faulty model, as it was bought off Aliexpress, so I ordered another one,
just to experience the same issue.
Then I tried to plug it into my ThinkPad T470 Arch machine and the blue D2 LED started glowing like there's no tomorrow. I then dual booted Windows 10 on the same machine and after a minute or so, windows updater picked it up, installed the driver and, again, blue LED was on. That meant something was off on my Mac. After a bit of searching I found a shady looking driver:
brew install --cask wch-ch34x-usb-serial-driver
With newer MacOS versions, including mine, it is also required to allow installing kernel extensions from given vendor in the settings and everywhere it is recommended to reboot after the installation. The blue LED was now on as well.
The serial device
With the driver on Mac installed and the blue D2 LED lit, next step is to determine the actual device the system has created for the communication. I could not find any good documentation on this however, so discovery here we go. Make sure the UART jumper is selected, unplug the CH341A device:
ls -l /dev/* > before.txt
Replug the device back:
ls -l /dev/* > after.txt
Compare the two:
diff before.txt after.txt
This results in the following on my system:
> crw-rw-rw- 1 root wheel 0x9000007 Feb 28 08:12 /dev/cu.wchusbserial1440
Thus the device is located at /dev/cu.wchusbserial1440
, but note that the
actual number can change over time. Test by reading the Arduino pro micro
ATmega 328P's signature:
avrdude -v -p m328p -P /dev/cu.wchusbserial1440 -c arduino -b 57600 -U signature:r:-:h
Which results in the following:
Avrdude version 8.0
Copyright see https://github.com/avrdudes/avrdude/blob/main/AUTHORS
System wide configuration file is /opt/homebrew/etc/avrdude.conf
User configuration file /Users/peterbabic/.avrduderc does not exist
Using port : /dev/cu.wchusbserial1440
Using programmer : arduino
Setting baud rate : 57600
AVR part : ATmega328P
Programming modes : SPM, ISP, HVPP, debugWIRE
Programmer type : Arduino
Description : Arduino bootloader using STK500 v1 protocol
HW Version : 2
FW Version : 1.16
AVR device initialized and ready to accept instructions
Device signature = 1E 95 0F (ATmega328P, ATA6614Q, LGT8F328P)
Reading signature memory ...
Writing 3 bytes to output file <stdout>
0x1e,0x95,0xf
Avrdude done. Thank you.
Note that we are now using aruidno
as a device, not ch341a
under the
-c
parameter. Also note that when using the bootloader mode, we need to
specify the baud rate of 57500. Programming is done the same way as with
the SPI mode:
avrdude -v -e -D -p m328p -P /dev/cu.wchusbserial1440 -c arduino -b 57600 -U flash:w:firmware.hex:i
Enjoy!
Links
- https://components101.com/ics/ch341-high-speed-usb-to-serial-chip-pinout-datasheet
- https://developer.apple.com/library/archive/technotes/tn2459/_index.html
- https://formulae.brew.sh/cask/wch-ch34x-usb-serial-driver
- https://gist.github.com/tspspi/2bd6a7dcf8f09e320f0d172de6dc622c
- https://github.com/WCHSoftGroup/ch34xser_macos
- https://www.codeweavers.com/support/forums/general/?t=27;forumc__=;msg=257754#c2
- https://www.eevblog.com/forum/beginners/usb-to-uart-ch341a-based-cannot-connect-win-11/msg4896038/#msg4896038
- https://www.onetransistor.eu/2018/02/program-arduino-pro-mini-with-ch341a.html
- https://dev.to/delusional/reading-avr-micro-controller-device-signatures-using-avrdude-command-line-program-1559