Een tijd geleden ben ik begonnen met UC en pwm. naar aanleiding daarvan heb ik al een aantal vragen gesteld. o.a. http://www.circuitsonline.net/forum/view/76687
wegens een aantal problemen ben ik er toen een tijdje mee gestopt.
nu wil ik er weer mee verder gaan.
inmiddels heb ik al een ledje branden

DEVICE 16F628A
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE



DIM DUTY AS BYTE
DIM DUTY_1 AS BYTE

test:  

'WHILE 1 = 1                   
  FOR Duty = 1 TO 254         
    PWM PORTA.0, 255-Duty, 20
  next
        
  FOR Duty = 1 TO 254         
    PWM PORTA.0, duty, 20
    next
    

  goto test
  

  
 end
 

dit werkt opzich goed nu wil ik dit alleen uitbreiden met in totaal 5 leds. ik heb echter geen idee hoe ik dit ga uitvoeren.
ik heb wel een aantal fora door gelezen maar in de meeste gevallen gaan ze over op een andere Uc. dat meerdere pwm kanalen heeft.Ik wil toch graag verder met de pic16f628a.
voor de duidelijkheid, de leds moeten in elkaar overlopen.
er moet dus altijd minimaal een led aan zijn.

wie helpt mij

Wat ik altijd doe is het volgende:

de software ziet er dan als volgt uit:

main:

if RGB_Rood < teller then high led_rood
if RGB_Rood > teller then low led_rood

'dit voor meerdere lampjes

if telller = 256 then teller = 0
teller = teller + 1

goto main

je krijgt in dit geval een softwarematige PWM. Als je echter veel andere berekeningen gaat doen gaat het fout.

als je verder hulp nodig hebt wil ik je graag helpen. Heb hetzelfde gedaan voo 15 Leds (dat viel nog behoorlijk tegen ivm de snelheid)

grs

[Bericht gewijzigd door Electronick op (15%)]

ik heb het artikel doorgelezen maar ik vind er niets over het tegelijkertijd aansturen van meerdere software PWM kanalen.
iemand nog een suggestie?

Even de datasheet een stuk of 5 keer doorlezen, tegen dan werkt je programma ;)
De eerste keer snap je er niet veel van, 2e keer zie je iets over interrupts, 3e keer ben je mee met de timer interrupts, 4e keer heb je het PWM'en via timer interrupt onder de knie en voor de laatste vergetelheden dient de 5e keer.

Timer-interrupt gebruiken, zodat je in je main lus enkel maar de 5 variabelen voor de PWMwaardes moet aanpassen.

Je moet dus Software PWM gebruiken en dan de PWM in een interrupt routine doen. De interrupt zorgt er voor dat, onafhankelijk van je hoofdprogramma, de ledjes aangestuurd worden.

Een voorbeeld voor 3 kanalen PWM op 100 Hz:

'****************************************************************
'* Voorbeeld programma voor het dimmen van een drietal leds     *
'* met behulp van software PWM. De PWM frequentie is 100 Hz     *
'****************************************************************
Device 16F628A
Config HS_OSC, WDT_OFF, PWRTE_ON, LVP_OFF
XTAL = 20
OPTIMISER_LEVEL = 3
ALL_DIGITAL TRUE

Declare FSR_Context_Save = OFF

                           
Symbol PEIE   = INTCON.6                  ; Pheripheral interrupt enable
Symbol GIE    = INTCON.7                  ; Global interrupt enable
Symbol TMR0IF = INTCON.2
Symbol TMR0IE = INTCON.5
Symbol T0CS   = OPTION_REG.5

TRISA = %11111111                         ; Definieer I/O lijnen
TRISB = %00000000

Symbol PWM_Output1 = PORTB.0
Symbol PWM_Output2 = PORTB.1
Symbol PWM_Output3 = PORTB.2

Dim PWM_Teller As Byte                   ; PWM periode teller 0..255
Dim PWM_Waarde1 As Byte
Dim PWM_Waarde2 As Byte
Dim PWM_Waarde3 As Byte

GoTo Main

On_Hardware_Interrupt GoTo PWM_ISR

