Arduino: Como obter o tipo de placa no código

13

Quero escrever um esboço que possa ser compilado em diferentes placas do Arduino. Quero exibir no PC qual placa está conectada no momento.

Isso significa que o usuário conecta o PC via cabo USB à placa Arduino / Teensy na qual executa meu sketch e meu sketch informa ao PC via Serial qual placa está conectada. No PC, meu aplicativo C # recebe esses dados e os exibe.

Portanto, preciso do quadro selecionado quando o esboço foi compilado:

Seletor da placa Arduino

Encontrei o código em https://github.com/backupbrain/ArduinoBoardManager, mas ele não fornece resultados corretos (além do fato de que várias placas estão ausentes).

Aqui está um trecho do código:

static const uint8_t BOARD_MICRO= 0x04;

....
#elif defined(__AVR_Atmega32U4__) // Yun 16Mhz, Micro, Leonardo, Esplora
  static const uint8_t BOARD = 0x04;
  static const uint8_t NUM_BITS = 8;
  static const uint16_t CPU = __AVR_Atmega32U4__;
  static const unsigned long SRAM_SIZE = 2500;
  static const unsigned long EEPROM_SIZE = 1000;
  static const unsigned long FLASH_SIZE = 32000;
#elif defined(.....

Portanto, esse código fornece o mesmo resultado (BOARD = 0x04 = Micro) para Yun 16MHz, Micro, Leonardo e Esplora.

Existe alguma maneira de entrar no meu código C exatamente a string que o usuário selecionou no menu do compilador Arduino?

Elmue
fonte
2
Se você estiver usando o arduino IDE para construir o firmware, não há previsão de passar um #define no nível do projeto para o compilador, além de F_CPU ARDUINO e AVR_whatever . Pode ser necessário usar um makefile para compilar, em vez do IDE do arduinio. Verifique o site do arduino.SE, Nick e Ignatio têm alguns bons exemplos.
26616 MarkU
Não consigo encontrar nada de interessante no Arduino.SE. (É isso sueco?)
Elmue
@Elmue arduino.StackExchange.com é o Arduino SE.
Avamander
Ahhhh. ESTÁ BEM. Mas o arduino.se existe!
Elmue
Por "Quero exibir no PC qual placa está conectada no momento", você quer exibi-lo quando um esboço compilado e carregado é executado, ou exibi-lo enquanto um esboço está sendo compilado ou enquanto o IDE está apenas sentado lá com um determinado placa anexada? (Nos dois últimos casos, a seleção da placa aparece na linha mais baixa do IDE 1.6.3, mas se você tiver um IDE antigo ou diferente, talvez não.) (Se o primeiro caso for aplicável, você deseja que ele apareça no monitor serial ?)
James Waldby - jwpat7

Respostas:

17

Graças à ajuda de Charlie Hanson e Jantje, encontrei a solução universal!

Como é uma pena que todo programador do Arduino tenha que passar pela mesma dificuldade para descobrir como obter o nome do quadro, vou oferecer meu código ao público para que todos possam copiá-lo e colá-lo.

Aqui está:

#if defined(TEENSYDUINO) 

    //  --------------- Teensy -----------------

    #if defined(__AVR_ATmega32U4__)
        #define BOARD "Teensy 2.0"
    #elif defined(__AVR_AT90USB1286__)       
        #define BOARD "Teensy++ 2.0"
    #elif defined(__MK20DX128__)       
        #define BOARD "Teensy 3.0"
    #elif defined(__MK20DX256__)       
        #define BOARD "Teensy 3.2" // and Teensy 3.1 (obsolete)
    #elif defined(__MKL26Z64__)       
        #define BOARD "Teensy LC"
    #elif defined(__MK64FX512__)
        #define BOARD "Teensy 3.5"
    #elif defined(__MK66FX1M0__)
        #define BOARD "Teensy 3.6"
    #else
       #error "Unknown board"
    #endif

