STM32Duino: Arduino dla STM32 (cz. 6)

W poprzednich artykułach z cyklu poświęconego STM32duino pokazałem jak skonfigurować środowisko programistyczne Arduino do pracy z mikrokontrolerami STM32 oraz jak zrealizować aplikacje używające podstawowych peryferiów mikrokontrolera. W tej części przekonamy się, że STM32duino to nie tylko wygodna platforma do pracy z peryferiami, ale również z podzespołami dołączonymi do mikrokontrolera.

Arduino i STM32 – przygotowanie do pracy

Pracę należy rozpocząć uruchamiając środowisko programistyczne Arduino (STM32duino). Przygotowanie do pisania kodu obejmuje kilka prostych kroków:

  • W pierwszym kroku konieczne jest stworzenie nowego projektu (zwanego sketchem w Arduino). W tym celu użytkownik wybiera z menu głównego środowiska programistycznego kolejno File i New (skrót klawiaturowy CTRL+N).
  • Następnie należy wskazać używaną platformę sprzętową. Na potrzeby poprzednich artykułów autor używał płytki NUCLEO-L476RG z 64-pinowym układem STM32L476RG. NUCLEO-L476RG doskonale sprawdza się jako tania platforma do nauki mikrokontrolera i prototypowania. Nie jest to jednak platforma wyposażona w podzespoły dołączone do mikrokontrolera. Z tego powodu tym razem wybór padł na lepiej wyposażoną płytkę STM32L4 Discovery kit IoT node (B-L475E-IOT01A) z mikrokontrolerem STM32L475VG. Aby wybrać platformę sprzętową w środowisku Arduino należy ponownie użyć menu głównego. Wybór platformy przebiega w dwóch etapach. Najpierw klikając Tools i Board wybrać należy Discovery. Następnie wybierając Tools i Board Part Number wybrać należy STM32L475VG-DISCOVERY-IOT.
  • W ostatnim kroku należy zapisać projekt na dysku twardym. Jednocześnie warto zmienić nazwę projektu na bardziej intuicyjną, gdyż domyślna nazwa zawiera tylko słowo sketch oraz nazwę aktualnego miesiąca i dnia.

Chcąc zapisać projekt STM32duino oraz zmienić jego nazwę użytkownik znowu korzysta z menu głównego środowiska programistycznego wybierając kolejno File i Save as… (skrót klawiaturowy CTRL+Shift+S). W ten sposób otworzone zostanie okno, które pozwoli na wybranie ścieżki na dysku twardym, pod którą zapisany zostanie projekt. Jednocześnie okno pozwala na wpisanie nowej nazwy projektu.

Rys. 1. Kolejne kroki przygotowania środowiska Arduino do pisania kodu dla wybranej platformy z układem STM32

Arduino i STM32 – struktura kodu

Każdy stworzony od nowa projekt (sketch) zawiera domyślnie kilka linii kodu tworzących szkielet aplikacji. Kod ten pokazano w listingu 1. Składa się on z dwóch funkcji:

  • Pierwsza nosi nazwę setup. Jej przeznaczenie można łatwo rozszyfrować zapoznając się z komentarzem. Programista umieszcza w niej kod, który ma zostać wykonany tylko raz, na początku aplikacji, a więc po doprowadzeniu napięcia zasilania do mikrokontrolera. Są to głównie funkcje konfigurujące peryferia mikrokontrolera (np. ustawiające parametry przetwornika A/C lub interfejsu UART) lub inicjujące podzespoły zewnętrzne (np. moduł Bluetooth).
  • Druga funkcja otrzymała nazwę loop. Ponownie w rozszyfrowaniu jej przeznaczenia pomaga komentarz. Jest to nieskończona pętla, w której programista umieszcza funkcje wykonywane cyklicznie (np. odczyt stanu przycisku lub odebranie danych z czujnika).

Zatem programista tworzy kod aplikacji uzupełniając ciała funkcji setup i loop o dodatkowy kod języka Arduino. Kod ten składa się z typowych elementów języka programowania takich jak zmienne, funkcje, instrukcje warunkowe czy też operacje matematyczne.

Listing 1. Kod nowego projektu w środowisku programistycznym Arduino (STM32duino)

Płytka STM32L4 Discovery kit IoT node – podstawowe informacje

