PIC met PWM

Alle vragen m.b.t. lichteffecten m.b.v. lampen, led's etc.
Plaats reactie
Gebruikersavatar
Termike
Berichten: 279
Lid geworden op: ma 14 mar 2005, 13:39
Locatie: Hoevenen, België. .

PIC met PWM

Bericht door Termike »

Wat ik wil maken is een bureaulamp die instelbaar is qua intensiteit. De schakeling werkt voor 66,67% goed. 2/3de dus, even een korte uitleg erbij. LED0 is een reeks van leds. LED1 is een ander type reeks leds. Allebei instelbaar qua intensiteit. Mijn probleem dus nu is als ze apart moeten werken wat instelbaar is via de keuzeschakelaar(=variabele in programma hieronder) dan zie je dat afhankelijk of er gedrukt wordt op S2 of niet gekozen wordt. Nu in de derde stand is het commando PWM niet meer handig. Hier zou ik dus zelf iets moeten schrijven met een soort van for next lus maar ik vind niet direct iets. Ik moet dus eigelijk iets zien te vinden om het alles-in-één-commando PWM te vervangen, enkel daar. De limiet van PWM is dat hij dit apart doet, hij peewee-emt eerst LED0, en daarna LED1, terwijl ze allebei moeten gaan. Dus, een alternatief voor PWM?

Groetjes
Robin

Code: Selecteer alles

DEVICE 16F628A                                                      ;We gebruiken een 16F628A type
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF    ;Fuses instellen
ALL_DIGITAL TRUE                                                    ;Alle info is digitaal

Dim Duty as byte
Dim Keuzeschakelaar as byte

SYMBOL LED0 = PORTA.0                                               ;Poort A.0 heeft nu de naam LED1
SYMBOL LED1 = PORTA.1                                               ;Poort A.1 heeft nu de naam LED2
SYMBOL LED2 = PORTA.2  
SYMBOL LED3 = PORTA.3                                             ;Poort A.2 heeft nu de naam LED3
SYMBOL S0   = PORTB.0                                               ;Poort B.0 heeft nu de naam S1
SYMBOL S1   = PORTB.1                                               ;Poort B.1 heeft nu de naam S2
SYMBOL S2   = PORTB.2                                               ;Poort B.2 heeft nu de naam S3
        ;76543210
PORTA = %00000000                                                   ;Alle niveaus van PORTA laag
PORTB = %00000000                                                   ;Alle niveaus van PORTB laag
TRISA = %00000000                                                   ;Alles als uitgang
TRISB = %00000111                                                   ;porten 0-2 als ingang, al de rest uitgang

PORTB_PULLUPS ON
LED3 = 1
Duty = 255
Keuzeschakelaar = 1
Loop:
While 1 = 1
Select case Keuzeschakelaar
    Case 1
        PWM LED0, Duty, 10 
        Call readaction
    Case 2
        PWM LED1, Duty, 10
        Call readaction    
    Case 3
        PWM LED0, Duty, 10
        PWM LED1, Duty, 10
        Call readaction
End Select
Wend ;Einde hoofdloop

readaction:
    Select Case 0
        Case S0
            If Duty = 30 then
                Duty = 30
            else
                Duty = Duty - 25
            End if
            while S0 = 0 : wend
        Case S1
            If Duty = 255 then
                Duty = 255
            else
                Duty = Duty + 25
            End if
            while S1 = 0 : wend
        Case S2
            If Keuzeschakelaar = 3 then
                Keuzeschakelaar = 1
            Else
                Keuzeschakelaar = Keuzeschakelaar + 1
            End if
            while S2 = 0 : wend
    End select            
return

END                           ;Einde programma
Gebruikersavatar
Termike
Berichten: 279
Lid geworden op: ma 14 mar 2005, 13:39
Locatie: Hoevenen, België. .

Bericht door Termike »

