Programming an arduino remotely using UART4 on the BeagleBone Black

I’ve been wanting to combine my BBB with my Arduino hacking, specifically, I like to be able to program my arduinos remotely and the BBB seemed like the right tool for that. For example, right now I have an arduino clone (a JeeNode) attached to my weather station sensors up on the hill and it’s really nice to be able to sit inside in the evening and iterate on the arduino weather station code, being able to upload one code iteration after the other with just a few keystrokes. I also like to keep all my source code and compilation on my fast linux server in the basement and that’s not near any arduino…

What I wanted out of the BBB is a serial port with a DTR to program the arduino that doesn’t use the USB host port so I could use the USB port for a wifi dongle. After way too many hours I finally realized that there is no UART on the BB that has a usable DTR pin! The DTR pin is necessary to reset the arduino so a fresh sketch can be uploaded. So I did some foolin’ around and eventually discovered that I could use RTS as a substitute for DTR. That was the key to hooking up the arduino clone to the BBB and programming it (quick warning here: the JeeNode operates on 3.3v so I can hook it up straight to the BBB but if you’re using a std arduino you need level shifters to deal with the 5v vs. 3.3v logic levels!).

The second part is the remote programming. I could edit and compile on the BBB sitting up nexy to the weather station arduino but that’s not my cup of tea. I edit my sketches on my linux box with vi and then use a Makefile to compile, upload, and connect to the arduino console. If you’re using the IDE you will have to tweak things a bit. The solution I came up with is to run ser2net on the BBB, which is a daemon that accepts TCP connections over the network and “connects them through” to a serial port. It turns out that avrdude, the program used to upload sketches to the arduino can send the data to a remote TCP port. Sounds like a match!

So now come all the steps to make the above happen. If you just want to program arduino from your BBB you just need the serial port part. If you’re using a USB serial dongle you just need the ser2net part. In other words, you may not want exactly the same set-up as I have but I hope my description helps you get there.

Step 1: disable HDMI
I decided to use UART4 because the pins conflict with HDMI, which I don’t need since the BBB is far away from me. You could use UART1 just as easily with a few tweaks, then you don’t need to do step 1. The nice thing about UART1 is that all the pins are on the P9 connector. Mhhh, maybe I should indeed switch to that…

You will need to add a device tree overlay to your BBB to enable UART4 with RTS and you will need to disable the HDMI device trees (you don’t need to do the latter if you’re using UART1). To disable HDMI run the following shell commands as root (I’m using Ubuntu but I believe these work the same on Angstrom):

mkdir /mnt/card; mount /dev/mmcblk0p1 /mnt/card
sed -i -e ‘/^optargs/ s/$/ capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN/’ /mnt/card/uEnv.txt
grep optargs /mnt/card/uEnv.txt

You should see something like this:

optargs=fixrtc capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN
Reboot your BBB so it comes up without HDMI (I’m assuming your logged in remotely).

Step 2: enable RTS on UART4
Now comes the device tree overlay for the UART. Download the attached BB-UART4-RTS-00A0.dtbo compiled tree or compile your own version from the attached source in BB-UART4-RTS.dts. You can find other overlays on the web to enable RTS on other uarts. Copy the dtbo file into /lib/firmware and then run:
echo BB-UART4-RTS >/sys/devices/bone_capemgr.*/slots

dmesg | tail
cat /proc/tty/driver/OMAP-SERIAL
You should see something like this:

[ 96.571871] bone-capemgr bone_capemgr.9: part_number ‘BB-UART4-RTS’, version ‘N/A’
[ 96.572057] bone-capemgr bone_capemgr.9: slot #7: generic override
[ 96.572106] bone-capemgr bone_capemgr.9: bone: Using override eeprom data at slot 7
[ 96.572156] bone-capemgr bone_capemgr.9: slot #7: ‘Override Board Name,00A0,Override Manuf,BB-UART4-RTS’
[ 96.572424] bone-capemgr bone_capemgr.9: slot #7: Requesting part number/version based 'BB-UART4-RTS-00A0.dtbo
[ 96.572477] bone-capemgr bone_capemgr.9: slot #7: Requesting firmware ‘BB-UART4-RTS-00A0.dtbo’ for board-name ‘Override Board Name’, version ‘00A0’
[ 96.584137] bone-capemgr bone_capemgr.9: slot #7: dtbo ‘BB-UART4-RTS-00A0.dtbo’ loaded; converting to live tree
[ 96.584779] bone-capemgr bone_capemgr.9: slot #7: #2 overlays
[ 96.599426] 481a8000.serial: ttyO4 at MMIO 0x481a8000 (irq = 61) is a OMAP UART4
[ 96.602062] bone-capemgr bone_capemgr.9: slot #7: Applied #2 overlays.

serinfo:1.0 driver revision:
0: uart:OMAP UART0 mmio:0x44E09000 irq:88 tx:61 rx:0 RTS|CTS|DTR|DSR
4: uart:OMAP UART4 mmio:0x481A8000 irq:61 tx:0 rx:0 CTS|DSR

The first chunk shows that the overlay got loaded and the second that UART4 is now available and has CTS (ignore the fact that it doesn’t say RTS too)

