logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[C] [C][Atmega128] - Jak wysyłać SMS co 2 minuty przez UART?

Bubu_PL 04 Sie 2012 19:00 2593 9
REKLAMA
  • #1 11175580
    Bubu_PL
    Poziom 11  
    Jak że poradziłem sobie z problemem GPS (narazie wszystko jest ok) z pomocą kolegów z forum, to brnę dalej ku marzeniom i walczę teraz z wysyłaniem owych danych przez SMS.

    zrobiłem sobie proste sprawdzanie czy jest odpowiedni czas na wysłanie smsa (co 2 min) w pętli w której pobierane są ramki z GPS:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    teraz w funkcji sendSMS() robię sobie coś takiego:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    natomiast w obsłudze USART:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    i przerwanie dla USART:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    no i nie działa.. tzn działa tyle o ile, podglądając odpowiedzi od modemu i to co nadaje dostaje w terminalu Putty:
    
    
    Time: 162056.000
    Time: 162057.000
    Time: 162058.000
    Time: 162059.000
    Time: 162100.000
    AT+CMGS="+48xxxxxxxxxx"
    OK
    Time: 162101.000
    


    a po podglądnięciu wlogach z putty nawet takie cos:
    
    Time: 162259.000
    Time: 162300.000
    AT
    AT+CMGF=1
    AT+CMGS="+485xxxxxxxxx"
    
    OK
    Time: 162301.000
    Time: 162302.000
    

    gdzie jest złe moje rozumowanie?
  • REKLAMA
  • #2 11176129
    Marico
    Poziom 20  
    1. Wysyłasz komendy at ciurkiem bez czekania na OK po każdej komendzie.
    2. Czy komendy at w twoim modemie konczy się na pewno samym '\r'? Widzę nieścisłość w ISR
    dlaczego uczulasz kod raz na \n a raz na \r?
    3. W ISR flagReadyToSend zawsze będzie 1, wcięcie sugeruje ze mialo to być w if, a tak jest poza warunkiem.
    4. Jak już używasz ISR, to ISR powinna wypelniac bufor otrzymanym znakiem plus ewentualnie flagi dla pozostałego kodu procesujacego bufor. U ciebie jakoś to na opak jest.
  • REKLAMA
  • #3 11176231
    Bubu_PL
    Poziom 11  
    Tamto była oczywiście literówki:)

    poprawiłem co nieco kod, komendy wysylam teraz przez funkcję:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    co jeśli w odpowiedzi mamy klika linii zakończonych '\n'?
    czy prawidłowe jest następujące podejście:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    w ISR:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • Pomocny post
    #4 11176715
    Marico
    Poziom 20  
    Funkcja czekająca na odpowiedz powinna być odporna na brak jakiekolwiek odpowiedzi. W przypadku braku odpowiedzi z modemu Twój kod się "zapetli". Jak wygląda kod usr0_getc()? Nie widzę związku między ISR a tą funkcją. Zakładam również, ze flagi (flagGotLine i pozostałe) zadeklarowales jako volatile.
    Postaraj się zaimplementować pkt. 4 z mojej poprzedniej odpowiedzi. ISR ma wypełniać bufor otrzymanymi bajtami z usart'a i ustawić flagi. Funkcja pobierająca odpowiedź z bufora modemu jako argument powinna przyjmować string spodziewanej odpowiedzi (wraz z ostatnim znakiem) a zwracac 0 gdy spodziewana odpowiedź nastąpiła lub wartość > 0 gdy odpowiedź była inna lub nie było jej wcale (nastąpił timeout), przykład funkcji inicjujacej modem:

    char modem_init(){

    usart_send("AT&F\r\n”)
    If(usart_get("OK\r\n")>0) return 1;
    else return 0;
    }

    Oczywiście wygodniejsza byłaby funkcja,
    której prototyp wyglądałby tak:

    char usart_sendget(char *stringToSend, char *expectedResponse);

    a przyklad użycia:
    if(usart_sendget("AT&F\r\n","OK\r\n"))
    {
    // wystąpił blad
    } else {

    // idp. prawidłowa
    }

    Jako zadanie domowe proponuje napisanie funkcji usart_get() lub usart_sendget().

    Jeśli czytasz po ang. polecam w google haslo ” motorola an2120.pdf". Dokument dotyczy implementacji tcp/ip ale na wstępie tlumaczy podstawowe zasady komunikacji z modemem, wyjasnia czym jest ring buffer, jak prawidłowo wysyłać komendy at i jak powinno się procesować odpowiedzi. Dokument zawiera listing kodu dla motoroli, ale został napisany tak, ze można w łatwy sposób zaimplementować go w dowolnym mcu.

    PS. Ewentualnych moderatorów przepraszam za formatowanie posta, piszę z telefonu a interfejs elektrody jest maksymalnie nieprzyjazny dla przeglądarki "mobilnej".
  • #5 11177022
    Bubu_PL
    Poziom 11  
    dzięki za wyczerpującą wypowiedź. Napisałem kawałek kodu i wydaje się ze działa ok dla komendy AT np. Co jednak gdy odpowiedź jest bardziej skomplikowana (np po wysłaniu SMS jest w stylu:
    
    +CMGS: 59
    
    OK
    


    a tutaj trochę kodu, proszę o zweryfkowanie:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    w konsoli dostaje:
    AT
    Wszystko ok
    OK
    AT
    Wszystko ok
    OK
    AT
    Wszystko ok
    OK
    AT
    Wszystko ok
    OK
    AT
    Wszystko ok
    OK
    
  • #6 11177520
    Marico
    Poziom 20  
    Funkcja czekająca na odpowiedź z modemu powinna czekać skonczony czas na oczekiwany string, przy czym jest bardzo ważne to, aby oczekiwany string zawierał ostatnie znaki z całego stringu odpowiedzi modemu. W Twoim przykładzie gdy modem odpowiada:
    CMGS: 59

    OK

    To modem tak naprawde wysyła znaki:
    CMGS: 59\r\n\r\nOK\r\n

    Funkcja czekająca na odpowiedź w argumencie answer ma "OK\r\n" więc bedzie czekać do ostatniego \n, dopiero zwróci wynik. Gdybyś np. jako answer podał tylko "OK" funkcja wróciłaby wynik wcześniej a modem by jeszcze wysłał "\r\n" co by zaburzylo komunikacje (nastepna komenda bylaby wysyłana gdy modem transmituje "\r\n" z poprzedniej odpowiedzi, przez to nie jest gotowy na kolejne polecenie).
    Podsumowujac: czekanie na pełny, końcowy string oczekiwanej odpowiedzi (z zaimplementowanym timeoutem gdy się ona nie pojawi) gwarantuje Ci to ze sekwencje polecenie-odpowiedź zawsze będą zsynchronizowane z gotowością interpretera komend AT w modemie.
    Popracuj jeszcze nad timoutem, czy aby na pewno Twoja implementacja usart 0_not_empty zabezpiecza przed brakiem odpowiedzi w ogóle (modem się "zawiesił") lub odpowiedział innym stringiem niż oczekiwany. Najprosciej dla testu jako answer podaj coś co na pewno się nie pojawi.
  • REKLAMA
  • #7 11177656
    Bubu_PL
    Poziom 11  
    dzieki Marico za odpowiedzi.
    Niby wszystko ok, ale jak już próbuję wysłać SMS to dostaje:
    AT+CMGS="+48xxxxxxxx"
    SMS: NOOT
    
    > AT+CMGS="+48xxxxxxxx"
    SMS:SMS
    
    +CMGS: 84
    
    OK
    AT+CMGS="+48xxxxxxxx"
    SMS: NOOT
    
    > AT+CMGS="+48xxxxxxxx"
    SMS:SMS
    
    +CMGS: 85
    
    OK
    
    


    przy kodzie:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    rozbudowałem funkcję talkGSM:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    uart0_Wait:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    uart0_getc:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #8 11177938
    Marico
    Poziom 20  
    _delay_ms powinien być wewnątrz pierwszej pętli wille i nie 100ms a 10ms wystarczy. Zmodyfikuj argument time aby pętla trwała ok 1 sek, czyli time powinno być ok 100.
    Dlaczego sytuacja zrownania indeksu w usart_getc zwraca 0? Bufor ma być ring, bez początku i końca, funkcja getc zawsze powinna zwracać ostatnio otrzymany znak z usart'a bez względu na aktualny indeks bufora. Mając dodatkowe flagi sygnalizujące czy coś nowego otrzymano plus ta funkcje do pobierania ostatniego znaku z bufora powinno dać spodziewany efekt.
    Nie rozumiem również linijki w usart_getc:

    UART0_RxTail = (UART0_RxTail + 1) & UART0_RX_BUF_MASK;

    Po co ta maska?
    Zajrzyj do przykładów z dokumentu o którym wspomniałem, tam jest opisany przyklad takiej funkcji getc z prawidłowo użytymi indeksami.
  • #9 11177965
    tymon_x
    Poziom 30  
    Marico napisał:
    Nie rozumiem również linijki w usart_getc:

    UART0_RxTail = (UART0_RxTail + 1) & UART0_RX_BUF_MASK;

    Po co ta maska?
    Zajrzyj do przykładów z dokumentu o którym wspomniałem, tam jest opisany przyklad takiej funkcji getc z prawidłowo użytymi indeksami.

    Wyjaśnię za autora. Masz tablicę 2*N elementową, maska (N jedynek) w tym przypadku ogranicza zasięg i wykorzystuje przepełnienie na Twoją korzyść. Czyli mając MASK = 0x07 i masz 8 elementową tablicę. Zmienna ciągle się inkrementuję, przekręca się, ale jest ciągle w zakresie 0-7. I to jest szybki i fajny sposób na bufor kołowy.
  • REKLAMA
  • #10 11178034
    Marico
    Poziom 20  
    Napisałem trochę nieścisle, getc musi zwrócić kolejny znak do pobrania z bufora a nie ostatnio otrzymany, rzecz jasna.
REKLAMA