Arduino: как получить тип доски в коде

13

Я хочу написать эскиз, который можно скомпилировать на разных платах Arduino. Я хочу показать на ПК, какая плата в данный момент подключена.

Это означает, что пользователь подключает ПК через USB-кабель к плате Arduino / Teensy, на которой выполняется мой эскиз, а мой эскиз сообщает ПК через Serial, какая плата подключена. На ПК запускается мое приложение C #, которое получает эти данные и отображает их.

Поэтому мне нужна доска, которая была выбрана при компиляции эскиза:

Arduino Board селектор

Я нашел код на 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(.....

Таким образом, этот код дает тот же результат (BOARD = 0x04 = Micro) для Yun 16 МГц, Micro, Leonardo y Esplora.

Есть ли способ получить в моем C-коде именно ту строку, которую пользователь выбрал в меню компилятора Arduino selecetd?

Elmue
источник
2
Если вы используете arduino IDE для сборки прошивки, нет никаких условий для передачи уровня проекта #define компилятору, кроме F_CPU ARDUINO и AVR_whothing . Возможно, вам придется использовать make-файл для сборки вместо arduinio IDE. Проверьте сайт arduino.SE, у Ника и Игнатио есть несколько хороших примеров.
MarkU
Я не могу найти ничего интересного на Arduino.SE. (Это шведский?)
Elmue
@ Elmue arduino.StackExchange.com - это Arduino SE.
Avamander
Аааа. OK. Но arduino.se существует!
Elmue
Под «Я хочу показать на ПК, какая плата в данный момент подключена», вы хотите отобразить ее, когда запускается скомпилированный и загруженный эскиз, или отображать его во время компиляции эскиза, или когда IDE просто сидит там с определенным доска прилагается? (В последних двух случаях выбор платы отображается в нижней строке IDE 1.6.3, но если у вас более старая или другая IDE, возможно, нет.) (Если применяется первый случай, хотите ли вы, чтобы он отображался на последовательном мониторе ?)
Джеймс Уолдби - jwpat7

Ответы:

17

Благодаря помощи Чарли Хансона и Янтье я нашел универсальное решение!

Жаль, что каждому программисту 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

Вы даже можете поместить этот код в новый заголовочный файл и включить его в свой проект.

PD Если вы хотите узнать дополнительно к плате также модель процессора, найдите файл avr_cpunames.h

Elmue
источник
еще одна вещь. вместо использования "return"? ";" когда вы не знаете, используйте #pragma, предупреждающее имя неизвестно
jantje
1.) Я заменил "?" с # ошибкой. 2.) Я не думаю, что строки действительно проблема. Вы понимали, что только ОДНА строка будет скомпилирована в конце? Смотрите мое обновление, которое объясняет это выше. Самая длинная строка составляет 11 байтов. Если вам нужно оптимизировать свой код настолько, что вас волнует 11 байтов, я рекомендую определить перечисление и вернуть его вместо строки. Тогда ваша функция вернет один байт вместо 11.
Elmue
3.) А что касается ремонтопригодности: грустно, что мне приходится писать такую ​​функцию. Это должно быть уже частью заголовочных файлов, которые устанавливаются вместе с компилятором, и должно поддерживаться разработчиками и обновляться с каждой новой версией.
Elmue
2) Я сделал ошибку при написании замечания по размеру. Я сделал замечание по этому 5 часов назад. Простите за это. 3) ремонтопригодность является проблемой. Я написал очень похожий код в прошлом. Я уверен, что многие другие тоже. Именно из-за удобства обслуживания я предпочитаю «лучшее решение IDE». Я уверен, что все «лучшие IDE» будут иметь решение, подобное тому, которое я упомянул в своем ответе. Рассматривайте это как дополнение: вы перерастаете IDE Arduino.
января
Если вы написали неправильный комментарий, лучше всего удалить его.
Эльмуе
2

обратите внимание, что это мод для Windows, что-то подобное должно существовать в Linux.

Первый быстрый и легкий. Просто измените файлы platform.txt, которые вы используете, как описано ниже. Недостатком этого является то, что вам нужно будет менять файлы platform.txt с каждым выпуском.

добавьте -DBOARD = \ "$ {build.board} \" к рецепту. Это позволит

   const char boardName[]=BOARD;

Что дает вам строку "ARDUINO_AVR_LEONARDO" (для Леонардо) в BoardName.

