Hallo,

ik ben bezig met servo's aansturen met een PIC16F877A, nou was mijn idee om Timer1 in testellen op 20ms en dan een variable puls maken dmv.

pin1 hoog
delay (1ms tot 2ms)
pin1 laag
pin2 hoog
delay (1ms tot 2ms)

Alleen nou kom ik er niet uit hoe ik de Timer1 instel zodat hij om de 20ms een interrupt maakt en dan 20ms later (en niet duur van timer interrupt +20ms) weer de zelfde interrupt.

Wie kan mij helpen om Timer1 in te stellen op 20ms en een delay maken die 1ms of 2ms duurd en die klopt.

Groeten,

Jeroen

Niemand, heb al wat dingen geprobeerd zoals instellen van TMR1 register maar niet gelukt

[Bericht gewijzigd door Jeroen13 op ]

Heb verschillende dingen geprobeerd om TMR1H en TMR1L te schrijven maar wil niet lukken.

Okee:

Timer 1 instellen:

T1CKPS1 = ; Prescaler bit1
T1CKPS0 = ; Prescaler bit0
TMR1CS = 0 ; Clock soure select: Fosc/4
TMR1ON = 1 ; Turn TMR1 on

Interrupts instellen:
T1IF = 0
T1IE = 1
PEIE = 1
GIE = 1

Nu heb je bij de overflow een interrupt.
Je moet alleen nog even de prescaler en de startwaarden van je timer uitrekenen.

Op 12 april 2006 18:54:11 schreef elmowww:
Okee:

Timer 1 instellen:

T1CKPS1 = ; Prescaler bit1
T1CKPS0 = ; Prescaler bit0
TMR1CS = 0 ; Clock soure select: Fosc/4
TMR1ON = 1 ; Turn TMR1 on

Interrupts instellen:
T1IF = 0
T1IE = 1
PEIE = 1
GIE = 1

Nu heb je bij de overflow een interrupt.
Je moet alleen nog even de prescaler en de startwaarden van je timer uitrekenen.

ey zo ver was ik al (A), alleen weet niet hoe ik de overflow waarde ofwel TMR1 kan veranderen, want hij moet pas na 20ms interrupten.

Timer1 instellen als timer met prescaler van bv 1:2.
Dit geeft dan Fosc/4/2 = 400us per tick (dus om de 0,4ms zal de timer met 1 verhoogd worden)
20ms / 0,4ms = 50

Als ik me goed herinner is timer1 een 16bits timer, dus de hoogste waarde is 65535.
Hier trek je dan de 50 van af, 65485, en dit zet je in de timerregisters (Timer1high en timer1low)
Na 50 ticks (20 ms) krijg je een overflow, et voila een interrupt op 20 ms.

Dit zij iemand tegen mij, alleen hoe kan ik de waarde FFCD op TMR1H en TMR1L zetten zodat hij van 0000h tot FFCDh naar 0000h gaat en niet FFFFh want het is een voor een servo aan te sturen.

Btw heb je toegevoegd op msn gezien jij veel weet van servo en robotica.

In je interrupt routine moet je iedere keer die waarde in je timer zetten. Wel geloof ik dat er een tmr match interupt in een PIC zit, weet niet waar. Geloof tmr 1 of 2.

Dus stukje in interrupt (picbasic, weet niet of je daar in werkt)


if t1if = 1 then
    tmr1h = tmr1h + 0xFF
    tmr1l = tmr1l + 0xCD
    ; hier iets om de servos te sturen
endif

Op 13 april 2006 11:20:00 schreef elmowww:
In je interrupt routine moet je iedere keer die waarde in je timer zetten. Wel geloof ik dat er een tmr match interupt in een PIC zit, weet niet waar. Geloof tmr 1 of 2.

Dus stukje in interrupt (picbasic, weet niet of je daar in werkt)


if t1if = 1 then
    tmr1h = tmr1h + 0xFF
    tmr1l = tmr1l + 0xCD
    ; hier iets om de servos te sturen
endif

