Electronics Software Development

Using The Arduino Command Line

Arduino Command Line
Written by John Woolsey

Skill Level: Intermediate

Introduction

This tutorial will teach you how to compile and upload Arduino sketches from the command line. A basic understanding of electronics and programming is expected along with some familiarity with the Arduino platform. If you are new to the Arduino platform or would just like to refresh your knowledge, please see our Blink: Making An LED Blink On An Arduino Uno tutorial before proceeding with this one.

I also created an Arduino Command Line Cheatsheet that you can download for future reference.

What Is Needed

Background Information

Although the Arduino IDE is a very nice, useful, and free integrated development environment for developing code within the Arduino platform space, sometimes you just want to use your tried and true code editor instead. Or perhaps you want to automate the build and release process through shell or batch scripting. Using the Arduino command line lets you do just that.

There are currently two methods available for building and managing your Arduino projects from the command line. The first is using the often overlooked command line functionality of the Arduino IDE itself. The other is a new purely command line tool named Arduino Command Line Interface (CLI) that was created by Arduino. It is currently only in the alpha release phase, but is planned to eventually be incorporated as the back-end processing utility into later versions of the Arduino IDE.

My development system consists of both the Arduino Uno R3 and the Arduino Uno WiFi Rev2 development boards connected to a macOS based computer with the desktop Arduino IDE. If you are using a different Arduino board or computer setup, the vast majority of this tutorial should still apply, however, some minor changes may be necessary.

If you need assistance with your particular setup, post a question in the comments section below and I, or someone else, can try to help you.

Board Names

Both command line methods utilize something called a Fully Qualified Board Name (FQBN) to distinguish among the various supported boards. Its format is defined as

<package>:<architecture>:<board>, where

  • <package> = vendor identifier; typically just arduino for Arduino boards
  • <architecture> = microcontroller architecture; e.g., avr, megaavr, sam, etc.
  • <board> = board name defined by the software; e.g., uno, uno2018, yun, etc.

For instance, the FQBN identifiers for my Arduino Uno R3 and Arduino Uno WiFi R2 boards are defined as arduino:avr:uno and arduino:megaavr:uno2018 respectively.

It is a bit convoluted to determine the FQBN for a board. First, we need to retrieve the board name from within the Arduino IDE. This is the board name chosen when selecting a board from Tools > Board: within the Arduino IDE main menu. Next, we need to inspect the hardware directory tree and boards.txt files installed with the Arduino IDE application. You will also need to inspect the location where your personal preferences are saved if you have additional boards installed. Vendors and architectures are defined by the directory structure. Board names are defined within the boards.txt files. On my Mac for example, the Arduino Uno R3 is defined in the

/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/boards.txt

file. We can discern the vendor is arduino and the architecture is avr by looking at the path. Searching for a board name of “Arduino/Genuino Uno” within that boards.txt file, we find the following entry that defines our board name with the uno identifier.

uno.name=Arduino/Genuino Uno

Hence, our FQBN becomes arduino:avr:uno. Easy peasy right? Don’t despair as this process will be much easier when using the Arduino CLI tool as shown later in this article.

Likewise, the Arduino Uno WiFi R2 board is defined on my Mac in

~/Library/Arduino15/packages/arduino/hardware/megaavr/1.6.26/boards.txt

with an entry of

uno2018.name=Arduino Uno WiFi Rev2

that makes our FQBN value arduino:megaavr:uno2018. Notice how the hardware and vendor directories are swapped in this location.

Arduino IDE Application

We will begin by using the command line functionality of the Arduino IDE itself.

We first need a way to execute the IDE application from the command line as opposed to just clicking on the application icon. The executable can be found in the Arduino IDE installation directory tree and is named arduino for Linux, Arduino for macOS, and arduino_debug.exe for Windows. When running the executable, we need to include the full path name in the command, make sure the path is in our path environment variable, or define some sort of alias or symbolic link to the executable. I chose to make an alias for the executable named arduino that will be used throughout the rest of this tutorial. We can test that it is working properly by running the following command within a command or terminal window.

$ arduino --version

Did you see the initialization screen pop up for a moment after the above command was run? Even though we are able to run the Arduino IDE from the command line, it is still inherently graphically based. We will continue to see this little window when running the various commands based on the Arduino IDE.

Part of our premise of being able to do our development on the command line involves creating a new program. The Arduino IDE does not have the command line capability for creating a program. This is not an issue, however, as we can just use our favorite text editor. Let’s do just that with a very simple blink style program.

Create a new directory named Blink_IDE, go into that directory, and then create a Blink_IDE.ino file using your text editor with the following contents. It is a simple program that blinks the built-in LED so that we can verify the uploaded code is running properly.

void setup() {
   pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
   digitalWrite(LED_BUILTIN, HIGH);
   delay(1000);
   digitalWrite(LED_BUILTIN, LOW);
   delay(1000);
}

