ATmega, 2-kanały PWM z przesunięciem fazowym

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From Polish to

Witam,

Pracuję nad układem na bazie ATmega128, który będzie sterował tranzystorami
za pomocą dwóch kanałów PWM. Kanały te powinny być przesunięte względem
siebie. Przygotowałem rysunek, który obrazuje to, o co mi chodzi:
http://img828.imageshack.us/img828/9135/pwm.png
Częstotliwość PWM ok. 20kHz (częstotliwość okresu pojedynczego kanału).
Rozdzielczość regulacji wypełnienia ok. 500 (najlepiej byłoby ok. 1000, ale
tak się chyba nie da przy zachowaniu częstotliwości na wymaganym poziomie).
(Zapewne jakoś będę musiał kosztem rozdzielczości regulacji wypełnienia
podbić częstotliwość albo na odwrót).
Przerwa między kanałami przy max. wypełnieniu to 2 mikrosekundy (jest to
czas potrzebny na wyłączenie tranzystorów).
Wypełnienia obydwu kanałów muszą być równe parami (żeby nie było niesymetrii
w sterowaniu par tranzystorów).

Napisałem też już kod na ATmega128. Niemniej może da się to prościej /
lepiej rozwiązać. Poza tym mam z tym programem mały problem (o tym poniżej).
Ewentualnie w grę wchodzi także rozwiązanie z jednym PWM (dwa razy szybszym)
i wyjściem, które przełączałoby sygnał z PWM raz na jedną parę, a raz na
drugą parę tranzystorów. Będę bardzo wdzięczny za sugestie, jak inaczej
można rozwiązać to, nad czym pracuję. Chciałbym, aby procesor nie był za
bardzo obciążony generowaniem PWM, gdyż oprócz tego będzie działał w pętli
głównej regulator sprzężenia zwrotnego sterujący wypełnieniem PWM oraz kilka
innych rzeczy.

Oto mój kod (wykorzystuję ATmega128, dwa 16-bitowe PWM-y Timer1 i Timer3).
Na razie wypełnienia zmieniają się parami (taki test): raz 100, raz 400, raz
100, raz 400 itd. Potem będzie regulator ze sprzężeniem zwrotnym.
Mam z tym programem mały problem. Polega on na tym, że ustawiam  TCNT3 = 511
oraz  TCNT1 = 0, aby uzyskać przesunięcie fazowe między kanałami PWM. Przy
czym te ustawienia odbywają się na pracujących PWM i po ustawieniu TCNT3 =
511 PWM już pracuje i liczy, zatem w momencie gdy ustawiam TCNT1 = 0, to
TCNT3 już kilka wartości zliczyło i przesunięcie między kanałami nie będzie
idealnie w połowie. Nie wiem na razie, jak zrobić, aby mieć idelnie w
połowie przesunięcie między kanałami, czy ktoś z Was ma pomysł?


Program ten daje taki obraz na oscyloskopie:
http://img849.imageshack.us/img849/8677/newfile2.png

#define __AVR_ATMEGA128__
#include <stdio.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/io.h>
#include <inttypes.h>

SIGNAL (SIG_OVERFLOW3)
{
    static uint8_t f2 = 0;

    if (f2 == 0)
        OCR1B = OCR3B = 100, f2 = 1;
    else
        OCR1B = OCR3B = 480, f2 = 0;
}


int main(void)
{
    DDRA = 0xff;
    DDRB = 0xff;
    DDRC = 0xff;
    DDRD = 0xff;
    DDRE = 0xff;
    DDRG = 0xff;

    cli();

    TCCR3A = _BV(COM3A1) | _BV(COM3B1) | _BV(WGM31) | _BV(WGM30);
    TCCR3B = _BV(WGM32) | _BV(CS30);

    TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(WGM11) | _BV(WGM10);
    TCCR1B = _BV(WGM12) | _BV(CS10);

    TCNT3 = 511;
    TCNT1 = 0;

    ETIMSK |= _BV(TOIE3);

    sei();

    while (1) {
    }

    return 0;
}



Z góry dziękuję za pomoc.

Robbo



Site Timeline