Arduino:如何在代码中获取板子类型


13

我想写一个可以在不同的Arduino板上编译的草图。我想在PC上显示当前连接的板。

这意味着用户通过USB电缆将PC连接到Arduino / Teensy板,在其中运行我的草图,而我的草图通过Serial告诉PC哪个板被连接。在PC上运行我的C#应用​​程序,该应用程序接收此数据并显示它。

因此,我需要在编译草图时选择的板:

Arduino开发板选择器

我在https://github.com/backupbrain/ArduinoBoardManager上找到了代码, 但是它没有给出正确的结果(除了缺少几块板的事实)。

这里是代码片段:

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(.....

因此,对于Yun 16MHz,Micro,Leonardo y Esplora,此代码给出的结果相同(BOARD = 0x04 = Micro)。

有什么办法可以让我的C代码准确地获得用户在Arduino编译器菜单中选择的字符串?


2
如果您使用的是arduino IDE来构建固件,除了F_CPU ARDUINO和AVR_whatever之外,没有任何规定将项目级别的#define传递给编译器。您可能需要使用makefile而不是arduinio IDE进行构建。检查arduino.SE网站,Nick和Ignatio都有一些很好的例子。
MarkU '16

我在Arduino.SE上找不到任何有趣的东西。(瑞典语吗?)
Elmue '16

@Elmue arduino.StackExchange.com是Arduino SE。
Avamander '16

啊 好。但是arduino.se存在!
Elmue '16

所谓“我想在PC上显示当前连接的板”,是指在运行已编译并上传的草图时显示它,还是在编译草图时显示IDE,或在IDE仅与特定的ID坐在一起时显示它。附板吗?(在后两种情况下,电路板选择显示在1.6.3 IDE的最低行中,但是如果您使用的是较旧或不同的IDE,则可能没有。)(如果适用第一种情况,是否希望它出现在串行监视器中? ?)
詹姆斯·沃尔德比-jwpat7'2

Answers:


17

多亏了查理·汉森(Charlie Hanson)和詹提(Jantje)的帮助,我找到了通用解决方案!

遗憾的是,每个Arduino程序员都必须经历同样的痛苦才能弄清楚如何获得板名,所以我将向公众公开我的代码,以便每个人都可以复制和粘贴它。

这里是:

#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

您甚至可以将此代码放入新的头文件中,并将其#include到您的项目中。

PD如果您还想了解板子和CPU型号,请搜索文件avr_cpunames.h


另一件事。而不是使用“ return”?“;” 当您不知道使用#pragma警告板名称时未知
jantje

1.)我已替换为“?” 带有#错误。2.)我认为字符串不是真正的问题。您确实知道最后只会编译一个字符串吗?请参阅我的更新,上面对此进行了解释。最长的字符串是11个字节。如果您需要优化代码以至于只关心11个字节,那么我建议定义一个枚举并返回它而不是字符串。然后你的函数会返回一个字节而不是11
Elmue

3.)与可维护性有关的问题:可悲的是我不得不编写这样的函数。这应该已经是与编译器一起安装的头文件的一部分,并且应该由开发人员维护并随每个新版本进行更新。
Elmue '16

2)在尺寸上写备注时我弄错了。我在5个小时前发表了评论。抱歉 3)可维护性是一个问题。我过去写过非常相似的代码。我相信还有很多其他人。这就是为什么我更喜欢“更好的IDE解决方案”的可维护性。我很确定所有“更好的IDE”都将具有与我在回答中提到的解决方案相似的解决方案。补充一下:您已经不再是Arduino IDE。
jantje '16

如果您输入了错误的评论,最好将其删除。
Elmue

2

请注意,这是Windows Mod,Linux上必须存在类似的东西。

首先是快速简便。只需按照下面的说明修改正在使用的platform.txt文件即可。缺点是您需要在每个发行版中更改platform.txt文件。

在配方中添加-DBOARD = \“ $ {build.board} \”。这将允许

   const char boardName[]=BOARD;

