Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki

KURS HOME ASSISTANT

Chcesz zautomatyzować swój dom bez skomplikowanego kodowania?
Zastanawiasz się nad wyborem sprzętu, oprogramowania i aplikacji?
Od czego zacząć przygodę z HA? Co będzie najlepsze na start?

Nasz kurs Home Assistant nauczy Cię krok po kroku, jak łatwo zautomatyzować swój dom i oszczędzić na rachunkach za prąd i ogrzewanie. Bez chmur, bez zbędnych abonamentów. Twoja przygoda z Home Assistant zaczyna się tutaj!

↓↓↓

    Szanujemy Twoją prywatność. Możesz wypisać się w dowolnym momencie.




    Teraz jest 15 cze 2025, o 20:44


    Strefa czasowa: UTC + 1





    Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 4 ] 
    Autor Wiadomość
    PostNapisane: 13 cze 2012, o 15:08 
    Offline
    Nowy
    Avatar użytkownika

    Dołączył(a): 06 maja 2012
    Posty: 13
    Pomógł: 0

    Chciałbym wam przedstawić bardzo ciekawy sposób komunikacji z naszymi mikrokontrolerami, a mianowicie sterowanie za pomocą własnych komunikatów. Na wstępie informuję iż przedstawioną bibliotekę pisałem na zajęciach z programowania ARM w C wg specyfikacji laboratorium. Służyła ona do sterowania serwomechanizmem poprzez interfejs RS232, jednak jej zastosowanie może być zgoła inne. Jako że piszę obecnie pracę mgr na temat bezprzewodowego systemu pomiarowego w oparciu o moduły RFM12B i mikrokontrolery ATmega88, pomyślałem że fajnie byłoby wysyłać komendy sterujące do modułu nadrzędnego przez UART. Przerobiłem bibliotekę na rzekomy AVR i chciałbym się tym z wami podzielić, aby każdy mógł z łatwością dogadywać się z mikrokontrolerem za pomocą własnych komend ASCII. Należy jeszcze tutaj wspomnieć o obsłudze interfejsu UART. Wszelkie dane wysłane przez UART są w postaci łańcuchów znakowych. Stworzone są dwa oddzielne bufory: dla nadajnika i odbiornika. Znaki odbierane są do momentu napotkania znaku terminatora, czyli Enter '\r', na końcu dodawany jest NULL. Całość oparta na przerwaniach. A więc do dzieła :)


    Komunikaty(komendy):
    Komunikaty mają postać łańcuchów znakowych zakończonych znakiem NULL (ang. Null terminated string) i składają się z jednego bądź więcej tokenów. Tokeny to sekwencje znaków oddzielone jednym lub wieloma delimiterami. Funkcję delimitera pełnić będzie znak spacji ‘\s’ (20h, 32).
    Przykład komunikatu pokazano poniżej:
    „Ola ma jeża”.
    Składa się on z trzech tokenów rozdzielonych dwoma delimiterami.

    Dekodowanie:
    Dekodowanie komunikatu polega na policzeniu ilości wykrytych tokenów, oraz ich zdekodowaniu. Zdekodowanie tokenu to określenie jego typu i wartości a następnie zapamiętanie ich w odpowiedniej strukturze danych.

    Typ tokenu:
    Będziemy rozróżniali trzy typy tokenów: KEYWORD, NUMBER i STRING.
    Token zostanie rozpoznany jako KEYWORD jeżeli będzie należał do listy słów kluczowych. W takim przypadku wartość tokenu stanowić będzie typ wyliczeniowy enum.

    Przykład: Załóżmy, że zadeklarowano następującą listę słów kluczowych:

    Keyword (enum)----------odpowiadający jej łańcuch znakowy (char[])
    LD-----------------------“load”
    ST ----------------------“store”
    RST----------------------“reset”

    Wtedy tokeny “store” i „reset” zostaną zdekodowane w sposób następujący
    token -------------- typ-----------wartość (enum)
    „reset” -------------KEYWORD------RST
    “store”--------------KEYWORD------ST

    Token zostanie rozpoznany jako NUMBER jeżeli będzie spełniał format liczby zapisanej w kodzie heksadecymalnie. W takim przypadku wartość tokenu stanowić będzie wartość liczby.

    Przykład:
    token----------typ-----------wartość (unsigned int )
    „0x10”--------- NUMBER------ 16 (decymalnie)
    „0x0A”---------NUMBER ------10 (decymalnie)

    Token zostanie rozpoznany jako STRING jeżeli nie zostanie rozpoznany jako KEYWORD ani jako NUMBER. Wartość tokenu typu STRING stanowi wskaźnik na ten token.

    Przykład:
    token---------typ----------wartość (char *)
    „add”---------STRING------Wskaźnik na „add”
    “subtract”----STRING------ Wskaźnik na “subtract”

    Typ tokenu jest przechowywany w zmiennej wyliczeniowej zdefiniowanej jak poniżej:
    Kod:
    typedef enum TokenType {KEYWORD, NUMBER, STRING};


    Wartość tokenu:
    Ponieważ typ tokenu może być różny (typ wyliczeniowy, liczba, łaocuch znakowy) dlatego jego wartość nie może być przechowywana w zmiennej jednego typu. Z tego względu do przechowywania wartości tokenu została wykorzystana unia zmiennych zdefiniowana jak poniżej:
    Kod:
    typedef enum KeywordCode { LD, ST, RST};
    typedef union TokenValue
    {
    enum KeywordCode eKeyword; // jezeli KEYWORD
    unsigned int uiNumber; // jezeli NUMBER
    char * pcString; // jezeli STRING
    };


    Tablica tokenów:

    Typ i wartośc tokenu są przechowywane w jednej strukturze zdefiniowanej jak poniżej:
    Kod:
    typedef enum TokenType { KEYWORD, NUMBER, STRING};
    typedef struct Token
    {
    enum TokenType eType; // KEYWORD, NUMBER, STRING
    union TokenValue uValue; // enum, unsigned int, char*
    }

    Ponieważ w pojedynczym komunikacie mamy najczęściej do czynienia więcej niż z jednym tokenem wiec wynik dekodowania jest przechowywany w tablicy tokenów zdefiniowanej jak poniżej:
    Kod:
    #define MAX_TOKEN_NR 3 //maksymalna dopuszczalna ilość tokenów
    struct Token asToken[MAX_TOKEN_NR]


    Ilośc tokenów:
    Oprócz wypełnienia tablicy tokenów wynikiem dekodowania będzie również liczba odebranych tokenów zapamiętana w zmiennej:
    Kod:
    unsigned char ucTokenNr;

    Dekodowanie komunikatu polega na wypełnieniu tablicy sToken na podstawie odebranego łaocucha znakowego.

    Przykład: Wynik rozkodowania komunikatu: „load 0x20 immediately”.
    token Type Value
    “load” ----------KEYWORD------ LD
    „0x20”----------NUMBER-------- 32 (decymalnie)
    „immediately”--- STRING-------- wskaznik na „immediately”

    Lista słów kluczowych:
    Do sprawdzenia czy token jest typu KEYWORD musi istnieć lista łańcuchów znakowych rozpoznawanych jako słowo kluczowe. Elementem listy jest struktura składająca się z dwóch elementów – typu słowa kluczowego oraz związanego z nim łańcucha znakowego.
    Kod:
    #define MAX_KEYWORD_STRING_LTH 10 // mksymalna dlugosc komendy
    typedef enum KeywordCode { LD, ST, RST};
    typedef struct Keyword
    {
    enum KeywordCode eCode;
    char cString[MAX_KEYWORD_STRING_LTH + 1];
    };

    Deklaracja listy poprawnych słów kluczowych wygląda następująco, to właśnie w tym miejscu definiujemy własne słowa kluczowe(oraz w samym enum KeywordCode):
    Kod:
    #define MAX_KEYWORD_NR 3
    struct Keyword asKeywordList[MAX_KEYWORD_NR]=
    {
    {RST,"reset"},
    {LD, "load" },
    {ST, "store"}
    };

    Zmienne globalne:
    Kod:
    asKeywordList[] // uzywana przez bStringToCommand
    asToken[] // wypelniana przez DecodeMsg
    ucTokenNr // liczba tokenów w zdekodowanym komunikacie

    Funkcje:
    Do dekodowania potrzebne są następujące funkcje:

    ucFindTokensInString (char *String)
    Argumentem funkcji jest wskaźnik na początek dekodowanego komunikatu, funkcja zwraca ilość znalezionych tokenów w komunikacie. Zadaniem funkcji jest wypełnianie pola uValue tablicy asToken wskaźnikami na początki znalezionych tokenów w łańcuchu String.
    Implementacja funkcji ma postać automatu, ponadto funkcja jest odporna na:
    - pusty łańcuch, tj. Łańcuch składający się z samych delimiterów
    - delimiter przed pierwszym tokenem
    - więcej niż jeden delimiter miedzy dwoma tokenami

    eSringToKeyword (char cStr[],enum eKeywordType *peKeyword)
    Zadaniem funkcji jest zamienić łańcuch znakowy na komendę na podstawie listy komend.
    W przypadku powodzenia funkcja zwraca wartość OK.
    W przypadku niepowodzenia funkcja zwraca wartości ERROR.

    DecodeTokens(void)

    Zadaniem funkcji jest zdekodować wszystkie tokeny tj. dla każdego tokenu ustalić jego typ i wartość i wpisać je do tablicy asToken.
    Funkcja korzysta ze wskaźników początków tokenów znajdujacych się w asToken[0..ucTokenNr].uValue.pcString (patrz funkcja ucFindTokensInString).

    DecodeMsg(char *String)

    Na podstawie String-a i asCommandList funkcja wypełnia tablice sToken i ustawia zmienna ucTokenNr.
    W tym celu:
    - indeksuje początki tokenów
    - zamienia wszystkie delmitery na nulle
    - dekoduje poszczególne tokeny.

    Ponadto do dekodowania wykorzystywane są jeszcze inne funkcje służące do pracy na łańcuchach:

    void ReplaceCharactersInString(char cString[], char cOldChar, char cNewChar);
    Funkcja służy do podmiany znaku cOldChar na znak cNewChar w łańcuch cString.

    enum CompResult eCompareString(char cStr1[], char cStr2[]);
    Funnkcja służy do porównywania dwóch stringów, jeżeli śa takie same funkcja zwraca EQUAL jeżeli nie są takie same zwraca NOTEQUAL

    void AppendUIntToString (unsigned int uiValue, char cDestinationStr[]);
    Funkcja służy do dodania liczby uiValue do końca łańcucha cDestinationStr, liczba zamieniana jest na string w postaci hexadecymalnej.

    Result eHexStringToUInt(char cStr[], unsigned int *puiValue);
    Funkcja zamienia string w postaci liczby hexadecymalnej cStr na jej wartość i umieszcza jak pod wskaźniekiem puiValue.

    Chwili wyjaśnienia wymaga program główny w pętli while. Otóż w pętli sprawdzany jest status odbiornika UART, jeśli pojawił się jakiś komunikat status odbiornika zmienia się na READY. Następnie komunikat jest dekodowany i w zależności od wysłanej komendy ustawiane są flagi, jest to tzw. „producent”. Jeżeli „producent” ustawi którąś z flag, oraz nadajnik jest w stanie bezczynności (FREE) to UART zajmie się „konsumpcją” „wyprodukowanej” flagi.

    Po wgraniu programu do AVR i wpisaniu w polu terminala np. komunikatu „calc 0x0002„
    Mikrokontroler natychmiast odeśle nam odpowiedź w postaci wartości odebranej pomnożonej przez 2 , czyli „calc 0x0004„.

    W taki prosty, nieblokujący sposób można rozkazywać naszemu prockowi. ;)

    Załączam kompletną bibliotekę pod ATmege88,


    Załączniki:

    Aby zobaczyć załączniki musisz się zalogować. Tylko zalogowani użytkownicy mogą oglądać i pobierać załączniki.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 13 cze 2012, o 15:19 
    Offline
    Użytkownik

    Dołączył(a): 04 paź 2011
    Posty: 8615
    Pomógł: 338

    No brawo kolego , przydatna zabaweczka i oczywiście ładnie napisana :)
    Tak przy okazji to połamania na obronie ...

    _________________
    Zbuduj swój system [url=https://helion.pl/ksiazki/w-labiryncie-iot-budowanie-urzadzen-z-wykorzystaniem-ukladow-esp8266-i-esp32-andrzej-gromczynski,wlablo.htm#format/d]IOT[/url]



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 13 cze 2012, o 15:39 
    Offline
    Moderator
    Avatar użytkownika

    Dołączył(a): 03 paź 2011
    Posty: 27409
    Lokalizacja: Szczecin
    Pomógł: 1043

    SunRiver udałoby ci się ten wątek przenieść do działu "Projekty programistyczne" ? bo zasługuje na to żeby tam się pojawić ;)

    _________________
    zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 13 cze 2012, o 15:46 
    Offline
    Użytkownik

    Dołączył(a): 04 paź 2011
    Posty: 8615
    Pomógł: 338

    Mówisz masz !!
    Proszę bardzo SZEFUŃCIU :P

    _________________
    Zbuduj swój system [url=https://helion.pl/ksiazki/w-labiryncie-iot-budowanie-urzadzen-z-wykorzystaniem-ukladow-esp8266-i-esp32-andrzej-gromczynski,wlablo.htm#format/d]IOT[/url]



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    Wyświetl posty nie starsze niż:  Sortuj wg  
    Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 4 ] 

    Strefa czasowa: UTC + 1


    Kto przegląda forum

    Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 0 gości


    Nie możesz rozpoczynać nowych wątków
    Nie możesz odpowiadać w wątkach
    Nie możesz edytować swoich postów
    Nie możesz usuwać swoich postów
    Nie możesz dodawać załączników

    Szukaj:
    Skocz do:  
    Sitemap
    Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
    phpBB SEO