Platformą sprzętową wybraną na potrzeby tego projektu w STM32duino jest STM32L4 Discovery kit IoT node (rysunek 2). Warto przyjrzeć się bliżej co jest wyposażeniem tego zestawu.
Użyty mikrokontroler to układ STM32L476VG bazujący na rdzeniu ARM Cortex-M4 i dysponujący pamięcią Flash i SRAM o pojemności odpowiednio 1MB i 128kB. Model ten należy do rodziny STM32L4, która łączy niski pobór prądu z wysoką mocą obliczeniową (do 80MHz) oraz bogatym wyposażeniem. Układ zamknięty jest w obudowie LQFP i dysponuje 100 pinami.

Zasoby wewnętrzne pamięci mikrokontrolera rozszerzone są o dodatkowy układ pamięci Flash (64-Mbit). Jest on połączony z mikrokontrolerem poprzez interfejs Quad-SPI.

Płytka dysponuje bogatym wyposażeniem do komunikacji bezprzewodowej. Składa się na nie moduł Wi-Fi zgodny ze standardem 802.11 b/g/n, moduł Bluetooth V4.1, oraz moduł do komunikacji w paśmie sub-GHz. Ponadto podzespołem o cechach komunikacji bezprzewodowej jest również układ pamięci NFC.

Płytka wyposażona jest też w komponenty umożliwiające realizację prostego interfejsu użytkownika. Jest to zestaw diod LED użytkownika oraz przycisk użytkownika.

Wyposażenie zestawu uzupełnia pokaźny zestaw czujników. Są to: 3-osiowy akcelerometr, 3-osiowy magnetometr, 3-osiowy żyroskop, czujnik ciśnienia atmosferycznego, czujnik wilgotności, czujnik odległości oraz mikrofon.

Na płytce zintegrowano urządzenie ST-Link. Jest to programator/debugger z interfejsem SWD do komunikacji z mikrokontrolerem i z interfejsem USB do zapewnienia łączności z komputerem. Płytka dodatkowo dysponuje drugim gniazdem USB. Jest ono połączone z interfejsem USB kontrolowanym przez mikrokontroler.

Większość portów I/O mikrokontrolera została wykorzystana do komunikacji z podzespołami otaczającymi układ STM32. Nieużyte porty I/O zostały połączone z listwami sygnałowymi zgodnymi ze standardem Arduino. Jest to grupa sześciu pinów analogowych oraz grupa szesnastu pinów cyfrowych (mogących służyć np. jako interfejs UART/SPI/I2C, wyjścia sygnału PWM lub cyfrowe wyjścia/wejścia). Są one uzupełnione o linie zasilania (np. masę, 3.3V, 5V) oraz linię resetu mikrokontrolera.

Rys. 2. Widok płytki STM32L4 Discovery kit IoT node

Przykłady aplikacji Arduino dla STM32

W ramach poprzednich odcinków cyklu o Arduino i STM32 nacisk położono na pracę niskopoziomową, konkretnie na skonfigurowanie, włączenie i użycie peryferiów wbudowanych w mikrokontroler.

Arduino to jednak nie tylko biblioteki pozwalające na sterowanie peryferiami mikrokontrolera, ale również biblioteki dla podzespołów połączonych z mikrokontrolerem. Temu właśnie aspektowi wysokopoziomowej pracy z mikrokontrolerem dedykowany jest ten artykuł.

Biblioteka przykładów

Zestaw przykładowych aplikacji dla Arduino udostępnia strona internetowa https://www.arduinolibraries.info/. Jako że jest to strona wspierająca wszystkie platformy sprzętowe, należy odnaleźć odnośnik do rodziny STM32 i na niego kliknąć. Na dzień pisania artykułu dostępnych jest 45 różnych pakietów z przykładami dla STM32.

Funkcjonalność przykładów dla STM32duino jest bardzo różna. Są to między innymi:

  • Przykład obsługi klawiatur pojemnościowych
  • System plików (FatFs) z zapisem/odczytem do/z karty SD
  • Obsługa modułu Wi-Fi
  • Aplikacja sterująca modułem Bluetooth
  • Przykłady dla płytek rozszerzeniowych X-Nucleo (z modułem Bluetooth, z modułem LoRa, z czujnikami, z kontrolerem silnika)
  • Aplikacja z energooszczędnymi trybami pracy mikrokontrolera
  • Przykład użycia systemu operacyjnego FreeRTOS
  • Aplikacje dla czujników środowiskowych i MEMS
  • Komunikacja w oparciu o stos TCP/IP
  • Obsługa zegara RTC
  • Aplikacja dla czujnika VL53L0X

