Ssh – How would/do I access/program a remote Arduino through SSH via an intermediate computer

arduinolinuxssh

I have Arduino IDE installed on my laptop and I'd like to program a remote Arduino (Uno) that is connected to a remote machine in the same network, say, for instance, a Raspberry Pi (to which the Arduino Uno would be plugged with the USB cable) connected to my wireless network. What would I need to set up to do that?

Note: I don't mean to use the Arduino as a SSH client. What I'd like to do is some kind of tunnelling, preferably SSH, between Arduino IDE on my laptop and the Raspberry PI, to which the Arduino board is connected with the USB cable.

Ideally what would happen when I press the Upload button is that the firmware, compiled locally would then be sent to the remote Arduino through the tunnel. Also I would use the serial monitor to remotely connect to the /dev/ttyACM0 device node on the remote Pi.

Best Answer

Lacking a usb device proxy (usbip as of Feb 2016 does not appear to be very portable) another method is to install avrdude on the Arduino-connected system (REMOTE). If this is possible, then the Arduino IDE running system (CLIENT) can be instructed to call a program that connects to avrdude on REMOTE. Downsides: requires fiddling around in the Arduino IDE configuration files, probably fragile, will require additional work to support things like arduinoOTA and so on...

CLIENT (Arduino IDE) -> ssh -> REMOTE (avrdude) -> usb -> arduino

The Arduino IDE should contain programmers.txt and platform.txt configuration files (located for example under Arduino.app/Contents/Java/hardware/arduino/avr on the mac version). What we need in these files is a new programmer that will make a connection to REMOTE and pass along the data to upload, and then on REMOTE to issue the actual avrdude programmer command using the data passed from the CLIENT system.

CLIENT programmer

In Java/hardware/arduino/avr/programmers.txt add something like

avrrelay.name=AVR RELAY
avrrelay.protocol=stk500v2
avrrelay.program.tool=avrrelay
avrrelay.program.extra_params=

More complicatedly, in Java/hardware/arduino/avr/platform.txt duplicate all the tools.avrdude. containing lines and adjust these to instead be named tools.avrrelay. and where necessary instead call avrrelay-client (most of these lines are not necessary but it's probably easier to sub all of them than to figure out which are necessary):

tools.avrrelay.path={runtime.tools.avrdude.path}
tools.avrrelay.cmd.path={path}/bin/avrrelay-client
tools.avrrelay.config.path={path}/etc/avrdude.conf
... many more of these not shown, e.g. the verbose one ...
tools.avrrelay.upload.pattern="{cmd.path}" "{build.path}/{build.project_name}.hex"
tools.avrrelay.program.pattern="{cmd.path}" "{build.path}/{build.project_name}.hex"

Then in the Java/hardware/tools/avr/bin directory (which should be identical to the runtime.tools.avrdude.path config option) create avrrelay-client and make it executable:

#!/bin/sh
# send the only argument (which should be the *.hex file) to avrrelay-remote
# this will need to use public key auth, or expect to automatically fill
# in any password promptes
ssh theremotehost avrrelay-remote < "$1"

REMOTE script

The Arduino IDE has a preference option to show verbose output during the upload, which will reveal the command that is run.

/Applications/Arduino.app/Contents/Java/hardware/tools/avr/bin/avrdude \
-C/Applications/Arduino.app/Contents/Java/hardware/tools/avr/etc/avrdude.conf \
-v -patmega328p -cstk500v2 -Pusb \
-Uflash:w:/blablabla.../Blink.ino.hex:i 

This command can be copied and adapted for the code on REMOTE, though avrdude(1) indicates that a filename must be specified, so the copied data will need to be placed in a tmp file, and that fed to avrdude; this is the avrrelay-remote program called by the CLIENT; it will need to be chmod +x and called by full path or located in a SSH-available PATH directory.

#!/bin/sh
FLASH=`mktemp /tmp/avrrelay.XXXXXXXXXX` || exit 1
# assume data passed via standard input
cat > "$FLASH"
# these flags will vary depending on programmer, etc
avrdude -C /path/to/avrdude.conf -v -patmega328p -cstk500v2 -Pusb \
"-Uflash:w:$FLASH:i"

In theory, restart the Arduino IDE and try using the new "AVR RELAY" programmer. Use your mad debugging skills to figure out where it breaks down, repeat.

remote serial monitor

For the serial monitor to work remotely, a likely option would be to forward that via socat:

Unbuffered socat command to connect serial ports in remote machines and log the data