Projektowanie urządzeń z modułami GSM. Oprogramowanie mikrokontrolera. cz. 3

Projektowanie urządzeń z modułami GSM. Oprogramowanie mikrokontrolera. cz. 3
Pobierz PDF Download icon

W trzeciej części cyklu poświęconego projektowaniu urządzeń z modułami GSM zajmiemy się zagadnieniem projektowania oprogramowania mikrokontrolera współpracującego z modułem GSM.

Zadania stojące przed projektantem oprogramowania, to:

  • Włączanie modułu i przesyłanie poleceń inicjujących.
  • Sprawdzanie poprawności pracy modułu i restartowanie go w razie potrzeby.
  • Komunikacja z modułem w celu zapewnienia założonej funkcjonalności urządzenia.

W dokumentacji większości modułów GSM znajdziemy uwagę o możliwości zawieszenia modułu i konieczności wykrywania stanu zawieszenia i restartu modułu podczas pracy urządzenia. Sama komunikacja z modułem musi odbywać się z zachowaniem zasad podanych w dokumentacji. Należy zwrócić uwagę m.in. na:

  • Możliwość przesyłania poleceń i danych wyłącznie wtedy, gdy moduł jest na to gotowy (aktywny stan linii CTS).
  • Wymagane odstępy czasowe pomiędzy poleceniami oraz pomiędzy odpowiedzią modułu na polecenie i kolejnym poleceniem.
  • Zachowanie odpowiedniej sekwencji zdarzeń przy poleceniach złożonych - dane można przesyłać po zgłoszeniu gotowości modułu.
  • Możliwość przesłania przez moduł komunikatu asynchronicznego, niezależnego od przesyłanych do modułu poleceń.

Błędem często popełnianym przez początkującym programistów jest projektowanie oprogramowania do komunikacji z modułem w postaci sekwencji przeplatających się akcji przesłania polecenia i oczekiwania na odpowiedź. Odpowiedź z modułu może nigdy nie nadejść lub moduł może przesłać komunikat niebędący odpowiedzi na przesłane wcześniej polecenie. Ponadto struktura programu musi przewidywać restart i powtórne inicjowanie modułu w dowolnym kontekście komunikacji.

Właściwym podejściem do konstrukcji oprogramowania jest napisanie go w postaci kilku współpracujących ze sobą automatów. Istotne jest rozdzielenie funkcji nadawania poleceń i odbioru odpowiedzi modułu. Nie należy zbyt silnie wiązać w oprogramowaniu obu tych czynności.

Automat zajmujący się odbiorem danych z modułu musi być gotowy do odbioru dowolnego komunikatu, a nie tylko spodziewanej odpowiedzi na polecenie. Automat wysyłający polecenia musi uwzględniać limity czasu odpowiedzi i zapewniać stosowną reakcję na brak odpowiedzi. Przy braku aktywności urządzenia trzeba okresowo sprawdzać poprawność działania modułu, np. przez przesyłanie pustego polecenia AT.

Przykładowa aplikacja

W celu zilustrowania procesu projektowania programu zdefiniujemy przykładową aplikację, w której komunikacja przez sieć GSM polega na wymianie wiadomości SMS. Model urządzenia został wykonany przy użyciu płytki STM32F0DISCOVERY z mikrokontrolerem STM32F051 i płytki z modułem Quectel M95. Do płytki DISCOVERY dołączono wyświetlacz LCD i diodę LED RGB.

Przy wykryciu zdarzenia (naciśnięcia przycisku) urządzenie wysyła wiadomość z informacją o napięciu zasilania i temperaturze. Przychodzące wiadomości SMS mogą sterować świeceniem diody RGB poprzez ustawienie jednego z ośmiu stopni jasności każdej ze składowych.

Oprogramowanie musi zapewniać:

  • Inicjowanie modułu GSM oraz jego restart w wypadku zawieszenia.
  • Wysyłanie wiadomości SMS.
  • Odbiór i rozpoznawanie treści wiadomości SMS.

Cały projekt oprogramowania znajduje się w pliku M95_sms_demo.zip. W artykule pokazano jedynie najistotniejsze fragmenty programu związane z obsługą komunikacji z modułem GSM.

Odbiór i rozpoznawanie komunikatów z modułu - parser odpowiedzi