#else // --------------- Arduino ------------------

    #if   defined(ARDUINO_AVR_ADK)       
        #define BOARD "Mega Adk"
    #elif defined(ARDUINO_AVR_BT)    // Bluetooth
        #define BOARD "Bt"
    #elif defined(ARDUINO_AVR_DUEMILANOVE)       
        #define BOARD "Duemilanove"
    #elif defined(ARDUINO_AVR_ESPLORA)       
        #define BOARD "Esplora"
    #elif defined(ARDUINO_AVR_ETHERNET)       
        #define BOARD "Ethernet"
    #elif defined(ARDUINO_AVR_FIO)       
        #define BOARD "Fio"
    #elif defined(ARDUINO_AVR_GEMMA)
        #define BOARD "Gemma"
    #elif defined(ARDUINO_AVR_LEONARDO)       
        #define BOARD "Leonardo"
    #elif defined(ARDUINO_AVR_LILYPAD)
        #define BOARD "Lilypad"
    #elif defined(ARDUINO_AVR_LILYPAD_USB)
        #define BOARD "Lilypad Usb"
    #elif defined(ARDUINO_AVR_MEGA)       
        #define BOARD "Mega"
    #elif defined(ARDUINO_AVR_MEGA2560)       
        #define BOARD "Mega 2560"
    #elif defined(ARDUINO_AVR_MICRO)       
        #define BOARD "Micro"
    #elif defined(ARDUINO_AVR_MINI)       
        #define BOARD "Mini"
    #elif defined(ARDUINO_AVR_NANO)       
        #define BOARD "Nano"
    #elif defined(ARDUINO_AVR_NG)       
        #define BOARD "NG"
    #elif defined(ARDUINO_AVR_PRO)       
        #define BOARD "Pro"
    #elif defined(ARDUINO_AVR_ROBOT_CONTROL)       
        #define BOARD "Robot Ctrl"
    #elif defined(ARDUINO_AVR_ROBOT_MOTOR)       
        #define BOARD "Robot Motor"
    #elif defined(ARDUINO_AVR_UNO)       
        #define BOARD "Uno"
    #elif defined(ARDUINO_AVR_YUN)       
        #define BOARD "Yun"

    // These boards must be installed separately:
    #elif defined(ARDUINO_SAM_DUE)       
        #define BOARD "Due"
    #elif defined(ARDUINO_SAMD_ZERO)       
        #define BOARD "Zero"
    #elif defined(ARDUINO_ARC32_TOOLS)       
        #define BOARD "101"
    #else
       #error "Unknown board"
    #endif

#endif

Você pode até colocar esse código em um novo arquivo de cabeçalho e # incluí-lo em seu projeto.

PD Se você deseja conhecer adicionalmente à placa também o modelo da CPU, procure o arquivo avr_cpunames.h

Elmue
fonte
outra coisa. em vez de usar "return"? ";" quando você não sabe o uso #pragma nome placa de advertência é desconhecida
jantje
1.) Substituí o "?" com um # erro. 2.) Eu não acho que as strings sejam realmente um problema. Você entendeu que apenas uma string será compilada no final? Veja minha atualização que explica isso acima. A sequência mais longa é de 11 bytes. Se você precisar otimizar tanto o seu código que se preocupe com 11 bytes, recomendo definir uma enumeração e retorná-la em vez de uma string. Em seguida, sua função retornará um byte em vez de 11.
Elmue
3.) E o que diz respeito à capacidade de manutenção: É triste que eu tenha que escrever essa função. Isso já deve fazer parte dos arquivos de cabeçalho instalados com o compilador e deve ser mantido pelos desenvolvedores e atualizado a cada nova versão.
Elmue
2) Cometi um erro ao escrever a observação sobre o tamanho. Fiz uma observação sobre isso há 5 horas. Desculpe por isso. 3) A manutenção é um problema. Eu escrevi código muito semelhante no passado. Tenho certeza que muitos outros também. É a manutenção porque eu prefiro a "melhor solução IDE". Tenho certeza de que todos os "melhores IDE" terão uma solução semelhante à mencionada na minha resposta. Veja isso como um complemento: Você está superando o IDE do Arduino.
jantje
Se você escreveu um comentário errado, o melhor seria excluí-lo.
Elmue
2

note que este é um mod do Windows. Algo semelhante deve existir no Linux.

O primeiro é rápido e fácil. Simplesmente modifique os arquivos platform.txt que você está usando, conforme descrito a seguir. A desvantagem disso é que você precisará alterar os arquivos platform.txt a cada versão.

adicione -DBOARD = \ "$ {build.board} \" à receita. Isso permitirá

   const char boardName[]=BOARD;

O que fornece a string "ARDUINO_AVR_LEONARDO" (para o leonardo) em boardName.

A segunda maneira é mudar para um IDE melhor (como já proposto por outros). Como criador do plug-in do arduino eclipse, aconselho usar o plug-in do arduino eclipse. No plug-in do arduino eclipse, faça o seguinte: Clique com o botão direito do mouse no projeto-> propriedades-> arduino-> guia "opções de compilação"

-DBOARD=\"${A.BUILD.BOARD}\" 

no campo anexar ao C e C ++.

Isso fará com que o código acima compile

Adendo

Eu não sabia que você queria o "nome bonito". Não tenho certeza se isso pode ser corrigido no platform.txt no arduino IDE. No plug-in do arduino eclipse, altere a correção acima em

-DBOARD=\"${A.NAME}\"

para obter o belo nome (para o leonardo "Arduino Leonardo") na placa de definição.

