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

[ATMega16][C] Program się zawiesza w losowych momentach

rassmuss 01 Wrz 2011 20:47 4690 56
  • #1 9886164
    rassmuss
    Poziom 11  
    Witam,
    zmagam się z tym problemem już dobrze ponad tydzień, miałem nadzieję, że uda mi się samemu go rozwiązać, jednak nie obejdzie się bez pomocy bardziej doświadczonych w temacie :wink:

    Otóż problem jest jak w temacie, dosyć rozbudowany wsad (ponad 96% pamięci) działa poprawnie, nie zauważyłem żadnych anomalii, błędów logicznych czy obliczeniowych. No wszystkie funkcje działają poprawnie, z tym, że program się wiesza w dość losowych momentach. Mam juz praktycznie gotowy wsad i zacząłem go testować przez dłuższy czas i dopiero teraz to wyszło na jaw.
    Czasami wiesza się po 3 godzinach, a czasami po 10.

    Trochę o samym układzie: całość składa się z dwóch procesorów, m16 jako nadrzędnego oraz m8 jako podrzędnego podpiętego po I2C. Do tego jest jeszcze PCF8583. Procesory poubierane w kondziory 100n. Stabilizacja zasilania typowa dla LM7805 (100n na we i wy, 100uF na we, 470uF na wy).
    Do m16 jest podpiętych 6 przycisków, wyświetlacz lcd, buzzer oraz sterowanie podświetleniem lcd. Jest także czujnik indukcyjny NPN NO podpięty pod wejście przerwaniowe oraz sygnał z PCFa pod drugie wejście przerwaniowe.

    Do czego doszedłem sam:
    -najprawdopodobniej można odrzucić zakłócenia z sieci, od tego zacząłem, bo wszystko było zasilane z mojego prymitywnego zasilacza +12V. Podłączyłem układ do zasilacza z laptopa (wydaje mi się, że powinien mieć zdecydowanie lepsze filtry) i problem nadal występuje.
    -początkowo nie miałem zmiennych używanych "wielowątkowo" jako volatile - co jednak nie powodowało żadnych problemów w działaniu. Poczytałem o konieczności używania tego słowa kluczowego oraz kwiatków jakie niektórzy przez jego brak mieli i podopisywałem gdzie trzeba - bez zmian w działaniu, nadal się wiesza.
    -wydaje mi się, że problemu nie stwarza I2C - PCF raczej chyba się nie wiesza, druga atmega również. Wykluczyłem to w prosty sposób - odłączałem m8, wtedy m16 zamierałą (while...) w oczekiwaniu na jej odpowiedź. Po podłączeniu m8 program ruszał dalej. W momencie zwisu podawałem ręcznie masę na reset m8, co wg mnie powinno spowodowac zachowanie jak wyżej jeśli powodem byłaby zwiecha m8 i oczekiwanie m16.
    -prawdopodobnie wieszanie ma związek z czujką indukcyjną (w założeniu ma pracować ona sobie przy kole pojazdu jako sensor prędkości i drogi), ponieważ gdy jej nie używałem (koło symulowałem wiatraczkiem z komputera z doczepionymi elementami metalowymi) program działał nieprzerwanie przez ponad dobę, gdy tylko "koło" zacznie pracować następuje zwis po jakimś, bliżej nieokreśłonym czasie ("koło" testowe zawsze obraca się mniej więcej z tą samą prędkością). W związku z tą losowością nie wiem do czego sie przyczepić, ponieważ czy program sobie coś zlicza (przejechana droga) czy nie zwis następuje (czyli zapewne samo działanie czujki czyli obliczanie prędkości powoduje problem).
    Przejżałem kod kilkukrotnie, pierwonie prędkość była obliczana w przerwaniu (wiem wiem, mnożenie i dzielenie floatów jest zbyt długie na obcowanie z przerwaniem, jednak podczas testów w trakcie programowania wszystko działało), przeniosłem więc tą najbardziej czasochłonną część do pętli głównej programu - też nic to nie dało.

    Jednym słowem skończyły mi się pomysły...program jest obszerny, całości nie będę wrzucał (1500 linii kodu w samym pliku głównym), proszę o wskazówki to umieszczę fragmenty odpowiedzialne za wybrane części.

    Pozdrawiam
  • #2 9886324
    snnaap
    Poziom 25  
    Taka mała porada, możesz podłączyć całość do kompa po rs? Jeżeli tak to możesz zrobić pewnego rodzaju loga i będziesz wiedział co się dzieje. A mianowicie musisz w momencie rozpoczęcia działania konkretnego fragmentu kodu wysłać po rs że akurat to coś zaczynasz i później wysłać że się skończyło i tak z wszystkimi ważniejszymi fragmentami oraz wszystkimi zdarzeniami (przerwania).
    Np: przy przerwanie zgłaszasz wejście w przerwanie a następnie zgłaszasz wyjście z przerwania - jak było wejście a nie było wyjścia to już bekiesz wiedział gdzie się zwiesił.
  • #3 9886378
    rassmuss
    Poziom 11  
    No to jest myśl, nawet na płytce jest miejsce na MAXa, aby go włożyć i podpiąć to pod RSa. Pierwotnie miało tak właśnie być, że obydwa procesorki sobie generują jakieś logi po RSie, a ja się podpinam pod wybrany żeby zobaczyć co się dzieje, jednakże transmisja po RSie (z prędkością 19200) tak masakrycznie spowalniała komunikację po I2C, że ją wywaliłem.

    Dokładnie tak jak piszesz miałem "ologowany" moduł z m8, jednakże jak pisałem, komunikatów było dość dużo i powodowało to spowolnienie komunikacji I2C i ogólnie wszystkiego (bo m16 czekała na m8).
    Spróbuję, jak za mocno mi to nie zamuli procesora to zostawię.
  • #4 9886490
    bolek
    Poziom 35  
    Sama zgłoszenie miejsca to połowa sukcesu, 3/4 gdy wyślesz parametry, z których wyczaisz dlaczego jest tak a nie inaczej i tu już możesz sobie pogratulować.
  • #5 9886492
    michalko12
    Specjalista - Mikrokontrolery
    Zacząłbym od sprawdzenia czy wystarcza RAMu na stos.
  • #6 9886519
    gaskoin
    Poziom 38  
    Albo czy gdzieś nie masz gdzieś miliona wywołań funkcji. Niektórzy w przerwaniu odblokowywują przerwania, albo wywołują inne cuda, dzięki czemu po kilkudziesięciu przerwaniach stos się rozsypuje.
  • #7 9886524
    janbernat
    Poziom 38  
    Troszkę niejasne.
    Gdy do wiatraczka doczepiałeś metalowe elementy- to co było czujnikiem?
    Ten sam czujnik indukcyjny- czy coś innego?
    No i następna niejasność- po wprowadzeniu volatile i przy zastosowaniu wiatraczka z elementami metalowymi i z nie wiadomo jakim czujnikiem wszystko działało?
    To trzeba robić metodami undo- wracać do stanu kiedy działało i nie zmieniać wielu rzeczy naraz- oczywiście czasem trzeba zmienić wiele rzeczy naraz- wtedy są duże kłopoty.
  • #8 9886582
    rassmuss
    Poziom 11  
    michalko12, gaskoin - m16 ma 1024KB ramu, kompilator wyrzuca, że .data, .bss i .noinit zajmują 711 bajtów, zostaje więc 313 na stos. Wydaje mi się, że raczej się nie przepełnia, ponieważ obsługę wszystkich przerwań mam jako SIGNAL i w żadnym z nich ręcznie nie odpalam sei().

    janbernat - czujka indukcyjna reaguje na metal, jest umieszczona na stelażu nad wiatraczkiem, do którego są przymocowane metalowe elementy powodujące zadziałanie czujki indukcyjnej (NPN NO).
    Czujkę tą mam od samego początku, wiatraczek z metalami również. Wiem o tym co napisałeś, ale mówię - dotychczas przy pisaniu jedynie odpalałem układ żeby go zaprogramować i sprawdzić czy program działa logicznie, obliczeniowo, czy nie ma jakiś krzaków. Wszystko było ok, dopiero jak zostawiłem go na noc, okazało się, że gdy koło się kręci (są impulsy na czujniku indukcyjnym, przerwanie od niego się odpala) występują zwiechy - raz po 3 godzinach, a raz po 10, a koło kręci się tak samo szybko. Gdy koło się nie kręci (brak impulsów -> wywołań przerwania) wszystko gra.

    bolek - wisi na amen, inna sprawa, że cały program działa w głownej pętli i po kolei sprawdza sobie a to stan przycisków, a to odczytuje czas, a to odczytuje dane z modułu podrzędnego (czyli m8), a to sobie wypluje coś na wyświetlacz i potem od początku). Czyli gdzieś staje i nie idzie dalej.
    Chciałem zrobić przycisk na przerwanie i sprawdzić czy jest to amen czy wisi gdzieś na pętli (choć tych mam jak na lekarstwo, główna oraz w obsłudze I2C), ale niestety wolnego brak.
    A po drodze nie miałem jak tego testować "na wymęczanie", bo pisałbym to rok :D
  • #9 9886655
    janbernat
    Poziom 38  
    Nie SIGNAL a ISR() może na początek.
    A potem policzyć ile to przerwanie trwa.
  • #10 9886785
    rassmuss
    Poziom 11  
    To też już wiem, ale ze kompilator się nie buntuje to chyba nie jest wielki grzech ;)

    Z policzeniem będzie problem, bo generator plików lss się wysypuje... O_o
  • #11 9886807
    gaskoin
    Poziom 38  
    Najlepiej jakbyś wrzucił schemat i skoro mówisz, że to obliczanie prędkości to może wrzuć kod jak są pobierane sygnały z czujników i jak zachodzi cały proces przeliczania tego na prędkość ? To , że kompuilator nic nie mówi, nie znaczy, że program jest ok ;)
  • #12 9886861
    rassmuss
    Poziom 11  
    Schemat w załączniku.

    A to fragmenty kodu odpowiedzialnego za czujnik:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    I potem w głównej pętli:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Transmisję RS dodałem przed chwilą.
  • #13 9886881
    Fredy
    Poziom 27  
    1) co z resetem? Masz tam kondensator do masy i rezystor podciągający?
    2) sprawdź kwarc i oba kondenstaory
    3) zamień Mega 16 na Mega 32 na próbę, może to wina stosu ?
    4) masz podciągnięcia wszystkich wejść przerwań INT ?
  • #14 9886895
    rassmuss
    Poziom 11  
    1) reset jest podciągnięty przez 4k7
    2) uzywam wewnetrzneg rezonatora
    3) niestety nie mam pod ręką m32
    4) sprzętowych brak, niestety tylko programowe
  • #15 9886925
    dondu
    Moderator na urlopie...
    Nie widzę na schemacie tej czujki indukcyjnej. Czy złącze P3 to złącze do niej?
    Pokaż jak to masz rozwiązane.

    Czasami strzela się oczywisty byk, który trudno znaleźć, więc może tak na wszelki wypadek zobacz, może to któryś z tych powodów - zapewne dla Ciebie oczywiste, a może pokierują Cię na jakiś trop: http://mikrokontrolery.blogspot.com/2011/04/nieoczekiwany-reset-mikrokontrolera.html

    Dla zasady jeszcze zapytam - warningi jakieś masz podczas kompilacji?
  • #16 9886958
    rassmuss
    Poziom 11  
    Tak, ze złącza P3 wchodzi poprzez wejście nr. 5 sygnał od czujki (zwarcie do masy). Nic innego tam nie ma, to idzie prosto do wyjścia czujki, a czujka jest zasilana prosto z zasilacza (w tej chwili 19V, jej zakres to 12-24V).

    Warningów brak.

    Co do wskazówek - o zakłoceniach pisałem na początku, wykluczyłem je po zmianie źródła zasilania. Może błędnie, ale w takim razie nie wiem czym to zasilić...
    Watchdoga nie uzylem. Zasilanie jest raczej stabilne - podwójmy LM7805. O pętlach pisałem wyżej - główna oraz w obsłudze I2C, więcej brak. Przerwania są ok, zegar to wewnętrzny 8Mhz, za słabe zasilanie też nie.

    Zapuściłem loga poprzez RSa, zobaczymy gdzie stanie.
  • #18 9886973
    mirekk36
    Poziom 42  
    To może nie bezpośredni powód ale masz w schemacie kilka "kfatkóf" ---> specjalnie tak napisałem.

    1. Kondensator 100nF od AREF do VCC ???? to jakaś pomyłka - do GND ma być

    2. Kondesator 470uF na zasilaniu procka??? dużo za dużo - 10-47uF i w pobliżu nóg procka jeden a drugi w pobliżu nóg stabilizatora. To na wejściu stabilizatora możesz sobie dać taki 470uF

    3. kondensator 33pF od nogo 2 (OSCO) do GND ??? powinien być do VCC i lepszy byłby 22pF jak już

    ----------------

    Nad samym stosem dosyć łatwo zapanować, ale czy w twoim przypadku 313 bajtów wolnej pamięci RAM to dużo czy mało - trudno powiedzieć na przykładzie takich tylko fragmentów kodu. Równie dobrze może to być wystarczająco na spokojnie a równie dobrze sporo za mało. Zależy to nie tylko od tego czy dajesz sei w przerwaniach ale choćby od tego jak definiujesz zmienne lokalne w funkcjach. Tego nie widzimy więc tylko można zgadywać. A tu wystarczy kilka tablic czy struktur większych gdzieś popełnić - i już TYLKO na podstawie wolnej pamięci RAM po kompilacji nie uda ci się tak wprost powiedzieć, że 313 bajtów wystarczy.
  • #19 9887013
    rassmuss
    Poziom 11  
    A trochę się wybronię z "kfiatkuff" :wink:
    3. Kondziora dobrałem aby zegar chodził w miarę punktualnie. Na schemacie jest 33pF, ale w układzie jest inny, nawet nie pamiętam jaki...dobrany doświadczalnie.
    Co do podłączenia do GND to przyznaję się, mój błąd przez niedopatrzenie.
    2. Taki dałem, ponieważ układ jest zasilany kabłem długości kilku m (kabel komunikacyjny z modulem drugim w którym znajduje się stabilizacja - chodziło mi o wyciągnięcie tych grzałeczek na wolne powietrze, gdzie zamontowany ma być moduł drugi).
    1. Wydaje mi się, że spotkałem to gdzieś dawno temu na jakimś schemacie i tak skopiowałem. Również mea culpa.

    Czyli również sugerujesz testową przesiadkę na m32?
  • #20 9887022
    mirekk36
    Poziom 42  
    Nie - po co m32 - pokaż albo opisz jakie zmienne stosujesz w funkcjach w tym w funkcji main() bo to też normalna funkcja - i zmienne tam zdefiniowane zwiększają na stałe stos (te z main)

    A co do zasilania hmmm piszesz, że długimi kablami ??? czy coś źle zrozumiałem ??? bo jeśli długimi to nie lepiej puszczać nimi np 12V a stabilizatory dać na płytce ??? albo jakieś przetworniczki żeby się tak nie grzały te 7805?
  • #21 9887032
    rassmuss
    Poziom 11  
    Mogę Ci podesłać cały kod jeśli chcesz, publicznie nie chcę go tu umieszczać.

    No tak, jest trochę nakręcone ale to przez to, ze te LMki się nagrzewają. Z modułu tego z m16 idzie +12V do modułu z m8, tam są stabilizatory i kondensatory, +5V zasila m8 i idzie spowrotem do modułu z m16 i tam zasila megę i resztę. A kondziora dałem tam dużego ze względu na kable oraz wyświetlacz - jest to ten wiekszy (określany jako BIG) i trochę prądu ciągnie.

    Myślałem już nad jakimiś przetworniczkami, pewnie zainteresuję się tymi Twoimi.
  • #22 9887257
    mirekk36
    Poziom 42  
    To podeślij kod na priv, nie obiecuję jakiejś analizy - ale na pewno rzucę okiem pod kątem tego co się dzieje względem stosu.

    A jeśli masz wyświetlacz , który pobiera sporo prądu i próbujesz to załatwić właśnie większym kondensatorem, tzn spadki napięcia - no to właśnie to może być problemem :( i to poważnym.

    Ale tutaj to możesz wrzucić też jak wygląda PCB - bo może tu masz jeszcze coś nie tak - a to też miewa poważny wpływ na działanie całości.

    Jeśli natomiast ten wyświetlacz ciągnie jak mówisz sporo prądu to poważnie warto się zastanowić nad wydzieleniem dla niego odrębnej gałęzi zasilania.

    Ja w takich przypadkach przestawiam przetworniczkę np na 6,5V bo można to spokojnie zrobić i z tego napięcia zasilam LED'y, podświetlenia, Wyświetlacze itp .... a po drodze do procka stosuję jeszcze wtedy na PCB jakiś mały stabilizator LDO typu LM1117-5.0

    Efekt jest taki, że procek nie pobiera wiele prądu, stabilizator LDO ma na wejściu nieduże napięcie i dzięki temu wszystkiemu - żadnych ale to żadnych strat ciepła. Za to napięcie wejściowe może się wahać w granicach od 8V do 24V i wszystko nadal pięknie działa. Tak więc wtedy zasilanie z jakiegoś zasilacza nawet niestabilizowanego na długich kablach to żaden problem.
  • #23 9888006
    LordBlick
    VIP Zasłużony dla elektroda
    Obsługa przerwania powinna być jak najkrótsza, jeśli zależy tobie na pozbyciu się zawieszeń... W ISR(INT0_vect) (nie SIGNAL(INT0_vect)) wystarczy licznik przerwań, a wręcz możesz to podpiąć pod wolny timer/counter ustawiając prescaler na wejście zewnętrzne liczenia - "External clock source on TX pin. ".
    http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html
  • #24 9889541
    rassmuss
    Poziom 11  
    mirekk36 - póki co, może obejdzie się bez angażowania Twojego czasu na analize moich krzaczków ;)
    Problem występuje także wtedy, gdy wyłączę podświetlenie (w opcjach ustawię na 0). Więc (byćmoże prądożerne) podświetlenie lcd nie jest przyczyną.

    Po założeniu loga na RSie doszedłem do tego, ze zawiesił się przy odczycie danych z drugiego modułu - czyli jednak jest coś na rzeczy z I2C. I teraz mam takie pytanko, czy jeżeli mam zmienną volatile i do niej przypisuję wartość zwróconą przez funkcję odczytu z magistrali I2C (czyli musi wystąpić poprawna transmisja aby zmienna mogła zostać przypisana), to jeśli w trakcie tejże transmisji wystąpi przerwanie w którym następuje odczyt tej wspomnianej zmiennej volatile to ta zmienna jest jakby zablokowana do momentu zakończenia transmisji i przypisania jej wartości? Innymi słowy czy jak jestem w trakcie przypisywania jej wartości to inny "wątek" może ją odczytywać widząc starą wartość (co byłoby logiczne), czy może on jest blokowany do momentu zakończenia przypisywania nowej wartości (czyli powstaje zwis, bo przerwanie wystąpi w trakcie transmisji i będzie czekać na jej zakończenie które nigdy nie nastąpi bo procesor zajmuje się właśnie przerwaniem)?
    Oto kod funkcji odczytującej:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    A to definicja struktury w której są przechowywane dane:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    LordBlick - zliczanie odpada przy liczeniu prędkości, przy każdym sygnale muszę mieć informację że on nadszedł, aby obliczyć obecną prędkość. Sygnały z wiatraczka napływają stosunkowo szybko (obroty pewnie nie mniejsze jak 1000, w tej chwili był jeden element metalowy na nim). Po montażu w miejscu docelowym impulsy te będą spływać dużo wolniej, w końcu koło pojazdu rolniczego nie rozwija ogromnych prędkości.
  • #25 9889717
    dondu
    Moderator na urlopie...
    rassmuss napisał:
    ... zliczanie odpada przy liczeniu prędkości, przy każdym sygnale muszę mieć informację że on nadszedł, aby obliczyć obecną prędkość.

    A w jakim celu musisz to robić tak często?
    Mam wrażenie, że koncepcja jest niewłaściwa.
  • #26 9889750
    rassmuss
    Poziom 11  
    Chodzi mi o to, aby prędkość była podawana zawsze aktualna. A jak pojazd porusza się z prędkością powiedzmy 7 km/h (niecałe 2 m/s), koło o obwodzie 2-3m obróci się więc niecały raz w ciągu sekundy, jeśli będzie miało 6 szpilek to da 6 impulsów na sekundę. Jeśli zliczałbym je i wykonywał obliczenie prędkości co 10 impulsów to już będę miał aktualny wynik co półtora sekundy - to trochę za długo. Stąd wybrałem obliczanie praktycznie kiedy tylko się da (pierwotnie liczyłem prędkość w przerwaniu, w tej chwili w przerwaniu tylko pobieram czas między impulsami i ustawiam flagę, a prędkość obliczam w pętli głównej).
    Odnośnie drogi to zliczam impulsy w przerwaniu i po osiągnięciu jakiejś ich ilości (zależnej od wielkości koła) aktualizuję potrzebne zmienne pamiętające drogę.
  • #27 9889767
    dondu
    Moderator na urlopie...
    Ale piszesz o 1000 obrotach z wiatraczka. Wyjaśnij to. bo nie rozumie.

    Inaczej pisze się program dla 1000 obrotów a inaczej dla tych parametrów które podajesz powyżej. Dlatego nie można testować programu na symulatorze wiatraczkowym, który wielokrotnie odbiega od tego, w jakich warunkach układ będzie działał w wersji końcowej.

    Pamiętaj, że są jeszcze tryby pracy timerów, do zliczania odcinków czasu, pomiędzy impulsami z koła.

    No chyba, że czegoś nie doczytałem.
  • #28 9889806
    LordBlick
    VIP Zasłużony dla elektroda
    Na pomiar prędkości są dwie szkoły:
    - dla wolnych obrotów zliczasz czas pomiędzy impulsami i to najlepiej licznikiem/timerem (hasło ICP)
    - dla szybkich obrotów zliczasz impulsy w ustalonym czasie i to też zrobisz najlepiej dwoma timerami/licznikami (jeden odlicza ustalony czas, drugi impulsy)
    Wybieraj... ;)
  • #30 9889879
    rassmuss
    Poziom 11  
    No przyznaję, że ja zrobiłem to w pełni programowo bo nie wiedziałem, że można zaprząc timera do zliczania czasu pomiędzy impulsami.

    Bo ja robię tak: uc ma zegar 8 Mhz, przy prescalerze 8 timer tyka sobie co bodajże 0,000001s, przepełnienie (8-bitowego) następuje po 0,000256s co mi bardzo uprościło liczenie czasu. Bo ile tyknięć i przepełnień, tyle 1x10^-6s i tu jest bardzo proste liczenie, jedno mnożenie (bo zliczam przepełnienia timera) i suma ze stanem timera w momencie impulsu z koła. Potem dzieliłem drogę (czyli wycinek koła między dwiema szpilkami - wartość praktycznie stała) przez ten czas, pomnożyłem przez 3.6 i już miałem prędkość w km/h.
    Wydaje mi się że zliczanie timerem czasu między impulsami nie będzie jakoś znacząco mniej zasobożerne.

    A o tych dwóch metodach liczenia prędkości to wiem :)

    Ja bym się skupił na tym fragmencie który wkleiłem, bo tu - tak wynika z loga - jest problem. Na tej funkcji stanęło. Po wywołaniu tej funkcji (a przed jej zakończeniem) w którymś momencie pojawiło się przerwanie od czujki koła i funkcja stanęła w miejscu. Myslałem (jak się okazało błędnie!), że wiesza się całość, ale jednak nie. Staje w tej funkcji, a reszta tj. przerwania od zegara oraz kolejne od czujki koła przychodzą dalej bo widziałem je w logu z RSa.
    Co więc może być tu źle?
REKLAMA