Projekt oprogramowania zaczniemy od części odpowiedzialnej za odbiór komunikatów z modułu. Parser komunikatów ma za zadanie wykrywanie odpowiedzi modułu GSM na istotne polecenia używane w aplikacji oraz wyłuskiwanie z odpowiedzi potrzebnych danych, np. numerów telefonów inicjujących połączenia lub treści SMS. Parser nie musi identyfikować wszystkich odpowiedzi modułu, lecz jedynie te, których odbiór jest istotny w danym zastosowaniu. W naszym przypadku będą to:

  • Echo pustego polecenia AT.
  • Odpowiedź OK kończąca poprawne wykonanie polecenia.
  • Odpowiedź +CMGL: zawierająca treść wiadomości SMS.

Spośród tych trzech komunikatów jedynie +CMTI wymaga interpretacji treści. Pozostałe trzy muszą być jedynie wykrywane. Rozpoznanie każdego z wymienionych komunikatów powoduje ustawienie odpowiadającego mu znacznika.

Informacja o odebranej wiadomości ma postać +CMGL: 1,"REC READ","+48600123456","","2015/05 /29 12:49:50+08" po czym, w następnym wierszu, następuje treść wiadomości.

Parsowanie komunikatów z modułu GSM nie wymaga buforowania całej ich treści; może ono następować znak po znaku, w miarę odbierania kolejnych bajtów przez interfejs UART. Zapisu do pamięci wymagają tylko dane z przychodzącej wiadomości - numer wiadomości (liczba następująca po znaku dwukropka), numer telefonu nadawcy i treść wiadomości.

Procedura parsująca dane z modułu GSM ma postać prostego automatu. Jest ona wywoływana przy odbiorze znaków z modemu następującym w przerwaniu z modułu UART. W przykładowym programie procedura ta nosi nazwę iparse(). Zrealizowany w niej automat ma 9 stanów zdefiniowanych przez typ wyliczeniowy istate_, z czego 4 są związane z analizą treści przychodzącej wiadomości SMS.

Do identyfikacji komunikatów procedura posługuje się tablicą wzorców początków komunikatów msg[], posortowaną alfabetycznie. Tablicy tej odpowiada typ wyliczeniowy imsg_ definiujacy symboliczne identyfikatory komunikatów.

Stanem początkowym parsera jest stan IS_START. Odebranie pierwszego znaku różnego od spacji i zgodnego z jednym z rozpoznawanych komunikatów powoduje przejście do stanu rozpoznawania komunikatu IS_MATCHING. Jeżeli pierwszy lub kolejny znak nie pasuje do żadnego z definiowanych wzorców, następuje przejście do stanu oczekiwania na początek wiersza IS_SKIPEOLN.

Każda dłuższa przerwa w odbiorze danych powoduje przejście automatu parsera do stanu początkowego.

Stwierdzenie zgodności z całym wzorcem komunikatu powoduje ustawienie znacznika odbioru danego komunikatu i przejście do oczekiwania na początek wiersza. Jedynie komunikat z treścią odebranej wiadomości wymaga bardziej złożonej obsługi- W tym przypadku automat przechodzi kolejno przez stany:

  • Oczekiwania na numer wiadomości IS_GETMSG1.
  • Gromadzenia numeru wiadomości IS_GETMSGNUM.
  • Szukania numeru telefonu nadawcy IS_MSGFINDNUM.
  • Gromadzenia numeru nadawcy IS_MSGGETNUM.
  • Pomijania dalszej części komunikatu IS_MSGSKIPEOLN.
  • Gromadzenia treści wiadomości IS_MSGBODY.

Zakończenie odczytywania wiadomości powoduje ustawienie znacznika msg_rdy. Numer wewnętrzny wiadomości, numer telefonu nadawcy i treść wiadomości zostają umieszczone odpowiednio w zmiennych łańcuchowych msgnum, msgphnum i msgbody.

Transmisja poleceń do modułu GSM

Transmisja danych przez moduł UART do modemu GSM jest realizowana w procedurze obsługi przerwania UART. Ponieważ polecenia są przesyłane pojedynczo, nie jest potrzebne ich dodatkowe buforowania w kolejce FIFO. Procedura transmisji łańcucha, z której korzysta główny automat, wpisuje jedynie adres początkowy polecenia do zmiennej sendptr i odblokowuje przerwanie nadajnika.

