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 14 lip 2025, o 10:57


    Strefa czasowa: UTC + 1





    Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 11 ] 
    Autor Wiadomość
    PostNapisane: 14 sie 2017, o 16:54 
    Offline
    Nowy

    Dołączył(a): 18 lis 2015
    Posty: 6
    Pomógł: 0

    Witam. Piszę sobie program do komunikacji z modułem sim800L. Chcę wysyłać do niego, a także odbierać z niego dane.
    Napisałem sobie już całą obsługę tego modułu, ale mam jeden problem. Komunikacja z modułem zwykle działa dobrze, ale od czasu do czasu podczas przesyłania danych ATMega resetuje się :o.

    Używam dosyć popularnej biblioteki uart dostępnej na tej stronie:
    http://homepage.hispeed.ch/peterfleury/avr-software.html

    Bibliotekę tą zmodyfikowałem dla własnych potrzeb tak, abym mógł odbierać całe stringi ;)

    W pliku uart.c dopisałem sobie taką funkcję wzorując się na poradniku YT pana Mirka:

    Składnia: [ Pobierz ] [ Ukryj ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


    Zmienna ascii_line inkrementowana jest w przerwaniu od odbioru danych uarta, gdy odebrany znak = 13 (ENTER). W ten sposób funkcja uart_get_str jest informowana, że dostępna jest linijka do odebrania. Wydaje mi się, że funkja uart_get_str jest tutaj problemem, ponieważ gdy ją usunę i ręcznie wysyłam z komputera dane do mikrokontrolera, resetów nie ma. Gdy funkcja jest włączona, podczas wysłania większej ilości danych następuje reset.



    Ostatnio edytowano 17 sie 2017, o 21:53 przez kamilo0, łącznie edytowano 3 razy

    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 14 sie 2017, o 17:53 
    Offline
    Użytkownik

    Dołączył(a): 07 cze 2016
    Posty: 563
    Pomógł: 143

    Spróbowałbym przed instrukcją ascii_line--; wyłączyć przerwania instrukcją cli();, a po instrukcji ascii_line--; włączyć przerwania instrukcją sei();



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 14 sie 2017, o 21:14 
    Offline
    Użytkownik

    Dołączył(a): 02 cze 2014
    Posty: 123
    Pomógł: 0

    Moja rada jest taka zrób sobie podsłuch taki to odbiera atmega poprzez terminal w kompie tzn. podlacz sie pod pin RX atmegi jakims konwerterem rs na usb i wyswietlaj co otrzymuje atmega.
    Moim zdaniem masz zle zbudowany program odbierajacy ale nie w tej czesci co przedstawiles tylko juz w tym gdzie rozpatrujesz odebrane linie. mam tu na mysli nadchodzacy ciag danych o zbyt wielkim rozmiarze w porownaniu do zadeklarownaj zmiennej. Powodje to nadpisywanie innych zmiennych z ramu i w konsekwencji reset przypadkowy.

    _________________
    http://mojekonstrukcje.pl/



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 15 sie 2017, o 08:54 
    Offline
    Użytkownik

    Dołączył(a): 07 cze 2016
    Posty: 563
    Pomógł: 143

    TomekTomek55 napisał(a):
    Moim zdaniem masz zle zbudowany program odbierajacy ale nie w tej czesci co przedstawiles
    W tej części, którą autor przedstawił, też jest błąd mogący powodować nieporządane efekty. Polega on na braku atomowości dostępu do zmiennej globalnej ascii_line i pokazałem sposób, jak ten błąd naprawić. Nie wykluczam oczywiście błędów w innych miejscach programu i nie neguję całkowicie tego co napisałeś, jednak niezależnie od wszystkiego akurat w tym miejscu zmiana jest niezbędna, jeśli program ma pracować stabilnie.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 15 sie 2017, o 10:52 
    Offline
    Nowy

    Dołączył(a): 18 lis 2015
    Posty: 6
    Pomógł: 0

    @andrews
    A możesz powiedzieć, dlaczego przerwania z ascii_line mogą powodować problemy?



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 15 sie 2017, o 14:45 
    Offline
    Nowy

    Dołączył(a): 18 lis 2015
    Posty: 6
    Pomógł: 0

    Zmodyfikowałem sobie funkcję uart_get_str, tak aby niemożliwe było zapisanie do bufora wiecej bajtów niż posiada bufor UART (oraz mój bufor z odebraną linijką w programie).

    Składnia: [ Pobierz ] [ Ukryj ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


    Teraz wygląda, że jest ok. Narazie nie zauważyłem resetów. Wie ktoś, dlaczego tak się działo? Przecież jeśli przerwanie inkrementowało zmienną ascii_line, to znaczy, że w buforze był znak Enter (13), a widocznie pętla while nie "zauważała" tego znaku i zapisywała więcej danych niż rozmiar mojego bufora.



    Ostatnio edytowano 17 sie 2017, o 21:52 przez kamilo0, łącznie edytowano 2 razy

    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 15 sie 2017, o 14:58 
    Offline
    Użytkownik

    Dołączył(a): 07 cze 2016
    Posty: 563
    Pomógł: 143

    Szczerze mówiąc chciałem tego uniknąć, bo to trochę pisania jest... Liczyłem, że po prostu spróbujesz czy to pomoże, nie wnikając w szczegóły.

    No ale spróbuję w miarę możliwości krótko. Zmienna globalna ascii_line jest modyfikowana zarówno w programie głównym, jak i w procedurze obsługi przerwania. Operacja ascii_line--; nie odbywa się w jednym takcie zegara, ponieważ jest zapisana w pamięci RAM, a nie mikrokontroler nie może wykonywać operacji bezpośrednio na komórkach pamięci. Wymagane więc jest:
    • wczytanie zmiennej z pamięci RAM do rejestru,
    • wykonanie operacji pomniejszenia wartości rejestru,
    • zapisanie wartości rejestr z powrotem do RAM.
    Jeśli w trakcie tej operacji (po wczytaniu zmiennej do rejestru) wystąpi przerwanie i zmodyfikuje wartość zmiennej, to program główny o tym nie wie, i nie wczyta ponownie zmiennej do rejestru, tylko wykona operację na rejestrze i zapisze wynik operacji z rejestru do zmiennej w RAM, czyli przykładowo:
    • program główny wczytuje do rejestru wartość zmiennej ascii_line równą 3,
    • występuje przerwanie i procedura jego obsługi zmienia wartość zmiennej ascii_line na 4,
    • po zakończeniu procedury obsługi program główny wraca do miejsca, w którym skończył, i wykonuje następną instrukcję, czyli zmniejsza wartość rejestru z 3 na 2,
    • po wykonaniu operacji zapisuje wartość z rejestru (czyli 2, a powinno być 3) do zmiennej ascii_line w pamięci RAM.
    W efekcie wartość zmiennej po tej operacji jest nieprawidłowa, bo nie uwzględnia tego, co doliczyła w międzyczasie procedura obsługi przerwania. W ten sposób w buforze zawsze zostaną dane nie uwzględnione przez zmienną ascii_line, przez co prędzej czy później bufor się przepełni. Jaki będzie tego efekt to jest uzależnione od tego, jak masz zorganizowaną resztę programu (szczególnie chodzi o obsługę bufora, czyli zadbanie o to, by nie szło go przepełnić).

    Prawdopodobieństwo "trafienia" nie jest wprawdzie duże, ale jakieś jest, dlatego program może przez jakiś czas pozornie pracować prawidłowo, a czas ten będzie losowy, choć w pewnej mierze zależny np. od częstotliwości i długości przesyłanych pakietów danych (u Ciebie ciągów znaków oddzielonych znakiem '\r', jeśli dobrze rozumiem). Im więcej krótkich pakietów w jednostce czasu, tym ryzyko problemów będzie większe.

    EDIT:
    kamilo0 napisał(a):
    Bibliotekę tą zmodyfikowałem dla własnych potrzeb tak, abym mógł odbierać całe stringi
    ...
    Zmodyfikowałem sobie funkcję uart_get_str, tak aby niemożliwe było zapisanie do bufora wiecej bajtów niż posiada bufor UART.
    ...
    Teraz wygląda, że jest ok. Narazie nie zauważyłem resetów. Wie ktoś, dlaczego tak się działo?

    By można było odpowiedzieć na to pytanie musiałbyś pokazać więcej kodu, szczególnie tego dotyczącego obsługi buforów. Bardzo istotne jest np. to, co tak na prawdę zwraca funkcja uart_getc(), bo nie jestem pewien, czy Twoja pętla odczytu bufora działa prawidłowo.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 15 sie 2017, o 18:34 
    Offline
    Użytkownik

    Dołączył(a): 07 cze 2016
    Posty: 563
    Pomógł: 143

    roske napisał(a):
    Dlatego, że w tej bibliotece uart_getc, przy braku znaków do pobrania zwraca całkiem coś innego niż Ci się wydaje.

    Przepraszam, a skąd kolega wie, co zwraca funkcja uart_getc(), skoro "biblioteka" była modyfikowana.

    Poza tym, nawet jeśli autor wątku nie jest jakiś biegły w programowaniu i popełnia błędy, to komentarze czy sformułowania w stylu "recepta na uzyskanie pierwszorzędnej popeliny" nie są raczej na tym forum mile widziane. Wydaje mi się oczywiste, że na forum pytania zadają Ci, którzy wiedzą mniej. Ci, którzy wiedzą więcej, pomagają z zachowaniem kultury osobistej lub wcale. Błąd można równie dobrze wskazać, nie używając tego typu zwrotów.

    roske napisał(a):
    A nawet jak się ma o niej pojęcie to nadal jest to bzdura (nie będę tłumaczył dlaczego).

    A dlaczego nie będzie kolega tłumaczył? Ja na przykład chciałbym wiedzieć, bo w swojej nieświadomości kilka razy już popełniłem ten błąd (i jakoś nie przestały działać, a nawet działały lepiej czy też były bardziej zgodne z moimi oczekiwaniami). Aż tu nagle okazuje się, że to "bzdura"...



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 17 sie 2017, o 16:49 
    Offline
    Nowy

    Dołączył(a): 18 lis 2015
    Posty: 6
    Pomógł: 0

    Nie denerwujcie się tak Panowie. Nie każdy ma za sobą kilkanaście lat doświadczenia w programowaniu uC. Ja nie mam, więc zdarzają się czasem takie błędy. Ważne, że w jakiś sposób udało mi się osiągnąć to, na czym mi zależało, a że w nie do końca dobry sposób, dlatego zapytałem na forum ;)

    Biblioteka nie jest modyfikowana, dołożyłem do niej tylko tą jedną flagę (ascii_line) w obsłudze przerwania, i dopisałem sobie tą funkcję do odbierania stringu.

    Dzięki za porady, w wolnym czasie je przetestuję i mam nadzieję, że problem już nie będzie występował.

    @andrews
    Dziękuję za dokładne wyjaśnienie problemu przerwań ;)



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 17 sie 2017, o 17:08 
    Offline
    Użytkownik

    Dołączył(a): 07 cze 2016
    Posty: 563
    Pomógł: 143

    kamilo0 napisał(a):
    Nie denerwujcie się tak Panowie.

    Tak to wyglądało?
    Zapewniam, że ja akurat jestem zupełnie spokojny. Chciałem tylko delikatnie zwrócić na coś uwagę. Nie miałem zamiaru być agresywny czy nieuprzejmy, ale wygląda na to, że chyba zostało to odebrane inaczej ;)



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 17 sie 2017, o 19:15 
    Offline
    Użytkownik

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

    <proszę autora o umieszczenie kodów w znacznikach syntax>

    _________________
    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: 11 ] 

    Strefa czasowa: UTC + 1


    Kto przegląda forum

    Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 16 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:  
    cron
    Sitemap
    Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
    phpBB SEO