PWM_ISR:                                ; PWM interrupt routine
    Clear TMR0IF
    TMR0 = TMR0 + 64                    ; Herlaad timer
    If PWM_Teller == 0 Then             ; Begin van een nieuwe cycle
        If PWM_Waarde1 == 0 Then Clear PWM_Output1 : Else : Set PWM_Output1
        If PWM_Waarde2 == 0 Then Clear PWM_Output2 : Else : Set PWM_Output2
        If PWM_Waarde3 == 0 Then Clear PWM_Output3 : Else : Set PWM_Output3
    Else                                ; Kijk of de maximale "aan" tijd is bereikt
        If PWM_Teller == PWM_Waarde1 Then Clear PWM_Output1
        If PWM_Teller == PWM_Waarde2 Then Clear PWM_Output2
        If PWM_Teller == PWM_Waarde3 Then Clear PWM_Output3
    EndIf
    Inc PWM_Teller
    Context Restore 
    
Main:

Clear GIE
DelayMS 500

TRISB = %11110000                       ; Poort B bit 0..3 output

PWM_Teller  = 0
PWM_Waarde1 = 192                       ; Kanaal 1 75% aan
PWM_Waarde2 = 128                       ; Kanaal 2 50% aan
PWM_Waarde3 = 64                        ; Kanaal 3 25% aan


TMR0   = 64                             ; Voor 39 usec periode (25.6 kHz)
T0CS   = 0                              ; Gebruik interne klok 
TMR0IF = 0
TMR0IE = 1                              ; Timer0 interrupt enabled
GIE    = 1                              ; Globale interupt enabled

; Nu de taken voor het hoofdprogramma, bijvoorbeeld faden van led1
; van uit naar aan en tegelijkertijd led2 van aan naar uit

While 1=1
    Inc PWM_Waarde1                     ; Springt naar nul bij 256
    Dec PWM_Waarde2
    DelayMS 10 
Wend
      
End

Hoe dat je een vierde of vijfde kanaal toe moet voegen is hopelijk wel duidelijk.

ontzettend bedankt voor deze code,
ik ga het vanavond proberen. ik laat weten hoe het afloopt.
nogmaals bedankt

hoi ik heb de code zojuist uit geprobeerd(na een kleine wijziging)

CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF

de ledjes branden nu on de beurt continu en andere 2 leds flikkeren zeer snel en van de led lijkt hier bij in en out te fade maar dat is moeilijk te zien.

de tmro heb ik al verschillende waardes gegeven maar zonder resultaat.
voor de duidelijkheid ik gebruik de interne klok van de Uc.

mocht dit niet mogelijk zijn hoor ik het ook graag dan bouw ik het met een kristal.

misschien zijn er nog andere dingen die van belang zijn om te wijzigen.

Kijk eens na hoe snel de interne klok loopt, in het voorbeeldprogramma staat dat op 20MHz. Je moet ook de interrupt-instellingen aanpassen (zie datasheet)!

ik ben nog eens aan het zoeken geweest. ik heb wel het een en ander aangepast, zie onder.

Device 16F628A
INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF


ALL_DIGITAL TRUE
 
Declare FSR_Context_Save = OFF
 
 
Symbol PEIE   = INTCON.6                  ; Pheripheral interrupt enable
Symbol GIE    = INTCON.7                  ; Global interrupt enable
Symbol TMR0IF = INTCON.2
Symbol TMR0IE = INTCON.5
Symbol T0CS   = OPTION_REG.5
 
TRISA = %11111111                         ; Definieer I/O lijnen
TRISB = %00000000
 
Symbol PWM_Output1 = PORTB.0
Symbol PWM_Output2 = PORTB.1
Symbol PWM_Output3 = PORTB.2
 
Dim PWM_Teller As Byte                   ; PWM periode teller 0..255
Dim PWM_Waarde1 As Byte
Dim PWM_Waarde2 As Byte
Dim PWM_Waarde3 As Byte
 
GoTo Main
 
On_Hardware_Interrupt GoTo PWM_ISR
 
PWM_ISR:                                ; PWM interrupt routine
    Clear TMR0IF
    TMR0 = TMR0 + 64                    ; Herlaad timer
    If PWM_Teller == 0 Then             ; Begin van een nieuwe cycle
        If PWM_Waarde1 == 0 Then Clear PWM_Output1 : Else : Set PWM_Output1
        If PWM_Waarde2 == 0 Then Clear PWM_Output2 : Else : Set PWM_Output2
        If PWM_Waarde3 == 0 Then Clear PWM_Output3 : Else : Set PWM_Output3
    Else                                ; Kijk of de maximale "aan" tijd is bereikt
        If PWM_Teller == PWM_Waarde1 Then Clear PWM_Output1
        If PWM_Teller == PWM_Waarde2 Then Clear PWM_Output2
        If PWM_Teller == PWM_Waarde3 Then Clear PWM_Output3
    EndIf
    Inc PWM_Teller
    Context Restore 
 
