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

ATmega128 gubi przerwania

--Jas-- 14 Maj 2011 08:48 1827 13
  • #1 9503602
    --Jas--
    Poziom 11  
    Witam,
    piszę program do sterowania silnikami krokowymi pod ATmega128. Mam problem przy sterowaniu. Podczas generowania impulsów sterujących ruchem za pomocą przerwania zdarza się, że czasem przerwanie nie generuje impulsu. Oglądałem przebiegi generowane na analizatorze stanów logicznych.
    Wygląda to tak jakby procek z niewiadomych mi przyczyn nie generował przerwania, albo nie ustawiał w przerwaniu odpowiednio stanu pinu wyjściowego.
    Efekt występuje rzadko, ale na tyle często żeby podczas poruszania silnikiem występowały lekkie zatrzymania w ruchu. W ten sposób bardzo szybko zniszczę silniki i resztę mechanizmu, z którym współpracują.
    Czy spotkał się ktoś z podobnym problem?
    Dodam, że próbowałem napisać to również w zwykłej pętli w funkcji głównej, ale efekt jest ten sam.
    Z góry dziękuję za wszystkie rady i wskazówki.
  • #2 9503632
    snow
    Poziom 31  
    Jakim zegarem taktujesz atmege i przy jakiej częstotliwości impulsów się gubi?
  • #3 9503810
    mirekk36
    Poziom 42  
    --Jas-- napisał:

    Wygląda to tak jakby procek z niewiadomych mi przyczyn nie generował przerwania, albo nie ustawiał w przerwaniu odpowiednio stanu pinu wyjściowego.


    Jak można w ogóle takie wnioski wyciągać a tym bardziej na podstawie tak lakonicznych informacji? Żaden procek nie gubi przerwań, to niestety autor kodu gubi się podczas pisania programu - i gdybyś tego się trzymał to szybciej rozwiązywałbyś sam problemy - albo lepiej formuował pytania.


    --Jas-- napisał:

    Efekt występuje rzadko, ale na tyle często żeby podczas poruszania silnikiem występowały lekkie zatrzymania w ruchu. W ten sposób bardzo szybko zniszczę silniki i resztę mechanizmu, z którym współpracują.


    Pewnie, że tak - jeśli jednak najpierw nie spróbujesz pouczyć się programowania. Lepiej doszukiwać się błędów we własnym kodzie niż szukać błędów w procesorach na takim etapie - uwierz to tylko pomaga.


    --Jas-- napisał:

    Czy spotkał się ktoś z podobny
    m problem?
    Dodam, że próbowałem napisać to również w zwykłej pętli w funkcji głównej, ale efekt jest ten sam.
    Z góry dziękuję za wszystkie rady i wskazówki.


    Pewnie, że się z tym spotkała i to nie jedna osoba a ni nie dwie a tysiące początkujących programistów, którzy jeszcze niestety nie słyszeli o tym co do są "drgania styków" podczas obsługi najzwyklejszych klawiszy (microsłiczy) itp ...

    Poza tym wypadałoby zadając tutaj takie pytanie podać jakiś fragment kodu jak to robisz, żeby ci pomóc - bo tak to można tylko wróżyć albo bawić się w zgaduj zgadulę

    asembler
    język C
    Bascom

    przynajmniej to warto podać w temacie postu (zgodnie zresztą z regulaminem forum)

    gdy zastosujesz się do tych wskazówek i pokażesz swoje fragmenty kodu to zobaczysz, że szybko uda ci się pomóc i ew pokazać dobrą drogę

    powodzenia
  • #5 9504054
    mirekk36
    Poziom 42  
    dondu napisał:
    Coś przeczuwam, że ma delay() czy waits() albo while() w przerwaniu :)


    taaak - to byłaby masakra niestety :(

    ale pisał też o testowaniu w pętli głównej więc podejrzewam właśnie, że pojęcie "drgania styków" są jeszcze autorowi obce....

    a można o tym ładnie przeczytać np tutaj ;)

    http://mikrokontrolery.blogspot.com/2011/04/przycisk-drgania-stykow-debouncing.html
  • #6 9506090
    --Jas--
    Poziom 11  
    Dzięki za zainteresowanie tematem. Rzeczywiście mogłem lepiej opisać problem na samym początku. Już naprawiam błąd.

    System wygląda w ten sposób, że Atmega128 taktowana sygnałem o częstotliwości 14.745600 MHz (F_CPU = 14745600) podłączona jest bezpośrednio do 3 osiowego drivera silników krokowych TB6560. Konkretnie mówiąc pin 3 portu D podłączony jest do pinu 3 w interfejsie 25-pinowym drivera TB6560. Jest to sygnał STEP Z.
    Próbowałem sterować tym driverem za pomocą przerwań w następujący sposób:

    Kod: text
    Zaloguj się, aby zobaczyć kod


    Jak robiłem to w ten sposób silnik sterowany na tej osi nie pracował cały czas płynnie, ale od czasu do czasu w charakterystyczny sposób "stukał". Przepraszam za kolokwialne określenia, ale nie jestem specjalistą od silników. Otrzymałem informację, że ten brak płynności w pracy silnika wywołany jest niewłaściwym sterowaniem. Oznacza to, że występują sytuacje, gdy sterowanie w powyższy sposób nie powoduje zmiany stanu nóżki D3 i silnik na chwilę się zatrzymuje.
    Sprawdziłem to na analizatorze stanów logicznych LA-2124A i wydaje się, że rzeczywiście tak jest. Nie wkleję teraz przebiegu, bo nie mam w tej chwili dostępu do układu, ale jeśli trzeba zamieszczę w następnym poście. W każdym razie zdarzało się, że przebieg wyglądał tak: 0101011010101 itd.. a powinien wyglądać tak: 0101010101 itd.. (gdzie 0 oznacza stan niski, a 1 oznacza stan wysoki).

    Założyłem, że może niewłaściwie ustawiam przerwania, więc spróbowałem zwykłej pętli while w funkcji głównej main i opóźnienia:

    Kod: text
    Zaloguj się, aby zobaczyć kod


    Przy czym w funkcji init_global mam wszystkie ustawienia konfiguracyjne oraz pilnowałem się, żeby zmienna time nie przybrała wartości większej niż podawana obsługiwana wartość opóźnienia tej funkcji (chyba coś koło 700).
    Niestety efekt działania był taki sam.

    Dlatego zacząłem podejrzewać, że może popełniłem błąd w konfiguracji kompilatora. Wykorzystuję WinAVR-20100110 i Programmers Notepad. Napisałem prosty programik w BASCOMie w BASCOM-AVR IDE o następującej postaci:

    Kod: text
    Zaloguj się, aby zobaczyć kod


    Próbowałem również wykorzystać przerwania (jakoś nie mogę teraz znaleźć tego kodu, którego użyłem).
    Na koniec zdesperowany spróbowałem jeszcze raz w ASM w pod BASCOM-AVR IDE, ale to też nie działało jak trzeba i postanowiłem najpierw napisać na forum i przemyśleć wszystko jeszcze raz, a nie brnąć w implementację (być może bez sensu). (w kodzie poniżej steruję osią X drivera, a nie osią Z)

    Kod: text
    Zaloguj się, aby zobaczyć kod


    W opisie tematu nie podałem języka programowania ani kodu ponieważ próbowałem wielu różnych i liczyłem cicho na to, że to jakaś generalna cecha, o której powszechnie wiadomo, a nie mój błąd. Na wszelkie dalsze pytania postaram się odpowiadać w miarę możliwości szybko. Proszę o konstruktywną krytykę.
  • #8 9506142
    --Jas--
    Poziom 11  
    A co powoduje wpisanie do _delay_us zmiennej? Bo kompilator to przełknął..
    Nie znałem tego operatora "^". Wielkie dzięki - to mi ułatwi pracę.
  • #10 9506225
    --Jas--
    Poziom 11  
    Tak, podlega zmianie. Dzięki za uwagę. Przepiszę to jutro z wykorzystaniem stałych. Przeoczyłem to w dokumentacji.
    A z tą analizą mam problem - nie bardzo rozumiem zapis asm w tej postaci jaka jest w delay_loop_2 i delay_loop_1.
  • #11 9506245
    BoskiDialer
    Poziom 34  
    Jak już wspomniano, mikrokontroler nie gubi przerwań. Może natomiast:
    - w przerwaniu zmieniać wartość rejestru IO, ale w pętli głównej może wystąpić modyfikacja tego rejestru, przez co uzyska się nieatomową operację w pętli głównej i istnieje możliwość utraty zmian dokonanych w przerwaniu - ten przypadek tutaj nie ma miejsca
    - źle ustawiony uC (np pracujący w trybie kompatybilności z m103) potrafi się resetować przy wychodzeniu z przerwań (uszkodzony spód stosu spowodowany inną ilością pamięci) - zwykle jest to skok albo pod adres z samych jedynek albo samych zer, co doprowadzi do rozpoczęcia programu od nowa, ale bez resetu peryferii. W szczególnych przypadkach przerwania będą dalej załączone, a więc możliwe jest wystąpienie przerwań w trakcie inicjalizacji procesora (wynik skoku pod adres 0 rozumiany przez kod wynikowy jako reset) - zachowanie w takim przypadku może być wyjątkowo dziwne.

    W przypadku tak prostego kodu jak ten załączony - i mimo to jego niedziałania, nasuwa mi się myśl, że uszkodzony może być kwarc, mogą być zimne luty, oscylacje wygasają (chociaż by przez brak zaprogramowanego [0] bitu CKOPT) lub inne usterki z zegarem.

    Najlepiej jest zrobić prosty program testowy nie zawierający żadnych przerwań ani pętli opóźniających (w tym _delay_us i _delay_ms), zmieniający stan wyjścia z maksymalną szybkością - mierząc na oscyloskopie można sprawdzić, czy procesor pracuje ciągle, czy miewa okresy, kiedy brak jest źródła taktowania.
  • #12 9506336
    --Jas--
    Poziom 11  
    Wydaje mi się, że ten drugi przypadek też nie występuje. Podczas testowania miałem też wersję bardziej skomplikowaną programu ze sterowaniem różnymi peryferiami i program nie rozpoczynał się w trakcie pracy od początku.
    Jutro sprawdzę jak zaprogramowałem CKOPT, ale do oscyloskopu nie mam niestety dostępu. Nie mogę też sprawdzić czy przy maksymalnej częstotliwości zmian działa silnik, bo driver silnika nie wyłapuje impulsów z tak wysoką częstotliwością.
    Myślę, że istnieje szansa błędu na płytce. Zdarzało się to odnośnie tego układu, ale do tej pory wszystkie błędy udawało mi się eliminować. Analiza tego źródła błędu zajmie mi dłuższy czas (jest to projekt wykonywany w czasie wolnym od pracy), więc raczej nie odpiszę szybko na tą uwagę. Na co szczególnie powinienem zwrócić uwagę przy szukaniu błędu na płytce?
  • #13 9506404
    Fredy
    Poziom 27  
    A ni jest tak, że włączenie silnika i wogóle pracujący silnik czasami resetuje ci procka? Daj długi delay na początku to szybko to zauważysz.
    Nie masz włączonego watchdoga którego nie kasujesz?
    Czy masz dobrze skonfigurowane rejestry od przerwań? Może włączyłeś jakieś przerwanie a nie zrobiłeś jego obsługi?
    Może nie masz podciągnięcia na wyjściu sterującym - dodaj rezystor np 10k do zasilania, albo włącz podciąganie w procku.
    Czy dałeś kondensatory przy kwarcu? Może oscylator ci fiksuje?


    I jeszcze jedno - czy prosty program typu zmieniaj stan pinu co jakiś czas też gubi ci impulsy?
  • #14 9506833
    --Jas--
    Poziom 11  
    Procek się nie resetuje. Efekt zaczął występować w systemie, gdzie mam podpięty wyświetlacz TFT i generuję na nim graficzny interfejs użytkownika. Proces uruchomienia programu trwa kilkanaście sekund i wywołuje określoną sekwencję zdarzeń na TFT i peryferiach (silnikach też). Zauważyłbym reset procka.
    Na potrzeby testów uprościłem program do minimum, jednak efekt pozostał taki sam i nadal występuje.
    Wachdoga nie mam włączonego.
    Co do konfiguracji nie jestem pewien. Prześlę kod jak będę mógł - mam jakiś problem z uruchomieniem kompa, na którym mam projekt (nie związane z tematem).
    Co się dzieje jeśli nie obsługuję przerwania, które jest włączone?
    Rezystora podciągającego nie mam - postaram się dodać dziś i sprawdzić jak działa (jeśli pozbędę się awarii komputera). Kondensatory mam dodane. Ale postaram się w tygodniu pożyczyć jakiś oscyloskop i sprawdzić kwarc (i przetestować wyjścia wg. zaleceń BoskiDialer).
    Tak prostego programu nie sprawdzałem. Dzięki za rady. Postaram się wszystko przetestować.

    I jeszcze jedno odnośnie _delay_us. Rozumiem, że taki kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    będzie działał poprawnie?
REKLAMA