Przykład z VL53L0X

Spośród wszystkich dostępnych aplikacji przykładowych dla STM32duino wybierzmy jedną i poddajmy ją bardziej szczegółowej analizie. Autor zdecydował się na aplikację z układem VL53L0X.
VL53L0X to układ firmy STMicroelectronics będący czujnikiem odległości.

Zastosowana w nim technologia pomiarowa nosi nazwę ToF (Time of Flight) i polega ona na określaniu odległości na podstawie czasu, który upłynął pomiędzy emisją fali i jej odebraniu po odbiciu od obiektu. Układ pozwala na pomiar odległości do 2 metrów. Komunikacja między czujnikiem i mikrokontrolerem realizowana jest za pomocą interfejsu I2C. Układ VL53L0X jest jednym z podzespołów umieszczonych na płytce STM32L4 Discovery kit IoT node.

Wszystkie przykładowe aplikacje STM32duino dla mikrokontrolerów STM32 dostępne są pod adresem https://www.arduinolibraries.info/architectures/stm32. Na liście należy odszukać pozycję o nazwie STM32duino VL53L0X i kliknąć na nią. Na skutek tego otworzona zostanie strona dedykowana temu przykładowi.

Odnaleźć tu można informacje o działaniu aplikacji oraz o autorze, a co najistotniejsze, link do pobrania biblioteki. Zapisany w ten sposób na dysku twardym komputera plik należy rozpakować. W folderze examples znajdują się trzy przykłady. Autor użył pierwszego z nich o nazwie DISCO_IOT_53L0A1_DataLogTerminal. Dwukrotne kliknięcie myszą na projekt (sketch) pozwala na wczytanie przykładu do środowiska Arduino.

Program

Aplikacja wykorzystuje trzy peryferia mikrokontrolera: port wejścia/wyjścia do sterowania diodą LED, interfejs I2C do komunikacji z czujnikiem oraz interfejs szeregowy do komunikacji z komputerem. Aplikacja nieustannie powtarza wykonanie następujących zadań: zamiganie diodą LED, odczytanie wyniku pomiaru z czujnika, wysłanie tej informacji do komputera. Zaprezentowany na listingu 2 kod zawiera kolejno:

  • Przed funkcją setup:
    • dodanie przez dyrektywę include do projektu bibliotek: do interfejsu I2C i do API czujnika VL53L0X,
    • stworzenie dwóch komponentów typu TwoWire oraz VL53L0X, określających które piny mikrokontrolera będą używane,
  • wewnątrz funkcji setup:
    • stworzenie zmiennej statusowej typu int,
    • następnie wywołanie funkcji pinMode konfigurującej wyprowadzenie mikrokontrolera pod kątem sterowania diodą LED,
    • w dalszej kolejności wywołanie funkcji Serial.begin włączającej interfejs UART i konfigurującej prędkość transmisji,
    • wywołanie funkcji WIRE1.begin włączającej interfejs I2C,
    • dalej wywołanie metody VL53L0X_Off wyłączającej czujnik VL53L0X,
    • wywołanie metody InitSensor inicjującej czujnik VL53L0X i przypisującej wartość zmiennej statusowej,
    • sprawdzenie wartości zmiennej statusowej i w przypadku wartości świadczącej o błędzie wywołanie funkcji Serial.println wysyłającej stosowny komunikat do komputera,
  • wewnątrz funkcji loop:
    • zamiganie diodą LED poprzez dwukrotne wywołanie funkcji digitalWrite, i jednokrotne wywołanie funkcji delay,
    • stworzenie zmiennej typu uint32_t przechowującej wynik pomiaru czujnika oraz zmiennej statusowej typu int,
    • wywołanie metody GetDistance odczytującej z czujnika wynik pomiaru i wpisującej go do zmiennej, dodatkowo też wpisującej wartość do zmiennej statusowej,
    • sprawdzenie wartości zmiennej statusowej i w przypadku braku błędu wywołanie funkcji snprintf formatującej komunikat, a następnie wywołanie funkcji Serial.println wysyłającej komunikat do komputera.

Kod programu należy skompilować wybierając przycisk Verify (skrót klawiaturowy CTRL+R). Po zakończeniu procesu kompilacji należy wgrać program do pamięci mikrokontrolera wybierając przycisk Upload (skrót klawiaturowy CTRL+U).

