Basit pwm oluşturmada hata

Başlatan kemalguler, 28 Mayıs 2010, 11:32:00

kemalguler

Pwm modülü olmayan bir pic için basitçe %50 çıkış gerilimi veren kod yazdım.
.
Basla:
porta0.0=1
pause 10
porta0.0=0
pause 10
goto Basla
.
Denedim çalışıyor.Sonra pause sürelerini değiştirerek %30 ve %70 için değişiklikler yaptım.Bunlar da çalıştı.Sorum şu;hepsini  beraberce ayrı ayrı pinlerden almak istediğimde çıkış değerleri çok farklı hale geldi.
.
Basla:
porta0.0=1   ;%50 oranlı
pause 10
porta0.0=0
pause 10

porta0.1=1  ;%30 oranlı yaklaşık
pause 3
porta0.1=0
pause 9

porta0.2=1  ;%70 oranlı yaklaşık
pause 9
porta0.2=0
pause 3
goto Basla
.
Yukardaki kodta yapmak istediğim işlem, istediğim gibi çalışmıyor.Bir yerde mantık hatam varNe yapmalıyım.Önerilerinizi bekliyorum.

parda

Mantık hatanız şu; yazdığınız kodun aynı anda çalıştığını hesap ediyorsunuz ama öyle değil bir pin in pwm sürelerine diğer iki pin için yazdığınız süreler ekleniyor.
Umarım anlatabildim.
Bildiğim tek şey, hiç bir şey bilmediğimdir.

t2

8 pini beraber kontrol edebilen, Proton Soft pwm kodu:
'implement PWM on 8 pins with individual duty cycles.

' Create eight PWM outputs, using interrupts
' Incremently increase brightness of eight LEDs attached to PORTD 

'------------------------------------------------------------

' Compiler Declares :-

    Device = 16F877

Reminders = Off

    Optimiser_Level = 1

    Dead_Code_Remove = On

    Xtal = 4

    Fsr_Context_Save = Off        ' Don't save the FSR register within the interrupt

'------------------------------------------------------------

' Variables :-

' Make sure these variables are located low in RAM. i.e. first in the Dim list

' This will minimise RAM bank switching

'

    Dim Temp As Byte

    Dim Accum0 As Byte           ' DutyCycle Accumumulators

    Dim Accum1 As Byte

    Dim Accum2 As Byte

    Dim Accum3 As Byte

    Dim Accum4 As Byte

    Dim Accum5 As Byte

    Dim Accum6 As Byte

    Dim Accum7 As Byte

 

    Dim DutyCycle0 As Byte        ' DutyCycle DUTY cycle registers

    Dim DutyCycle1 As Byte

    Dim DutyCycle2 As Byte

    Dim DutyCycle3 As Byte

    Dim DutyCycle4 As Byte

    Dim DutyCycle5 As Byte

    Dim DutyCycle6 As Byte

    Dim DutyCycle7 As Byte 

 

 

'------------------------------------------------------------

' Symbol Alias's

    Symbol T0IE INTCON.5        ' Timer0 Overflow Interrupt Enable

    Symbol T0IF INTCON.2        ' Timer0 Overflow Interrupt Flag

    Symbol GIE  INTCON.7        ' Global Interrupt Enable

 

    Symbol PS0 OPTION_REG.0     ' Prescaler ratio bit-0

    Symbol PS1 OPTION_REG.1     ' Prescaler ratio bit-1

    Symbol PS2 OPTION_REG.2     ' Prescaler ratio bit-2

    Symbol PSA OPTION_REG.3     ' Prescaler Assignment (1=assigned to WDT, 0=assigned to oscillator)

    Symbol T0CS OPTION_REG.5    ' Timer0 Clock Source Select (0=Internal clock, 1=External PORTA.4)

 

'------------------------------------------------------------

 

    On_Hardware_Interrupt GoTo PWM_interrupt ' Point interrupt to handler

    All_Digital = True                  ' Set PORTA and PORTD to all digital

    GoTo Main                           ' Jump over the interrupt handler

 

'------------------------------------------------------------

' Interrupt Subroutine

' Update eight 8-bit PWM'S on PORTD

