PlatformIO (https://platformio.org/), which is both a command-line version and can be used to convert your favorite text editor into an IDE to develop Arduino software – if your favorite editor is Atom or VSCode/VSCodium, that is, but fear not. It can also be used to create project files for a number of popular IDEs.
The all-new Arduino CLI, (https://github.com/arduino/arduino-cli), which is still in its alpha release status but which is available and surprisingly usable. This is proposed as a compilation replacement for the current Java-based IDE in a forthcoming version, but is specifically designed to be used in make files.
Bear in mind that the latter is in its alpha release status, so is likely to change as time passes.
6.1 PlatformIO
PlatformIO is a system which allows you to write, compile, and upload programs to your Arduino board, either in plain Arduino format – as you are used to in the Arduino IDE – or in plain vanilla AVR C/C++ format, which removes the hand holding that you get from the Arduino IDE and only sets up and runs the code that you write. There is no millis() function, for example – you are on your own.
PlatformIO Core – Which installs command-line utilities.
PlatformIO IDE – Which installs an IDE-style plugin for the Atom editor and also for the Visual Studio Code editor. Other IDE systems, Eclipse or Code::Blocks, for example, don’t have plugins as such, but the pio command can generate project files for those IDEs to allow you to develop AVR code in a familiar IDE environment.
6.1.1 Installing PlatformIO Core
PlatformIO Core runs in a bash shell, but don’t panic. There are IDE versions if you wish to use one; however, I think it’s better to understand what is happening before heading off to a GUI tool – you never know when you will be without a GUI.
This requires Python 2.7 as, currently, no other versions are able to be used. If you have Linux, as I do, the chances are that Python 2.7 is already installed alongside Python 3.
The response needs to be something like Python 2.7.x; Python3 does not yet work.
Don’t worry if you already have Python version 3.x installed. This command shouldn’t overwrite your Python 3 installation as, on all the systems I’ve looked at, it is known as python3 when installing and when executing code written in version 3 syntax.
You might see warnings informing you that the bottle and/or symantic-version wheels cannot be built. Don’t worry about this. As long as you see the following, or something remarkably similar at the end, you are good to go:
Successfully installed bottle-0.12.13 certifi-2018.8.24chardet-3.0.4 click-5.1 colorama-0.3.9 idna-2.7platformio-3.6.0 pyserial-3.4 requests-2.19.1semantic-version-2.6.0 urllib3-1.23
You can see that both bottle and symantic-version were installed, regardless of the errors listed.
6.1.2 Testing PlatformIO Core
The commands pio and platformio are now installed, in my case to /home/norman/.local/bin, and both are actually the same thing. Because I’m lazy, I use the shorter version, pio. Feel free to use the longer version if this appeals to you.
6.1.2.1 Set Up Your Environment
This will add you to the desired group when you next log in, so log out and log back in again. This isn’t Windows, so you don’t have to reboot! Once logged in, make sure you are now a member of dialout as mentioned.
Using an ICSP Programming Device
If you intend to use an ICSP device, rather than the Arduino bootloader, then you will need to download the appropriate udev rules file from https://github.com/platformio/platformio-core/blob/develop/scripts/99-platformio-udev.rules and copy it, as root with sudo, to /etc/udev/rules.d so that the programmer will be recognized and permissions given to allow your user (any user actually) to upload programs to the Arduino board.
In my setup, I originally had a few difficulties with the ICSP device, both in the Arduino IDE and using PlatformIO, so I had to edit the downloaded rules file as follows for my USBtiny ICSP device.
Setting the group to plugdev allows anyone in that group to use the device. I could have set it to dialout I suppose, but I’m sure that the relevant document outlining the solution to my (long forgotten) problem said to use plugdev.
It is a minor annoyance that if you have to make changes to this file, every time that you compile some code with PlatformIO, it will warn you that the file is missing or out of date and must be reinstalled. This appears in the output for the compilation and not, thankfully, as a pop-up.
Now, if your Arduino board is connected to the computer, you must unplug it and plug it back in to pick up the changes.
None of this is necessary if you only intend to use the bootloader built in to the Arduino.
If you do intend to use a programmer, then you must be aware that any time you program the Arduino with such a device, the AVR microcontroller will be erased completely and you can no longer use the bootloader as it has been overwritten.
You can, thankfully, restore the bootloader, either with PlatformIO (see in the following) or with the Arduino IDE – just pick your board and programmer in the normal manner and then go to Tools ➤ Burn Bootloader, and it will be restored. You will, of course, have to use the ICSP device to burn the bootloader, for obvious reasons!
6.1.2.2 Set Up a New Project
In order to save wrapping text around, I’ve trimmed the excess from the preceding output. The output also lists a description of the setting name, which is useful.
The previous setting is listed, at the end of the line, in square brackets, but is not shown here.
PlatformIO has the idea of a default location for projects, but strangely, it is not used except in PlatformIO Home which is a browser-based pseudo-IDE, which is discussed later on in Section 6.1.5, “PlatformIO Home.”
When creating new projects, you must be located in the folder or directory where you wish to create the new project. The pio init command creates all its files right where you are currently located – so beware.
The output text has a lot more information – but it’s far too wide for the page, so I’ve trimmed it of irrelevant detail.
As I’m using the latter version with the ATmega328P, I need to initialize the new project with the diecimilaatmega328 board name. If you have an Arduino Uno, the process is similar, but has many more results. You should be looking under the Platform: atmelavr for your Uno, which will be called uno.
There is no need to install any tools, compilers, etc. for the various boards as PlatformIO will do this automatically for you if it detects that you are using a board for which no tools yet exist.
Unfortunately, it doesn’t use the existing tools that were installed by the Arduino IDE, so you may end up with two separate versions of the AVR compiler and so on. This is not a major problem and does mean that when you decide to continue writing Arduino code using PlatformIO, instead of the Arduino IDE, you can simply uninstall the Arduino stuff and still be able to compile with PlatformIO.
6.1.2.3 Initialize the Project
The following example sets up a new project for the Duemilanove board which I’m using. You can also create the same project for numerous boards. To show how this can be done, I’ll create the project for an Arduino Uno as well as my Duemilanove.
If you accidentally forget to initialize a second or subsequent board, you can easily do it by making another call to pio init --board with the additional board(s). Those new boards will be added to the current project.
pio init --board diecimilaatmega328 --board uno
After a very short delay, the screen will be filled with useful information about the new project and a list of commands to compile, upload, and clean the project files.
platformio.ini is a file that holds all the configuration for the project. Any changes you make to this file will only affect the project in the current directory – but all environments may be involved. The file itself contains settings for all the boards with which the project was initialized. Listing 6-1 shows the default file in full.
include is a folder expected to be used for any header files for your project. These are the *.h files.
src is a folder where you are expected to save all the C/C++ files that make up the project.
lib is a folder where any libraries, private to this project, should be saved or copied. A readme.txt file is also created within this directory explaining how it should be used.
Some commands are displayed as examples of how to build and upload sketches to the board. However, these assume that you will be using the normal Arduino bootloader to do the uploading.
Now I can compile for the Duemilanove with the name 2009 instead. It’s easier to remember and less typing too.
Example platformio.ini file
From version 4.1.0 onward, it appears that the uploader line is no longer required, just the upload_protocol line. I assume (always a bad idea) that the protocol gives PlatformIO all the detail it needs to determine the uploader device.
It does no harm to leave the line in; however, you will receive a warning at upload time if you do. I’ve simply commented mine out with a leading semicolon to disable the warning message.
Also available in recent versions is the ability to extract common lines to a separate section and just add in the specific lines for the environments in your file. This is not shown here.
You can now run pio run -e 2009 -t upload to upload using the bootloader or the preceding command to use the ICSP device. Be aware that once you have used the programmer, you no longer have a bootloader and cannot then use pio run -t -e 2009 upload to upload. You must always use pio run -t -e 2009_programmer program – until you recreate the bootloader of course.
I suppose we need to create the ubiquitous Blink sketch now?
6.1.2.4 Arduino-Style Projects
As mentioned earlier, PlatformIO allows you to continue using the Arduino Language in your projects. This section will explain how the Blink sketch can be converted and compiled in the new environment.
Arduino blink sketch
① You normally do not need to do this in the Arduino IDE, but in PlatformIO, you must.
② This is just a safety check to ensure that the built-in LED has been given a name in the Arduino.h file. In most cases, it has been done, but it’s always best to check and avoid any compilation errors that may arise.
As you see, apart from adding one line, nothing has changed. You can now use your favorite text editor to write code for your Arduino.
6.1.2.4.1 Compiling Arduino Projects
Compile the preceding code by first making sure that you are located in the directory where the file platformio.ini exists. If you have changed into the src directory to edit the file as in the preceding text, then please change back up one level.
① This line summarizes the platform and board in use. In this case, the platform is Atmel AVR, and the board is a Duemilanove (even though I renamed it to 2009 in the platformio.ini file).
② This line summarizes the capacity of the chosen device.
③ The PlatformIO dependency finder goes hunting for anything that it thinks needs to be included in this compilation. I removed the URL that’s normally listed here to get the line on the page.
④ This is the number of files and others that the finder thinks are required.
⑤ The system is looking for any dependencies here. It decided that there were none.
⑥ This is where my source file got compiled. Your file name should appear here too.
⑦ Do you recognize these file names? They are all the files that are included by default when you compile an Arduino sketch in the Arduino IDE.
⑧ All the Arduino code is statically linked to the elf file. This will be converted to a hex file for uploading.
⑨ The hex file is the one that will be uploaded to the Arduino board. It has only been compiled at present, not yet uploaded.
➉ The memory usage section shows that this Arduino sketch used 9 bytes of RAM and 928 bytes of flash program memory. This is standard for the default Arduino Blink sketch. The blank spaces between the square brackets here look pointless; however, when you compile large sketches, this shows a histogram of the amounts of Static and Flash RAM used.
① The “SUMMARY” shows that this compilation only affected the 2009 environment/board and that the uno was not touched.
On the first compilation of any target device, PlatformIO will download the required toolchain. In my example, it downloaded the gcc-avr compiler toolset. This already exists under my Arduino IDE installation, but is sadly not found or used by PlatformIO.
6.1.2.4.2 Uploading Arduino Projects
Don’t forget that you need to edit the platformio.ini file if you want to use a programmer instead of the bootloader – see preceding text.
You should note that in the absence of an -e option, all environments/boards in the current project will be compiled and uploaded. This is best avoided as you could end up with Uno code uploaded to your Duemilanove, which may not work correctly – it depends on which board is attached to the USB at the time.
It appears that you will always see the following message until you install the requested file or if it has been installed but has been modified from the released file:
Warning! Please install 99-platformio-udev.rules and check that your board’s PID and VID are listed in the rules. http://docs.platformio.org/en/latest/faq.html#platformio-udev-rules
This can be a little irritating, but if anything goes wrong with the upload, at least you have a couple of clues as to what to check. It’s especially irritating as the file is only required for ICSP devices. Using a bootloader only requires that your user be in the dialout group.
You should be able to see the built-in LED flashing away merrily in the usual manner.
So that’s how easy it is to create Arduino-style projects using the command-line versions of the PlatformIO Core code. I admit that it would be nice to have an IDE, even one as simple as the Arduino IDE, so later on, in Section 6.1.4, “PlatformIO in an IDE,” I’ll explain how easy it is to add PlatformIO features to one of a number of existing IDEs.
In the meantime, the next section shows how to create the Blink sketch as a plain AVR C/C++ program.
Create a new project in the usual manner.
Edit the platform.ini file and make sure that the Arduino framework is listed.
Copy the existing Arduino project’s ino file into the src folder.
Edit the ino file and add the line #include "Arduino.h" at the top.
6.1.2.5 AVR-Style Projects
The preceding project used the standard Arduino Language and compiled down to a hex file the same size as you would have seen if the Arduino IDE had been used instead. You can, however, go commando and bypass the entire Arduino system, as shown in the following. Remember, however, that it is your responsibility to make all the decisions about ports, pins, and so on.
If you are still in the TestProject directory, change back up one level to the standard location for PlatformIO projects. Then create a new project similar to the previous one. I’m not using an additional uno variant this time, but there’s no reason that you cannot use “uno,” for example.
Remember this is no longer an Arduino board; it’s a plain vanilla Atmel AVR development board – it just happens to look like an Arduino!
The new platform.ini file
You can hopefully see that I’ve also deleted the line framework = arduino as this is no longer required for plain AVR programming. Leaving it in will cause all the Arduino files to be compiled regardless of the fact that they are not used.
Yes, the actual physical board is an Arduino of some kind, but it is now being used as an AVR development board instead of an Arduino.
Another blink sketch
① This brings in the correct settings, register names, pin numbers and other definitions for the particular AVR microcontroller in use.
② We need this to enable us to call the _delay_ms() function (delay in milliseconds).
③ This is effectively pinMode(13, OUTPUT). Digital pin 13 is on PORTB and is bit 5 of that port.
④ This delays for 1 second.
⑤ Pin toggling is carried out by writing a 1binary to the appropriate bit in the PIN register for the pin to be toggled.
⑥ We never get here, but because main() is always declared as returning an int, then the compiler complains if we leave this off. There are other ways to silence the compiler, but this is the easiest, in my opinion.
6.1.2.5.1 Compiling AVR Projects
① This line summarizes the platform and board in use.
② This line summarizes the capacity of the chosen device. You may notice that it appears to have an extra 1.5 Kb of flash over the Duemilanove that I used previously. This is using the Uno bootloader which is smaller, by 1.5 Kb.
③ The PlatformIO dependency finder goes hunting for anything that it thinks needs to be included in this compilation. The URL (not shown) that would normally be on this line is that of the documentation for the Library Dependency Finder. I removed it to fit the page width.
④ This is the number of libraries that the finder thinks are required. It says nothing else will be required.
⑤ The system is looking for any dependencies here. It decided that there were none.
⑥ This is where my source file got compiled. Your file name should appear here too.
⑦ The code is first compiled into an elf file. This will be converted to a hex file later.
⑧ The hex file is the one that will be uploaded to the Arduino board. It has only been compiled at present, not yet uploaded.
⑨ The memory usage section shows that this Arduino sketch used no RAM and only 158 bytes of flash program memory.
In bare-bones AVR code, the standard blink sketch takes 158 bytes of flash program memory rather than the Arduino’s 928. It also does not create any variables in RAM.
6.1.2.5.2 Uploading AVR Projects
Remember to edit the platformio.ini file if you want to use a programmer instead of, or as well as, the bootloader – see preceding text.
The output from the upload is very similar to that when an Arduino-style project is uploaded, so has not been reproduced here.
The plain AVR style of programming takes less time to compile as it is not required to compile all the Arduino support code – what you see in the program is what you get.
Those readers who are slightly ahead of me here will realize that this means that you don’t get things like millis() and micros(),Timer/counter 0 Overflow interrupts, or even interrupts enabled when you compile an AVR-style project. Everything you need, you have to enable. The Arduino does a heck of a lot of stuff in the background to make your life easy.
I wish I had £1.00 (about $1.28 currently) for every project that didn’t work initially because I forgot to enable interrupts!
You should now be able to see the built-in LED flashing away merrily in the usual manner, but this time, using far fewer bytes of flash – 158 as opposed to 928 – and even better 0 bytes of scarce Static RAM for variables, as opposed to 9 bytes previously.
6.1.3 Burning Bootloaders
Edit the platformio.ini file and add the lines required to use an ICSP device, rather than the bootloader, to do the uploading.
Run the command pio run --target bootloader to do the burn.
As mentioned, you will have to use an ICSP device, or a spare Arduino to use as an ISP, but it does work and is simple. The current version of the arduino-cli, 0.6.0 (see Section 6.2), does not yet have the ability to burn a bootloader.
So that’s a very brief introduction to the PlatformIO system on the command line. As promised, I shall now demonstrate how you can install PlatformIO so that you can use an existing IDE to develop code for your Arduino boards – be that in Arduino Language or plain AVR C/C++ – the choice is yours.
6.1.4 PlatformIO in an IDE
You have seen how PlatformIO can be used in the command line, but let’s face it. It’s not an easy task switching from the editor back to the command line to compile, then back to the editor to fix, and so on. Some Linux editors do allow you to open a terminal within the editor, so that’s handy. However, wouldn’t it be nice to add PlatformIO to our current favorite development IDE?
There is a variant of PlatformIO which is named PlatformIO IDE and this is used as a plugin for, among others, the Atom editor (https://atom.io/) or the VSCode editor (https://code.visualstudio.com/).
The VSCode editor apparently feeds some data back to Microsoft. People are upset about this, and as the code for VSCode is open source, a variant of VSCode without the telemetry has been created. This is named VSCodium and can be obtained from https://github.com/VSCodium/vscodium/releases/latest if you don’t want data fed back to Microsoft.
Having said that, the PlatformIO IDE Integration page at https://docs.platformio.org/en/latest/ide.html gives details on using PlatformIO Core (yes, Core, not IDE) to create project files for various IDEs. For the rest of the PlatformIO section of the book, I’ll be looking at Code::Blocks (http://codeblocks.org/) as that’s an IDE that I use on Windows (at work) and on Linux.
These are the various options that the command accepts. Look at the --ide options. There are facilities for PlatformIO to create project files for a number of IDEs such as Eclipse, QT Creator, Code::Blocks, etc. I’m a big fan of QT Creator and Code::Blocks, so let’s set up a project for Code::Blocks.
I have recently noticed that QT Creator projects don’t compile properly. This is due to the AVR version of the g++ compiler not being correctly configured into the project file. Unlike Code::Blocks, which does include the compiler in the project settings, QT Creator doesn’t. You have to pick it manually in the settings to use the AVR version of g++.
There’s no other software that you need to install. The PlatformIO Core software has everything you need to integrate into one of the many supported IDEs.
6.1.4.1 Set Up a New Code::Blocks Arduino Project
Once the command has completed, you will be able to find the usual files and folders as previously; however, in addition, there will be a platformio.cbp file – a Code::Blocks project file.
Open the Code::Blocks IDE as usual and select File ➤ Open, navigate to the directory where the project was just initialized within, and open the project file platformio.cbp in the normal manner.
This time, it doesn’t matter that the environment has such a long-winded name. I’ll never be referring to it again. Please also note that in this case I’m not intending to use the programmer – I’ll be using the normal Arduino bootloader to program my board this time, but the process of setting up the ICSP is as before.
Click File ➤ New to add a new file. Select “Blank File” when prompted, and then choose to add it to the project. You will have to save the file first, so make sure that you select the src directory and save the file as Blink.cpp as usual.
Code::Blocks blink sketch
Now click the build button – it looks like a cogwheel – or click Build ➤ Build or press Ctrl+F9 to compile the code. The build log tab at the bottom should fill with the usual text.
When it compiles cleanly, it’s ready to be uploaded. This is done by clicking the run button (the green arrow), clicking Build ➤ Run, or pressing Ctrl+F10.
A new window will open, and the normal PlatformIO text that we are by now used to will scroll up the screen. Your Arduino board has now been programmed and should once more be blinking. Press Enter in the newly opened window to close it and return to the IDE.
6.1.4.2 Set Up a New Code::Blocks AVR Project
It is just as simple to create a new project to code in plain AVR C/C++.
Open the platformio.ini file within the Code::Blocks IDE as normal and delete the last line that says framework = arduino – we don’t need it. You may also add the lines to use your programmer, if necessary. I’m again using a bootloader in this example.
As before, click File ➤ New to add a new file. Select “Blank File” when prompted, and then choose to add it to the project. You will have to save the file first, so make sure that you select the src directory and save the file as Blink.cpp as usual.
Another blink sketch.
Now click the build button, click Build ➤ Build, or press Ctrl+F9 to compile the code. When it compiles cleanly, it’s ready to be uploaded. This is done by clicking the run button (the green arrow), clicking Build ➤ Run, or pressing Ctrl+F10.
A new window will open, and the normal PlatformIO text that we are by now used to will scroll up the screen. Your Arduino board has now been programmed and should once more be blinking. Press Enter in the newly opened window to close it and return to the IDE.
You should be aware that there isn’t, apparently, an option to determine the environment/board to be compiled and programmed when using the IDE in this manner. At least, I’ve not been able to find one! So don’t go adding numerous boards to your project file at creation time.
Also, as before, when programming your device with an ICSP device, you will need to edit the platformio.ini file to suit your programmer.
6.1.5 PlatformIO Home
After a short delay, the default browser on your system should open at the page http://localhost:8008, and an IDE-alike screen will be waiting for you.
The pio home command will hang up the session it was opened in until closed by pressing Ctrl+C. If you do this while the browser is open, then the browser will stop responding as the HTML server has just been "crashed."
When you are finished in the "pio home" page, close it in the browser and then shut down the server by pressing Ctrl+C in the session you typed the pio home command.
On this browser screen, you can search for boards, libraries, etc. and install them. You can add new or update existing platforms and so on. However, this is where you can create new projects without needing to remember all those pio init commands and options.
6.1.5.1 Creating Projects
Click the “New Project” button, and on the following dialogue, give the project a name and choose a board and a framework – if there are options available for the chosen board, the framework will usually be automatically selected based on the board you have chosen. When choosing a board, start typing, and the list will be filtered according to your typed text.
This is where the pio settings get projects_dir is used. As you may have noticed, although you set this way back when installing PlatformIO, it was never apparently used for new projects – you always had to be in the desired location to create a new project. So leaving the box ticked to “use the default location,” the project will be created there. Hover over the “?” to see where the default location will be. You can also click the “custom” link to define where you want to create the new project.
Click the “Finish” button, and after a small delay, a message will appear telling you that the project has been created and will be found wherever you chose and that you can process it with the command platformio run. Hmmm – and there was me thinking I could use PIO Home to edit projects. No such luck I’m afraid.
6.1.5.2 Opening Projects
It’s useful to create projects, but the option to “Open Project” simply tells you to go to the location where the project is and open it in your favorite IDE. However, maybe the future will be different, and we can edit and so on within the browser. That would be fun!
So, after creating the project, you are pretty much back in your favorite IDE or editor, editing and running pio run commands to compile the code and pio run -t upload to upload with the bootloader.
6.1.5.3 Importing Arduino Sketches
Choose a board.
Select the existing Arduino project.
Then click the “Import” button.
A new folder will be created in your default PlatformIO project directory. It will not be named in a meaningful manner, so renaming it might be helpful and wise. Within that directory, you will find the usual PlatformIO directories and files, and, finally, the original sketch will be found in the src directory, with its original *.ino name.
To compile the imported project, simply execute the command pio run within the project’s top-level directory where the file platformio.ini is to be found.
To be honest, pio home doesn’t appear to be of much use as described earlier, other than as an easy way to import existing Arduino sketches. However, when you use the PlatformIO IDE variant, coming next, that home screen is much more useful in that environment.
6.1.6 PlatformIO IDE
This section of the book will concentrate on the PlatformIO IDE variant using the VSCode editor or, in my case, the VSCodium version which is slightly different from the original in that it doesn’t “phone home” to Microsoft with details of what you might have been doing.
What’s the difference between PlatformIO Core and PlatformIO IDE?
PlatformIO Core, as discussed, installs a number of command-line tools to allow you to use your favorite editor, or programming IDE, to develop software for the Arduino board, either in Arduino Language or in the AVR’s native C++ format. You normally edit the code in your editor and compile it from the command line.
PlatformIO IDE is simply an extension or plugin to the Atom and the VSCode editors which effectively turns those two editors into an IDE to develop Arduino software. In this variant, you develop the code in the editor and then compile and upload it also from within the editor.
Don’t get confused. PlatformIO IDE isn’t necessary to generate project files for a number of IDEs.
The "IDE" part of the name comes from the fact that this version of PlatformIO turns your favorite editor into an IDE for generating code for your embedded devices. This assumes that your favorite editor is Atom or VSCode/VSCodium, that is!
I use VSCodium as my editor, so the remainder of this chapter will look at installing PlatformIO into that specific editor; however, the process is almost identical if you are using Atom.
With Atom, there is a toolbar with big chunky buttons down the left side where you can compile and upload projects. With VSCode/VSCodium, there is an alien’s head icon added to the left toolbar, which opens the Project Tasks list, from where you can click any of the activated options to run compilations and so on. There does appear to be more options in VSCode/VSCodium than in Atom.
6.1.6.1 Installation
Open the extensions view on the left side.
Press Ctrl+Shift+X.
Click View ➤ Extensions.
The extensions search should now open on the left side of the editor window.
In the search box at the top, type in “PlatformIO” and choose to install the option which appears, probably at the top of the list, “PlatformIO IDE.”
After it installs, a window at the bottom of the editor window will open, and a few tools will be installed to enable PlatformIO IDE. Do not close the window or move to another editor tab until you are advised that the installation is complete.
To start using the new plugin, you have to restart the editor, so click the button helpfully displayed by the PlatformIO installation process.
A new editor tab appears named “PIO Home,” with an alien’s head as an icon.
The command palette (View ➤ Command Palette or Ctrl+Shift+P) has a number of new PlatformIO commands listed.
6.1.6.2 PIO Home Tab
Home – Takes you back to the PIO Home page, if you happen to have chosen one of the following options.
Inspect – Allows various details of an existing project to be inspected and displayed. The code is analyzed as in memory usage and so on.
Libraries – Allows you to search for and install libraries that may be required by some Arduino and AVR projects.
Boards – Allows you to search for a board. Try entering “Duemilanove” and clicking the search icon. The two variants of the board will be shown alongside some important details of the boards such as the platform and framework required, the memory sizes, etc.
Platforms – Displays any installed platforms and allows you to uninstall them or to install any new requirements for a new board.
Devices – Assuming you have an Arduino board attached, this option will display details of the board(s), the type of communications chip, and the port it is attached to. Similarly to the arduino-cli, this option will not detect an ICSP device.
New Project – This should be fairly obvious. It allows you to create a new project and pick as many boards for it as you wish.
Import Arduino Project – This option lets you navigate to an existing Arduino project and import it into PlatformIO’s favored format.
Open Project – Opens an existing project within the editor and allows you to continue developing it.
Example Projects – Displays a few example projects and allows you to import them into PlatformIO for inspection or learning. You can, of course, compile the example projects.
At the bottom of the screen is a couple of items of recent PlatformIO news and a list of your most recent projects. If this is a new install, you probably don’t have any listed. If you did, you have options here to hide the projects from this list or to open it. Clicking the “open” link opens the VSCode/VSCodium explorer on the left side of the screen to the top-level directory for the project. From there you can open files for editing in the usual manner.
6.1.6.3 Creating a New Project
A new project is created from the PIO Home screen. If it is not already being displayed, then click the PlatformIO icon in the left-side toolbar to open the PlatformIO menu. Under quick access, open the list of options under “PIO Home” and click “Open.” A new tab appears named “PIO Home.”
On this tab, click the new project option. Then fill in (or select) the appropriate options for the project name, the board you want to use, and the location for the project. You can supply a custom location or simply accept the default, which will be displayed if you hover over the “?”.
If you wish to use the same source code for numerous different boards, simply keep adding new ones until you have everything set up as you wish.
Click the “Finish” button to create the project. After a short delay, the PIO Home tab will close. This never used to happen prior to version 4.1.0, so was a little disconcerting! On the left, the explorer will open with the various files and directories of the new project on display. The PIO Home tab will then reopen, after another short delay. I usually keep it closed as it is of little use during development.
You can now edit your files in the usual manner.
6.1.6.4 Opening Existing Projects
If your project already exists, then you can use the PIO Home tab to open it. As in the preceding text, make sure the tab is visible in the editor, then click the “Open Project” option, navigate to the project’s location, and click the “Open <project name>” button.
As before, the PIO Home tab will close, and the explorer on the left will open at the project’s location. The project can now be edited as required.
6.1.6.5 Editing the Project
Yet another blink sketch!
6.1.6.6 Compiling a Project
Once editing is done, you can compile the project either from the left-side toolbar or from a terminal which can be opened in the editor (Terminal ➤ New Terminal or Ctrl+Shift+#). If you use the terminal, it opens into the project’s location, and you can run any of the usual PlatformIO commands already described in Section 6.1.2, “Testing PlatformIO Core.”
To compile from the toolbar, you need to open the PlatformIO window on the left by clicking the icon. Then, under the “Project Tasks” list, select “Build” to build the project. You can also press Ctrl+Alt+B to build it from within one of the project’s files open in the editor.
A new terminal will open, and progress will be displayed. You are requested to close this terminal when finished with it, by pressing any key. This will only work if the terminal has focus. (Ask me how I know this.)
If all looks okay with the compilation, we are ready to upload or program the board.
6.1.6.7 Upload or Program a Project
From PlatformIO 4.1.0 onward, the preceding first line is no longer required and has been commented out.
Another new terminal will open, and progress messages will be displayed as appropriate. Then when it completes, your Arduino board should be blinking happily again.
That’s a very quick and high-level overview of something that’s becoming very popular in the Arduino world, especially with users of 3D printers running the Marlin Firmware as Marlin 2.0 onward uses PlatformIO to build and upload the firmware.
I personally have swapped over from the Arduino IDE to PlatformIO for most of my projects and experimenting with AVRs and Arduinos. I find it a lot faster to develop software using PlatformIO, and I’m more comfortable in the editor than in the Arduino IDE.
Coming up next, I’ll be taking a look at the new, but still under development, Arduino CLI – a command-line version of the Arduino IDE which allows you to use your own favorite editor and make files to create and build your Arduino projects.
6.2 Arduino Command Line
The Arduino IDE has always had a sort of command-line version, at least on Linux. Windows had a separate version due to the way that Windows GUI and command-line applications are so different. However, in August 2018, a new Arduino command-line application, arduino-cli, came out in alpha test.
It is possible that what is explained here might be likely subject to some changes as time goes by.
When I first started looking into the arduino-cli, it was September 2018, and the latest release at that time was 0.2.1-alpha. It had quite a few bug and foibles, but hey, it’s an alpha release so it’s expected. The version I’m looking at here is a much later release, 0.6.0 (it’s November 2019 now), and many of the original bugs and foibles have been sorted. As more releases are, ahem, released, things can only get better.
The use of the Arduino CLI is to help in getting code built using make files, for incorporating into other IDEs and, most likely, as the basis for whatever IDE changes appear in version 2 of the Arduino IDE itself. It has been noted on the Arduino Developers Google Group (https://groups.google.com/a/arduino.cc/forum/#!forum/developers) that visually impaired users have great difficulty with IDEs and that command-line versions are much better, so this can only be helpful.
6.2.1 Obtaining the Arduino CLI
Stable releases are available for download from the project’s main release page at https://github.com/arduino/arduino-cli/releases which has links to the all binary releases for numerous platforms – there are 32- and 64-bit versions for Linux and a version for Linux on ARM chips – Raspberry Pi, for example. Users with Windows or Macs are not left out either. Click the link to download the appropriate version for your system.
You can always get to the most up-to-date release using the URL https://github.com/arduino/arduinocli/releases/latest.
On the main project page, there are additional links to various nightly builds. These can be used if you want the latest, bleeding-edge release; however, you are advised to stick with the stable releases.
Failing all this, you can, if you are so inclined, build your own from the source code. Links are on the preceding home page with the details. I’m avoiding this option as I’d want to look at the source and I’m not a Go (Golang) developer, yet.
6.2.2 Installing
There are details on the home page which hint that you can download and install the arduino-cli with a single curl command. While I’m sure that this will work perfectly well, I would be blindly allowing a script, downloaded from the Internet, to be executed without checking what it might do. I’m going with the latest release from the preceding URL instead.
Pick the file that’s appropriate for your system. I’m on 64-bit Linux Mint, so my file is arduino-cli_0.6.0_Linux_64bit.tar.gz.
arduino-cli which is the utility itself.
License.txt which is the license.
readme.md which is a markdown file used on the project’s main GitHub page. This is a good place to start reading.
6.2.3 Configuring the CLI
You now have all the default config stored in the file name listed earlier. You may edit the file and change the configuration as desired. Currently, there’s not much to change, but the readme file that came with the download does have some information of uses for this file, which may be of interest, but are not covered here.
If a sketch name only is passed as parameter, assume that the sketch directory is the current directory.
If a relative path for the sketch is passed, join it with the current directory path.
If an absolute path for the sketch is passed, simply use it.
This is to be applied to the sketch new command in addition to compile and upload commands.
So, no reference at all to the sketchbook , so I would consider leaving the configuration well alone until the application settles down to at least release candidate or release level.
6.2.4 Creating Sketches
A brand-new sketch
MyFirstSketch.ino
Well, I can’t just keep using the same blink sketch all the time, can I? I need a bit of variety!
After a short delay, I see the information relating to my two boards displayed. Unfortunately, the lines of text are far too wide for this page, so I shall have to summarize.
Is attached to port /dev/ttyACM0 which is a Serial Port (USB) type of port
Has a board name of Arduino/Genuino Mega 2560
Uses the arduino:avr core
Has arduino:avr:mega as its FQBN
The board’s FBQN is its “Fully Qualified Board Name” and is required, later, to compile and upload sketches.
Attached to port /dev/ttyUSB0 which is a Serial Port (USB) port type
Has a board name of Unknown
Apparently, has no known core
Apparently, has no FQBN
The readme advises that boards will be listed as “unknown” if they are connected via an FTDI adaptor. I’m using the Arduino-supplied USB cable on my Duemilanove, but on that board there is an FTDI chip, so I see the board listed as unknown.
Boards are detected based on a vendor and product ID, VID/PID. On boards with FTDI, these identifiers are generic, so the actual board cannot be determined. This is not a major problem here, however, as both my boards have at least been identified as being present.
Boards will not be detected if they are connected to your computer with an ICSP device.
Now we need to install a core (aka platform) for the boards. The Mega is easy as it lists its core as “arduino:avr” which is useful. The Duemilanove, on the other hand, doesn’t list a core, so how do we determine the correct core?
This is useful as it lists the board’s name followed by its FQBN. The Fully Qualified Board Name is required when compiling or uploading sketches to the board. It also starts with the appropriate platform/core name, “arduino:avr”.
6.2.5 Installing Platforms
Those numbers seem to match up with the list of downloaded “stuff,” so we should be good to go.
Don’t worry. You don’t need to jump through all these hoops every time you want to compile with the arduino-cli, just the first time, or when you add a new board that had a different core of course.
6.2.6 Compiling Sketches
If you are located in the parent directory of the sketch, /home/norman/Arduino in my case, the preceding command works fine.
If you are located elsewhere on the system, perhaps in /home/norman, then you need to supply the full path to the sketch’s top-level directory – /home/norman/Arduino/MyFirstSketch or, the short version, ~/Arduino/MyFirstSketch.
When compiling a sketch, you must supply the board’s FQBN. If the compilation succeeds, the usual details about the RAM usage will be displayed. If you need verbose output, simply add the -v command-line option to the preceding compile command.
Yes, on Linux, you can split a long command over a number of lines if it makes it more readable. Each line, except the last, must end with the backslash character and an immediate linefeed – there are no spaces between those characters.
You will see other occasions in this book where I do this. It helps keep things on the page.
This is a compiler error, and it is telling you that the command line passed to the compiler was missing an option telling it the microcontroller in use on the board in question.
In older versions of arduino-cli, this used to happen for my Duemilanove and my Nano, so I had to update the board’s FQBN at compile and upload time, to specify the appropriate AVR microcontroller. This actually makes sense as some early boards have an ATmega168, while later boards, mine, for example, have an ATmega328.
Adding the cpu to the FQBN gets rid of the error, and the sketch compiles.
If, like me, you have a Duemilanove or a Nano, then either of these can use the ATmega168 or the Atmega328 family of microcontrollers. While you might not need to, you can always specify the cpu option and be absolutely certain that the compiler will compile the code for the correct CPU. Doing this is the equivalent of selecting the correct board option from the Tools ➤ Boards menu in the IDE.
You can use the -v option on the compile command to see the full, verbose, compilation text. This is similar to what is produced in the Arduino IDE when you have the verbose compilation option enabled.
6.2.7 Uploading Sketches
Uploading a sketch uses a similar command to compiling, and you must remember to always use the same FQBN, or it will ask you to compile the sketch first. The port name is always required when uploading. If you forget the port, then the arduino-cli board list command is your friend.
If you left the cpu=atmega328 parameter attached to the FQBN, it will be ignored.
There will be no output displayed on screen if all went well with the upload. If you wish to see the upload details, just add -v to the command, and you will get the same verbose output as you would have seen in the IDE.
Unfortunately, you will need to log out and back in again to pick up the new group. This is mildly irritating, so here’s a quick tip on temporarily working around the need to log out.
You will be asked for your password and will start a new shell with the new group assigned. Test it by running the groups command again, and note that now you do have dialout present.
Now you can upload to your Arduino board.
6.2.8 Uploading Sketches with an ICSP
At present, uploading is only possible when you are using an Arduino board which still has a bootloader present. In-Circuit System Programmers (ICSPs) are not yet supported. If you have a board connected using an ICSP, then the arduino-cli board list command will not see it.
There is a workaround, but it’s not completely ideal, but it does work.
If you open a sketch in the Arduino IDE, then go to File ➤ Preferences and set the upload option to verbose. Now, compile and upload the sketch to the board with the ICSP device you want to use with arduino-cli. Any sketch will do, even an empty one.
The upload.sh shell script for Linux
① This is a copy of the device name extracted from the upload command line displayed by the IDE.
② This is a copy of the uploading device name, again, extracted from the IDE’s command line for the upload.
③ This is the parent directory where the avrdude applications, bin directories, etc. are to be found. No trailing “/” is required. As before, this path is extracted from the IDE output.
④ This is where we find the avrdude file, relative to $AVRDUDE_HOME.
⑤ This is where we find the avrdude.conf file, relative to $AVRDUDE_HOME.
⑥ We want verbose output. If you don’t want all the chatter from avrdude, remove the -v and you will get less output when uploading.
⑦ From here down, we do a bit of validation. Did we get a file name passed to us? Is it actually a file name for a file that physically exists? Does it have an extension of “hex” on the file name?
⑧ Nobody said that bash coding was easy! This extracts the file name’s extension. We are looking for “hex.”
⑨ The upload happens here. Of course, this will overwrite your Arduino’s bootloader, so from now on, you will have to continue using the ICSP device or burn a new bootloader.
Your will need to check and maybe replace my directory names to those appropriate to your system.
If you decide to follow my example and create an upload.sh script, beware when using the Arduino IDE if it asks to update your boards or libraries. This can have the effect of changing the names of some of the directories I’ve used in the following in my script. If you suddenly start getting upload errors, check what’s been updated and amend the script.
This script also doesn’t upload any data to the ATmega328P’s EEPROM. I did say that this wasn’t an ideal solution.
We can see from the preceding code that different boards have different files. The cpu that we may have needed to use when compiling, however, is not part of the output file name – only the FQBN is used.
You can now pass the required file name to the upload.sh script as a parameter, and the sketch will be uploaded via the ICSP device instead of using the bootloader.
6.2.9 Burning Bootloaders
As of version 0.6.0, the latest version available at the time I wrote this, it is still not possible to burn a bootloader with the arduino-cli utility. So, if you have managed to either corrupt or overwrite the bootloader, what can you do?
In a manner similar to that described earlier to enable uploads using an ICSP device, there is a workaround – and again, the Arduino IDE is required.
Obviously, if you have the Arduino IDE installed, you can burn a bootloader for your device at any time you like using Tools ➤ Burn Bootloader.
The process is very similar to that described earlier to upload a sketch with an ICSP. We use the Arduino IDE, in verbose mode, to extract the required command lines used when burning a bootloader and then simply create a shell script with just about everything parameterized, ready to be run on the command line.
Extracting was easy. I burned a bootloader to my Duemilanove with my USBtiny device and copied the two calls to avrdude from the verbose output. You will see them at the bottom of Listing 6-11, my burnBootloader.sh script.
The burnBootloader.sh shell script for Linux
① This is a copy of the device name extracted from the upload command line displayed by the IDE.
② This is a copy of the uploading device name, again, extracted from the IDE’s command line for the upload.
③ This is the parent directory where the avrdude applications, bin directories, etc. are to be found. No trailing “/” is required. As before, this path is extracted from the IDE output.
④ This is where we find the avrdude file, relative to $AVRDUDE_HOME.
⑤ This is where we find the avrdude.conf file, relative to $AVRDUDE_HOME.
⑥ We want verbose output. If you don’t want all the chatter from avrdude, remove the -v and you will get less output when uploading.
⑦ This is where the bootloader used by the IDE is to be found. This is extracted from the command line passed from the IDE to avrdude.
⑧ We need to set three fuse bytes for the Duemilanove. These are defined here and are as per the IDE’s command line. There are a couple of lock bytes also that we need.
⑨ From here down, we do a bit of validation. Is the bootloader file name a file that physically exists? Does it have an extension of “hex” on the file name?
➉ This call to avrdude unlocks the device and sets the three fuse bytes as required for a Duemilanove. The fuse settings can be extracted from the Arduino installation’s boards.txt file, if you are stuck, but they are also able to be extracted from the command line used by the IDE to burn the bootloader.
⑪ This call to avrdude burns the bootloader file, as supplied with the Arduino IDE software, and then locks the device again.
If you decide to follow my example and create a burnBootloader.sh script, beware when subsequently using the Arduino IDE if it asks to update your boards or libraries. This can have the effect of changing the names of some of the directories I’ve used in the following in my script.
If you suddenly start getting upload errors, check what’s been updated and amend the script. In my case, the BOOTLOADER_HOME location changed from version 1.8.1 to 1.8.2 and broke my script.
I did say that this wasn’t an ideal solution, but at least it was a simple fix.
6.2.10 Serial Usage
You would most likely replace COM4 with the port you uploaded the sketch on. Linux users would use /dev/ttyuUSB0 or similar.
After a short pause, the display should begin showing what the Arduino is sending. To exit from the screen session, press Ctrl+A followed by the letter “k” in upper- or lowercase. You will be asked to confirm your wish to kill the session. Press “y” to continue.
To exit from putty, just close the window and confirm your intention to do so when prompted.
Obviously, 9600 is the baud rate and must match that which you used in your call to Serial.begin(), and /dev/ttyUSB0 is the same port that you uploaded the sketch to. Use the arduino-cli board list to see what it should be if necessary.
It’s possible to send data from the screen session to the Arduino, but it doesn’t echo on the display and seems to be quite slow for some reason. Further investigations appear to be required – there’s probably an option when starting screen that resolves it.
The -n may be required to flush the buffer and make sure that the data are sent to the Arduino.
That’s a very quick overview of something that’s to come soon in the Arduino world. It certainly looks interesting, and I’ll be keeping an eye on it. It’s not yet perfect, it is an alpha release after all, and I have not covered all the options and commands available – installing libraries, for example. I think it’s best to wait a while for a proper release to see if anything changes, but hopefully, this will have whetted your appetite.
I’ve seen comments on the Arduino forums about this utility, and a lot of people seem to be very happy that they no longer require to install Java to develop Arduino code.
After that slight deviation, I think it’s now time to look into the features of the ATmega328P that we need to know about in order to continue from where we were in Chapter 5 where we started replacing functions like pinMode(), digitalWrite(), and digitalRead() with plain AVR C++ variations.