Arduino: Jak uzyskać kod typu płyty

13

Chcę napisać szkic, który można skompilować na różnych tablicach Arduino. Chcę wyświetlić na komputerze, która płyta jest aktualnie podłączona.

Oznacza to, że użytkownik łączy komputer za pomocą kabla USB z płytą Arduino / Teensy, w której uruchamia się mój szkic, a mój szkic informuje komputer za pośrednictwem portu szeregowego, która płyta jest podłączona. Na komputerze działa moja aplikacja C #, która odbiera te dane i wyświetla je.

Dlatego potrzebuję tablicy, która została wybrana po skompilowaniu szkicu:

Selektor tablic Arduino

Znalazłem kod na https://github.com/backupbrain/ArduinoBoardManager, ale nie daje poprawnych wyników (poza tym, że brakuje kilku płyt).

Oto fragment kodu:

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

Więc ten kod daje ten sam wynik (TABLICA = 0x04 = Mikro) dla Yun 16MHz, Micro, Leonardo y Esplora.

Czy jest jakiś sposób, aby uzyskać w moim kodzie C dokładnie ten ciąg, który użytkownik wybrał w menu kompilatora Arduino?

Elmue
źródło
2
Jeśli używasz arduino IDE do zbudowania oprogramowania układowego, nie ma przepisu, aby przekazać kompilatorowi #define na poziomie projektu, oprócz F_CPU ARDUINO i AVR_ cokolwiek . Być może trzeba będzie grauate przy użyciu makefile do budowania, zamiast arduinio IDE. Sprawdź stronę arduino.SE, Nick i Ignatio mają kilka dobrych przykładów.
MarkU
Nie mogę znaleźć niczego interesującego na Arduino.SE. (Czy to szwedzki?)
Elmue
@Elmue arduino.StackExchange.com to Arduino SE.
Avamander
Ahhh DOBRZE. Ale arduino.se istnieje!
Elmue
Mówiąc „Chcę wyświetlić na komputerze, która płyta jest aktualnie podłączona”, masz na myśli to, że wyświetla się, gdy działa skompilowany i przesłany szkic, czy wyświetlasz go podczas kompilacji szkicu lub gdy IDE po prostu tam siedzi z określonym deska dołączona? (W dwóch ostatnich przypadkach wybór płytki pojawia się w najniższej linii IDE 1.6.3, ale jeśli masz starsze lub inne IDE, może nie.) (Jeśli pierwszy przypadek ma zastosowanie, czy chcesz, aby pojawiał się na monitorze szeregowym ?)
James Waldby - jwpat7

Odpowiedzi:

17

Dzięki pomocy Charliego Hansona i jantje znalazłem uniwersalne rozwiązanie!

Ponieważ szkoda, że ​​każdy programista Arduino musi przejść ten sam ból, aby dowiedzieć się, jak uzyskać nazwę płyty, dlatego podam swój kod do wiadomości publicznej, aby każdy mógł go po prostu skopiować i wkleić.

Oto on:

#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

Możesz nawet wstawić ten kod do nowego pliku nagłówka i #include go w swoim projekcie.

PD Jeśli chcesz dowiedzieć się więcej o płytce procesora, poszukaj pliku avr_cpunames.h

Elmue
źródło
inna rzecz. zamiast używać „return”? ”;„ jeśli nie wiesz, użyj #pragma nazwa tablicy ostrzegawczej jest nieznana
jantje
1.) Zastąpiłem „?” z # błędem. 2.) Nie sądzę, że ciągi naprawdę stanowią problem. Zrozumiałeś, że tylko JEDEN ciąg zostanie skompilowany na końcu? Zobacz moją aktualizację, która wyjaśnia to powyżej. Najdłuższy ciąg ma 11 bajtów. Jeśli potrzebujesz zoptymalizować swój kod tak bardzo, że zależy ci na 11 bajtach, zalecam zdefiniowanie wyliczenia i zwrócenie go zamiast ciągu. Wtedy funkcja zwróci jeden bajt zamiast 11.
Elmue
3.) A co dotyczy łatwości konserwacji: Szkoda, że ​​muszę napisać taką funkcję. Powinno to już być częścią plików nagłówkowych, które są instalowane z kompilatorem i powinny być utrzymywane przez programistów i aktualizowane przy każdej nowej wersji.
Elmue
2) Popełniłem błąd, pisząc uwagę o rozmiarze. Zwróciłem na to uwagę 5 godzin temu. Przepraszam za to. 3) Utrzymanie jest problemem. W przeszłości napisałem bardzo podobny kod. Jestem pewien, że wielu innych też. Właśnie z powodu łatwości konserwacji preferuję „lepsze rozwiązanie IDE”. Jestem prawie pewien, że wszystkie „lepsze IDE” będą miały podobne rozwiązanie jak to, o którym wspomniałem w mojej odpowiedzi. Uznaj to za uzupełnienie: przerastasz Arduino IDE.
jantje
Jeśli napisałeś zły komentarz, najlepiej go usunąć.
Elmue
2

zauważ, że jest to mod systemu Windows, coś podobnego musi istnieć na Linuksie.

Pierwszy jest szybki i łatwy. Po prostu zmodyfikuj używane pliki platform.txt zgodnie z opisem poniżej. Wadą tego jest to, że będziesz musiał zmieniać pliki platform.txt w każdym wydaniu.

dodaj -DBOARD = \ "$ {build.board} \" do przepisu. Pozwoli to na

   const char boardName[]=BOARD;

Który daje ci ciąg „ARDUINO_AVR_LEONARDO” (dla leonardo) w boardName.

