Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

ADC- błędy poczas pomiaru na kilku kanałach

INTOUCH 21 May 2011 15:32 2302 24
  • #1
    INTOUCH
    Level 30  
    Witam.
    Pomiar dla pojedynczego kanału, który bym nie wybrał jest zawsze poprawny.
    Problem pojawia się gdy występuje multipleksowanie (zmiana kanału).
    Podejrzewam, że może być problem z przesłuchem od kanałów.

    Poniżej przedstawiam dwa kody: Proszę o pomoc bardziej doświadczonych forumowiczów o rozwiązanie problemu.

    Pomiar z wykorzystaniem pojedynczego kanału:
    Code: c
    Log in, to see the code



    Pomiar z wykorzystaniem kilku kanałów
    Code: c
    Log in, to see the code
  • #2
    tadzik85
    Level 38  
    Tryb free running nie jest najlepszy przy pomiarze wielu kanałów. Zastosuj tryb single. lub pobieraj 2 pomiar z danego kanału.
  • #3
    INTOUCH
    Level 30  
    Czy tryb single mogę zrobić na przerwaniu.
    Nie uśmiecha mi się pisanie funkcji ponieważ kod wykonywany w pętli głównej programu może być długi.
  • #4
    tadzik85
    Level 38  
    oczywiście, że może po odczytanie ADC zmienia kanału ponownie startujesz ADC. i to wszystko. W twoim przypadku jest błąd bo kanał zmieniasz podczas konwersji. Stąd błędy.

    A zmiana jest prosta wyłącz free running dodaj na końcu przerwania uruchomienie przetwornika.
  • #5
    tmf
    Moderator of Microcontroller designs
    Błąd wynika z tego, że zmiana MUX będzie obowiązywać dopiero przy kolejnym pomiarze ADC. W momencie kiedy jesteś w procedurze obsługi przerwania pomiar już trwa. Stąd też odczytywany wynik dotyczy poprzedniego kanału, a nie tego, który aktualnie znajduje się w rejestrze MUX.
  • #6
    McMonster
    Level 32  
    I jeszcze zamiast starych nazw przerwań zaczynających się od "SIG_" powinno się używać tych kończących się na "_vect".
  • #7
    INTOUCH
    Level 30  
    Czyli krótko mówiąc muszę ustawić ADATE w stan zero i na końcu obsługi przerwania do ADSC wpisać 1.
    Potrzebuję tylko 2 kanałów w których pomiar będzie wykonywany z częstotliwością 1100Hz.
    Czy mogę do przerwania wrzucić opóźnienie?
  • #8
    tadzik85
    Level 38  
    nie! a jeśli chcesz próbkować określoną F proponuję pobierać 2 pomiar z próbkowania z 2xf. do wyzwalania można wykorzystać timer.
  • #9
    krru
    Level 33  
    Żadnych opóźnień lepiej nie umieszczaj w obsłudze przerwania. Podłącz przerwania z timera 1100 razy na sekundę, tam startuj przetwornik na jednym kanale, w pierwszym przerwaniu od ADC odczytaj wartosc i wystartuj przetwarzanie na drugim kanale, w kolejnym przerwaniu odczytaj wynik i już nie ruszaj ADC. Niech czeka na przerwanie z zegara. Będziesz potrzebował prościutki automat stanowy pamiętający, w której fazie przetwarzania jesteś, by wiedzieć co zrobić w przerwaniu od ADC. Być może da się wykorzystać do tego odczyt rejestru MUX, ale lepiej na zmiennej. Przy okazji możesz sprawdzić czy wyrabia się przetwornik (jak za szybko dostaniesz przerwanie od timera).
  • #10
    INTOUCH
    Level 30  
    Nadal nie działa.
    Czyta mi mi tylko z kanału 1;

    Auto wyzwalanie wyłączone.
    CLR_BIT(ADCSRA, ADATE);//AUTOWYZWALANIE WYŁĄCZONE

    ISR(ADC_vect)
    {
    pomiar[kanal]=ADC;
    ADMUX =(ADMUX & 0b11000000) + kanal;
    ++kanal;

    if(kanal > 7)
    {
    kanal = 0;
    }
    SET_BIT(ADCSRA, ADSC);
    }
  • #12
    INTOUCH
    Level 30  
    Wszystkie Timery będą wykorzystane do innych celów dlatego nice chcę wykorzysta któregokolwiek timera do przetwarzania ADC




    Code: c
    Log in, to see the code
  • #13
    GSM
    Level 25  
    Code: c
    Log in, to see the code


    Nawiasem mówiąc, inkrementując zmienną 'kanal' PO ustawieniu multipleksera przy następnej konwersji do tablicy 'pomiar' do pozycji n'tej zapisze się wynik z n+1'tego kanału.
    I ja to bym zrobił raczej jakoś tak:

    Code: c
    Log in, to see the code


    Poza tym, możesz powiedzieć na jakim mikrokontrolerze pracujesz?

    Pozdrawiam,
    GSM
  • #14
    INTOUCH
    Level 30  
    Mikrokontroler to ATMEGA32.

    Nie bardzo rozumiem jak to ma działać?
    Ile kanałów obsłuży poniższy kod?
    pomiary[kanal++] = ADC;
    ADMUX = 0b11000000 | (kanal & 0b00000111);
  • #15
    GSM
    Level 25  
    Tyle samo ile kolegi wersja - 8;
    Czego dokładnie nie rozumiesz?
    Po zakończonym pomiarze wartości napięcia na kanale N,
    zapisana zostanie wartość z przetwornika do N'tej komórki tablicy 'pomiary',
    zmienna 'kanal' zostanie zwiększona o 1,
    do rejestru ADMUX zostanie wpisany stały nastaw źródła referencyjnego 2,56V (0b11000000) zsumowany z 3 ostatnimi bitami zmiennej 'kanal' (kanal & 0b00000111).
    Gdy zmienna kanał będzie miała wartosc 7 (0b111) i zwiększymy ja o 1 otrzymamy 8 (0b1000), porzucają wszystko poza 3 najmłodszymi bitami otrzymamy liczbę 0 (0b000). Gdy 9 (0b1001) to 3 ostatnie bity będą miały wartość 1, i tak w kółko.
    Oszczędzamy sobie tym samym skoku warunkowego.

    Pozdrawiam,
    GSM
  • #16
    INTOUCH
    Level 30  
    Według DTR dla(0b1000) (ustawienie najmłodszych bitów) uruchamiany jest pomiar dla kanałów różnicowych. Po co miałbym przechodzić z pomiaru z pojedynczych kanałów na różnicowe?
  • #17
    tadzik85
    Level 38  
    Przecież kanał nigdy nie przekroczy wartości 7. Maskowane są bity od 3 w gore. czyli z 7 przeskoczysz na 0.
  • #18
    INTOUCH
    Level 30  
    Można jaśniej z tym maskowaniem?
    Jak dla mnie taka realizacja może zmienić stan trzech najstarszych bitów i wtedy pomiar nie będzie działa tak jak powinien.
  • #19
    tadzik85
    Level 38  
    gdy po kanal++ kanal wyniesie 8 czyli 0001000 maskowane jest 5 starszych bitów czyli w wyniku uzyskujesz 0

    więc w czym problem?
  • #20
    INTOUCH
    Level 30  
    Chodzi mi o wynik.

    Code: c
    Log in, to see the code



    ADMUX = 0b11000000 | (kanal & 0b00000111) dla kanału =0 ADMUX = 0b11000111

    ADMUX = 0b11000000 | (kanal & 0b00000111) dla kanału =1 ADMUX = 0b11001000
    dla wartości 0b11001000 wchodzi na pomiar różnicowy.

    Gdy ADMUX będzie miał wartość 0b11100000 włączy się bit ADLAR.

    Według mnie to tak działa. No chyba że się mylę.
  • #21
    tadzik85
    Level 38  
    mylisz się zapis jest poprawny i obsługa 8 kanałów różnicówka nigdy się nie włączy po kanale 7 wybrany zostanie 0 nie różnicowy.

    Ale jak nie rozumiesz zrób sobie to inaczej.

    prościej ci to zapiszę.

    Code: c
    Log in, to see the code
  • #22
    INTOUCH
    Level 30  
    Opisz mi słowami czemu się nie włączy a nie kodem.
  • #23
    tadzik85
    Level 38  
    bo operacja & 0b00000111 zeruje bity od 3 do najstarszego więc niemożliwe jest by bit 3 się ustawił a co za tym idzie włączył pomiar różnicowy.
  • #24
    INTOUCH
    Level 30  
    Wygląda na to że jeden z forumowiczów wprowadził mnie w błąd poniższą treścią
    Quote:
    Gdy zmienna kanał będzie miała wartosc 7 (0b111) i zwiększymy ja o 1 otrzymamy 8 (0b1000), porzucają wszystko poza 3 najmłodszymi bitami otrzymamy liczbę 0 (0b000). Gdy 9 (0b1001) to 3 ostatnie bity będą miały wartość 1, i tak w kółko.
    Oszczędzamy sobie tym samym skoku warunkowego.


    dla wartości kanal=1;

    kanal &= 0b00000111; będzie 0b00000001, a nie 0b1000 ostatnie bity z wartości 0b00001000.
  • #25
    tadzik85
    Level 38  
    Pisał dobrze ale ty masz problem ze zrozumieniem tego myślisz dziesiętni nie binarnie. a binarne myślenie wielokrotnie ułatwia życie. np w tym przypadku.


    Choć jego przykład z 9 jest nie na miejscu bo nigdy nie wystąpi bo nie wystąpi również 8 ale dobrze pokazuje zasadę działania.