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
Electronick
In theory there's no diffrence between theory and practice, in practice there is!
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?
Videomodulator
AKA Naftebakje @Tweakers.net --- Zonder dwarsliggers geen spoor
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
EndHoe 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_OFFde 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.
Videomodulator
AKA Naftebakje @Tweakers.net --- Zonder dwarsliggers geen spoor
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
EndWaarschijnlijk 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 mainik 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%)]