Listing 2. Kod programu realizującego generowanie sygnału PWM

Działanie przykładu

Działanie aplikacji można obserwować z poziomu środowiska programistycznego Arduino IDE, które dysponuje terminalem komputerowym portu COM. Terminal można włączyć z poziomu menu głównego wybierając kolejno Tools i Serial Monitor (skrót klawiaturowy CTRL+Shift+M). Widok okna terminala podczas działania aplikacji mikrokontrolera pokazano na rysunku 3. Okno to wyświetla komunikaty otrzymane od mikrokontrolera z płytki STM32L4 Discovery kit IoT node. Komunikaty te zawierają informację o odległości (jednostka: mm) obiektu od czujnika VL53L0X.

Rys. 3. Efekt działania aplikacji – wyniki pomiaru odległości wykonane przez czujnik VL53L0X

STM32duino – bilans zalet i wad

Ostatni artykuł z cyklu o Arduino i STM32 jest dobrym miejscem na bilans zalet i wad Arduino. Cechy te warto podeprzeć doświadczeniami wyniesionymi z lektury artykułów.
Zacznijmy od zalet. Jako pierwszą zaletę warto wymienić prostotę tworzenia aplikacji.

Składa się na to gotowe API (biblioteki) do peryferiów mikrokontrolera i do podzespołów go otaczających. Co więcej, API stworzono z myślą o maksymalnej prostocie użycia. W artykułach z tego cyklu opisano sposób użycia różnych peryferiów mikrokontrolera. Korzystanie z każdego z nich wymagało wywołania zaledwie kilku funkcji.

Kolejną niewątpliwą zaletą jest wypracowanie wspólnego API dla różnych platform. Dzięki temu kod aplikacji jest taki sam dla mikrokontrolerów pochodzących od różnych producentów. W ramach tego cyklu kod napisano dla układów STM32, jednak bez żadnych zmian można go uruchomić np. na układach AVR.

Punktem wartym wspomnienia w kontekście zalet jest wsparcie dla różnych systemów operacyjnych. Arduino IDE dostępne jest dla Windowsa, Linuxa i MacOSa. Na potrzeby artykułów autor testował dwa pierwsze warianty.

Korzystanie ze środowiska Arduino jest bezpłatne. Nie ma też żadnych ograniczeń związanych z czasem użytkowania i wielkością kodu. Jest to kolejna niewątpliwa zaleta Arduino.
Ostatnią z zalet jest otwarty charakter Arduino (open source). Biblioteki są tworzone przez społeczność wspierającą tą platformę.

Teraz przejdźmy do wad. Pierwszym ograniczeniem środowiska Arduino jest niepełna liczba układów z danej rodziny mikrokontrolerów. Przykładowo rodzina STM32 liczy ponad 1000 układów, z czego Arduino wspiera kilkadziesiąt.

Niedogodnością Arduino jest też brak wsparcia dla wszystkich peryferiów mikrokontrolera. Biblioteki i API pozwalają na pracę jedynie z częścią dostępnych zasobów, głównie tych podstawowych.
Ostatnim minusem Arduino jest ograniczona możliwość analizowania pracy aplikacji i wyszukiwania w niej błędów. Domyślnie debugowanie nie jest wspierane. Głównym narzędziem sprawdzania działania aplikacji są wiadomości statusowe wysyłane przez aplikację za pomocą interfejsu szeregowego UART, których dodanie do kodu spoczywa na programiście.

Podsumowanie

Szósta część jest ostatnim odcinkiem kończącym cykl traktujący o platformie Arduino i mikrokontrolerach STM32. Dla przypomnienia i podsumowania warto wspomnieć tematykę wszystkich części. Pierwszy artykuł jest swoistym wprowadzeniem do Arduino, pokazujemy w nim dodatkowo jak skonfigurować środowisko programistyczne Arduino do pracy z mikrokontrolerami STM32. W drugim artykule prezentujemy jak zacząć pisanie kodu i jak sterować z poziomu kodu podstawowym zasobem mikrokontrolera – portami wejścia/wyjścia. W kolejnych trzech artykułach kontynuujemy tematykę pracy z peryferiami koncentrując się kolejno na interfejsie szeregowym UART, przetworniku A/C oraz timerze w trybie PWM.

Cały cykl kończy niniejszy artykuł dotyczący przykładowych aplikacji dla podzespołów towarzyszących mikrokontrolerowi.

O autorze