Cadena de herramientas de desarrollo Arduino para conocedores de la línea de comandos: PlatformIO o cómo dejar de usar el IDE Arduino


Durante el año pasado, escribí bastante código para Arduino y simultáneamente cambié varias herramientas de desarrollo. El artículo menciona las opciones que probé y con más detalle sobre lo que paré. Se tratará de un conjunto de herramientas para el caso cuando> 10 proyectos para diferentes tableros y un poco sobre el desarrollo e instalación de bibliotecas.


Entorno de desarrollo


Cual es el problema


Probablemente porque Arduino no está enfocado en desarrolladores profesionales, el ecosistema alrededor del IDE estándar se distingue por la ausencia de las herramientas habituales para mí:
  • Solo en versiones recientes apareció algún tipo de gestión de biblioteca, mientras que sin la similitud de Gemfile / require.txt / package.json, es decir, es imposible que el proyecto especifique qué versiones se usan
  • sin integración con git u otros vcs
  • un editor de texto no se compara con mi editor de texto favorito
  • no hay forma de guardar la selección del tablero en el proyecto
  • salida inconveniente de errores de compilación

El sitio web de Arduino tiene una lista de herramientas de desarrollo alternativas . En esta lista hay opciones que por varias razones no probé. Por ejemplo, Atmel Studio y Visual Studio CE no consideraron. Quería encontrar una herramienta que apoyara el trabajo desde la línea de comandos.


Que intentó


Ino


Ino : un proyecto de la compañía rusa Amperka, una utilidad de línea de comandos para el firmware Arduino.
El proyecto fue bastante popular,> 200 tenedores. La última confirmación fue en abril de 2014, por lo que no funciona con las últimas versiones del IDE (parece que desde 1.5).
Hay un tenedor vivo de Arturo , lo usé un poco, pero hubo problemas en algunos casos exóticos.


Arduino-makefile


Arduino-Makefile : compila y descarga con make. Arduino Due, Zero y otras placas de 32 bits no son compatibles. La diferencia con el IDE estándar es que los métodos deben declararse antes de su uso, por lo que al transferir proyectos terminados, es posible que deba editar la fuente. Si no recuerdo mal, no podría hacerme amigo de Arduino-Makefile y SparkFun Pro Micro.


Lo que uso


PlatformIO


PlatformIO es un excelente proyecto creado por desarrolladores de Ucrania. Incluye una utilidad de línea de comandos a través de la cual puede comenzar a compilar y descargar programas a varias familias de microcontroladores (Atmel AVR, Atmel SAM, ST STM32, TI MSP430 y otros). Al mismo tiempo, se admiten diferentes conjuntos de bibliotecas (en el sitio web PlatformIO se denominan frameworks): Arduino, Energia, mbed, así como código nativo para Atmel AVR, espressif, MSP430.
PlatformIO se orientó inicialmente para trabajar desde la línea de comandos, también hay complementos para la integración con editores de texto e IDE: Atom, CLion, Eclipse, Emacs, NetBeans, Qt Creator, Sublime Text, Vim y Visual Studio
PlatformIO es especialmente adecuado si tiene:
  • un proyecto para varias juntas, es decir el mismo código debe compilarse para diferentes tableros
  • , .. ,
  • ssh, PlatformIO Raspberry Pi

imagen


Arduino

No volveré a contar la documentación, aquí están las instrucciones de instalación , para su uso, consulte la sección de Inicio rápido .
La estructura de carpetas del proyecto para PlatformIO difiere del proyecto Arduino IDE, cada proyecto contiene un archivo platformio.ini que indica qué placas se utilizan. Por lo tanto, no tiene que elegir el tablero correcto cada vez.
Te contaré un ejemplo de cómo uso PlatformIO cuando desarrollo una biblioteca para Arduino. La biblioteca tiene dos ejemplos, cada uno de ellos es un proyecto en formato PlatformIO. El archivo de configuración del proyecto platformio.ini enumera todas las placas en las que debe ejecutarse la biblioteca:
[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

Puede compilar un ejemplo para todos los tableros con el comando:
platformio run

Puede compilar solo para uno como este:
platformio run -e uno

Descargar firmware en uno:
platformio run --target upload -e uno

Inicie el monitor del puerto serie:
platformio serialports monitor

Se agregaron alias a .zshrc para acortar los comandos:
alias compile="platformio run"
alias upload="platformio run --target upload"
alias serial="platformio serialports monitor"

Con ellos la misma secuencia de acciones:
compile         #    
compile -e uno  #   uno
upload  -e uno  #  uno
serial          #   

También hay integración con Travis CI y otras herramientas de CI, más detalles aquí .
En realidad, el IDE de Arduino tiene una interfaz de línea de comandos , pero está lejos de ser perfecto.


PlataformaIO Matices

PlatformIO acelera el trabajo; es una herramienta más flexible en comparación con Arduino IDE y facilita la automatización de tareas rutinarias. Hay varios puntos a considerar:
  • la compilación en PlatformIO no siempre es equivalente a compilar en Arduino IDE, lo que se compiló en PlatformIO puede no compilarse en Arduino IDE y viceversa
  • la estructura de la carpeta del proyecto no coincide con la estructura para Arduino IDE
  • no todas las bibliotecas están disponibles para la instalación a través de platformio lib

Serial.print ("Podría ser mejor");


Cual es el problema


El Serial.print () estándar es un poco incómodo si necesita imprimir el
nombre y el valor de la variable, por ejemplo, para generar "pin_2 = <state pin 2>, pin_3 = <state pin 3>" debe hacer esto:
Serial.print("pin_2 = ");
Serial.print(digitalRead(2));

Serial.print(", pin_3 = ");
Serial.println(digitalRead(3));

Todavía a veces quiero deshabilitar parcial o completamente la salida a la serie, por ejemplo, si se usa solo para la depuración. Por supuesto, puede comentar las llamadas a Serial.print () para esto, pero me gustaría una opción más elegante.


Que intentó


arduinoLogging


Esta biblioteca utiliza una sintaxis similar a printf para imprimir, y también le permite configurar LOGLEVEL y así deshabilitar la salida de algunos o todos los mensajes. Los mensajes se muestran usando los métodos Error, Info, Debug y Verbose.
Un ejemplo:
  #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");
  }