Второй способ - перейти на более совершенную IDE (как уже было предложено другими). Как создатель плагина arduino eclipse я бы посоветовал использовать плагин arduino eclipse. В плагине arduino eclipse вы делаете это следующим образом: Щелкните правой кнопкой мыши по проекту -> свойства -> arduino-> вкладка «Параметры компиляции»

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

в приложении к полю C и C ++.

Это сделает приведенный выше код для компиляции

Adendum

Я не знал, что вы хотели "красивое имя". Я не уверен, что это можно исправить в платформе .txt в IDE Arduino. В плагине arduino eclipse измените исправление выше в

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

чтобы получить красивое имя (для леонардо "Arduino Leonardo") в определении доски.

jantje
источник
Будет ли downvoter или кто-либо еще, пожалуйста, так любезно указать, почему это ответ нуждается в понижении?
Янв
1.) Да, StackExchange должен заставить всех, кто проголосует, написать объяснение. (Это был не мой отрицательный отзыв) 2.) Нет необходимости использовать Eclipse для решения этой проблемы. 3.) Смотрите мой ответ здесь.
Elmue
Elmue, 1) спасибо за согласие :-). 2) Я согласен. Первая часть ответа - как это исправить, изменив платформу txt, чтобы она работала в Arduino IDE. В вашем ответе более подробно рассказывается, как это исправить. Для этого не нужно иметь затмение или какую-либо лучшую среду IDE. Упоминается лучшее решение для ide, поскольку Arduino-иду необходимо проанализировать board.txt, поэтому, вероятно, он где-то хранит эту информацию и имеет возможность работать без необходимости изменения platform.txt. Поскольку я очень хорошо знаю плагин arduino eclipse, я приведу пример, как это сделать с помощью этого инструмента. 3) См. Мое редактирование
jantje
Eclise также работает с Teensy? Какими еще преимуществами обладает Exclipse?
Эльмуе
Да, teensy поддерживается плагином arduino eclipse, но вам нужно будет изменить платформу platform.txt (должно быть исправлено в teensyduino 1.28)
jantje
0

Точные названия в меню взяты из файлаboards.txt в вашей среде разработки Arduino (Arduino \ hardware \ arduino \ avr \ boards.txt). Я думаю, вам придется проанализировать файл самостоятельно и найти там обнаруженную плату.

PW
источник
Разобрать файл ?? И как я узнаю, какой из них находится в меню?
Elmue
0

Я задал связанный вопрос некоторое время назад.

Существует внутренний файл * .h, который создается в среде IDE и в котором хранится выбранный тип платы. Список возможных опций приведен в связанном вопросе, но только для плат AVR. Я считаю, что список не-AVR намного короче.

Это просто вопрос добавления некоторых условных операторов для отправки ПК правильной информации. Простой пример:

//...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кусок из ваших функций.

Вам, конечно, придется написать по одному для каждой платы, которую, как вы ожидаете, может иметь ваш конечный пользователь, и вам, возможно, придется обновлять этот список по мере появления новых моделей.

CharlieHanson
источник
Спасибо за Ваш ответ. Это мне очень помогло. (Смотрите мой ответ здесь) Но в вашем коде есть ошибка. Вместо AVR_UNO это должно быть ARDUINO_AVR_UNO.
Эльмуе
Возможно, вы захотите удалить точку с запятой в конце вашего #defines; они не являются операторами C и не нуждаются в разделителях; фактически, разделители будут вставлены там, где используются макросы, ссылки внутри паренов функции println (). (Если точки с запятой удалены, этот комментарий не будет иметь смысла для последующих читателей).
Зеф
0

Оригинальный ответ устарел, так как были добавлены новые доски. Базовый тест правильный, но неясно, откуда берется список плат.

Если вы найдете boards.txtфайл и просмотрите его (например, ~\Library\Arduino\hardware\arduino\avr\boards.txtна Mac), на каждой плате будет запись по строкам <BOARD>.build.board=<NAME>, например, у MKR1000 будет строка:

mkr1000.build.board=SAMD_MKR1000

Соответствующий #define может быть сгенерирован с префиксом <NAME>with, ARDUINO_поэтому в этом примере следующий код выдаст ошибку для платы MKR1000 ...

#if defined(ARDUINO_SAMD_MKR1000) #error

Джейсон Крокер
источник
Этот ответ просто бла бла. Почему бы вам просто не опубликовать полный список всех новых досок со всеми определениями?
Эльмуэ