Main:

Clear GIE
DelayMS 500
 
TRISB = %11110000                       ; Poort B bit 0..3 output
 
PWM_Teller  = 0
PWM_Waarde1 = 192                       ; Kanaal 1 75% aan
PWM_Waarde2 = 128                       ; Kanaal 2 50% aan
PWM_Waarde3 = 64                        ; Kanaal 3 25% aan
 
 
TMR0   = 64                             ; Voor 39 usec periode (25.6 kHz)
T0CS   = 0                              ; Gebruik interne klok 
TMR0IF = 0
TMR0IE = 1                              ; Timer0 interrupt enabled
GIE    = 1                              ; Globale interupt enabled
 
; Nu de taken voor het hoofdprogramma, bijvoorbeeld faden van led1
; van uit naar aan en tegelijkertijd led2 van aan naar uit
 
While 1=1
    Inc PWM_Waarde1                     ; Springt naar nul bij 256
    Dec PWM_Waarde2
    DelayMS 10 
Wend
 
End

Waarschijnlijk ben ik nog iets vergeten. na aanleiding van Videomodulator ben ik gaan zoeken naar de termen TMR0 en en die paar daar onder, hier word ik echter niet veel wijzer van.
hopelijk kan iemand me hiermee op weg helpen.

alvast bedankt

Ik bekijk zojuist de code van electronick, deze ben ik ook aan het proberen. ik kom er alleen niet helemaal uit. hoe zorg je ervoor met deze code dat de leds op verschillende momenten in en out fade?
btw mijn Uc hoeft alleen maar te PWM dus van andere berekeningen is dus geen spraken.

graag zou ik hier over nog wat info hebben.
is het mogelijk om deze code te gebruiken met behulp van de interne osc? of moet het een ext kristal zijn

alvast bedankt.

De geposte code werkt anders prima bij mij. Misschien ziet het er wat logischer uit als je voor de while loop PWM_WAARDE1 en PWM_WAARDE2 op 0 zet, dan lopen ze in tegenfase (nu zijn de fases verschoven).

Als je de interne RC oscillator gebruikt is alleen de PWM frequentie 25Hz ipv 100Hz. Dan kan je corrigeren door TMR0 anders te laden, maar hou er wel rekening mee dat de tijd tussen de interrupts langer moet zijn dan dat de interrupt duurt. Als dat niet waar is hangt je programma in de interrupt routine.

Het helderheids verloop is trouwens niet lineair omdat de helderheid van de led niet lineair is met de stroom, dan moet je een gamma correctie toepassen.

ik heb wat met de waardes gespeeld maar zonder resultaat. het probleem is dat ze plots aan of uit gaan.
bv. 0%-100%-99%-98%-97%enz.
en andere leds van 100%-0%-1%-2%-3% enz.

dat zou dus niet moeten.
Ik heb de leds dmv een 330 weerstand aangesloten op de +5V.
Ik gebruikt inmiddels ook een 20mHz kristal.

iemand nog tips?

Alvast bedankt

Ik ben nog eens begonnen aan de code van elektronick.
inmiddels heb ik de volgende code:

Device 16F628A
Config HS_OSC, WDT_OFF, PWRTE_ON, LVP_OFF
XTAL = 20
OPTIMISER_LEVEL = 3
ALL_DIGITAL TRUE
 
Declare FSR_Context_Save = OFF
dim rgb_rood as byte
dim RGB_groen as byte
Dim rgb_blauw as byte
dim teller as byte

Main:


if RGB_Rood < teller then high portb.0
if RGB_Rood > teller then low  portb.0
if RGB_groen < teller then high  portb.1
if RGB_groen > teller then low     portb.1
if RGB_blauw < teller then high   portb.2
if RGB_blauw > teller then low  portb.2
'dit voor meerdere lampjes

if teller = 256 then teller = 0
teller = teller + 1

goto main

ik moet er nog voor zorgen dat rgb_rood, rgb_groen en RGB_blauw toenemen in waarde. hoe kan ik dit het beste doen?

[Bericht gewijzigd door Henry S. op (54%)]