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

Za mała częstotliwość fali nośnej (przebiegu trójkątnego) ATMEGA16

xyzboro 23 Lut 2012 19:22 2972 23
REKLAMA
  • #1 10588731
    xyzboro
    Poziom 10  
    Proszę o pomoc w zwiększeniu częstotliwość fali nośnej, którą jest przebieg trójkątny. Mam kod który porównuje dwa przebiegi sinusoidalny i trójkątny, a na wyjściu generuje przebieg prostokątny. Jest to nic innego jak sinusoidalna modulacja szerokości impulsów PWM do sterowania falownikiem trójfazowym. Wszystko jest napisane w C, a procesor jaki użyłem to ATMEGA16.
    Jednak po sprawdzeniu na oscyloskopie częstotliwości przebiegu trójkątnego wyszło mi niecałe 2 kHz, a potrzebuję co najmniej 6kHz.
    I teraz pytanie do szanownych kolegów, czy da się wyciągnąć coś więcej z tego procesora jeżeli chodzi o ten przebieg czy to jest max??

    Poniżej zamieszczam kod.

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




    Dodam, że zmniejszanie ilości próbkowanie trójkąta już próbowałem i za wiele nie pomogło tylko pojawił się większy błąd pomiarowy.
    Dziękuję za każdą pomoc.
  • REKLAMA
  • #2 10590101
    Konto nie istnieje
    Konto nie istnieje  
  • #3 10590496
    xyzboro
    Poziom 10  
    Nie próbowałem bo boje się że nie będzie stabilny, a błąd pomiarowy wzrośnie jeszcze bardziej.
  • #5 10590529
    xyzboro
    Poziom 10  
    dziękuję dondu Twoje wskazówki pomogły i o jakieś 0,5kHz zaczął szybciej generować przebieg. Jednak to i tak jeszcze mnie nie ratuje.

    Poniżej podaję program główny:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • #6 10590738
    _StinG_
    Poziom 14  
    Co jest w funkcjach:
    A=amplituda();
    W=wypelnienie();
    T=okres();

    Czy mógł byś wstawić cały kod (np. w formie pliku)?
    To by mogło ułatwić nieco analizę.
  • #10 10594571
    xyzboro
    Poziom 10  
    _StinG_ pisał żebym dał w pliku więc tak zrobiłem.... Ale to chyba nie jest najważniejsze? ;)

    Dodano po 1 [minuty]:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #11 10594595
    dondu
    Moderator na urlopie...
    Zawsze można wrzucić tak i tak :)
    Rzucę okiem za parę minut.

    EDIT:
    Czytałem dokładnie pierwszy post, ale opisz proszę w paru słowach co za co odpowiada, poszczególne timery, ADC, które przerwanie jest do czego, itd. ... bo w kodzie tego nie masz.
  • #12 10594750
    xyzboro
    Poziom 10  
    Starałem się jak tylko potrafię żeby opisać poszczególne etapy kodu.
    Ale ogólnie zasada działania jest prosta:
    Deklarujemy dwie tablice sinusa i trójkąta, następnie deklaruję 3 zmienne, które są regulowane on-line. Podczas pracy sterownika możemy regulować amplitudą sinusoidy (od 0 do 5V), dalej możemy również regulować częstotliwością trójkąta (wypełnieniem) poprzez przełączanie odpowiednich zakresów, czyli:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    dodatkowo jest również możliwa płynna regulacja:
    TCNT2=W;//dodatkowa płynna regulacja częstotliwości.
    Dalej mamy deklarację częstotliwości sinusoidy (okres) którą regulujemy płynnie.
  • REKLAMA
  • #13 10594811
    dondu
    Moderator na urlopie...
    Przede wszystkim powinieneś inaczej rozwiązać przerwanie TIMER2_OVF_vect,
    Ono wykonuje się rzadko, ale za to bardzo długo - czy wiesz dlaczego?
    A w tym czasie, masz zablokowane przerwania.

    EDIT:
    Dodatkowo czy jesteś świadomy, z jaką częstotliwością pracuje tak ustawiony ADC?
  • #14 10595297
    xyzboro
    Poziom 10  
    Na wyjściu musiałem zrobić trzy fazy, które są przesunięte o 120st, a następnie unormować przebieg sinusa (okres T) do przebiegu trójkąta czyli ilość próbek 32. Sinus może się tutaj długo wykonywać, ale jeżeli zmniejszę ilość jego próbek to boję się, że te przebiegi troche się rozjadą.

    Dodano po 5 [minuty]:

    tak się zastanawiam czy faktycznie ten sinus i ilość próbek (1021) to nie jest za dużo?

    A i wydaję mi się że częstotliwość ADC to częstotliwość taktowania zegara przez wartość preskalera. Max. może być CK/2.
    Zatem w naszym przypadku ADC to 8Mhz?
  • #15 10595714
    dondu
    Moderator na urlopie...
    Zacznijmy od wyjaśnienia i poprawy sprawy ADC.

    xyzboro napisał:
    A i wydaję mi się że częstotliwość ADC to częstotliwość taktowania zegara przez wartość preskalera. Max. może być CK/2.
    Zatem w naszym przypadku ADC to 8Mhz?

    Skąd to info o CK/2?

    Ograniczenia dla zegara ADC to przedział 50kHz-200kHz (o ile dobrze pamiętam) - sprawdź w datasheet
    Ty masz ustawiony preskaler na 8, czyli ADC traktujesz zegarem 2MHz (!)
    Jeżeli tak jest, to ADC pracuje stanowczo poza jego możliwościami.
    Sprawdź program i datasheet.
  • #16 10596590
    xyzboro
    Poziom 10  
    Masz racje dzielnik częstotliwości dla kwarcu 16MHz powinien mieć 128 i tylko ta wartość, bo 16000000/128=125 kHz, a więc mieści się nam w zakresie od 50 do 200kHz. Tylko to chyba sprawie, że częstotliwość trójkąta będzie jeszcze mniejsza;/
  • #17 10597356
    dondu
    Moderator na urlopie...
    To pierwszy problem z głowy.

    Teraz drugi - zadałem Ci wcześniej pytanie dot. czy wiesz dlaczego Twoje przerwanie TIMER2_OVF_vect wykonuje się strasznie długo.
    Analizując swój kod podaj przyczyny tego problemu.

    Dodam, że teraz wykonywać się będzie jeszcze dłużej.
  • REKLAMA
  • #18 10597733
    xyzboro
    Poziom 10  
    Pewnie przez to: pgm_read_word, więc funkcja zwraca wartość stałej 16-bitowej? Sugerujesz, że powinno być pgm_read_byte?
  • #19 10597739
    dondu
    Moderator na urlopie...
    xyzboro napisał:
    Pewnie przez to: pgm_read_word, więc funkcja zwraca wartość stałej 16-bitowej? Sugerujesz, że powinno być pgm_read_byte?

    Jest coś znacznie gorszego. Zastanów się nad tym fragmentem:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #20 10597957
    xyzboro
    Poziom 10  
    Przez to, że wszędzie tam gdzie pojawia się zmienna A, W, T odnosimy się do funkcji amplituda, wypełnienie, okres, a te wykonywane są od nowa. Ale za bardzo i tak nie wiem do czego chcesz mnie naprowadzić i jak to zmienić żeby było dobrze (jeszcze dłużej).
  • #22 10598784
    xyzboro
    Poziom 10  
    jakieś 100us dla jednej funkcji. Ale czy możesz mi w końcu zdradzić tajemnice czy w ogóle da się podkręcić tą częstotliwość czy chcesz żebym sam doszedł do tego - że się nie da;)
  • #24 10609014
    dondu
    Moderator na urlopie...
    Spróbowałem dogłębnie zrozumieć Twój program, ale mam z tym duży problem.

    Timer2 ustawiasz na przerwania w celu pomiaru zadanych potencjometrami wartości.
    Taktowany jest 16MHz / 1024 preskaler = 15.625Hz

    W funkcji przerwania od przepełnienia timera2 zmieniasz mu licznik na odczytaną wartość z potencjometru regulującego wypełnienie:

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


    Przy tak skonstruowanym programie, masz baaardzo niepewne momenty przerwań, ponieważ zmieniasz licznik TCNT2, w trakcie zliczania przez niego przy jednoczesnym czekaniu na pomiary (łącznie ok. 300us). To kompletnie pomieszanie z poplątaniem :)

    Reszta kodu (algorytm) niestety jest dla mnie niezrozumiały.
    Nawet przy zmianie o której pisałeś mi na PW, także kodu nie rozumie.

    Dlatego potrzebny jest algorytm jaki chcesz osiągnąć. dokładnie opisujący zależności czasowe itp.
    Sądzę, że z tego samego powodu, nikt inny za ten temat się nie wziął :)
REKLAMA