Electronic Projects, forums and more.

Go Back   Electronic Circuits Projects Diagrams Free > Electronics Categories > Micro Controllers


Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc.

Reply
 
Thread Tools Display Modes
Old 21st May 2008, 08:23 PM   (permalink)
Default to generate 50hz pwm using 16f877

hi guys,

i am pretty new in dis field of micro-controllers, could you guys please help me by sharing how to generate a 50 hz PWM , am using 16f877 as pic and
20MHz crystal oscillator. can i generate this pwm using software methods?
actually my purpose is to control a servo motor with pwm 50 hz(20ms) and to vary between 1ms to 2ms duty cycle to obtain the angular motion of servo. we have budget constraints, so keen to know the software method that can be adopted.

thanks in advance....
cgsumesh77 is offline   Reply With Quote
Old 21st May 2008, 09:51 PM   (permalink)
Default

Hi cgsumesh77,

If you were using a 4 MHz or 16 MHz crystal it would be relatively easy to use the PWM module plus some (interrupt) software for that solution. Unfortunately, a 20 MHz clock isn't the best frequency to use with the Timer 2 prescalers.

Still, here's one possible solution for a 16 MHz clock which you might like to study. Basically, you setup the PWM module with a 1 KHz (1 msec) period and you use 20 of these 1 msec PWM "frames" to make up your 20 msec Servo period. At the end of each "frame" you setup the duty cycle for the next PWM "frame". At the end of 20 "frames" (20 msecs) you start over.

Regards, Mike

Code:
;******************************************************************
;
;  //  setup a 1000 usec PWM period with PR2 = 249 and prescaler
;  //  16:1 (16 MHz clock) for 20 PWM 'frames' per 20 msec Servo
;  //  period and 1 usec pulse width resolution
;
;  int servo = 1500;            // 0..20000 in 1 usec 'ticks'
;  int width = 0;               // ISR work variable
;  int frame = 1;               // frame number 1..20
;
;  void ISR()
;  { PIR1bits.TMR2IF = 0;       // clear Timer 2 interrupt flag
;    if (--frame == 0)          // if end of the 20 msec period
;    { frame = 20;              // reset for new 20 msec period
;      width = servo;           // reset 'width' work variable
;    }
;    if ((width > 1000)         // if width > 1000 usecs
;    { CCPR1L = 250;            // do a 100% duty cycle frame
;      CCP1CONbits.CCP1Y = 0;   //
;      CCP1CONbits.CCP1X = 0;   //
;      width -= 1000;           // subtract 1000 usecs
;    }
;    else
;    { CCP1CONbits.CCP1Y = (width & 1);
;      CCP1CONbits.CCP1X = (width & 2);
;      CCPR1L = (width >> 2);   // 0..249 (0..999 usecs)
;      width = 0;               // force remaining frames to 0%
;    }
;  }
;
ISR_vect
;
;  save main program context
;
        movwf   W_ISR           ; save W-reg                      |B?
        swapf   STATUS,W        ; doesn't change STATUS bits      |B?
        movwf   S_ISR           ; save STATUS reg                 |B?
        clrf    STATUS          ; force bank 0                    |B0
;
        bcf     PIR1,TMR2IF     ; clear Timer 2 interrupt flag    |B0
;
;  check for start of new 20 msec servo period
;
        decfsz  frame,F         ; end of 20 msec period?          |B0
        goto    doframex        ; no, branch, else                |B0
        movlw   d'20'           ; reset pwm frame number          |B0
        movwf   frame           ;                                 |B0
        movf    servo,W         ; setup 'pulse' work variable     |B0
        movwf   width           ; for new 20 msec servo period    |B0
        movf    servo+1,W       ;                                 |B0
        movwf   width+1         ;                                 |B0
doframex
        movlw   low(1000)       ; width = width - 1000            |B0
        subwf   width,F         ;                                 |B0
        movlw   high(1000)      ;                                 |B0
        skpc                    ;                                 |B0
        movlw   high(1001)      ;                                 |B0
        subwf   width+1,F       ;                                 |B0
        movlw   d'250'          ; assume 100% duty cycle frame    |B0
        bcf     CCP1CON,CCP1Y   ;                                 |B0
        bcf     CCP1CON,CCP1X   ;                                 |B0
        bc      setdutyx        ; borrow? no, branch, else        |B0
        movlw   low(1000)       ;                                 |B0
        addwf   width,F         ;                                 |B0
        movlw   high(1000)      ;                                 |B0
        skpnc                   ;                                 |B0
        movlw   high(1001)      ;                                 |B0
        addwf   width+1,F       ;                                 |B0
        btfsc   width,1         ;                                 |B0
        bsf     CCP1CON,CCP1X   ;                                 |B0
        btfsc   width,0         ;                                 |B0
        bsf     CCP1CON,CCP1Y   ;                                 |B0
        rrf     width+1,F       ;                                 |B0
        rrf     width,F         ;                                 |B0
        rrf     width+1,F       ;                                 |B0
        rrf     width,W         ; W = 0..250                      |B0
        clrf    width           ; force 0% duty cycle for the     |B0
        clrf    width+1         ; remaining pwm frames            |B0
setdutyx
        movwf   CCPR1L          ; set duty cycle for next frame   |B0
;
;  restore main program context
;
        swapf   S_ISR,W         ;                                 |B0
        movwf   STATUS          ; restore STATUS                  |B?
        swapf   W_ISR,f         ; don't screw up STATUS           |B?
        swapf   W_ISR,W         ; restore W-reg                   |B?
        retfie                  ; return from interrupt           |B?

Last edited by Mike, K8LH; 21st May 2008 at 09:51 PM.
Mike, K8LH is offline   Reply With Quote
Old 22nd May 2008, 04:41 PM   (permalink)
Default

hi mike... thanks for the help man... let me try it out tomorrow in my lab...
cgsumesh77 is offline   Reply With Quote
Old 23rd May 2008, 01:17 AM   (permalink)
Default

hi mike...
could i get the codes in c or assembly, or else can you please explain a bit more elaborated way, bcoz am still a bit unclear about how exactly does it works. i can generate a 1.22 khz instead of 1khz using 20Mhz frequency. then where should i connect my motor to.... am i going to get my 50 hz frequency from the pwm out pin of pwm module? is there a way that i can adjust this 1.22 khz to get a 1khz and then use the interrupt method to get a 50 hz frequency.. am using IAR work bench to compile my files... am really a beginer in dis stream...

thanks for the help

Last edited by cgsumesh77; 23rd May 2008 at 01:23 AM.
cgsumesh77 is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes


Similar Threads
Thread Thread Starter Forum Replies Latest
PIC 50Hz square barkerben Micro Controllers 21 17th December 2007 11:12 AM
50Hz Vs. 60Hz samcheetah General Electronics Chat 19 1st October 2004 06:20 PM
110V 50HZ adapter bandit General Electronics Chat 2 13th August 2004 08:00 AM
Getting 230V 50Hz from Car Battery Clyd3 Electronic Projects Design/Ideas/Reviews 11 13th July 2004 11:52 PM
50hz transmitter dark_conqueror Electronic Projects Design/Ideas/Reviews 1 10th November 2003 08:09 PM



All times are GMT. The time now is 12:52 PM.


Electronic Circuits  |  Electronics Wiki
Powered by vBulletin® Version 3.7.0
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.