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.

Wyświetlacz widmowy - Schemat działania

xamrex 05 Sie 2015 09:53 1203 24
  • #1 05 Sie 2015 09:53
    xamrex
    Poziom 28  

    Witam,
    Przymierzam się do zrobienia wyświetlacza widmowego.
    Póki co mam prototyp, który działa, ale nie bardzo dobrze.
    Wydaje mi się, że wiem w czym tkwi problem, ale nie wiem do końca jak go rozwiązać..

    Założyłem sobie, że wyświetlacz będzie podzielony na 20 części, czyli mogę wyświetlić obraz co 18stopni(360/20).

    Czytając informacje znalezione w Internecie zasada takiego wyświetlacza powinna być następująca.

    1.Odpalamy Timer0(jako licznik), który zlicza czas potrzeby do zrobienia jednego okrążenia wiatraka
    2.Konfigurujemy Timer2 tak, aby przerwanie było 20 razy(bo taką założyłem rozdzielczość) częściej niż obrót pełnego obrotu wentylatora.

    W przerwaniu Timera2 wystawiamy na port, do którego podpięte są diody nasz obraz.

    Czy taka zasada jest poprawna?
    #############################################
    Bo w rzeczywistości nie działa to najlepiej..
    Tzn.
    Mój wentylator potrzebuje ok 25ms na wykonanie obrotu (2400 obr/min)
    Mam uC napędzany kwarcem 8Mhz.
    Konfiguruję prescaler licznika(timera0) na podział przez 1024, co daje mi jeden 'impuls' co 128us.
    Więc maksymalną wartość do jakiej może doliczyć licznik (aby się nie przekręcić to ) 128us*255= 32640us=32,6ms.
    Czyli wszystko OK.

    Teraz ustawiam timer2 jako CTC i wpisuję do niego wartość 20 razy mniejszą niż tą do której doliczył Timer0.

    I wszystko niby działa, ale na końcu obrotu widać, że obraz się przesuwa/drga/jest niewyraźny.
    Dzieje się to z pewnością dlatego, że te przerwania nie są DOKŁADNIE wykonywane 20 razy w ciągu pełnego obrotu wentylatora.

    No bo załóżmy, że licznik(timer0) doliczył do 176 (czyli wentylator obraca się co 176*128us=22,5ms)
    i teraz dzielimy 176/20=8.8 niestety nie można wpisać wartości ułamkowej do TIMERA2, aby wyzwolić przerwania więc zostanie ta wpisana wartość 8, i tym samym przerwania nie będą wykonywane 20 razy w ciągu obrotu wentylatora a OKOŁO 20 razy (pewnie coś koło 19 albo)...

    Chciałbym się dowiedzieć, czy coś źle robię, czy ta koncepcja jest zła...
    Albo jak to rozwiązać?? Mogę użyć timera 16bit, ale mało prockow ma 2 timery 16 bit..
    Jak inne osoby to rozwiązaly?

    0 24
  • #2 05 Sie 2015 10:24
    Wirnick
    Poziom 26  

    A jakby w przerwaniu timera0 wstawić flagę zliczającą do 20. Wtedy, wystarczyłaby korekcja czasu jednego timera do czasu obrotu wentylatora.

    0
  • #3 05 Sie 2015 10:33
    xamrex
    Poziom 28  

    Nie rozumem o co dokładnie chodzi.
    U mnie nie występuje przerwanie Timera0, używam go tylko jako licznik. (aby dostać informacje jak długo trwa jeden płeny obrót wentylatora)
    Wartość nigdy nie przekroczy 255(timer nigdy się nie 'przekręci')..

    0
  • #4 05 Sie 2015 11:05
    zumek
    Poziom 39  

    A napisz nam, jak obliczasz położenie wałka silnika/wyświetlacza i/lub czas pełnego obrotu:?:

    0
  • #5 05 Sie 2015 11:10
    piotrva
    Moderator na urlopie...

    Musisz na pewno wykrywać przejście ramienia z diodami nad "punktem zero".
    Dzięki temu będziesz miał 2 pieczenie na 1 ogniu - zmierzysz okres obrotu i zawsze będziesz zaczynać wyświetlanie od tego samego punktu (kąta).

    Możesz to zrobić za pomocą hallotronu i małego magnesu lub metodą optyczną.

    0
  • #6 05 Sie 2015 12:10
    xamrex
    Poziom 28  

    Mam to za pomocą fototranzysotra.
    Po wykryciu przerwania od fototranzysotra (na INT1)
    odczytuję wartość z rejestru TCNT0 i mnoże razy 128us, co daje mi czas pełnego borotu
    następnie kasuję wartość TCNT0 ,aby znów mierzył od początku,,,

    Ale tak jak pisałem, ja to już mam zrobione, tylko jeśli licznik doliczy do np 176, to jeśli podzielę te wartość przez 20(aby wpisać ją do drugiego licznika, który działa w trybie CTC, ) to ta wartość wynosi 8.8!!! co jest zaokrąglane do 8 więc stąd biorą się te niedokładności!.
    Myślę nad odpaleniem zamiast timera8bit timera 16 bit, wtedy będzie to dokładniej i nie powinno być problemów..

    Spójrzcie.
    Jeśli licznik policzy do 176us, to pełnu obrót trwa 176*128us=22528us

    Teraz jesli do timera pracującego w trybie CTC wpiszę 176/20=~8
    to przerwanie wykonuje się co 1250us,
    a 1250*20=25000us
    a 25000us != 22528us

    Dodano po 36 [minuty]:

    Widzę, problem jest w tym, że licznik2, który miał działac 20 razy cześciej niż licznik0, miał ten sa prescaler, i po prostu do ORC2 wpisywałem wartość TCNT0/20..
    To powodowało błędy w dokładności na poziomie nawet 10%

    A muszę zmienić prescaler, i wpisać odpowiednią wyliczoną warotść (wtey błędy zmaleją do 0.5%)

    0
  • #7 05 Sie 2015 18:36
    xamrex
    Poziom 28  

    COś mi to nie działa tak jak ma ;/
    Mam taki kod:
    Pełny obrót trwa ok 26ms..

    Kod: c
    Zaloguj się, aby zobaczyć kod

    A to test jak to wygląda..
    Widać, że skacze...

    Link




    Dlaczego ten obraz tak skacze?
    Kod jest strasznie prosty.. W czym może tkwić problem?

    0
  • #8 05 Sie 2015 19:29
    zumek
    Poziom 39  

    xamrex napisał:

    Dlaczego ten obraz tak skacze?
    Kod jest strasznie prosty.. W czym może tkwić problem?

    Ja bym jeszcze resetował preskaler T0/T2 .

    0
  • #9 05 Sie 2015 19:38
    xamrex
    Poziom 28  

    zumek napisał:
    a bym jeszcze resetował preskaler T0/T2 .

    Resetował? Tzn ustalał na nowo??
    Przecież on się nie zmienia.

    Naprawdę liczę na pomoc ;-)

    0
  • #10 05 Sie 2015 19:56
    Wirnick
    Poziom 26  

    "Mam uC napędzany kwarcem 8Mhz.
    uint16_t freq=((50000UL/((TCNT0*128)/20))*10);" Tu jest jakiś błąd w kodzie?

    0
  • #11 05 Sie 2015 20:19
    xamrex
    Poziom 28  

    Wirnick napisał:
    "Mam uC napędzany kwarcem 8Mhz.
    uint16_t freq=((50000UL/((TCNT0*128)/20))*10);" Tu jest jakiś błąd w kodzie?

    Nie, po prostu trochę zminimalizowałem obliczenia.
    Wynik powinien wyjść poprawnie ;-)

    0
  • #12 05 Sie 2015 20:30
    dondu
    Moderator Mikrokontrolery Projektowanie

    xamrex napisał:
    zumek napisał:
    a bym jeszcze resetował preskaler T0/T2 .

    Resetował? Tzn ustalał na nowo??
    Przecież on się nie zmienia.

    Zumek miał na myśli resetowanie licznika preskalera, a nie ustawień preskalera.
    Zobacz w ATmega8 bit PSR10 i rysunek Prescaler for Timer/Counter0 and Timer/Counter1

    Patrz: http://mikrokontrolery.blogspot.com/2011/03/prescaler-postscaler-co-to.html

    0
  • #13 05 Sie 2015 20:48
    xamrex
    Poziom 28  

    dondu, czyli powinienem ustawiać za każdym razem ten bit (PSR10) w rejestrze SFIOR na jednen, w obsłudze przerwania ISR(INT1_vect)?

    0
  • Pomocny post
    #14 05 Sie 2015 20:53
    Andrzej__S
    Poziom 28  

    A spróbuj może takiego sposobu:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    1
  • #16 05 Sie 2015 21:09
    xamrex
    Poziom 28  

    Andrzej__S napisał:
    A spróbuj może takiego sposobu:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Nie jest nic lepiej ;-(
    Dalej obraz 'skacze'

    Dondu ->
    1. Dla lepszej dokładności..
    Jeśli miałbym oba ustawione na 1024.
    i jeśli pierwszy licznik wskazywałby np. 123 to w drugim, aby przerwanie było wykonywane musiałbym wpisać 123/20 a to jest 6.15 i byłoby zaokrąglenie co nie jest dokładne.
    Dlatego postanowiłem na zwiększenie precyzji ustawiając mniejszy prescaler.
    2.Atmega8A-PU
    Dodano po 2 [minuty]:

    Ustalenie tego bitu PSR10 również nie pomogło..
    Zaczynam się zastanawiać czy to nie jest przypadkiem od konstrukcji mecvhanicznej..
    Tzn. mam to zrobione na wentylatorze z zasilacza PC..
    Może po prostu zbyt mocno zmieniają się obroty w czasie i z tego wynika te przesuwanie się obrazu?

    0
  • #18 05 Sie 2015 21:52
    xamrex
    Poziom 28  

    Znalazłem pewną zależność.
    Jeśli podzielę obraz na większą ilość kawałków

    Kod: csharp
    Zaloguj się, aby zobaczyć kod

    Chodzi mi o tą wartość w tym wypadku 20..
    to jeśli zwiększe np. na 30, to obraz tak nie skacze
    Natomiast jeśli zmniejsze na 10. to obraz jeszce bardziej skacze

    Tutaj filmy to prezentujące:
    a)30 kawałków

    Link


    b)10 kawałków

    Link


    Tylko w czym jest problem?

    Dodano po 1 [minuty]:

    dondu napisał:
    Nadal w przerwaniu INT1 nie zatrzymujesz i nie zerujesz preskalera Timer2. Musisz być pewien, że timer0 i timer2 zawsze rozpoczynają dokładnie od początku.

    dondu-> w kodzie Andrzej__S rzeczywiście tego nie robiłem. ale u siebie to robię

    0
  • #20 05 Sie 2015 22:11
    xamrex
    Poziom 28  

    Kod: csharp
    Zaloguj się, aby zobaczyć kod


    Przepraszam nie zamieściłem aktualnego kodu ;-(
    Ale te zerowanie nic nie daje..
    Zastanawia mnie dlaczego przy mniejszej rozdzielczości obraz bardziej skacze, a przy mniejszej mniej..
    Coś chyba musi być nie tak z tym kodem ;-(
    A trudno zauważyć co to ;-(

    Teraz zauwżyłem minimalną poprawkę jaką mozna zrobić..
    tzn dodać tę linijkę w obsłudze przerwania:
    Kod: csharp
    Zaloguj się, aby zobaczyć kod

    Czyli cała poprawna obsługa wyglądałaby tak:
    Kod: csharp
    Zaloguj się, aby zobaczyć kod


    Bo teraz po osiągnięciu pełnego obrotu nie był wyświetlany pierwszy element z tablicy, a dopiero po odczekaniu pewnego czasu (aż licznik 2 się przepełni i przejdzie do osługi przerwania)..
    teraz jest to chyba bardziej poprawnie,
    ale mimo to dalej obraz skacze ;/
    ##################################
    ##################################
    CAŁY AKTUALNY KOD:
    Kod: csharp
    Zaloguj się, aby zobaczyć kod

    Ale dalej problem dalej nie rozwiązany, bo dalej skacze;(

    0
  • Pomocny post
    #21 05 Sie 2015 22:42
    dondu
    Moderator Mikrokontrolery Projektowanie

    Jeszcze raz muszę napisać:

    dondu napisał:
    Nadal w przerwaniu INT1 nie zatrzymujesz i nie zerujesz preskalera Timer2. Musisz być pewien, że timer0 i timer2 zawsze rozpoczynają dokładnie od początku.

    czyli by być pewnym poprawnego działania powinieneś w przerwaniu INT1:
    - zatrzymać oba timery,
    - wyzerować ich preskalery,
    - obliczyć co ma być obliczone,
    - wyzerować liczniki (oba),
    - ustawić OCR2,
    - włączyć oba timery.

    Tylko taka procedura zapewniać będzie zawsze prawidłowe i powtarzalne odliczanie czasów.

    1
  • #22 05 Sie 2015 22:44
    xamrex
    Poziom 28  

    Okej ;-) JUtro zrobię dokładnie tak jak piszesz ;-)
    Teraz lecę spać ;-)
    Póki co serdecznie dziękuję za pomoc!

    0
  • #23 06 Sie 2015 08:25
    Andrzej__S
    Poziom 28  

    Kolega dondu ma rajcję, przedstawiłem prostszy sposob obliczania OCR2, a zapomniałem o synchronizacji timera2.

    Spróbuj może jeszcze raz z moim kodem, ustawiając preskaler timera 2 na 64:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #24 06 Sie 2015 08:44
    Wirnick
    Poziom 26  

    Mam pytanie. czy nota ATMEL obejmuje wszystkie rejestry konfiguracyjne AVR - " SFIOR |= 1<<PSR2;" jest błędem ? A powinno być bez or -" SFIOR = 1<<PSR2;

    0
  • #25 06 Sie 2015 16:06
    xamrex
    Poziom 28  

    Andrzej__S -> tak jak pisał Dondu, brakuje jeszcze (i tobie i mi) resetowanie(ustawianie na 0) timera TCNT0/TCNT2
    Ja zapomniałem w kodzie o resetowaniu TCNT2, a widzę ty o TCNT0 ;-)
    Chyba to będzie powodowało problem ze skakaniem wyświetlacza..

    Jak wrócę z pracy do domu to przetestuję i dam znac.
    Jeszcze raz chciałbym gorąco podziękować koledze dodnu za pomoc jak i za jego nieocenionego bloga;-)
    Mam nadzieję, że wszystko będzie działało ;-)

    Dodano po 5 [godziny] 49 [minuty]:

    Tak jak myślałem,
    Nie kasowałem obu timerów, tylko jeden i dlatego to nie działało;-(
    cały kod (już działa wszystko wygląda tak):

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0