Wat bedoel je met die match interrupt hoor verschillende mensen praten over CCP Compare module.

En moet het dan TMR1H + 0xFF zijn of TMR1H=0xFF dus erbij optellen of gelijk maken ?

Als je TMR2 nog niet gebruikt dan is het daarmee makkelijker te verwezenlijken. Die kan je namelijk laten tellen tot een ingestelde waarde en dan is het niet nodig om in de interrupt routine de timer opnieuw te laden.

Op 13 april 2006 14:40:50 schreef JoWi:
Als je TMR2 nog niet gebruikt dan is het daarmee makkelijker te verwezenlijken. Die kan je namelijk laten tellen tot een ingestelde waarde en dan is het niet nodig om in de interrupt routine de timer opnieuw te laden.

Nadeel als ik timer2 gebruik kan ik geen PWM meet opwekken voor andere doeleinden

Op 13 april 2006 14:31:05 schreef DJJeroen:
En moet het dan TMR1H + 0xFF zijn of TMR1H=0xFF dus erbij optellen of gelijk maken ?

Optellen is het netste, of uitrekenen hoeveel cycles hij reeds geteld heeft

Op 13 april 2006 15:00:29 schreef DJJeroen:
[...]
Nadeel als ik timer2 gebruik kan ik geen PWM meet opwekken voor andere doe einden

Klopt, dat kan alleen nog als je de PWM frequentie een veelvoud laat zijn van de timerfrequentie. Dat is de oplossing die ik vaak kies: bijv 20 kHz PWM en dan een 10 milliseconden klok. Dan hou ik met een software teller de PWM ticks bij en als je er 200 hebt is er .01 seconde voorbij.

Op 13 april 2006 15:13:50 schreef elmowww:
[...]
Optellen is het netste, of uitrekenen hoeveel cycles hij reeds geteld heeft

if( TMR1IF=1 )
{
GLED=1;
TMR1H=0x00;
TMR1L=0xAA;
Teller3++;
TMR1IF=0;
}

Dit heb ik nu maar maar het TMR1 register heeft een grotere waarde dan 0x00 aan. en als ik TMR1H+ doe doet hij het zelfde het GLED1 is aan maar is heel ver "gedimt", en teller3 wordt ook steeds hoger als ik in de interrupt kijk

en als ik de waarde 0x00 verander in 0xAA krijgt teller 3 de zelfde waarde na ongeveer 5seconden (700000)

[Bericht gewijzigd door Jeroen13 op ]

Hmm, heb TMR1ON=0; gedaan in het T1CON register maar hij blijft in de interrupt komen ?
Als ik T0IE=0; doet hij dat niet meer, hoe kan dat ?

Omdat TMR0 altijd loopt als de clock source op Fosc staat... RTFD

Op 13 april 2006 15:47:24 schreef elmowww:
Omdat TMR0 altijd loopt als de clock source op Fosc staat... RTFD

Oeps :+ was het net aan het lezen.

heb nu dus T0IE=0; gedaan
dan bij mijn functie InitInt:

T1CON = 0b00110001; neer gezet met prescaler op 1:8 en TMR10N=1;

void interrupt intA(void) @ 0x04
{
    if( TMR1IF=1 )
    {
        Teller3++;
        TMR1H=0x00;
        TMR1L=0xAA;
        TMR1IF=0;
    }
    else 
    {
        TMR1IF=0;
    }

}

En dit heb ik in de interrupt, het hoofdprogramma loopt zie alleen teller3 niet oplopen in de debugger maar TMR1 veranderd wel. wat doe ik nu nog fout ?

TMR1IE=1;
PEIE=1;

alleen zie ik TMR1H nog wel meer als 0x00 worden in de debugger

Teller loopt veel langzamer op als net, alvast bedenkt ga nu zelf even proberen te veranderen, en kijken of ik het verder werkent krijg.

[Bericht gewijzigd door Jeroen13 op ]

Het is gelukt, om er een blokgolf uit te krijgen 390Hz DutyCycle 12 % althans dat is wat mijn multimeter aan geeft