Dit heb ik zelf in elkaar gegooid, maar het geheel gaat nogal schokkend, daarom dacht ik van ik toon elk beeld wat vaker door een 2de for next loop maar dat blijkt niet echt te helpen...
Iemand een idee?

Code: Selecteer alles

For I = 0 to 255
    For J = 0 to 10
        led0 = 1
        LED1 = 1
        delayms I / 15
        led0 = 0
        LED1 = 0
        delayms (255 - I) / 15
    Next J
Next I
marcob
Berichten: 13
Lid geworden op: wo 18 apr 2007, 15:36
Locatie: . .. .. .. .

Bericht door marcob »

Wat je moet doen is, dooor middel van een interrupt door timer 0 of timer 1, steeds PWM laten uitvoeren. Zal je even een voorbeeld geven.
Ik heb het zo germaakt dat nu de kleuren een beetje overvloeien, maar dat kun j ezelf aanpassen. Teller1 is een kleur en teller2 is een kleur en teller3 is een kleur.

Code: Selecteer alles

'****************************************************************
'*  Name    : UNTITLED.BAS                                      *
'*  Author  : Naam                                                *
'*  Notice  : Copyright (c) 2007                               *
'*          : All Rights Reserved                               *
'*  Date    : 04/01/2007                                        *
'*  Version : 1.0                                               *
'*  Notes   :                                                   *
'*          :                                                   *
'****************************************************************
'COMPILER DECLARES :-
DEVICE 18f252                 ;We gebruiken een 18F242 type
xtal 12
all_digital = 1               ; ALL PORTS TO DIGITAL
'****************************************************************
'VARIABLES :-
DIM TELLER1  AS BYTE
DIM TELLER2  AS BYTE
DIM TELLER3  AS BYTE
DIM TEMP     AS WORD
DIM TEMP2    AS WORD
DIM LUS1     AS BYTE
DIM VERTR    AS byte
'****************************************************************
'SYMBOL ALIAS'S :-
SYMBOL T0IF = INTCON.2        ; TMR0 Overflow Interrupt Flag
SYMBOL T0IE = INTCON.5        ; TMR0 Overflow Interrupt Enable
SYMBOL GIE  = INTCON.7        ; Global Interrupt Enable

SYMBOL PS0  = T0CON.0         ; Prescaler Rate Select
SYMBOL PS1  = T0CON.1         ; Prescaler Rate Select
SYMBOL PS2  = T0CON.2         ; Prescaler Rate Select
SYMBOL PSA  = T0CON.3         ; Prescaler Assignment
SYMBOL T0CS = T0CON.5         ; TMR0 Clock Source Select

SYMBOL GROEN = PORTc.4        ; PWM uitgang Groene led
SYMBOL BLAUW = PORTc.5        ; PWM uitgang Blauwe led        
SYMBOL ROOD  = PORTc.6        ; PWM uitgang Rood led        

'****************************************************************
'DATA STATEMENTS ;-
'****************************************************************
'JUMP OVER SUBROUTINES
ON_INTERRUPT GOTO PWM_INT     ; POINT INTERRUPT TO HANDLER

GOTO MAIN
'****************************************************************
'INTERRUPT SUBROUTINE
PWM_INT:
  PWM ROOD,  TELLER1, 2
  PWM GROEN, TELLER2, 2
  PWM BLAUW, TELLER3, 2
T0IF = 0
CONTEXT RESTORE 
'****************************************************************
' MAIN PROGRAM :-
MAIN:
;        76543210
PORTc = %00000000             ;Alle niveaus van PORTC eerst laag maken
TRISc = %00000000             ;PORTC  als uitgang
trisb = %00000000
trisa = %11111111
GIE = 0                       ; UITSCHAKELEN GLOBAL INTERRUPTS
WHILE GIE = 1: GIE = 0: WEND  ; ZEKER WETEN DAT GIE UIT IS
PSA  = 0                      ; PRESCALER TO EXTERNEL INTERRUPT
PS0  = 1
PS1  = 0
PS2  = 0
T0CS = 0
TMR0L  = 1
TMR0H  = 1
T0IE = 1
GIE  = 1 
TELLER1 = 10
TELLER2 = 10
TELLER3 = 10

