📜 ⬆️ ⬇️

Developed under the Arduino for fans of the command line: PlatformIO or how to stop using the Arduino IDE


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:

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 Studio
PlatformIO is especially suitable if you have:

image


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 #     compile -e uno #   uno upload -e uno #  uno serial #    

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:

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" // LOGLEVEL   LOG_LEVEL_X,  X ∈ { NOOUTPUT, ERRORS, INFOS, DEBUG, VERBOSE } #define LOGLEVEL LOG_LEVEL_INFOS void setup() { Serial.begin(9600); Log.Init(LOGLEVEL, &Serial); //    Log.Info("pin_2 = %d, pin_3 = %d"CR, digitalRead(2), digitalRead(3)); //     Log.Debug("   ,   LOGLEVEL = LOG_LEVEL_INFOS"); } 

Available modifiers

wildcardcommentExample
% sreplace with an string (char *)Log.Info ("String% s", myString);
% creplace with an characterLog.Info ("use% c as input", myChar)
% dreplace with an integer valueLog.Info ("current value% d", myValue);
% lreplace with an long valueLog.Info ("current long% l", myLong);
% xreplace and convert integer value into hexLog.Info ("as hex% x), myValue);
% Xlike% x but combine with 0x123ABLog.Info ("as hex% X), myValue);
% breplace and convert integer value into binaryLog.Info ("as bin% b), myValue);
% Blike% x but combine with 0b10100011Log.Info ("as bin% B), myValue);
% treplace and convert boolean value into "t" or "f"Log.Info ("is it true?% T), myBool);
% Tlike% 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); //      aSerial.p("a = ").p(a).p("b = ").pln(b); 

Full example Basic.ino
Since 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); //       //  ,      v  vv,  vvv  vvvv    aSerial.setFilter(Level::vv); } void loop() { aSerial.l(Level::vv).pln(" "); aSerial.l(Level::vvv).pln("  "); delay(3000); } 

Full example Advanced.ino


Memory 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.ino
storage space: 9%
dynamic memory: 26%

examples / Advanced.ino using F () macro
storage 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 .

Source: https://habr.com/ru/post/392639/


All Articles