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

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:

formatting link
ę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:

formatting link
#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

Reply to
Robbo
Loading thread data ...

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.