while 1=1

vertr = porta

WHILE TELLER1 <250> 1
 DEC TELLER3
 vertr = porta
FOR TEMP = 0 TO VERTR : NEXT 
wend

WHILE TELLER2 <250> 1
 DEC TELLER1
 vertr = porta
FOR TEMP = 0 TO VERTR : NEXT
WEND

WHILE TELLER3 <250> 1
 DEC TELLER2
 vertr = porta
FOR TEMP = 0 TO VERTR : NEXT
WEND

WEND

END                           ;Einde programma

Gebruikersavatar
Termike
Berichten: 279
Lid geworden op: ma 14 mar 2005, 13:39
Locatie: Hoevenen, België. .

Bericht door Termike »

SYMBOL T0IF = INTCON.2 ; TMR0 Overflow Interrupt Flag
SYMBOL T0IE = INTCON.5 ; TMR0 Overflow Interrupt Enable
SYMBOL GIE = INTCON.7 ; Global Interrupt Enable

SYMBOL PS0 = T0CON.0 ; Prescaler Rate Select
SYMBOL PS1 = T0CON.1 ; Prescaler Rate Select
SYMBOL PS2 = T0CON.2 ; Prescaler Rate Select
SYMBOL PSA = T0CON.3 ; Prescaler Assignment
SYMBOL T0CS = T0CON.5 ; TMR0 Clock Source Select

Dat zegt me echt niets... Ik ken namelijk nog geen interrupts :s Kan je daar een beetje uitleg bij geven?

Alvast bedankt
Groetjes
Robin
marcob
Berichten: 13
Lid geworden op: wo 18 apr 2007, 15:36
Locatie: . .. .. .. .

Bericht door marcob »

Interrupts zijn iets waar je maar eens mee moet spelen.
Wat ik in mijn programma doe, is het volgende.
Ik heb het zo ingesteld, dat steeds wanner timer 0 zijn max bereikt, het programma naar de intterrupt stap (PWM_INT:) nadat de commando's daar zijn uitgevoerd, start timer 0 opnieuw en het programma gaat verder op de plek waar hij was voor het interrupt.
Timer 0 is zo ingesteld dat deze wel meerdere malen per seconde gebeurt, dus je kunt je voorstellen dat de LED's goed regelbaar zijn.

Maar ik zie dat jij een 16F628A gebruikt, en daar werkt het even anders, ik zal het morgen probveren uit te zoeken voor je.
Mischien kun je al even spitten in de datasheet, wat ik snel zie is dat je deze bits moet gebruiken:

Code: Selecteer alles

SYMBOL PS0      = OPTION_REG.0      ' Prescaler Rate Select
SYMBOL PS1      = OPTION_REG.1      ' Prescaler Rate Select
SYMBOL PS2      = OPTION_REG.2      ' Prescaler Rate Select
SYMBOL PSA      = OPTION_REG.3      ' Prescaler Assignment
SYMBOL T0SE     = OPTION_REG.4      ' TMR0 Source Edge Select
SYMBOL T0CS     = OPTION_REG.5      ' TMR0 Clock Source Select
SYMBOL INTEDG   = OPTION_REG.6      ' Interrupt Edge Select
SYMBOL NOT_RBPU = OPTION_REG.7      ' PORTB Pull-up Enable
Maar zoals ik zei, zal morgen eens een voorbeeld voor jouw proberen te maken.
Gebruikersavatar
Termike
Berichten: 279
Lid geworden op: ma 14 mar 2005, 13:39
Locatie: Hoevenen, België. .

Bericht door Termike »