Alleen blijft TMR1H boven de 0 gaan en TMR1L ook boven zijn waarde.

En moet nu nog bereken hoe ik aan 50hz, dc 1ms tot 2ms met 20mhz kristal.

if( TMR1IF=1 )
{
    TMR1H=0x00;
    TMR1L=0xAA;
    while( Teller3<=500 )
    {
        GLED=1;
        Teller3++;
        CLRWDT();
    }
    Teller3=0;
    GLED=0;
    TMR1IF=0;
}
else 
{
    TMR1IF=0;
}

[Bericht gewijzigd door Jeroen13 op ]

Heb even de waardes gemeten met scoop:

1:1 80Hz
1:2 40Hz
1:4 20Hz
1:8 10Hz

Hoe kan ik nou op 50 hz aan komen ?

Door 1:2 te kiezen en zelf een startwaarde naar Timer te sturen.

Op 13 april 2006 17:40:02 schreef JuuL:
Door 1:2 te kiezen en zelf een startwaarde naar Timer te sturen.

Ja dat lukt dus niet, hij blijft over 0x00 gaan als ik dat als start waarde invoer.

heb hem nu wel draaiende gekregen met geen main programma, maar als ik nu een ander main programma kies met meer instructies doet hij niks

Op 13 april 2006 18:21:03 schreef DJJeroen:
[...]
Ja dat lukt dus niet, hij blijft over 0x00 gaan als ik dat als start waarde invoer.

Bij elke Timer interrupt moet je dus de timer reloaden.
Als je het netjes doet hou je ook rekening met de interrupt latency en mogelijke timer-rollover. (Ik weet niet hoe exact je wil zijn)

Op 13 april 2006 18:25:01 schreef JoWi:
[...]Bij elke Timer interrupt moet je dus de timer reloaden.
Als je het netjes doet hou je ook rekening met de interrupt latency en mogelijke timer-rollover. (Ik weet niet hoe exact je wil zijn)

wat bedoel je daar allemaal mee ? en vooral timer reloaden ?

Hmm wazig nou doet hij helemaal niks meer, kwa timer heb verder niks veranderd

[Bericht gewijzigd door Jeroen13 op ]

De timer telt omhoog van 0 naar 65.535 en genereert een interrupt. Dan telt ie vanaf 0 weer omhoog.
Als je nu een kortere tijd wil dan laad je timer 1 met bijv. 20.000. Vervolgens telt hij naar 66.535 (maar dat duurt nu slechts 45.535 klokpulsen), genereert een interrupt en gaat vanaf 0 verder. De tijd tot de volgende interrupt is dan 65.535 klokpulsen. In de interrupt moet je dus opnieuw 20.000 in de timer laden. Dus bij elke interrupt.

Nu zijn er twee problemen:
1) Het duurt even voor je in de interrupt de timer opnieuw laadt. De teller staat dus niet op 0 maar bijv. al op 7. Er zijn dus al 7 kloks voorbij gegaan (Dit is niet constant, het kan meer zijn afhankelijk van je code (meerdere interruptbronnen) en de interrupt latency.
Dat moet je corrigeren. Dat doe je door niet bijv. 20.000 in de timer te laden maar door dit op te tellen bij de huidige timer waarde.
2) Omdat de timer 16 bit is en je slechts 8 bit tegelijk kan laden kan het voorkomen dat het lage byte net rondloopt (van 255->0) tussen het laden van het lage en hoge byte in. (De timer telt onafhankelijk van je programma) Je hebt dan een fout van 256 kloks omdat het hoge byte van de timer met 1 is opgehoogt. Je moet dus controleren of zo'n roll-over is opgetreden tijdens het laden van de timer. Ergens in de datasheets kan je wel vinden hoe je daarop moet testen en dan corrigeren.

Met klokpuls bedoel ik trouwens de timer-klok, en dat hoeft niet gelijk te zijn aan de processorklok (zoals door gebruik van de prescaler of een externe bron)