Cadeia de ferramentas de desenvolvimento do Arduino para conhecedores da linha de comandos: PlatformIO ou como parar de usar o IDE do Arduino


No ano passado, escrevi bastante código para o Arduino e, simultaneamente, mudei várias ferramentas de desenvolvimento. O artigo menciona as opções que eu tentei e em mais detalhes sobre o que eu parei. Será sobre um conjunto de ferramentas para o caso em que> 10 projetos para diferentes placas e um pouco sobre o desenvolvimento e instalação de bibliotecas.


Ambiente de desenvolvimento


Qual é o problema?


Provavelmente porque o Arduino não está focado em desenvolvedores profissionais, o ecossistema em torno do IDE padrão se distingue pela ausência das ferramentas usuais para mim:
  • Somente nas versões recentes apareceu algum tipo de gerenciamento de biblioteca, sem a semelhança de Gemfile / requirements.txt / package.json, ou seja, é impossível para o projeto especificar quais versões são usadas
  • nenhuma integração com git ou outros vcs
  • um editor de texto não se compara ao meu editor de texto favorito
  • não há como salvar a seleção do quadro no projeto
  • saída inconveniente de erros de compilação

O site do Arduino possui uma lista de ferramentas alternativas de desenvolvimento . Nesta lista, existem opções que, por várias razões, não tentei. Por exemplo, o Atmel Studio e o Visual Studio CE não consideraram. Eu queria encontrar uma ferramenta de suporte ao trabalho na linha de comando.


O que tentou


Ino


Ino - um projeto da empresa russa Amperka, um utilitário de linha de comando para o firmware do Arduino.
O projeto foi bastante popular,> 200 garfos. A última confirmação foi em abril de 2014, portanto, não funciona com as versões mais recentes do IDE (parece desde a versão 1.5).
Há um garfo vivo do Arturo , usei um pouco, mas houve problemas em alguns casos exóticos.


Arduino-makefile


Arduino-Makefile - compile e faça o download com o make. Arduino Due, Zero e outras placas de 32 bits não são suportadas. A diferença do IDE padrão é que os métodos devem ser declarados antes do uso; portanto, ao transferir projetos concluídos, pode ser necessário editar a fonte. Se bem me lembro, não consegui fazer amizade com o Arduino-Makefile e o SparkFun Pro Micro.


O que eu uso


PlatformIO


O PlatformIO é um excelente projeto criado por desenvolvedores da Ucrânia. Ele inclui um utilitário de linha de comando por meio do qual você pode começar a compilar e baixar programas para várias famílias de microcontroladores (Atmel AVR, Atmel SAM, ST STM32, TI MSP430 e outros). Ao mesmo tempo, diferentes conjuntos de bibliotecas são suportados (no site da PlatformIO, eles são chamados de estruturas): Arduino, Energia, mbed, bem como o código nativo do Atmel AVR, espressif, MSP430.
O PlatformIO foi inicialmente orientado para trabalhar a partir da linha de comando, também existem plugins para integração com editores de texto e IDEs: Atom, CLion, Eclipse, Emacs, NetBeans, Qt Creator, Sublime Text, Vim e Visual Studio
PlatformIO é especialmente adequado se você tiver:
  • um projeto para várias placas, ou seja, o mesmo código deve ser compilado para placas diferentes
  • , .. ,
  • ssh, PlatformIO Raspberry Pi

imagem


Arduino