marcob schreef:Interrupts zijn iets waar je maar eens mee moet spelen.
Wat ik in mijn programma doe, is het volgende.
Ik heb het zo ingesteld, dat steeds wanner timer 0 zijn max bereikt, het programma naar de intterrupt stap (PWM_INT:) nadat de commando's daar zijn uitgevoerd, start timer 0 opnieuw en het programma gaat verder op de plek waar hij was voor het interrupt.
Timer 0 is zo ingesteld dat deze wel meerdere malen per seconde gebeurt, dus je kunt je voorstellen dat de LED's goed regelbaar zijn.

Maar ik zie dat jij een 16F628A gebruikt, en daar werkt het even anders, ik zal het morgen probveren uit te zoeken voor je.
Mischien kun je al even spitten in de datasheet, wat ik snel zie is dat je deze bits moet gebruiken:

Code: Selecteer alles

SYMBOL PS0      = OPTION_REG.0      ' Prescaler Rate Select
SYMBOL PS1      = OPTION_REG.1      ' Prescaler Rate Select
SYMBOL PS2      = OPTION_REG.2      ' Prescaler Rate Select
SYMBOL PSA      = OPTION_REG.3      ' Prescaler Assignment
SYMBOL T0SE     = OPTION_REG.4      ' TMR0 Source Edge Select
SYMBOL T0CS     = OPTION_REG.5      ' TMR0 Clock Source Select
SYMBOL INTEDG   = OPTION_REG.6      ' Interrupt Edge Select
SYMBOL NOT_RBPU = OPTION_REG.7      ' PORTB Pull-up Enable
Maar zoals ik zei, zal morgen eens een voorbeeld voor jouw proberen te maken.
Heb jij al enig succes, want als je vanaf 0 kennis over timers moet beginnen blijkt dat niet zo simpel te zijn...

Groetjes
marcob
Berichten: 13
Lid geworden op: wo 18 apr 2007, 15:36
Locatie: . .. .. .. .

Bericht door marcob »

Hierbij iets opgezet. Dit geeft het principe weer.

Code: Selecteer alles

'**************************************************************** 
'*  Name    : UNTITLED.BAS                                      * 
'*  Author  : Marco Bakker                                      * 
'*  Notice  : Copyright (c) 2007 MarcoB                         * 
'*          : All Rights Reserved                               * 
'*  Date    : 04/01/2007                                        * 
'*  Version : 1.0                                               * 
'*  Notes   : Programma welke 3 leds laat overvloeien           * 
'*          :                                                   * 
'**************************************************************** 

' ----------------------------------------------------------------------------- 
'COMPILER DECLARES :- 
' ----------------------------------------------------------------------------- 
   DEVICE 16F628a 
    REMARKS ON 
   cONFIG HS_OSC,PWRTE_ON,CP_OFF,WDT_OFF,LVP_OFF,MCLRE_OFF,BODEN_ON 
    ON_INTERRUPT INT_PWM 
   ALL_DIGITAL ON 
    DECLARE XTAL=20 
' ----------------------------------------------------------------------------- 
'VARIABLES :- 
' ----------------------------------------------------------------------------- 
    DIM TELLER1  AS BYTE                            ; Waarde van de LED sterkte 1 
    DIM TELLER2  AS BYTE                            ; Waarde van de LED sterkte 2 
    DIM TELLER3  AS BYTE                            ; Waarde van de LED sterkte 3 
    DIM TEMP     AS WORD                            ; Tijdelijke Variable 1 
    DIM TEMP2    AS WORD                            ; Tijdelijke Variable 2 
    DIM VERTR    AS byte                            ; Waarde van de fade vertraging 