Step 3: hook your arduino up to the BBB
You will need to hook the serial port up to the FTDI connector of the arduino. Warning: for a normal arduino running at 5v you will need a level converter for the RXD, TXD, and RTS signals. My JeeNode runs at 3.3v so I don’t need that. The connections I made:

  • GND on P9 pin1 to FDTI pin 1
  • SYS_5V on P9 pin 7 to FTDI pin 3
  • UART4_RXD on P9 pin 11 to FTDI pin 5 (needs level conversion on std arduino)
  • UART4_TXD on P9 pin 13 to FTDI pin 4 (needs level conversion on std arduino)
  • UART4_RTS on P8(!) pin 33 to FTDI pin 6 (needs level conversion on std arduino)
    In order to see what’s going on I also connected a small LED with a 150 Ohm resistor between the RTS line and 3.3v (P9 pin 3). This LED comes on when avrdude uploads the sketch and then goes off again. It comes on again when I connect to the console but doesn’t turn off when I disconnect, sigh. But good enough to see that something’s happenin’.

Step 4: install and configure ser2net
With ubuntu the installation is as easy as
apt-get install ser2net
and then you need to edit /etc/ser2net.conf. Scan through the comments in that file and get to the end where the sample lines are. Comment out the telnet ports that are there and set two up for your arduino. I am using ports 2000 and 2001 but you can use any you like that are otherwise unused. Here’s the end of my config file (oops, looks like the first line may be wrapping):

2001:telnet:600:/dev/ttyO4:57600 8DATABITS NONE 1STOPBIT banner

#2000:telnet:600:/dev/ttyS0:9600 8DATABITS NONE 1STOPBIT banner
#2001:telnet:600:/dev/ttyS1:9600 8DATABITS NONE 1STOPBIT banner
#3000:telnet:600:/dev/ttyS0:19200 8DATABITS NONE 1STOPBIT banner
#3001:telnet:600:/dev/ttyS1:19200 8DATABITS NONE 1STOPBIT banner

A few things to note here:

  • I use port 2000 to upload sketches to the arduino using 115200 baud, I believe that’s standard. The LOCAL and HANGUP_WHEN_DONE flags tell ser2net to reset the uart, which is what will cause RTS to toggle and thereby reset the arduino.
  • I use port 2001 to connect to the serial output/console of the sketch. I’m running that at 57600 baud for some obscure reason, you will need to use the speed you set in your sketch. This port doesn’t have the extra flags so I can connect to the running sketch at any time without resetting the arduino.

You can now test ser2net. But first you need to start it. On Ubuntu it comes with an init file in /etc/init.d so you can fire it up:
service ser2net start
Now load some sketch that prints something on a regular basis to the console using your normal means and hook it up to the BBB. On the BBB type:
nc localhost 2000
Your arduino should reset and you should see your sketch output if it’s running at the right baud rate or some garbage if it’s not. Exit with Ctrl-C and type:
nc localhost 2001
Now you should be connected with the correct baud rate (if you configured things right) and see more output from your sketch. Again, hit Ctrl-C to disconnect.

Step 5: remote compilation and upload
I use edam’s Arduino makefile to compile my sketches on my linux server and then upload them to the remote arduino. Unfortunately a small patch is necessary. Edit the Makefile (I have version 0.5) and around line 338 make this one-line change:

BB-UART4-RTS.dts (1.39 KB)

BB-UART4-RTS-00A0.dtbo (897 Bytes)

This is very helpful. I’ve been playing around with it a bit and have had some trouble getting it to respond, however. Avrdude says:

Using Port : /dev/ttyO4
Using Programmer : arduino
Overriding Baud Rate : 115200
avrdude: ser_recv(): programmer is not responding
avrdude: stk500_recv(): programmer is not responding

I’ve got pin 11 on the BBB to ‘D0’ on the arduino, and pin 13 to D1, then the RTS pin on BBB to RESET on arduino. I’ve tried that, and through a 10nF capacitor, the difference being that the latter performs a momentary reset, while the former freezes the arduino through the duration of the avrdude command. The current sketch on the arduino is an LED string test, so I can easily see when the Arduino resets or freezes. I have tested the ttyO4 against ttyO1, and it seems to work fine, so I am left wondering if certain Arduino bootloaders don’t allow serial programming (???).

I should add that I am running the arduino at 3.3v, and directly connecting the bbb pins. This seems to be how you are doing it as well, though talk of the FTDI port had me confused for a second as mine doesn’t have one.

I have also verified with a simple serial sketch that bidirectional communication works between the bbb and arduino in this wiring scheme. It just doesn’t seem that avrdude wants to speak over it, or isn’t communicating with the bootloader on reset.

This is the script I used to upload to an ATmega328p, 3.3V, 8Mhz on

In the avrdude line I specify 57600, which works well for me. The
OpenROV cape uses an attached ATmega like this and so does the


1 Like

Thanks. I think it’s a bootloader issue (wrong fuses or something), as it starts immediately. Admittedly I’m not using a bona-fide Arduino, but a factory atmega chip I installed the bootloader on myself. I see your script issues a reset and then waits a fraction of a second, mine would already be running.

I ended up utilizing the linuxgpio programming in avrdude, with the advantage that I can program chips with nothing on them, using any arbitrary gpio pins.