Modificadores Disponibles

comodíncomentarEjemplo
% 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 into "true" or "false"Log.Info ("is it true? %T), myBool);


advancedSerial


Los nombres de los niveles de mensaje de Error, Información, Depuración y Verbose en arduinoLogging no son neutrales. El error no necesariamente produce un error, es solo un mensaje que se muestra en cualquier LOGLEVEL (excepto NOOUTPUT).
Dado también algunos de los inconvenientes de printf, escribí mi propia versión, advancedSerial .
En realidad, advancedSerial es dos cosas: la capacidad de llamar a print () e println () en los niveles de cadena y mensaje.
  int a = 1;
  int b = 2;

  aSerial.print("a = ").print(a).print("b = ").println(b);

  //     
  aSerial.p("a = ").p(a).p("b = ").pln(b);

Ejemplo completo de Basic.ino
Dado que los nombres de los métodos coinciden con los nombres de los métodos estándar Serial.print () y Serial.println (), opcionalmente puede reemplazar Serial con aSerial en las fuentes.
Para el nombre de los niveles de mensaje, elegí v, vv, vvv, vvvv, una forma bastante común de indicar los niveles de detalle de los mensajes mostrados, que generalmente se encuentran como banderas -v, -vv, etc.
Con estos nombres, es más fácil editar un nivel a otro, por ejemplo vv -> vvv es más fácil que Información -> Depurar.
  #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);
   }

Ejemplo completo de Advanced.ino


Ahorro de memoria

Si envuelve la cadena en la macro F (), entonces no se cargará en la memoria (SRAM), por lo que para ahorrar memoria, use F ():
  aSerial.print(F(" 16 "));

Por supuesto, usando advancedSerial agrega algo de sobrecarga en comparación con el Serial estándar, traté de estimar aproximadamente cuál. A continuación, presento los resultados de la compilación para Arduino Uno, ya que tiene 2 KB de memoria y este es el mínimo entre las placas que suelo usar.

Serie normal, sin ninguna biblioteca:
  void setup() {
   Serial.begin(9600);
  }

  void loop() {
    Serial.print("test");
    Serial.println("test");
  }

espacio de almacenamiento: 5%
memoria dinámica: 9%

avanzado Serie:
  #include <advancedSerial.h>

  void setup() {
   Serial.begin(9600);

   aSerial.setPrinter(Serial);
   aSerial.setFilter(Level::vv);
  }

  void loop() {
    aSerial.print("test").println("test");
  }

espacio de almacenamiento: 5%
memoria dinámica: 10%

ejemplos / Advanced.ino
espacio de almacenamiento: 9%
memoria dinámica: 26%

ejemplos / Advanced.ino utilizando el
espacio de almacenamiento macro F () : 9%
memoria dinámica: 10%
Resulta que el uso de memoria aumenta ligeramente Pero advancedSerial no es una solución óptima en términos de recursos, hay implementaciones alternativas, por ejemplo, Depuración .


Instalación de biblioteca


Cual es el problema


Por defecto, el IDE de Arduino instala las bibliotecas a nivel mundial y el boceto no registra exactamente qué bibliotecas se utilizan (a excepción de las directivas #include, por supuesto) y qué versiones. Debido a esto, para compilar el boceto en otra computadora, necesita saber dónde descargar las bibliotecas requeridas, nuevamente las versiones de la biblioteca también deben especificarse. Para evitar tales problemas, instalo bibliotecas solo localmente, dentro de la carpeta de croquis. A continuación hay dos formas de instalar bibliotecas localmente para Arduino IDE y PlatformIO.


IDE Arduino


Raramente uso el IDE de Arduino, tal vez hay una mejor manera. El método es este: instale bibliotecas en una subcarpeta de su proyecto y coloque enlaces simbólicos (¿atajos?) Para cada biblioteca en la carpeta de bibliotecas (en la carpeta donde están instaladas las bibliotecas Arduino IDE).
Por cierto, si no recuerdo mal, el IDE de Arduino compila todas las bibliotecas de la carpeta de bibliotecas al compilar cualquier boceto, por lo que el tiempo de compilación aumenta si hay muchas bibliotecas en las bibliotecas. Otra razón para no usar el IDE de Arduino.


PlatformIO


Cada proyecto PlatformIO tiene una subcarpeta lib en la que se pueden colocar bibliotecas. Esto es cuando se instalan bibliotecas manualmente. PlatformIO también tiene un comando separado para instalar las bibliotecas de plataformaio lib, desafortunadamente instala las bibliotecas de forma global de manera predeterminada, por lo que las bibliotecas se instalan localmente en la subcarpeta lib, debe agregar el proyecto platformio.ini:
[platformio]
lib_dir = ./lib

Para obtener más información sobre platformio lib, consulte la documentación .

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


All Articles