Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[atmega8][Bascom] Zewnętrzne przerwania uniemożliwiają komunikację przez I2C

komanche 15 Kwi 2012 19:54 2960 10
  • #1 15 Kwi 2012 19:54
    komanche
    Poziom 13  

    Witam!
    Kolega poprosił mnie o zrobienie mini-komputerka do Opla Corsy, mającego wyświetlać dane na wyświetlaczu radia. Problem pojawił się, kiedy zechciałem wyświetlać na bieżąco prędkość - program zgłupiał (choć, raz na kilka odświeżeń wyświetlacza pojawiła się poprawna prędkość) a przy większych prędkościach Atmega ulegała resetom lub się zawiesza.
    Wyświetlacz to standardowy TID, korzystający ze zmodyfikowanego I2C do komunikacji, prędkość zbierana jest z wbudowanego w skrzynię impulsatora dającego 16256 impulsów/kilometr. Poniżej program, opierający się na znalezionej w sieci metodzie wyświetlania danych na TID. W załączniku schemat urządzenia.
    [atmega8][Bascom] Zewnętrzne przerwania uniemożliwiają komunikację przez I2C

    Cały kod:

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    A tutaj tylko część odpowiedzialna za obliczanie prędkości:
    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    Proszę o pomoc, bo zadanie mnie odrobinę przerasta. Dawno nie bawiłem się mikrokontrolerami i większości rzeczy pozapominałem. Może zabrałem się za mierzenie prędkości od złej strony? Mam wrażenie, że problem leży w przerwaniach, które mogą pojawić się w trakcie przesyłania danych na ekran wyświetlacza i zakłócać transmisję. Jeśli ktoś, kto zna Bascoma trochę lepiej niż ja (a o to nie trudno) zna sposób na mierzenie prędkości z przyzwoitą rozdzielczością, który nie zakłóci wyświetlania, czekam. Układ jest na razie zmontowany "na pająka" i przelutowanie impulsów np. na wejście jakiegoś timera nie stanowi problemu.

    Pozdrawiam!

    0 10
  • #2 15 Kwi 2012 20:16
    speedy9
    Pomocny dla użytkowników

    Rzuciłem okien na kod i nie znalazłem w procedurze wyświeltlania po I2C "DISABLE INTERRUPTS". Powinno pomóc. Możesz też wyłączać tylko INT0 lub INT1. Pamiętaj tylko by je potem włączyć po zakończeniu wyświetlania ("ENABLE INTERRUPTS").

    0
  • #3 15 Kwi 2012 20:22
    komanche
    Poziom 13  

    To była moja pierwsza myśl, Disable INT0 umieściłem w pętli głównej na zasadzie

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod



    I działanie to przyniosło efekt w postaci narastania licznika impulsów z f<1Hz i w konsekwencji V<0.1 km/h. W tym momencie własnie straciłem wiarę we własne siły. Częstotliwość impulsów nie jest aż tak duża, żeby atmega8 nie dała sobie z tym rady - jest to około 4,515imp/s/kph (451,5 imp/s dla 100km/h)

    0
  • #4 15 Kwi 2012 21:10
    Mundi1970
    Poziom 24  

    Problem na pewno jest tu :):

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod

    Jeżeli wykorzystujesz opcje Nosave , to musisz wiedzieć jakie rejestry (R0-R31) wykorzystuje twoja procedura przerwanie. Przed wykonaniem przerwania musisz je sam wysłać na stos, a po zakończeniu przerwania z powrotem ściągnąć ze stosu. Skonfiguruj przerwanie bez opcji Nosave, a kompilator sam zadba o wszystko :). Druga sprawa brak definicji wielkości stosów, zainteresuj się $hwstack, $swstack i $frame.

    0
  • #5 16 Kwi 2012 23:53
    komanche
    Poziom 13  

    Mundi1970, bardzo dziękuję Ci za trafną odpowiedź. Tak kończy się korzystanie z poleceń, których działania się nie rozumie. Nadal męczy mnie jeden problem, mianowicie raz na kilka odczytów pojawia się dziwna wartość (np. utrzymując Vconst = 50km/h raz na kilka odświeżeń wyświetlacza pojawia się wartość 35km/h albo 70km/h - przykłady przypadkowe, nie stanowią reguły). Nie wiem teraz, czy jest to objaw braku bezwładności wobec wskazówkowego prędkościomierza samochodu czy efekt błędów obliczeń. Próba uśrednienia pomiaru na zasadzie

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod

    Kończy się całkowitą utratą poprawności wskazań. Nieszczęśliwie kończy się również wyłączenie przerwań na czas wyświetlania napisu na wyświetlaczu - mierzona prędkość wynosi wtedy niewiele ponad 0. Na etapie uśredniania korzystam ze zmiennych typu single, jeśli ma to jakiekolwiek znaczenie. Dla prędkości do 20km/h (ok 90imp/s) błąd praktycznie nie występuje, pojawia się dopiero powyżej tej wartości.

    0
  • Pomocny post
    #6 17 Kwi 2012 02:54
    xury
    Poziom 38  

    Aż mnie dziwi, że przy takiej ilości zagnieżdżonych skoków program się nie wysypuje. Albo może się wysypuje i stąd te dziwne wyniki. Za radą kolegi Mundi1970 zainteresuj się definicjami stosów i przebadaj zagnieżdżanie podprogramów.

    0
  • #7 17 Kwi 2012 16:57
    komanche
    Poziom 13  

    Kod obsługujący wyświetlacz nie jest mojego autorstwa, nie analizowałem go i cieszyłem się, że działa. Czy wobec tego, lepiej byłoby zrobić mniej podprogramów, przepisując ich treść w miejsce poleceń gosub*? Czy może przyniesie to efekt odwrotny do zamierzonego?
    Stosy to dla mnie czarna magia, wiem tylko, że każdy przeskok wymaga zapisania adresu zwrotnego, ale nic poza tym :oops:


    * - Czy mając kod

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    Przerobienie go do postaci:
    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    Spowoduje poprawę jego jakości?

    0
  • #8 17 Kwi 2012 22:25
    xury
    Poziom 38  

    Akurat podany przez Ciebie przykład jest poprawny i warto używać podprogramów w celu redukcji kodu wynikowego. Ale już poniższy program jest zły. Dojdź sam dlaczego.

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod

    0
  • Pomocny post
    #9 17 Kwi 2012 22:26
    Mundi1970
    Poziom 24  

    komanche napisał:
    Stosy to dla mnie czarna magia, wiem tylko, że każdy przeskok wymaga zapisania adresu zwrotnego, ale nic poza tym :oops:

    No przy takim podprogramie to 1 megabajtowy stos to za mało :D, to się chyba nazywa rekurencja:

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    Przy wartości 31249 wpisywanej do timera1, przerwanie od przepełnienia licznika występuje co 1,09718400 sek. Żeby odliczyć 1 sekundę, musisz wpisać 34286.

    0
  • #10 18 Kwi 2012 16:47
    komanche
    Poziom 13  

    Wziąłem sobie Wasze uwagi do serca, choć nie wiem, czy dobrze je zrozumiałem.
    Kod wygląda teraz tak:

    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod


    Poczyniłem następujące zmiany:
    •Zamieniłem polecenia gosub [x] na kod kryjący się w podprogramie [x]
    •Usunąłem nosave z przerwań
    •Usunąłem przerwanie od timer1
    •Pozbyłem się zapętlenia w postaci
    Kod: basic4gl
    Zaloguj się, aby zobaczyć kod

    zastępując je drugą pętlą Do::Loop until

    Ktoś ma jeszcze jakieś propozycje, jak usprawnić ten program, albo widzi jakiś błąd w moim dotychczasowym postępowaniu?


    Edit: Xury, do mnie trochę jak do dziecka, ale zapewne chodzi Ci o błąd w postaci zapętlenia podprogramów? Po dokonaniu w/w zmian, objętość kodu wzrosła o około 30%, rozumiem już, co miałeś na myśli pod pojęciem "redukcji kodu wynikowego". Teraz już nie wiem, dobrze zrobiłem pozbywając się nadmiaru gosub?

    0
  • #11 18 Kwi 2012 22:48
    xury
    Poziom 38  

    Tu nie chodzi o ilość Gosub'ów ale o rekurencyjność i iloś zagnieżdżeń. Trzeba pilnować by każdy podprogram kiedyś zakończył się i wyszedł przez Return. Czym więcej zagnieżdżeń tym więcej potrzeba pamięci na tzw. HW Stack. Jeśli masz wolny RAM to zwiększ ilość pamięci na hwstack ,a przy okazji możesz dorzucić na framesize i swstack.
    Podkreślam jeszcze raz, że nie każę Ci rezygnować z "Gołsabów" tylko pilnować by nie zrobić gdzieś zapętlenia rekurencyjnego ,oraz ustawić odpowiednią ilość pamięci na stosy. Jest to bardzo ważna sprawa (o ile nie najważniejsza) ponieważ zbyt mała rezerwa RAMU na stosy będzie skutkować nadpisaniem zmiennych (tzw. stack owerlap), a jak wiadomo wtedy cały program zaczyna żyć własnym życiem. Dla zobrazowania problemu proponuję zrobić sobie taki eksperyment i zapuścić taki przykładowy program jak ten co podałem wcześniej w symulatorze i obserwować co się dzieje z pamięcią RAM, patrząc na nią od końcowych adresów, gdzie jest stos właśnie i jak po pewnym czasie stos się rozrośnie na tą cześć gdzie znajdują się zmienne.

    0