Attach your board(s) to your computer’s USB port(s) if you have not done so already. Now run the following command to verify (compile) the program. You should see the familiar program compilation output.

$ arduino --verify Blink_IDE.ino

To upload and run the program on the board, use the following.

$ arduino --upload Blink_IDE.ino

Congratulations, we now have a blinking LED.

Before moving on, let’s “reset” our board to a bare minimum sketch. On your own, create and upload a very simple program with empty setup() and loop() functions to your board. The LED should stop blinking. This will help us ensure our next steps are running properly.

We are able to run the simple verify and upload commands shown above because a) our default board should already be saved from our normal Arduino IDE usage, and b) we do not need to specify the full path to the sketch file since we are already inside of the project folder. If you do not have a default board saved or use multiple boards, we need a little bit more specified. This is where the Fully Qualified Board Name (FQBN) that we discussed above comes into play. To distinguish among multiple boards, we need to include the board option to specify our fully qualified board names.

$ arduino --board <fqbn> --verify Blink_IDE.ino

where <fqbn> represents your board’s fully qualified board name. The following is what I use to compile code for my two boards.

Arduino Uno R3:      $ arduino --board arduino:avr:uno --verify Blink_IDE.ino
Arduino Uno WiFi R2: $ arduino --board arduino:megaavr:uno2018 --verify Blink_IDE.ino

Run the appropriate verify command for your board.

To upload programs, we also need to know which USB port(s) our board(s) are using. This information can be determined by opening the Arduino IDE and reviewing the port selection under Tools > Port from within the main menu. The upload command uses the following syntax.

$ arduino --board <fqbn> --port <port> --upload <path>/<sketch>.ino

The following is what I use to upload code for the two boards connected to my Mac.

Arduino Uno R3:      $ arduino --board arduino:avr:uno --port /dev/cu.usbserial-A6028SP5 --upload Blink_IDE.ino
Arduino Uno WiFi R2: $ arduino --board arduino:megaavr:uno2018 --port /dev/cu.usbmodem14202 --upload Blink_IDE.ino

Upload the code for your board and you should see the built-in LED blinking again.

I know it feels a bit odd to have to open the Arduino IDE in order run on the command line, but once we retrieve the information we need, we should no longer need to open it for general usage in the future. We can even save our default board preference so that we do not have to keep specifying the board and port options every time when using the same board. This is accomplished with the save-prefs option and below are my preferences.

Arduino Uno R3:      $ arduino --board arduino:avr:uno --port /dev/cu.usbserial-A6028SP5 --save-prefs
Arduino Uno WiFi R2: $ arduino --board arduino:megaavr:uno2018 --port /dev/cu.usbmodem14202 --save-prefs

You can even determine which board is currently set to be your default by running the following.

$ arduino --get-pref board

In my case, the command output will either show uno or uno2018 depending on the last preference I set.

Please see the Arduino IDE Man Page for additional details and general information on using the Arduino IDE from the command line. Try some additional command line options and see what you get.

Before moving to the next section, upload your bare program sketch again to “reset” your board.

Arduino CLI Tool

Now let’s turn our attention to the new Arduino Command Line Interface (CLI) tool. Download the tool for your particular operating system from the GitHub repository. This program is still in alpha phase so please keep in mind that some commands and options will probably change before the stable release. The executable name will be based on the OS and release phase. For me, that name was arduino-cli-0.3.6-alpha.preview-macosx. Since I don’t want to type that long name and path each time, I created an alias named arduino-cli that will be used throughout the rest of this tutorial.

Test that everything is working properly by running

$ arduino-cli version

and it should print the version information.

Before going any further, it is recommended that we update the core (platform) indexes each time we install a new version of the Arduino CLI tool. Cores are the platforms to which supported boards belong and define the first portion of the FQBN identifier, i.e., <package>:<architecture>. This process will update our configuration files with the latest information for the various supported boards. It is accomplished by running the following command.

$ arduino-cli core update-index

Now comes the fun part. Remember the struggle we had determining the FQBNs and ports for the boards above? Well with the Arduino CLI tool, it will automatically discover these parameters for you. Make sure your board(s) are connected and run the following command.

$ arduino-cli board list

Voila! We get a nice table listing the FQBM, port, and other board information for all of our connected boards.

If for some reason your board is not discovered properly, you may need to update the Arduino configuration by installing a platform core that supports your board. On my Mac for example, the Arduino Uno R3 was not found, so I had to run the following process to install it. The Arduino Uno WiFi R2 core had already been installed through the Arduino IDE when I originally set up the new board.

I used the following command to perform a search for all cores supporting uno boards

$ arduino-cli core search uno

which provided the following output.

Searching for platforms matching 'uno'

ID              Version Name
arduino:avr     1.6.23  Arduino AVR Boards
arduino:megaavr 1.6.26  Arduino megaAVR Boards

The first entry is the one I need. It just so happens the last entry is the one necessary for the Arduino Uno WiFi R2.

