Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Generacja sinusa za pomocą PWM - atmega

zajczyk 13 Gru 2008 13:26 5050 1
  • #1 13 Gru 2008 13:26
    zajczyk
    Poziom 13  

    Mój problemik polega na tym że chciałbym zbudować przetwornice DC/AC z wyjściem sinus. Mam wystarczające doświadczenie jeśli chodzi o część wykonawczą, kłopotem jest tylko wygenerowanie sygnału PWM dla kluczy. W linku zamieszczam przykładowy projekcik w którym autorzy niestety nie zamieścili procedur obsługi timera.

    http://www.scribd.com/doc/3270064/New-Sine-Wave-Inverter

    Napisałem własną procedurę generacji sinusa PWM opartą o odczyt tablicy wartości funkcji. Efekt pomimo małej liczby kroków jest zachęcający i przedstawiam zrzuty z oscyloskopu, przebieg sinusoidy uzyskano wstępnie po odfiltrowaniu obwodem RC sygnału z portu.

    Generacja sinusa za pomocą PWM - atmega
    Generacja sinusa za pomocą PWM - atmega

    Program generuje na linii portu połówki sinusoidy (wyjście timera).Chciałbym abyście mi podpowiedzieli jak rozdzielić sygnał z timera,tak aby jedna połówka sinusoidy pojawiała się na lini A a druga na linii B tak aby można było sterować kluczami. W danej chwili sygnał mógłby pojawiać się tylko na jednym z pinów procesora. Po głowie chodzi mi jakiś sprzętowy demultiplekser ale z oczywistych względów wolałbym to zrobić programowo


    kod źródłowy w asemblerze jak niżej:

    Code:

    .INCLUDE "m16def.inc"
    .DSEG
    .ORG 0x0060
       wskaznik:   .BYTE 1         ;wskaznik położenia w tablicy sinus
    .CSEG

          
    .ORG   0                     ;wektor zerowania
       jmp RESET
    .ORG   Oc0addr               ;wektor zgodnego porównania w timerze 0
       jmp obsluga_PWM


    RESET:
       ldi R17, high(RAMEND)
       ldi R16, low(RAMEND)
       out SPH, R17
       out SPL, R16             ;inicjalizacja stosu
       clr R16
       ldi R17,2
       ldi XH,high(0x0060)
       ldi Xl,low(0x0060)
    Reset_RAM:
       st X+,R16
       dec R17
       brne Reset_RAM
       call inicjal_PWM                       ;przeprowadź inicjalizację PWM




       sei                     ;odblokuj przerwania

    petla_glowna:
       rjmp petla_glowna         ;pętla główna

    inicjal_PWM:
       push R16
       push R17
       ldi r16,1
       sts wskaznik,R16               ;odłóż zawartość rejestrów aby nie zmieniać
       sbi DDRB, DDB3            ;linia3 portu B jako wyjście licznika Oc0   
       ldi R16, (1<<WGM00)|(1<<WGM01)|(1<<COM01)|(1<<COM00)|(1<<CS01);|(1<<CS00)
       out TCCR0, R16            ;licznik 0 w trybie fast PWM,wyjście zanegowane,
                            ;zegar procesora dzielony przez 8
       ldi ZH, high(tabl_sin<<1)
       ldi ZL, low(tabl_sin<<1)
       lpm R16,Z               ;podaj do rejesru wartości porównywanych pierwszy
       out OCR0,R16            ;tablicy
       in R16, TIMSK
       sbr R16,1<<OCIE0         ;uaktywnij przerwanie timera
       out TIMSK, R16
       pop R17
       pop R16
       ret

    obsluga_PWM:
       push R16
       push R17
       cli                     ;zablokuj przerwania
       ldi ZH, high(tabl_sin<<1)
       ldi ZL, low(tabl_sin<<1)
       lds R16, wskaznik
       clr R17
       add ZL,R16               ;dodaj wskażnik do do adresu początka tablicy
       adc ZH,R17
       lpm R17,Z               ;odczytaj z tablicy nowa wartość sinus
       out OCR0,R17            ;załaduj nową wartość porównywaną do licznika 0
       inc R16                  ;zwiększ wskaznik o 1 aby zachować postęp
       cpi R16,30
       brlo inkr_wsk
       clr R16
    inkr_wsk:   
       sts wskaznik,R16
       pop R17
       pop R16
       sei
       reti

    tabl_sin:   .DB 27, 53, 79, 104, 128, 150, 171, 190, 206, 221, 233, 243, 249, 254, 255, 254, 249, 243, 233, 221, 206, 190, 171, 150, 128, 104, 79, 53, 27, 0


    Proszę używać znaczników [code] - uzupełniłem.
    [zumek]

    0 1
  • #2 13 Gru 2008 18:49
    ZbeeGin
    Poziom 38  

    Przenieś się na licznik TIMER1 - wtedy masz dwa wyjścia OC1A i OC1B taktowane z jednego licznika. W programie umieść dwie tablice, gdzie w pierwszej będzie tylko górna półówka sinusa, a w drugiej tylko dolnia połówka sinusa. Wysyłaj dane z tablic równocześnie do rejestrów OCR1A i OCR1B. Uzyskasz to czego potrzebujesz.

    Nie używaj trybu Fast PWM do tego celu. Jak już to raczej Phase Correct PWM.

    0