Drugi sposób to przejście na lepsze IDE (jak już zaproponowali inni). Jako twórca wtyczki arduino eclipse radziłbym używać wtyczki arduino eclipse. We wtyczce arduino eclipse możesz to zrobić w następujący sposób: Kliknij prawym przyciskiem myszy projekt-> właściwości-> arduino-> zakładka „wstaw opcje kompilacji”

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

w polu dołącz do C i C ++.

Spowoduje to, że powyższy kod zostanie skompilowany

Adendum

Nie wiedziałem, że chcesz „miłego imienia”. Nie jestem pewien, czy można to naprawić w platformie.txt w arduino IDE. We wtyczce arduino eclipse zmień powyższą poprawkę w

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

aby uzyskać ładną nazwę (dla Leonarda „Arduino Leonardo”) w Zdefiniuj tablicę.

jantje
źródło
Czy downvoter lub ktokolwiek inny byłby tak uprzejmy, aby sprecyzować, dlaczego ta odpowiedź wymaga głosowania niższego szczebla?
jantje
1.) Tak, StackExchange powinien zmusić każdego, kto zagłosuje, do napisania wyjaśnienia. (To nie była moja opinia) 2.) Nie ma potrzeby używania Eclipse do rozwiązania tego problemu. 3.) Zobacz moją odpowiedź tutaj.
Elmue
Elmue, 1) dziękuję za zgodę :-). 2) Zgadzam się. Pierwsza część odpowiedzi brzmi: jak to naprawić modyfikując platformę txt, aby działała w IDE Arduino. Twoja odpowiedź zawiera bardziej szczegółowe informacje na temat tego, jak to naprawić. Nie musisz mieć zaćmienia ani lepszego IDE. Wspomniano o lepszym rozwiązaniu, ponieważ ide Arduino musi przeanalizować pady board.txt, więc prawdopodobnie ma gdzieś te informacje i ma możliwość pracy bez potrzeby modyfikowania platformy.txt. Ponieważ bardzo dobrze znam wtyczkę arduino eclipse, podam przykład, jak to zrobić za pomocą tego narzędzia. 3) Zobacz moją edycję
jantje
Czy Eclise działa również z Teensy? Jakie inne zalety ma Exclipse?
Elmue
Tak, teensy jest obsługiwane przez wtyczkę arduino eclipse, ale będziesz musiał zmodyfikować platform.txt (powinien zostać naprawiony w teensyduino 1.28)
jantje
0

Dokładne nazwy w menu pochodzą z pliku deski.txt w twoim Arduino IDE (Arduino \ hardware \ arduino \ avr \ boards.txt). Myślę, że musisz sam przeanalizować plik i znaleźć tam wykrytą tablicę.

PW
źródło
Analizować plik? A skąd mam wiedzieć, który jest wybrany w menu?
Elmue
0

Jakiś czas temu zadałem powiązane pytanie .

Istnieje wewnętrzny plik * .h, który jest tworzony przez IDE i zawiera w sobie typ wybranej płyty. Lista możliwych opcji znajduje się w powiązanym pytaniu, ale tylko w przypadku płyt AVR. Uważam, że lista nie-AVR jest znacznie krótsza.

Wystarczy po prostu dodać kilka instrukcji warunkowych, aby przesłać PC poprawne informacje. Prosty przykład:

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

Jeśli chcesz odwołać się do typu planszy więcej niż raz w szkicu, użyj następującego formatu:

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

Ten ostatni jest znacznie bardziej uporządkowany, nawet jeśli potrzebujesz go tylko __BOARD_TYPEraz, ponieważ usuwa nieporęczny #ifdeffragment z twoich funkcji.

Będziesz oczywiście musiał napisać jedną dla każdej płyty, jakiej spodziewasz się użytkownik końcowy, i być może będziesz musiał zaktualizować tę listę, gdy pojawią się nowe modele.

CharlieHanson
źródło
Dzięki za odpowiedź. Bardzo mi pomogło. (Zobacz moją odpowiedź tutaj). Ale w kodzie jest błąd. Zamiast AVR_UNO musi to być ARDUINO_AVR_UNO.
Elmue
Możesz usunąć średniki na końcu #defines; nie są instrukcjami C i nie wymagają separatorów; w rzeczywistości separatory zostaną wstawione tam, gdzie używane są makra, link wewnątrz parens funkcji println (). (Jeśli średniki zostaną usunięte, ten komentarz nie będzie miał sensu dla późniejszych czytelników).
Zeph
0

Oryginalna odpowiedź jest nieaktualna, ponieważ dodano nowe tablice. Podstawowy test jest poprawny, ale nie jest jasne, skąd pochodzi lista desek.

Jeśli zlokalizujesz boards.txtplik i przejrzysz go (np. ~\Library\Arduino\hardware\arduino\avr\boards.txtNa komputerze Mac), każda płyta będzie miała wpis wzdłuż linii <BOARD>.build.board=<NAME>, więc na przykład MKR1000 będzie miał linię:

mkr1000.build.board=SAMD_MKR1000

Odpowiadająca #define mogą być generowane poprzedzając <NAME>z ARDUINO_więc w tym przykładzie następujący kod błędu dla MKR1000 pokładzie ...

#if defined(ARDUINO_SAMD_MKR1000) #error

Jason Crocker
źródło
Ta odpowiedź jest po prostu bla bla. Dlaczego po prostu nie opublikujesz pełnej listy wszystkich nowych plansz ze wszystkimi definicjami?
Elmue