
Over the past year I have written quite a lot of code for Arduino and in the process I changed several development tools. The article mentions the options that I tried and in more detail about where I stopped. We will talk about a set of tools for the case when> 10 projects for different boards and a little about the development and installation of libraries.
Development environment
What is the problem?
Probably because Arduino is not focused on professional developers, the ecosystem around the standard IDE is lacking the usual tools for me:
- Only in the latest versions some kind of library management has appeared, so far without the similarity of Gemfile / requirements.txt / package.json, that is, it is impossible to specify for the project which versions are used.
- no integration with git or other vcs
- text editor does not compare with my favorite text editor
- there is no possibility to save the board selection in the project
- awkward compilation error output
The Arduino website has a
list of alternative development tools . In this list there are options that for various reasons did not begin to try. For example, Atmel Studio and Visual Studio CE did not consider. I wanted to find a tool that supports work from the command line.
What I tried
Ino
Ino - a project from the Russian company Amperka, a command line utility for the Arduino firmware.
Quite a popular project was,> 200 forks. Last commit in April 2014, therefore does not work with fresh versions of IDE (it seems starting from 1.5).
There is a live fork
Arturo , used it a little, but there were problems in some exotic cases.
Arduino-makefile
Arduino-Makefile - compile and load with make. Arduino Due, Zero and other 32-bit boards are not supported. The difference from the standard IDE is that the methods must be declared before use, so that when transferring finished projects you may need to edit the source code. If I remember correctly, I could not make friends with the Arduino-Makefile and SparkFun Pro Micro.
')
What I use
PlatformIO
PlatformIO is an excellent project created by developers from Ukraine. It includes a command line utility through which you can start compiling and downloading programs to several microcontroller families (Atmel AVR, Atmel SAM, ST STM32, TI MSP430 and others). At the same time, different sets of libraries are supported (on the PlatformIO website they are called frameworks): Arduino, Energia, mbed, and also the native code for Atmel AVR, espressif, MSP430.
PlatformIO is initially oriented to work from the command line, there are also plugins for integration with text editors and IDE:
Atom, CLion, Eclipse, Emacs, NetBeans, Qt Creator, Sublime Text, Vim and Visual StudioPlatformIO is especially suitable if you have:
- one project for several boards, i.e. the same code should be compiled for different boards
- many projects for different fees, i.e. each project is under one fee, but there are many projects and boards are different
- there is a need to work via ssh, for example, if PlatformIO is installed on Raspberry Pi
- keen rejection of the graphical interface