Next, I installed the core for the Arduino Uno R3 with the following command.

$ arduino-cli core install arduino:avr

We can verify which cores are installed with the

$ arduino-cli core list

command which provided the following output.

ID                     Installed Latest Name
arduino:[email protected]     1.6.23    1.6.23 Arduino AVR Boards
arduino:[email protected] 1.6.26    1.6.26 Arduino megaAVR Boards

All of the necessary cores are now installed for my boards. Make sure to do the same to install any core(s) necessary for your board(s).

Now back to our regularly scheduled programming. Yes, pun intended.

Ready to create a new project? The Arduino CLI tool has the capability of creating a new project for you with the

$ arduino-cli sketch new <sketch>

command where <sketch> is a placeholder for your sketch (project) name and does not include the path or the .ino extension. The reason for this is that the project is automatically created in your default sketch folder. Let’s go ahead and create the Blink_CLI project

$ arduino-cli sketch new Blink_CLI

and go into the project directory that it created to view the code. It created a file with only the setup() and loop() functions. You could have just as easily created your own project directory and enclosed .ino file anywhere you wanted with your favorite editor and the rest of the build process would work the same.

Edit the Blink_CLI.ino file to make it the same as the one we used for the Blink_IDE project.

To compile (verify) the code from within the project directory, we use the following command.

$ arduino-cli compile --fqbn <fqbn>

where <fqbn> represents your board’s fully qualified board name. I use the following for my boards.

Arduino Uno R3:      $ arduino-cli compile --fqbn arduino:avr:uno
Arduino Uno WiFi R2: $ arduino-cli compile --fqbn arduino:megaavr:uno2018

If you are not in the project directory, just append the full path name of the project directory to the command. Now run the appropriate compile command for your board. Again, you should see the familiar program compilation output.

Did you notice the files that were generated in your project directory? You should see new temporary build files whose names are based on the sketch name along with the fully qualified board name. The .elf file is the binary object created when your code is compiled by the compiler. The .elf file is converted to a standardized hexadecimal .hex file that is used to program AVR microcontrollers. There is no harm in deleting these files as they will be generated as needed. My project directory contains the following build files.

Blink_CLI.arduino.avr.uno.elf
Blink_CLI.arduino.avr.uno.hex
Blink_CLI.arduino.megaavr.uno2018.elf
Blink_CLI.arduino.megaavr.uno2018.hex

To upload the code to a board, use the following syntax with the optional sketch path.

$ arduino-cli upload --fqbn <fqbn> --port <port> [<path>/<sketch>]

This equates to the following for my boards on my Mac while within the Blink_CLI project directory.

Arduino Uno R3:      $ arduino-cli upload --fqbn arduino:avr:uno --port /dev/cu.usbserial-A6028SP5
Arduino Uno WiFi R2: $ arduino-cli upload --fqbn arduino:megaavr:uno2018 --port /dev/cu.usbmodem14202

Upload the code to your board and you should see the LED start blinking again.

You can view help at anytime by running the executable without any commands or options.

$ arduino-cli

To view all of the commands and options available, please see the GitHub README for additional details and general information on using the Arduino CLI tool. Try some additional commands and options and see what you get.

Before we end, we should upload a bare minimum sketch to the board like we did above to put all pins back to their default states. New sketches created by the Arduino CLI are bare minimum by default. On your own, create, compile, and upload a new sketch named Bare to your board.

Summary

In this tutorial, we learned how to use the command line with both the Arduino IDE application and the Arduino CLI tool. We learned how to create, compile, and upload sketches along with how to manage and configure certain aspects of our development environment. I only covered some of the capabilities that these command line programs provide. For instance, you are also able to install libraries from the command line if you so choose. Don’t forget to check out the documentation for each of the methods to learn more.

As we saw, there are some subtle differences between the Arduino IDE application and the Arduino CLI tool. The IDE uses the --board option whereas the CLI uses the --fqbn option. The IDE requires a path to your sketch file for building processes and the CLI does not. The IDE still pulls up graphical windows whereas the CLI is purely command line. The CLI leaves the .elf and .hex files in your project directory and the IDE does not not.

Thank you for joining me in this journey and I hope you enjoyed the experience. Please feel free to share your thoughts in the comments section below.

About the author

John Woolsey

John is an electrical engineer who loves science, math, and technology and teaching it to others even more.
 
He knew he wanted to work with technology from an early age, building his first robot when he was in 8th grade. His first computer was a Timex/Sinclair 2068 followed by the Tandy 1000 TL (aka really old stuff).
 
He put himself through college (University of Texas at Austin) by working at Motorola where he worked for many years after that in Research and Development.
 
John started developing mobile app software in 2010 for himself and for other companies. He has also taught programming to kids for summer school and enjoyed years of judging kids science projects at the Austin Energy Regional Science Festival.
 
Electronics, software, and teaching all culminate in his new venture to learn, make, and teach others via the Woolsey Workshop website.

Leave a Comment