Struktura oprogramowania urządzenia

Całe oprogramowanie składa się z procedury inicjującej oraz dwóch procedur obsługi przerwań: timera SysTick i UART. Procedura inicjująca korzysta ze struktury danych zawierającej adresy inicjowanych rejestrów i ich wartości. Przerwanie Systick jest wywoływane z częstotliwością 1600 Hz, wynikającą z zastosowanej metody obsługi wyświetlacza LCD. Obsługa pomiarów ADC i przycisków oraz automat główny są wywołane z częstotliwością 100 Hz. Oprogramowanie naprzemiennie mierzy i filtruje wartości napięcia zasilania i temperatury urządzenia.

Działanie fragmentów oprogramowania niezwiązanych z obsługą modułu GSM zostało opisane w serii artykułów "32 bity jak najprościej", prezentowanej niedawno w EP.

Główny automat

Główny automat urządzenia odpowiada za współpracę z modułem GSM i realizację podstawowej funkcjonalności urządzenia. Logika automatu została zawarta w procedurze M95_handler(), wywoływanej z procedury obsługi przerwania timera systemowego. Zmiany stanów automatu zachodzą na podstawie zdarzeń specyficznych dla poszczególnych stanów oraz - w przypadku niewystąpienia zdarzenia - w wyniku przekroczenia limitu czasu spędzanego w poszczególnych stanach (listing 1).

Ponieważ każdy stan ma określony limit czasu, a reakcja na zdarzenia następuje tylko w niektórych stanach, wygodniej było zrealizować automat w niezbyt typowej postaci nie jednej, a dwóch instrukcji switch(). Pierwsza instrukcja switch() zapewnia obsługę przekroczenia limitów czasu zależną od stanu automatu. Druga instrukcja switch() obsługuje wyłącznie zmiany stanów wynikające z innych zdarzeń.

Stan automatu jest przechowywany w zmiennej typu wyliczeniowego mstate.

Stanem początkowym jest stan MS_INIT, z którego wyjście następuje wyłączeni w wyniku upłynięcia limitu czasu. Przy starcie oprogramowania limit jest ustawiana na 3 sekundy, co zapewnia odczekanie odpowiedniego czasu dla stabilizacji zasilania całego urządzenia. Po tym czasie następuje rozpoczęcie włączania modułu GSM i przejście do stanu włączania MS_TURNON, w którym generowany jest impuls włączający moduł o wymaganym czasie trwania 2,2 s. Po tym czasie następuje zakończenia impulsu włączającego i przejście do stanu MS_SYNC. W stanie MS_SYNC, po upływie czasu 0,5 sekundy, jest przesyłane puste polecenie AT służące do synchronizacji interfejsu UART modułu, po czym następuje przejście do stanu MS_SYNC2.

Odebranie odpowiedzi AT<CR><LF>OK<CR<LF> w stanie MS_SYNC2 powoduje wysłanie do modułu polecenia AT+CMGF=1, ustawiającego tekstową reprezentację wiadomości SMS. Gdyby do zainicjowania modułu były potrzebne inne polecenia (np. wprowadzenia PIN), należałoby je analogicznie obudować kolejnymi stanami składającymi się na sekwencję inicjującą.

Przekroczenie limitu czasu odpowiedzi na którekolwiek polecenie wysyłane do modułu powoduje restart modułu, którego algorytm jest opisany w dalszej części artykułu.

Pomyślne zakończenie inicjowania modułu, sygnalizowane odpowiedzią OK na ostatnie polecenie inicjujące powoduje przejście do stanu MS_RDY. W stanie tym automat sprawdza, czy wystąpiło zdarzenie wymagające przesłania SMS i w razie takiej potrzeby wysyła do modułu polecenie inicjujące przesyłania wiadomości w postaci AT+CMGS="<nr_teL_ odbiorcy>"<CR>, po czym przechodzi do stanu MS_SENDING, w którym oczekuje na zgłoszenie gotowości modułu do przekazania treści wiadomości.

