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

ADC - błędy przy multipleksowaniu kanałów, możliwy przesłuch między kanałami

INTOUCH 21 Maj 2011 15:32 2551 24
REKLAMA
  • #1 9529847
    INTOUCH
    Poziom 30  
    Posty: 1581
    Pomógł: 99
    Ocena: 199
    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:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    Pomiar z wykorzystaniem kilku kanałów
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • #2 9529893
    tadzik85
    Poziom 38  
    Posty: 3404
    Pomógł: 415
    Ocena: 16
    Tryb free running nie jest najlepszy przy pomiarze wielu kanałów. Zastosuj tryb single. lub pobieraj 2 pomiar z danego kanału.
  • REKLAMA
  • #3 9529966
    INTOUCH
    Poziom 30  
    Posty: 1581
    Pomógł: 99
    Ocena: 199
    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 9529977
    tadzik85
    Poziom 38  
    Posty: 3404
    Pomógł: 415
    Ocena: 16
    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 9529984
    tmf
    VIP Zasłużony dla elektroda
    Posty: 14318
    Pomógł: 2090
    Ocena: 2203
    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 9530242
    McMonster
    Poziom 32  
    Posty: 1942
    Pomógł: 182
    Ocena: 57
    I jeszcze zamiast starych nazw przerwań zaczynających się od "SIG_" powinno się używać tych kończących się na "_vect".
  • REKLAMA
  • #7 9530413
    INTOUCH
    Poziom 30  
    Posty: 1581
    Pomógł: 99
    Ocena: 199
    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 9530426
    tadzik85
    Poziom 38  
    Posty: 3404
    Pomógł: 415
    Ocena: 16
    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 9530435
    krru
    Poziom 33  
    Posty: 1819
    Pomógł: 230
    Ocena: 214
    Ż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 9530570
    INTOUCH
    Poziom 30  
    Posty: 1581
    Pomógł: 99
    Ocena: 199
    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);
    }
  • #11 9530631
    tadzik85
    Poziom 38  
    Posty: 3404
    Pomógł: 415
    Ocena: 16
    pokaż cały kod.
  • #12 9530705
    INTOUCH
    Poziom 30  
    Posty: 1581
    Pomógł: 99
    Ocena: 199
    Wszystkie Timery będą wykorzystane do innych celów dlatego nice chcę wykorzysta któregokolwiek timera do przetwarzania ADC




    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #13 9530726
    GSM
    Poziom 25  
    Posty: 543
    Pomógł: 72
    Ocena: 16
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    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:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


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

    Pozdrawiam,
    GSM
  • #14 9530869
    INTOUCH
    Poziom 30  
    Posty: 1581
    Pomógł: 99
    Ocena: 199
    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);
  • REKLAMA
  • #15 9531064
    GSM
    Poziom 25  
    Posty: 543
    Pomógł: 72
    Ocena: 16
    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 9532879
    INTOUCH
    Poziom 30  
    Posty: 1581
    Pomógł: 99
    Ocena: 199
    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 9532914
    tadzik85
    Poziom 38  
    Posty: 3404
    Pomógł: 415
    Ocena: 16
    Przecież kanał nigdy nie przekroczy wartości 7. Maskowane są bity od 3 w gore. czyli z 7 przeskoczysz na 0.
  • #18 9533116
    INTOUCH
    Poziom 30  
    Posty: 1581
    Pomógł: 99
    Ocena: 199
    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 9533154
    tadzik85
    Poziom 38  
    Posty: 3404
    Pomógł: 415
    Ocena: 16
    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 9533493
    INTOUCH
    Poziom 30  
    Posty: 1581
    Pomógł: 99
    Ocena: 199
    Chodzi mi o wynik.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    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 9533518
    tadzik85
    Poziom 38  
    Posty: 3404
    Pomógł: 415
    Ocena: 16
    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ę.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #22 9533568
    INTOUCH
    Poziom 30  
    Posty: 1581
    Pomógł: 99
    Ocena: 199
    Opisz mi słowami czemu się nie włączy a nie kodem.
  • #23 9533603
    tadzik85
    Poziom 38  
    Posty: 3404
    Pomógł: 415
    Ocena: 16
    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 9533621
    INTOUCH
    Poziom 30  
    Posty: 1581
    Pomógł: 99
    Ocena: 199
    Wygląda na to że jeden z forumowiczów wprowadził mnie w błąd poniższą treścią
    Cytat:
    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 9533696
    tadzik85
    Poziom 38  
    Posty: 3404
    Pomógł: 415
    Ocena: 16
    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.

Podsumowanie tematu

✨ W dyskusji poruszono problem błędów pomiarowych przy multipleksowaniu kanałów w przetwornikach ADC, szczególnie w kontekście przesłuchu między kanałami. Użytkownik zauważył, że pomiary dla pojedynczego kanału są poprawne, ale pojawiają się problemy przy zmianie kanałów. Forumowicze sugerują, aby wyłączyć tryb free running i zamiast tego używać trybu single, co pozwoli na dokładniejsze pomiary. Zwracają uwagę na konieczność zmiany kanału po zakończeniu konwersji, aby uniknąć błędnych odczytów. Wskazano również na poprawne ustawienie rejestru ADMUX oraz na znaczenie używania przerwań do zarządzania pomiarami. Użytkownik pracuje na mikrokontrolerze ATMEGA32 i poszukuje rozwiązania, które umożliwi mu pomiar z dwóch kanałów z częstotliwością 1100Hz.
Wygenerowane przez model językowy.
REKLAMA