Page 1 of 1

Help with PWM using Timer0

Posted: 20 Oct 2014 05:25
by alvaroevc5
Hello MikroElectronika memebers, I hope I don't sound too demanding, but I'll cut to the chase.

The PIC I'm playing with is a 18F2550 and I'm using Timer0 in order to move three servo motors in different directions simultaneously. The prescaler, the ports, and the interrupt bits are well set as far as I can consider, however, when I simulate the program on Proteus I only get one of the three square waves with the "perfect" duty cycle.

In the example below, the variables I use are set so the three square waves can have the same duty cycle, therefore, they should have the same shape on the oscilloscope, but unfortunately no, the first two appear as if they switched off right after switching on for some reason. Appreciating beforehand any kind of help or comments.

Code: Select all

/******************************Variable Designation****************************/
char counter=0;
char posone, postwo, posthree;

/********************************Interrupt Routine*****************************/
void interrupt()
{
 if (INTCON.TMR0IF==1)
 {
   INTCON.TMR0IF=0;
   counter++;
 /**********************Three PWMs Start Here Simultaneously*******************/
   if (counter==39)
   {
    PORTA.RA0=1;
    PORTA.RA1=1;
    PORTA.RA2=1;
    counter=0;
   }

   if(counter==posone)
   PORTA.RA0=0;
   if(counter==postwo)
   PORTA.RA1=0;
   if(counter==posthree)
   PORTA.RA2=0;
 }

}
/**********************************Main Routine********************************/
void main() {

INTCON.GIE=1;
INTCON.TMR0IE=1;

TRISA.RA0=0;
TRISA.RA1=0;
TRISA.RA2=0;
PORTA.RA0=0;
PORTA.RA1=0;
PORTA.RA2=0;

T0CON.T0CS=0;
T0CON.PSA=0;
T0CON.T0PS2=0;
T0CON.T0PS1=0;
T0CON.T0PS0=0;

while(1)
{
posone=20;
postwo=20;
posthree=20;
}
}

Re: Help with PWM using Timer0

Posted: 20 Oct 2014 13:26
by janni
Apparently you've stumbled on RMW (Read-Modify-Write) effect. Use LATx registers to switch individual output pins states and configure respective port pins as digital (when configured as analog (default after reset) PORTx.y reads zero).

Re: Help with PWM using Timer0

Posted: 20 Oct 2014 16:34
by alvaroevc5
Thank you so much for the help, it completely worked. I didn't know there was such a difference between LAT and PORT, the kind of stuff that happens when you learn about PICs empirically.

Now, another question if I may. I want to make changes on the PWM proportional to an analog input, but the changes in the duty cycle using the actual prescaler vary every 0.5ms, that would mean abrupt movements on the servo's angle.

Any suggestions on this problem?

Re: Help with PWM using Timer0

Posted: 20 Oct 2014 22:32
by janni
Obvious solution would be more frequent interrupts but, for just 3 servos, one could also use one 16-bit timer per servo. You should browse the forum or check on Libstock how others solved the same problem and choose.