jantje
fonte
O downvoter ou qualquer outra pessoa, por favor, seria gentil a ponto de especificar por que essa resposta precisa de votação rebaixada?
jantje
1.) Sim, o StackExchange deve forçar todos os que votam para baixo a escrever uma explicação. (Não foi o meu voto negativo) 2.) Não há necessidade de usar o Eclipse para resolver esse problema. 3.) Veja minha resposta aqui.
Elmue
Elmue, 1) obrigado por concordar :-). 2) eu concordo. A primeira parte da resposta é como você pode corrigir isso modificando a plataforma txt para que funcione no IDE do Arduino. Sua resposta entra em mais detalhes sobre como corrigir isso. Não há necessidade de eclipse ou IDE melhor para isso. A melhor solução de ide é mencionada porque um ide do Arduino precisa analisar o boards.txt, portanto provavelmente possui essas informações em algum lugar e tem a possibilidade de trabalhar sem a necessidade de modificar o platform.txt. Como conheço muito bem o plug-in do arduino eclipse, dou um exemplo de como fazer isso com esta ferramenta. 3) Veja minha edição
jantje 1/16/16
Eclise também trabalha com Teensy? Que outras vantagens tem o Exclipse?
precisa saber é
Sim teensy é suportado pelo arduino eclipse plugin, mas você vai ter que mod o platform.txt (deve ser fixado em teensyduino 1,28)
jantje
0

Os nomes exatos no menu vêm do arquivo boards.txt no IDE do Arduino (Arduino \ hardware \ arduino \ avr \ boards.txt). Eu acho que você teria que analisar o arquivo sozinho e encontrar a placa detectada lá.

PW
fonte
Analisar o arquivo ?? E como sei qual é selecionado no menu?
Elmue
0

Eu fiz uma pergunta relacionada há um tempo atrás.

Existe um arquivo interno * .h, criado pelo IDE, e contém o tipo de placa que foi selecionada. A lista de opções possíveis é fornecida na pergunta vinculada, mas apenas para placas AVR. Eu acredito que a lista não-AVR é ​​muito menor.

É simplesmente uma questão de adicionar algumas instruções condicionais para enviar ao PC as informações corretas. Um exemplo simples:

//...within your code, perhaps during setup()...
#ifdef ARDUINO_AVR_UNO
    serial.println("UNO");
#endif
#ifdef ARDUINO_AVR_LEONARDO
    serial.println("LEONARDO");
#endif
// etc...

Se você precisar consultar o tipo de quadro mais de uma vez no esboço, use o seguinte formato:

//...BEFORE setup(), or otherwise in the global namespace...
#ifdef ARDUINO_AVR_UNO
    #define __BOARD_TYPE "UNO"
#endif
#ifdef ARDUINO_AVR_LEONARDO
    #define __BOARD_TYPE "LEONARDO"
#endif
// etc...

// within your code, wherever necessary:
serial.println(__BOARD_TYPE);

O último é muito mais organizado, mesmo que você precise apenas __BOARD_TYPEuma vez, pois remove o #ifdefpedaço pesado de suas funções.

Obviamente, você precisará escrever um para cada quadro que espera que o usuário final possa ter, e possivelmente precisará atualizar esta lista à medida que novos modelos aparecerem.

CharlieHanson
fonte
Obrigado pela sua resposta. Isso me ajudou muito. (Veja minha resposta aqui) Mas há um erro no seu código. Em vez de AVR_UNO, ele deve ser ARDUINO_AVR_UNO.
Elmue
Você pode remover os pontos e vírgulas no final dos seus #defines; eles não são instruções C e não precisam de separadores; de fato, os separadores serão inseridos onde as macros são usadas, vinculadas dentro dos parênteses da função println (). (Se o ponto e vírgula for removido, esse comentário não fará sentido para os leitores posteriores).
precisa
0

A resposta original está desatualizada à medida que novas placas foram adicionadas. O teste básico está correto, mas não está claro de onde vem a lista de painéis.

Se você localizar o boards.txtarquivo e examiná-lo (por exemplo, ~\Library\Arduino\hardware\arduino\avr\boards.txtem um Mac), cada placa terá uma entrada ao longo das linhas de <BOARD>.build.board=<NAME>, portanto, por exemplo, o MKR1000 teria uma linha:

mkr1000.build.board=SAMD_MKR1000

O #define correspondente pode ser gerado prefixando o <NAME>com ARDUINO_neste exemplo, o código a seguir apresentará um erro para uma placa MKR1000 ...

#if defined(ARDUINO_SAMD_MKR1000) #error

Jason Crocker
fonte
Esta resposta é apenas bla bla. Por que você simplesmente não publica uma lista completa de todos os novos painéis com todas as definições?
Elmue