PWM_interrupt:

    Context Save                        ' Save WREG, STATUS, and PCLATH

    Accum0 = Accum0 + DutyCycle0        ' Update DutyCycle0

    rol Temp    

    Accum1 = Accum1 + DutyCycle1        ' Update DutyCycle1

    rol Temp    

    Accum2 = Accum2 + DutyCycle2        ' Update DutyCycle2

    rol Temp    

    Accum3 = Accum3 + DutyCycle3        ' Update DutyCycle3

    rol Temp    

    Accum4 = Accum4 + DutyCycle4        ' Update DutyCycle4

    rol Temp    

    Accum5 = Accum5 + DutyCycle5        ' Update DutyCycle5

    rol Temp    

    Accum6 = Accum6 + DutyCycle6        ' Update DutyCycle6

    rol Temp    

    Accum7 = Accum7 + DutyCycle7        ' Update DutyCycle7

    rlf Temp,W

    movwf PORTD                         ' Output DutyCycle States

    T0IF = 0                            ' Clear the TMR0 overflow flag

    Context Restore                     ' Restore WREG, STATUS, and PCLATH. Then exit the interrupt

'------------------------------------------------------------

' Subroutines can go here

 

'------------------------------------------------------------

' Main Demonstration Loop

Main:

    Temp = 0

    Accum0 = 0: Accum1 = 0: Accum2 = 0: Accum3 = 0

    Accum4 = 0: Accum5 = 0: Accum6 = 0: Accum7 = 0        

    DutyCycle0 = 0: DutyCycle1 = 0: DutyCycle2 = 0: DutyCycle3 = 0

    DutyCycle4 = 0: DutyCycle5 = 0: DutyCycle6 = 0: DutyCycle7 = 0

 

    Low PORTD                       ' Make PortD an output and extinguish the LEDs

    PSA = 0                         ' Assign the prescaler to external oscillator

    PS0 = 1                         ' Set the prescaler

    PS1 = 0                         '       to increment TMR0

    PS2 = 0                         '       every nth instruction cycle

    T0CS = 0                        ' Assign TMR0 clock to internal source

    TMR0 = 0                        ' Clear TMR0 initially

    T0IE = 1                        ' Enable TMR0 overflow interrupt

    GIE = 1                         ' Enable global interrupts    

    While 1 = 1

        For DutyCycle0 = 255 To 1 Step -1

            DutyCycle1 = ~DutyCycle0

            DelayMS 1

        Next

        For DutyCycle1 = 255 To 1 Step -1

            DutyCycle2 = ~DutyCycle1

            DelayMS 1

        Next

        For DutyCycle2 = 255 To 1 Step -1

            DutyCycle3 = ~DutyCycle2

            DelayMS 1

        Next

        For DutyCycle3 = 255 To 1 Step -1

            DutyCycle4 = ~DutyCycle3

            DelayMS 1

        Next

        For DutyCycle4 = 255 To 1 Step -1

            DutyCycle5 = ~DutyCycle4

            DelayMS 1

        Next

        For DutyCycle5 = 255 To 1 Step -1

            DutyCycle6 = ~DutyCycle5

            DelayMS 1

        Next

        For DutyCycle6 = 255 To 1 Step -1

            DutyCycle7 = ~DutyCycle6

            DelayMS 1

        Next

        For DutyCycle7 = 255 To 1 Step -1

            DutyCycle0 = ~DutyCycle7

            DelayMS 1

        Next

    Wend

Ruzgarbey

pwm çıkışı olmayan veya birden çok pwm ye ihtiyaç duyduğunuzda bunu timer0 kesmesi ile yapmanızı öneririm.yazmış olduğunuz kodlar mantık olarak doğru ama süresi fazla. 4 mhz ile çalışan bir picin 1 pwm periyodu 5ms dir.buna göre prescalar oranını ayarlayıp kesme mantığında pwm yaptırın.ben 16f628 ile rgb led devresi yapmış idim.bulabilirsem kodları buraya yazarım.ama bu konuyu kesme ile yapın derim.kolay gelsin..saygılarımla.
Hayatta En Hakiki Mürşid İlimdir. M.K. ATATÜRK

Erol YILMAZ