Não vou recontar a documentação, aqui estão as instruções de instalação , para uso, consulte a seção Início
Rápido.A estrutura de pastas do projeto para PlatformIO difere do projeto Arduino IDE, cada projeto contém um arquivo platformio.ini que indica quais placas são usadas. Portanto, você não precisa escolher o painel certo o tempo todo.
Vou lhe dar um exemplo de como uso o PlatformIO ao desenvolver uma biblioteca para o Arduino. A biblioteca possui dois exemplos, cada um deles é um projeto no formato PlatformIO. O arquivo de configurações do projeto platformio.ini lista todos os painéis nos quais a biblioteca deve ser executada:
[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

Você pode compilar um exemplo para todas as placas com o comando:
platformio run

Você pode compilar apenas para uno como este:
platformio run -e uno

Faça o download do firmware em uno:
platformio run --target upload -e uno

Inicie o monitor da porta serial:
platformio serialports monitor

Aliases adicionados ao .zshrc para tornar os comandos mais curtos:
alias compile="platformio run"
alias upload="platformio run --target upload"
alias serial="platformio serialports monitor"

Com eles a mesma sequência de ações:
compile         #    
compile -e uno  #   uno
upload  -e uno  #  uno
serial          #   

Também há integração com o Travis CI e outras ferramentas de CI, mais detalhes aqui .
Na verdade, o Arduino IDE possui uma interface de linha de comando , mas está longe de ser perfeita.


Nuances do PlatformIO

O PlatformIO acelera o trabalho; é uma ferramenta mais flexível em comparação ao IDE do Arduino e facilita a automatização de tarefas de rotina. Há vários pontos a serem considerados:
  • compilação no PlatformIO nem sempre é equivalente à compilação no Arduino IDE, o que foi compilado no PlatformIO pode não compilar no Arduino IDE e vice-versa
  • a estrutura de pastas do projeto não corresponde à estrutura do Arduino IDE
  • nem todas as bibliotecas estão disponíveis para instalação através da platformio lib

Serial.print ("Poderia ser melhor");


Qual é o problema?


O padrão Serial.print () é um pouco inconveniente se você precisar imprimir o
nome e o valor da variável, por exemplo, para exibir "pin_2 = <estado pino 2>, pin_3 = <estado pino 3>", você deve fazer isso:
Serial.print("pin_2 = ");
Serial.print(digitalRead(2));

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

Ainda às vezes, desejo desabilitar parcial ou completamente a saída da série, por exemplo, se for usada apenas para depuração. Claro, você pode comentar as chamadas para Serial.print () para isso, mas eu gostaria de uma opção mais elegante.


O que tentou


arduinoLogging


Essa lib usa sintaxe do tipo printf para impressão, e também permite definir LOGLEVEL e, assim, desativar a saída de algumas ou de todas as mensagens. As mensagens são exibidas usando os métodos Error, Info, Debug e Verbose.
Um exemplo:
  #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 disponíveis

curingacomentárioExemplo
% 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


Os nomes dos níveis de mensagem Erro, Informações, Depuração e Verbose no arduinoLogging não são neutros. Erro não produz necessariamente um erro, é apenas uma mensagem exibida em qualquer LOGLEVEL (exceto NOOUTPUT).
Dado também alguns dos inconvenientes do printf, escrevi minha própria versão, advancedSerial .
Na verdade, advancedSerial é duas coisas: a capacidade de chamar print () e println () nos níveis de cadeia e mensagem.
  int a = 1;
  int b = 2;

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

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

Exemplo completo de Basic.ino
Como os nomes dos métodos coincidem com os nomes dos métodos padrão Serial.print () e Serial.println (), você pode opcionalmente substituir Serial por aSerial nas fontes.
Para o nome dos níveis de mensagem, escolhi v, vv, vvv, vvvv, uma maneira bastante comum de indicar os níveis de detalhe das mensagens exibidas, geralmente encontradas como sinalizadores -v, -vv etc.
Com esses nomes, é mais fácil editar um nível para outro, por exemplo, vv -> vvv é mais fácil que 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);
   }

Exemplo completo de Advanced.ino


Economia de memória

Se você quebrar a sequência na macro F (), ela não será carregada na memória (SRAM); portanto, para economizar memória, use F ():
  aSerial.print(F(" 16 "));

É claro que o uso do advancedSerial adiciona alguma sobrecarga em comparação com o Serial padrão. Tentei estimar qual deles. A seguir, apresento os resultados da compilação do Arduino Uno, pois ele possui 2 KB de memória e esse é o mínimo entre as placas que eu costumo usar.

Séries normais, sem nenhuma biblioteca:
  void setup() {
   Serial.begin(9600);
  }

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

espaço de armazenamento: 5%
memória dinâmica: 9%

avançado
  #include <advancedSerial.h>

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

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

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

espaço de armazenamento: 5% de
memória dinâmica: 10% de

exemplos / Advanced.ino
espaço de armazenamento: 9% de
memória dinâmica: 26% de

exemplos / Advanced.ino usando a macro F ()
espaço de armazenamento: 9% de
memória dinâmica: 10%
Acontece que o uso da memória aumenta ligeiramente. Mas o advancedSerial não é uma solução ideal em termos de recursos, existem implementações alternativas, por exemplo, Debug .


Instalação da biblioteca


Qual é o problema?


Por padrão, o IDE do Arduino instala bibliotecas globalmente e o esboço não registra exatamente quais bibliotecas são usadas (exceto as diretivas #include, é claro) e quais versões. Por esse motivo, para compilar o esboço em outro computador, você precisa saber para onde baixar as bibliotecas necessárias, novamente as versões das bibliotecas também precisam ser especificadas. Para evitar esses problemas, instalo bibliotecas apenas localmente, dentro da pasta de esboço. Abaixo estão duas maneiras de instalar bibliotecas localmente para o Arduino IDE e o PlatformIO.


Arduino IDE


Eu raramente uso o IDE do Arduino, talvez haja uma maneira melhor. O método é o seguinte: instale bibliotecas em uma subpasta do seu projeto e coloque links simbólicos (atalhos?) Para cada biblioteca na pasta libraries (na pasta em que as bibliotecas do Arduino IDE estão instaladas).
A propósito, se bem me lembro, o Arduino IDE compila todas as bibliotecas da pasta libraries ao compilar qualquer esboço, portanto o tempo de compilação aumenta se houver muitas bibliotecas nas bibliotecas. Outro motivo para não usar o IDE do Arduino.


PlatformIO


Todo projeto do PlatformIO possui uma subpasta lib na qual as bibliotecas podem ser colocadas. É quando instalando bibliotecas manualmente. O PlatformIO também possui um comando separado para instalar as bibliotecas platformio lib, infelizmente instala bibliotecas globalmente por padrão, para que as bibliotecas sejam instaladas localmente na subpasta lib, você precisa adicionar o projeto platformio.ini:
[platformio]
lib_dir = ./lib

Para mais informações sobre platformio lib, consulte a documentação .

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


All Articles