A quick glance at the projects I’ve posted on this website makes it evident that I prefer to use CircuitPython when programming microcontrollers. Adafruit and the community have done an exceptional job maintaining the language and releasing libraries for a wide variety of sensors and peripherals. You can iterate, troubleshoot and finalize a project considerably faster than when using something like Arduino, for example.

The Version Control Problem

Just like coding on a computer, CircuitPython would benefit from some form of version control, like git. However, since the code resides in the microncontroller’s internal memory, which is usually very limited, it doesn’t make much sense to keep a version control system on device. This leaves us with only one option: working off of a local folder in the computer and setup git there. Then, when ready to test, drag the appropriate files to the microcontroller. This, however, is a tedious process and doesn’t facilitate rapid prototyping.

(One) Solution

Chances are you are already on the terminal when working with git or CircuitPython, in general. Then, the simple solution I came up with is creating git repositories for each project on the computer and setup a script that only copies the appropriate files in the current folder to the microncontroller board, which usually shows as an external USB drive.1

Here is the script:

#!/bin/bash

# Text file holding filenames and folders to be excluded
excluded_files="excluded_files.txt"

# Use the current directory as the source folder
source_folder="."

# Check if the destination folder argument is provided
if [ -z "$1" ]; then
  echo "Usage: $0 <destination_folder>"
  exit 1
fi

# Set the destination folder variable to the first argument
destination_folder="$1"


# Check if destination folder exists
if [[ ! -d "$destination_folder" ]]; then
    echo "Error: destination folder not found."
    exit 1
fi

# Check if exclude file exists
if [[ ! -f "$excluded_files" ]]; then
    echo "-- Warning --" 
    echo "$excluded_files not found."
    echo "Copying all files..."
    exclude_option=""
else
    exclude_option="--exclude-from="$excluded_files""
fi

# Use rsync to copy files
rsync -avz --progress --delete "$source_folder/" "$destination_folder/" $exclude_option  

In summary, the script checks if the required argument - the destination folder - has been provided and then checks if it exists (i.e. controller board is mounted). Then, it verifies if the file excluded_files.txt, which lists the files and folders to be excluded, is present. With this information, it proceeds to copy the required files from the current folder to the mounted drive, deleting files that are not in the source/current folder.

The script must be made executable. Also, to be able to run it within any folder, it should by added to the computer’s PATH environment variable. The following lines show how to perform these two actions:

chmod +x send_to.sh
# Assuming script was placed in ~/Scripts:
export PATH="$PATH:$HOME/Scripts" 

Whenever files need to be copied from the current folder to the microcontroller board, just go to the CircuitPython project folder and type the following in the command line:

send_to.sh <board path>

Replace <board path> with the path to the connected microcontroller board (usually /Volumes/CIRCUITPY on a Mac).

This can be further automated by, for example, running the script every time a file is changed in the CircuitPython project folder. However, that may be conducive to errors when working with several microcontroller boards, so I rather do it manually. It only takes a second when autocomplete is enabled on the terminal.


  1. Assuming your board is a CircuitPython compatible board with native USB support. ↩︎