在boardName中为您提供字符串“ ARDUINO_AVR_LEONARDO”(对于莱昂纳多)。

第二种方法是切换到更好的IDE(就像其他人已经提出的那样)。作为arduino eclipse插件的创建者,我建议使用arduino eclipse插件。在arduino eclipse插件中,您可以执行以下操作:右键单击project-> properties-> arduino-> tab的“ compile options”

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

在“附加到C和C ++”字段中。

这将使上面的代码得以编译

附录

我不知道您想要“好名字”。我不确定可以在arduino IDE中的platform.txt中修复此问题。在arduino eclipse插件中更改上面的修复

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

在定义板上获得漂亮的名称(对于leonardo“ Arduino Leonardo”)。


请拒绝者或其他任何人请客,以说明为什么答案需要拒绝吗?
jantje '16

1.)是的,StackExchange应该强迫每个投票否决的人写一个解释。(这不是我的不赞成意见)2.)无需使用Eclipse即可解决此问题。3.)在这里查看我的答案。
Elmue'3

Elmue,1)感谢您同意:-)。2)我同意。答案的第一部分是如何修复平台txt以使其在Arduino IDE中正常工作。您的答案将更详细地说明如何解决此问题,无需Eclipse或任何更好的IDE。提到了更好的ide解决方案,因为Arduino ide需要解析boards.txt,因此它可能在某处具有此信息,并且有可能无需修改platform.txt就可以工作。当我碰巧非常了解arduino eclipse插件时,我举了一个如何使用此工具的示例。3)查看我的编辑内容
jantje '16

Eclise是否也可以与Teensy合作?Exclipse还有什么其他优点?
Elmue

是的,arduino eclipse插件支持teensy,但您必须修改platform.txt(应在teensyduino 1.28中修复)
jantje

0

菜单中的确切名称来自Arduino IDE中的board.txt文件(Arduino \ hardware \ arduino \ avr \ boards.txt)。我认为您必须自己解析文件并在此处找到检测到的板。


解析文件 我怎么知道菜单中选哪个?
Elmue '16

0

我前段时间问了一个相关的问题

存在一个内部* .h文件,该文件由IDE创建,并在其中保存所选板的类型。链接的问题中给出了可能的选项列表,但仅适用于AVR板。我相信非AVR的清单要短得多。

只需添加一些条件语句即可向PC发送正确的信息。一个简单的例子:

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

如果您需要在草图中多次引用电路板类型,请使用以下格式:

//...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);

即使您只需要__BOARD_TYPE一次,后者也会更加整洁,因为它消除了#ifdef函数中的繁琐代码块。

当然,您将必须为最终用户希望拥有的每块板写一个,并且可能需要在出现新型号时更新此列表。


感谢您的回答。这对我很有帮助。(在这里查看我的答案)但是您的代码中有错误。必须是ARDUINO_AVR_UNO而不是AVR_UNO。
Elmue'3

您可能希望在#define的末尾删除分号;它们不是C语句,不需要分隔符;实际上,分隔符将插入到使用宏的位置,并链接到println()函数的括号内。(如果删除分号,则此注释对以后的读者没有意义)。
Zeph

0

由于添加了新板,原始答案已过时。基本测试是正确的,但尚不清楚板列表来自何处。

如果找到boards.txt文件并进行浏览(例如~\Library\Arduino\hardware\arduino\avr\boards.txt,在Mac上),则每个板子上都有一个沿的行<BOARD>.build.board=<NAME>,因此,例如,MKR1000会有一行:

mkr1000.build.board=SAMD_MKR1000

可以通过在前面<NAME>加上来生成相应的#define ,ARDUINO_因此在此示例中,对于MKR1000板,以下代码将出错。

#if defined(ARDUINO_SAMD_MKR1000) #error


这个答案就是bla bla。您为什么不简单地发布所有带有所有定义的新板的完整列表?
Elmue
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.