Use with Arduino
I will not retell the documentation,
here the installation instructions , you can see the usage in the
Quick Start section.
The project folder structure for PlatformIO differs from the Arduino IDE project, each project contains a file platformio.ini which indicates which boards are used. Thus, it is not necessary to choose the right board each time.
I'll tell you by example how I use PlatformIO when developing a library for Arduino. The library has two examples, each of them is a project in the PlatformIO format. The projectio file platformio.ini lists all the cards on which the library should work:
[env:nanoatmega328] platform = atmelavr framework = arduino board = nanoatmega328 [env:sparkfun_promicro16] platform = atmelavr framework = arduino board = sparkfun_promicro16 [env:due] platform = atmelsam framework = arduino board = due [env:teensy31] platform = teensy framework = arduino board = teensy31 [env:nodemcu] platform = espressif framework = arduino board = nodemcu [env:uno] platform = atmelavr framework = arduino board = uno
You can compile an example for all boards using the command:
platformio run
You can compile only for uno like this:
platformio run -e uno
Download uno firmware:
platformio run --target upload -e uno
Start the serial monitor:
platformio serialports monitor
Added aliases to .zshrc to make the commands shorter:
alias compile="platformio run" alias upload="platformio run --target upload" alias serial="platformio serialports monitor"
With them the same sequence of actions:
compile
There is also integration with Travis CI and other CI tools,
more here .
Actually, the Arduino IDE has
a command line interface , but it is far from perfect.
Nuances of PlatformIO
PlatformIO speeds up work; it is more flexible than the Arduino IDE and it’s easier to automate routine tasks. There are several things to consider:
- compilation in PlatformIO is not always equivalent to compiling in the Arduino IDE, something that was collected in PlatformIO may not compile in the Arduino IDE and vice versa
- project folder structure does not match the structure for the Arduino IDE
- Not all libraries are available for installation via platformio lib
Serial.print ("Maybe better");
What is the problem?
Standard Serial.print () is slightly inconvenient in case you need to type
the name and value of the variable, for example, to display "pin_2 = <pin state 2>, pin_3 = <pin state 3>" you have to do this:
Serial.print("pin_2 = "); Serial.print(digitalRead(2)); Serial.print(", pin_3 = "); Serial.println(digitalRead(3));
Sometimes you also want to partially or completely disable the output to the series, for example, if it is used only for debugging. Of course, you can comment on the calls to Serial.print () for this, but I would like a more elegant option.
What I tried
arduinoLogging
This lib uses printf-like syntax for printing, and also allows you to set LOGLEVEL and thus disable the output of some or all messages. Messages are displayed using the Error, Info, Debug, and Verbose methods.
Example:
#include "Logging.h"
Available modifiers
wildcard | comment | Example |
---|
% s | replace with an string (char *) | Log.Info ("String% s", myString); |
% c | replace with an character | Log.Info ("use% c as input", myChar) |
% d | replace with an integer value | Log.Info ("current value% d", myValue); |
% l | replace with an long value | Log.Info ("current long% l", myLong); |
% x | replace and convert integer value into hex | Log.Info ("as hex% x), myValue); |
% X | like% x but combine with 0x123AB | Log.Info ("as hex% X), myValue); |
% b | replace and convert integer value into binary | Log.Info ("as bin% b), myValue); |
% B | like% x but combine with 0b10100011 | Log.Info ("as bin% B), myValue); |
% t | replace and convert boolean value into "t" or "f" | Log.Info ("is it true?% T), myBool); |
% T | like% t but convert to "true" or "false" | Log.Info ("is it true?% T), myBool); |
What I use
advancedSerial
The names of the Error, Info, Debug, and Verbose message levels in arduinoLogging are not neutral. Error does not necessarily print an error, it is just a message that is output on any LOGLEVEL (except NOOUTPUT).
Considering also some disadvantages of printf, I wrote my own version,
advancedSerial .
Actually advancedSerial is two things: the ability to call print () and println () in a chain and message levels.
int a = 1; int b = 2; aSerial.print("a = ").print(a).print("b = ").println(b);
Full example
Basic.inoSince the names of the methods coincide with the names of the standard methods Serial.print () and Serial.println (), then, if desired, in the source code you can simply replace Serial with aSerial.
For the name of the message levels, I chose v, vv, vvv, vvvv, a fairly common way to denote the levels of detail of the output messages, usually found as flags -v, -vv and so on.
With such names it is easier to edit one level to another, for example, vv -> vvv is easier than Info -> Debug.
#include "advancedSerial.h" void setup() { Serial.begin(9600); aSerial.setPrinter(Serial);
Full example
Advanced.inoMemory saving
If you wrap a string in the F () macro, it will not be loaded into memory (SRAM), so to save memory, use F ():
aSerial.print(F(" 16 "));
Of course, using advancedSerial adds some overhead projector compared to the standard Serial, I tried to estimate which one. Below are the compilation results for the Arduino Uno, since it has 2KB of memory and this is the minimum among the boards that I usually use.
The usual series, without any libraries: void setup() { Serial.begin(9600); } void loop() { Serial.print("test"); Serial.println("test"); }
storage space: 5%
dynamic memory: 9%
advancedSerial: #include <advancedSerial.h> void setup() { Serial.begin(9600); aSerial.setPrinter(Serial); aSerial.setFilter(Level::vv); } void loop() { aSerial.print("test").println("test"); }
storage space: 5%
dynamic memory: 10%
examples / Advanced.inostorage space: 9%
dynamic memory: 26%
examples / Advanced.ino using F () macrostorage space: 9%
dynamic memory: 10%
It turns out that the memory usage increases slightly. But advancedSerial is not the optimal solution in terms of resources, there are alternative implementations, for example,
Debug .
Installing Libraries
What is the problem?
By default, the Arduino IDE installs globally and in the sketch it does not fix exactly which libraries are used (except for #include directives of course) and which versions. Because of this, in order to compile the sketch on another computer you need to know where to download the necessary libraries, again, the library versions must also be specified. To avoid such problems, I install libraries only locally, inside the folder with the sketch. Below are two ways to install libraries locally for the Arduino IDE and for PlatformIO.
Arduino IDE
I rarely use the Arduino IDE, maybe there is a better way. The method is as follows: install the libraries in a subfolder of your project and place the symlinks (shortcuts?) For each library in the libraries folder (in the folder where the Arduino IDE libraries are installed).
By the way, if I remember correctly, the Arduino IDE compiles all libraries from the libraries folder when compiling any sketch, so the compile time increases if there are many libraries in libraries. Another reason not to use the Arduino IDE.
PlatformIO
Each PlatformIO project has a lib subfolder into which libraries can be placed. This is when manually installing libraries. Also, PlatformIO has a separate command to install the platformio lib libraries, unfortunately it defaults to installing libraries globally so that the libraries are installed locally in the lib subfolder you need to add to the platformio.ini of the project:
[platformio] lib_dir = ./lib
Read more about platformio lib in the
documentation .