Jeżeli w stanie MS_RDY w ciągu 10 sekund nie nastąpi zdarzenie, do modułu jest przesyłane polecenie AT+CMGL="ALL"<CR>, które powoduje przesłanie przez moduł listy wszystkich odebranych wiadomości, po czym automat przechodzi do stanu MS_PING. Gdyby nasze urządzenie nie reagowało na SMS, należałoby w tym przypadku przesyłać dowolne inne polecenie, np. puste, w celu okresowego testu aktywności modułu. Brak odpowiedzi na to polecenie powinien powodować restart modułu.

Odpowiedź na polecenie AT+CMGL zawiera listę wiadomości, zakończoną napisem OK. Każdy element listy jest rozpoznawany przez parser odpowiedzi z modułu, który zapisuje dane pierwszej wiadomości z listy. W ten sposób po zakończeniu odpowiedzi, co jest sygnalizowane przez parser ustawieniem znacznika ok_received i pobraniu przez parser wiadomości (znacznik msg_rdy) automat może zinterpretować treść pierwszej wiadomości, a następnie wydać polecenie jej skasowania AT+CMGD=<numer_wiadomości>, niezbędne dla umożliwienia odbioru kolejnych wiadomości (listing 2).

Restart modułu

Restart modułu jest inicjowany w przypadku niewykrycia odpowiedzi modułu w określonym indywidualnie dla poszczególnych poleceń maksymalnym czasie odpowiedzi. Moduł M95 jest wyposażony przez producenta w dwa mechanizmy restartu: zwykły, poprzez normalne wyłączenie modułu po wcześniejszym wylogowaniu z sieci oraz awaryjny, wymuszający wyłączenie modułu nawet przy całkowitym zawieszeniu oprogramowania.

Przekroczenie limitu czasu odpowiedz na polecenie powoduje uruchomienie jednego z tych mechanizmów. Początkowo jest to mechanizm normalnego wyłączenia poprzez podanie na wejście włączające impulsu o czasie 800 ms.

Jeżeli po próbie powtórnego włączenia moduł nie odpowiada na polecenia, zostaje użyty mechanizm restartu awaryjnego, wyzwalany poprzez podanie na wejście EMG_OFF impulsu o czasie 400 ms. Oby typy wyłączenia są obsługiwane w jednym stanie MS_TURNOFF, po którym następuje przejście do stanu MS_ INIT, w którym po 3 sekundach nastąpi włączenie modułu.

Podsumowanie

Opisana struktura oprogramowanie zapewnia poprawną współpracę urządzenia mikroprocesorowego z modułem GSM Quectel M95. Analogiczny schemat może zostać zastosowany dla dowolnego innego modułu, po odpowiedniej modyfikacji parametrów czasowych i sekwencji inicjującej, co może wiązać się ze zwiększeniem liczby stanów automatu.

Funkcjonalność urządzenia w zakresie wspśłpracy z modułem GSM może zostać łatwo rozbudowana poprzez dodanie kolejnych odpowiedzi modemu do listy odpowiedzi rozpoznawanych przez parser. I ewentualną rozbudowę parsera w celu zapewnienia rozpoznawania elementów treści tych odpowiedzi.

Oprogramowanie zbudowane w taki sposób zapewnia pełny asynchronizm i nie wymaga oczekiwania w pętli zdarzeń programu na zdarzenie, które może nigdy nie wystąpić, dzięki czemu można łatwo zaimplementować obsługę sytuacji awaryjnych.

Grzegorz Mazur

Artykuł ukazał się w
Elektronika Praktyczna
sierpień 2015
DO POBRANIA
Pobierz PDF Download icon

Elektronika Praktyczna Plus lipiec - grudzień 2012

Elektronika Praktyczna Plus

Monograficzne wydania specjalne

Elektronik kwiecień 2024

Elektronik

Magazyn elektroniki profesjonalnej

Raspberry Pi 2015

Raspberry Pi

Wykorzystaj wszystkie możliwości wyjątkowego minikomputera

Świat Radio marzec - kwiecień 2024

Świat Radio

Magazyn krótkofalowców i amatorów CB

Automatyka, Podzespoły, Aplikacje marzec 2024

Automatyka, Podzespoły, Aplikacje

Technika i rynek systemów automatyki

Elektronika Praktyczna kwiecień 2024

Elektronika Praktyczna

Międzynarodowy magazyn elektroników konstruktorów

Elektronika dla Wszystkich kwiecień 2024

Elektronika dla Wszystkich

Interesująca elektronika dla pasjonatów