' ----------------------------------------------------------------------------- 
'SYMBOL ALIAS'S :- 
' ----------------------------------------------------------------------------- 
    SYMBOL T0IF     = INTCON.2                      ; TMR0 Overflow Interrupt Flag 
   SYMBOL T0IE     = INTCON.5                      ; TMR0 Overflow Interrupt Enable 
   SYMBOL GIE      = INTCON.7                      ; Global Interrupt Enable 
        
   SYMBOL PS0      = OPTION_REG.0                  ; Prescaler Rate Select 
    SYMBOL PS1      = OPTION_REG.1                  ; Prescaler Rate Select 
    SYMBOL PS2      = OPTION_REG.2                  ; Prescaler Rate Select 
    SYMBOL PSA      = OPTION_REG.3                  ; Prescaler Assignment 
    SYMBOL T0SE     = OPTION_REG.4                  ; TMR0 Source Edge Select 
    SYMBOL T0CS     = OPTION_REG.5                  ; TMR0 Clock Source Select 

    SYMBOL GROEN    = PORTb.4                       ; PWM uitgang Groene led 
    SYMBOL BLAUW    = PORTb.5                       ; PWM uitgang Blauwe led        
    SYMBOL ROOD     = PORTb.6                       ; PWM uitgang Rood led     

' ----------------------------------------------------------------------------- 
'JUMP OVER SUBROUTINES 
' ----------------------------------------------------------------------------- 
    ON_INTERRUPT GOTO INT_PWM                       ; POINT INTERRUPT TO HANDLER 
   GOTO Initialisation                             ; Altijd eerst de intterrupt routine, spring erover heen 

' ----------------------------------------------------------------------------- 
' INTERRUPT ROUTINE 
' ----------------------------------------------------------------------------- 
INT_PWM: 
    PWM ROOD,  TELLER1, 2                          ; UITGANG sturen 
    PWM GROEN, TELLER2, 2 
    PWM BLAUW, TELLER3, 2 
    T0IF = 0                                       ; Timer 0 Reset 
    CONTEXT RESTORE                                ; Terug naar main: programma 

' ----------------------------------------------------------------------------- 
' INITIALISATION ROUTINE 
' ----------------------------------------------------------------------------- 
Initialisation: 
    ;        76543210 
    PORTb = %00000000             ; Alle niveaus van PORTC eerst laag maken 
    TRISb = %00000000             ; Port b is uitgang 

   GIE = 0                        ; UITSCHAKELEN GLOBAL INTERRUPTS 
   WHILE GIE = 1: GIE = 0: WEND   ; ZEKER WETEN DAT GIE UIT IS 
    
   T0SE  = 0                     ; TIMER0 triggered by ascending edge 
   T0CS  = 0                     ; TIMER0 gebruikt interne clock 
   PSA   = 0                     ; Prescaler gekoppeld aan TIMER0 
   PS0   = 1                     ; Prescaler set at 1:256 
   PS1   = 1  
   PS2   = 1    
             
   vertr     = 100                ; Vertraging staat op 100 
   TELLER1   = 10                 ; Start van de tellers 
   TELLER2   = 10                
   TELLER3   = 10    
             
   TMR0=0                         ; Reset TIMER0 
   T0IE=1                         ; Inschakelen  TIMER0 interrupt 
   GIE=1                         ; Inschakelen Alle interrupts 
           
' ----------------------------------------------------------------------------- 
' MAIN PROGRAM 
' Dit een simpel programma welke de tellers 1 t/m 3 simpel van waarde veranderd. 
' Maar dit kun je zelf makkelijk aanpassen naar eigen wensen. 
' De tellers tellen van 0 tot 255 en weer terug. 
' ----------------------------------------------------------------------------- 
             
MAIN: 
while 1=1 

WHILE TELLER1 <250> 1 
 DEC TELLER3 
FOR TEMP = 0 TO VERTR : NEXT 
wend 

WHILE TELLER2 <250> 1 
 DEC TELLER1 
FOR TEMP = 0 TO VERTR : NEXT 
WEND 

WHILE TELLER3 <250> 1 
 DEC TELLER2 
FOR TEMP = 0 TO VERTR : NEXT 
WEND 

WEND 
  

END 
Plaats reactie