Alıntı yapılan: Ruzgarbey - 30 Mayıs 2010, 11:40:40
pwm çıkışı olmayan veya birden çok pwm ye ihtiyaç duyduğunuzda bunu timer0 kesmesi ile yapmanızı öneririm.yazmış olduğunuz kodlar mantık olarak doğru ama süresi fazla. 4 mhz ile çalışan bir picin 1 pwm periyodu 5ms dir.buna göre prescalar oranını ayarlayıp kesme mantığında pwm yaptırın.ben 16f628 ile rgb led devresi yapmış idim.bulabilirsem kodları buraya yazarım.ama bu konuyu kesme ile yapın derim.kolay gelsin..saygılarımla.

5 ms de bir PWM periyodu ile çıkış verirsek yaklaşık 200 hz lik PWM sinyali elde ederiz.
Bu da Led li sistemler için gayet uygun bi değer...
Bunu nasıl yaparız ?
Biraz örneklermisin ?

Ruzgarbey

Alıntı yapılan: Allegro - 30 Mayıs 2010, 11:49:46
Alıntı yapılan: Ruzgarbey - 30 Mayıs 2010, 11:40:40
pwm çıkışı olmayan veya birden çok pwm ye ihtiyaç duyduğunuzda bunu timer0 kesmesi ile yapmanızı öneririm.yazmış olduğunuz kodlar mantık olarak doğru ama süresi fazla. 4 mhz ile çalışan bir picin 1 pwm periyodu 5ms dir.buna göre prescalar oranını ayarlayıp kesme mantığında pwm yaptırın.ben 16f628 ile rgb led devresi yapmış idim.bulabilirsem kodları buraya yazarım.ama bu konuyu kesme ile yapın derim.kolay gelsin..saygılarımla.

5 ms de bir PWM periyodu ile çıkış verirsek yaklaşık 200 hz lik PWM sinyali elde ederiz.
Bu da Led li sistemler için gayet uygun bi değer...
Bunu nasıl yaparız ?
Biraz örneklermisin ?
Allegro Hocam yazdığım kodlar şu anda cevap yazdığım makinada değil ama aklımda kaldığı kadarıyla örneklemeye çalışayım.
4 mhz ile çalışan bir pic in 1 komut çevrim süresini 1us olarak ele aldım.4 mhz ile çalışan bir işlemcinin 1 pwm periyodu 5 ms olduğunu düşünürsek 5000/256= yaklaşık olarak 19us bir kesme oluşturmamız lazım.buna göre prescalar oranını ayarlamamız gerekiyor.
örnek kod:
INTCON=%10100000
OPTION_REG=%00001000' Option yazmacını WDT ye göre kurduk bunun nedeni tmr0 prescalar 1:1 oranını saymamasıdır.bizde arkasından dolanıp işlemciyi kandırıyoruz :)bölme oranı 1/1
ON INTERTRUP GOTO KESME
RED VAR PORTB.0
GREEN VAR PORTB.1
BLUE VAR PORTB.2
SAYAC VAR BYTE
CLEAR
tmr0=237 '19us de bir kesme oluşması için tmro değerini 256-19 olarak belirledik.

BASLA:
LED1=215 'burada pwm sinyalimizin duty cycle değerini belirliyoruz.yani high kalma süresi
LED2=150
LED3=90
GOTO BASLA

DISABLE
KESME:
SAYAC=SAYAC+1
IF SAYAC >LED1 THEN ' RED PINININ PWM PERİYODU
LOW RED
ELSE
HIGH RED
ENDIF

IF SAYAC>LED2 THEN
LOW GREEN
ELSE
HIGH GREEN
ENDIF

IF SAYAC>LED3 THEN
LOW BLUE
ELSE
HIGH BLUE
ENDIF
'Yukarıda 3 pine pwm uyguladık.pwm adımımız 255 dir.normal komut gibi 
tmr0=237
INTCON.2=0 'tmr0 kesme bayrağını sıfırladık.tekrar kesme oluşması için
ENABLE
RESUME

elimden geldiği kadar açıklamaya çalıştım hocam.umarım arkadaşlarımıza yardımı dokunur.saygılarımla..
Hayatta En Hakiki Mürşid İlimdir. M.K. ATATÜRK