Pololu wrote some code to interface the Raspberry Pi with the Arduino. It uses a Python web server to host a webpage on the Raspberry Pi. When it’s connected to your network, you can go to its IP address, and interact with the web page. Then, the Python web server sends and receives information from the Arduino over the I2C bus. Both the Raspberry Pi and the Arduino are connected with a few wires to make the I2C bus, so that they can share information.

The cool thing about this setup is that you can edit the Python web server quickly to change the web page without uploading to the Arduino with a USB cord (This takes some time). You could have new robot scripts just by editing what commands are sent to the Arduino, or by introducing a camera to dynamically recognize and follow objects!

Pololu’s guide has you download the Python code onto the Raspberry Pi and start running the server. This is great for setting up one time, but if you want to do a series of quick edits you’ll need some way to automate deploying code.

The process consists of

  • Logging into the server using SSH, a secure computer control protocol
  • Downloading code
  • Restarting the service

We can make that into one Python script that is run from another computer using Fabric. I think their website says what it is best: “Fabric is a high level Python (2.7, 3.4+) library designed to execute shell commands remotely over SSH, yielding useful Python objects in return.”

A Connection from the library lets you execute shell commands on the server.

# pi is the default username on the Raspberry Pi
# the number is the IP address of the Raspberry Pi
c = Connection("pi@192.168.1.109")

# This lists all the files in the home directory on the server
c.run("ls")

What we want to do is transfer files from our computer to the Raspberry Pi, then run a command to restart the Python code.

On the Getting started docs, there is a command, Connection.put(file), for transferring files. Because there are many Python files that make up the server functionality, I checked the put() docs which lead to the Transfer.put() docs. Unfortunately it seems that Transfer.put() or put() doesn’t support uploading files, so we have to implement that ourselves.

I was honestly too lazy to make a function to open a folder and manually upload each file, so I decided to compress the folder into a single file, then upload that. I knew of the Linux tar command, but I didn’t know exactly what arguments to provide so I used the man command in the shell, and judicious Google.

Here’s what I found out:

  • tar -cf archive.tar folder/ puts the folder/ into a compressed archive named archive.tar
  • tar -xf archive.tar -C folder/ extracts the compressed files from archive.tar and puts it in folder/

So the process for uploading a folder should look like this:

  • Make a compressed archive of the folder locally
  • Use the put() command to upload the compressed archive
  • Use the run() command on the Connection to extract the folder from the compressed archive
  • Delete the compressed archive locally
  • Delete the compressed archive stored on the server

From the Fabric docs, I learned that Fabric internally uses this library called Invoke to run commands, and Fabric does the SSH remote server stuff. I can use the run() command from Invoke to make the local archive and delete it.

This is the function I ended up with for uploading folders:

def upload(c, folder, destination):
    # Make a compressed archive locally
    run("tar -cf test.tar " + folder)

    # Put the compressed archive on the server at the destination
    c.put("test.tar", remote=destination + "test.tar")

    # Extract the archive's files into the destination folder
    c.run("tar -xf " + destination + "test.tar -C " + destination)

    # Delete the remote archive
    c.run("rm " + destination + "test.tar")

    # Delete the local archive
    run("rm test.tar")

Now all that needs to be done is run the upload() function, and restart the Python code. Running the shell command to restart the code requires sudo administrator priviledges, so I copied the sudo helper code from the Fabric docs to ask me for my password then securely use it on the server.

# Asks the user for the password, then safely stores it 
# Later when we restart the server it uses the sudo password
sudo_pass = getpass.getpass("What's your sudo password? ")
config = Config(overrides={'sudo': {'password': sudo_pass}})

# Had to setup a ssh key for this to work
c = Connection('pi@192.168.1.118', config=config)

# Upload the src/ folder to /home/pi/tank-drive/
upload(c, "src/", "/home/pi/tank-drive/")

# Uses the sudo password to get administrator priviledges
# Restarts the server like in the Pololu guide
c.sudo("systemctl restart a_star_slave")
c.sudo("systemctl restart a_star_heartbeat")

Hope you enjoyed it! The next post will focus on designing simple 3d printed gears using OpenSCAD.

Check out other posts in this series

Join me in learning about how computers work

Just enter your email into the box below. You'll also receive my free 12 page guide, Getting Started with Operating System Development, straight to your inbox just for subscribing.

Getting Started with Operating System Development Ebook

Where do I send your free guide to?