Low freq PWM problem


Closed Thread
Results 1 to 6 of 6

Hybrid View

  1. #1
    Join Date
    Aug 2005
    Location
    Michigan, USA
    Posts
    224


    Did you find this post helpful? Yes | No

    Default

    You might also consider using the PWM module along with a small interrupt driven "helper" to link together several smaller PWM period "frames" into the much longer 120-Hz PWM period. This method produces a relatively low overhead high resolution jitter free PWM output.

    I don't have PBP but perhaps you and other Forum members can muddle through this pseudo C code example.

    This example uses a 12-MHz clock (Tcy = 0.3334-usecs) with PWM module settings that produce a PWM period of 333.3334-usecs (250 x 1.3334-usec 'steps'). The interrupt "helper" links together 25 of these short 333.3334-usec PWM period "frames" to produce a precise 120-Hz (8333.3334-usec) period with an output pulse width of 0 to 6250 x 1.3334-usec "steps".

    Regards, Mike

    Code:
    ;******************************************************************
    ;
    ;  // setup PWM for a 333.3 usec period (12-MHz xtal, Timer 2
    ;  // prescale 4:1, PR2 = 249) and use 25 of these 333.3 usec
    ;  // PWM "frames" for a precise 120-Hz (8.3334 msec) period.
    ;
    ;  char frame = 1;              // initialize "frame" var'
    ;  int width = 100;             // 0..6250 (1.333 usec steps)
    ;  int pulse;                   // isr work variable, 0..6250
    ;
    ;  void interrupt()             // 120-Hz example
    ;  { pir1.TMR2IF = 0;           // clear timer 2 interrupt flag
    ;    frame--;                   // decrement 'frame' number
    ;    if(frame == 0)             // if end-of-period
    ;    { frame = 25;              // reset for new period
    ;      pulse = width;           // refresh work variable
    ;    }
    ;    if(pulse > 250)            //
    ;    { ccpr1l = 250;            // do a 100% duty cycle frame
    ;      pulse -= 250;            // update 'pulse'
    ;    }
    ;    else                       //
    ;    { ccpr1l = pulse;          // do variable duty cycle
    ;      pulse = 0;               // force remaining frames to 0%
    ;    }
    ;
    ;
    ;
    ;  void Main()                  //
    ;  { cmcon0 = 7;                // comparators off
    ;    ansel = 0;                 // a2d convertor off
    ;    pir1 = 0;                  // clear all interrupt flags
    ;    pie1.TMR2IE = 1;           // enable TMR2 interrupts
    ;    ccpr1l = 0;                // set 0% duty cycle (output off)
    ;    t2con = 0b00000101;        // '0-------' unimplemented bit
    ;                               // '-0000---' TOUTPS<3:0>, postscale 1
    ;                               // '-----1--' TMR2ON, turn Timer 2 on
    ;                               // '------01' T2CKPS<1:0>, prescale 4
    ;    pr2 = 250-1;               // 250 x 1333-nsec 'ticks' = 333 usecs
    ;    intcon = 0b11000000;       // '1-------' GIE, enable global ints
    ;                               // '-1------' PEIE, enable peripheral ints
    ;                               // '--0-----' T0IE, TMR0 ints disabled
    ;                               // '----0---' GPIE, IOC disabled
    ;                               // '-----000' T0IF/INTF/GPIF flags
    ;    while(1)                   //
    ;    {                          //
    ;    }                          //
    ;  }
    ;
    Last edited by Mike, K8LH; - 7th February 2010 at 13:53.

  2. #2
    Join Date
    Apr 2006
    Location
    GearSweaterMountain, The Netherlands
    Posts
    52


    Did you find this post helpful? Yes | No

    Default Low frequency PWM

    Hi all,

    Thanks for the helping hand and code. I used your code samples but it just didn't do the trick. My goal was to be able to have 2 low freqency PWM signals with a 90 degree phase shift.

    I finally accomplished this by using a 18F1230 @ 8Mhz , DT-INTS and a few lines of code.

    The code below produces a 30Hz PWM that increments it's dutycycle every interrupt until it reaches 100%, it will then decrement to 1% and start over. It uses a 'base' frequency of 60Hz (PTPER 519), and distributes the dutycycle over the 30Hz periods.

    Code:
    '==== Set fuses
    @ __CONFIG    _CONFIG1H, _OSC_INTIO2_1H & _FCMEN_OFF_1H & _IESO_OFF_1H
    @ __CONFIG    _CONFIG2L, _PWRT_OFF_2L & _BOR_OFF_2L & _BORV_3_2L
    @ __CONFIG    _CONFIG2H, _WDT_OFF_2H & _WDTPS_1_2H
    @ __CONFIG    _CONFIG3L, _HPOL_HIGH_3L & _LPOL_HIGH_3L & _PWMPIN_ON_3L
    @ __CONFIG    _CONFIG3H, _FLTAMX_RA5_3H & _T1OSCMX_HIGH_3H & _MCLRE_OFF_3H
    @ __CONFIG    _CONFIG4L, _STVREN_OFF_4L & _BBSIZ_BB256_4L & _XINST_OFF_4L & _DEBUG_OFF_4L
    @ __CONFIG    _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L
    @ __CONFIG    _CONFIG5H, _CPB_OFF_5H & _CPD_OFF_5H
    @ __CONFIG    _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L
    @ __CONFIG    _CONFIG6H, _WRTB_OFF_6H & _WRTC_OFF_6H & _WRTD_OFF_6H
    @ __CONFIG    _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L
    
    '==== Include DT interrupts
    INCLUDE "DT_INTS-18.bas" ;Base Interrupt System
    INCLUDE "ReEnterPBP-18.bas" ;Include if using PBP interrupts
    
    '==== Dec's for OSC
    OSCCON  = %01110000 'Int OSC @ 8 MHz
    'OSCTUNE = %00000000  'PLL disabled, center freqency
    DEFINE OSC 8 'Int OSC @ 8 MHz, for PBP
    
    '==== Initialize DT_INTS
    ASM
    INT_LIST  macro    ; IntSource,	  Label,   Type,	ResetFlag?
            INT_Handler		PT_INT,	_pwmINT,	PBP,	YES
        endm
        INT_CREATE ;Creates the interrupt processor
    ENDASM                     
    
    '==== Set port associated registers
    ADCON0  = %00000000 'A/D convertor disabled
    ADCON1  = %00001111 'All ports configured digital
    ADCON2  = %10000000 'Right justify results
    CMCON   = %00000000 'Comparator modules disabled
    CVRCON  = %00000000
    
    PTCON0  = %00001100 'Fosc/4 Prescale 1:64, Free running mode
    PWMCON0 = %00110111 'PWM0,1,2,3 enabled, independent mode
    PWMCON1 = %00000001 'Special event on count upwards, Sync PWM timebase 
    
    PORTA   = %00000000
    PORTB   = %00000000
    TRISA   = %01100000
    TRISB   = %00000100
    
    '==== Dec's for pin aliasing INPUT'S
    'none  
    
    '==== Dec's for pin aliasing OUTPUT'S
    'none
    
    '==== Reset PWM duty registers
    PDC0L = 0: PDC0H = 0 'Reset duty register 0
    PDC1L = 0: PDC1H = 0 'Reset duty register 1
    PDC2L = 0: PDC2H = 0 'Reset duty register 2
                                           
    '==== Dec's for variables
    pwmFREQ var word
    pwmDUTY_TGT var word
    pwmDUTY var word
    pwmDIR  var bit
    pwmTOG  var bit
    pwmFL   var bit
    
    
    '==== Initialise variables
    pwmFREQ = 0
    pwmDUTY_TGT = 0
    pwmDUTY = 0
    pwmDIR  = 0
    pwmTOG  = 0
    pwmFL   = 0
    
    
    '==== Wait for hardware settle
    Pause 500 'Settle for 0,5 seconds
    
    '==== Enable PWM interrupts
    @ INT_ENABLE   PT_INT ;Enable PWM to PTPER match interrupts            
    
    '==== SET PWM frequency and dutycycle
    pwmFREQ = 519 'Makes 60,010 Hz, 100% dutycycle = 2076
    pwmDUTY = 1 'Initial dutycycle
    PTPERL = pwmFREQ.lowbyte 'Set PWM frequency lowbyte
    PTPERH = pwmFREQ.highbyte 'Set PWM frequency lowbyte
    'pwmFREQ_CO = 2076 '100% dutycycle
    
    'Find out if desired PWM is below 50% or over.
    'Double the ammount of dutycycle because 
    'the frequency will be half the base frequency .. 
    if pwmDUTY <= 1038 then
    	pwmDUTY_TGT = pwmDUTY * 2
    	pwmDIR = 0
    else
    	pwmDUTY_TGT = (pwmDUTY - 1038) * 2
    	pwmDIR = 1
    endif
    
    PTCON1 	= %10000000 'Start PWM output 
    
    '==== Main program loop
    main_loop:
    @ nop 'Do nothing
    
    goto main_loop
              
    '==== The End
    theend: 'Endless loop
    goto theend 'Endless loop
    
    '==== Routines
    pwmINT:
    PWMCON1.1 = 1
        if pwmDIR = 0 then	
            if pwmTOG = 0 then
                PDC0L = 0 
                PDC0H = 0
                PDC1L = pwmDUTY_TGT.lowbyte 
                PDC1H = pwmDUTY_TGT.highbyte
                pwmTOG = 1
    	   		else     
                PDC0L = pwmDUTY_TGT.lowbyte 
                PDC0H = pwmDUTY_TGT.highbyte
                PDC1L = 0 
                PDC1H = 0
                pwmTOG = 0
    	   		endif
        else
            if pwmTOG = 0 then
                PDC0L = 2076 
                PDC0H = 2076
                PDC1L = pwmDUTY_TGT.lowbyte 
                PDC1H = pwmDUTY_TGT.highbyte
                pwmTOG = 1
    	   		else
                PDC0L = pwmDUTY_TGT.lowbyte 
                PDC0H = pwmDUTY_TGT.highbyte
                PDC1L = 2076 
                PDC1H = 2076
                pwmTOG = 0
    	   		endif
        endif
    
    		if pwmfl = 0 then
        		pwmduty = pwmduty + 1
    		else
        		pwmduty = pwmduty - 1
    		endif
    
    		if pwmduty >= 2076 then pwmfl = 1
    		if pwmduty <= 0 then pwmfl = 0    
    
    		if pwmDUTY < 1038 then
    				pwmDUTY_TGT = pwmDUTY * 2
    				pwmDIR = 0
    		else
    				pwmDUTY_TGT = (pwmDUTY - 1038) * 2
    				pwmDIR = 1
    		endif
    PWMCON1.1 = 0
    @ INT_RETURN
    Problem solved, Thanks guys !
    Best regards, UltiBlade
    Last edited by ultiblade; - 17th February 2010 at 07:14. Reason: Code formatting was off

Similar Threads

  1. Old and beyond help ?
    By DavidFMarks in forum mel PIC BASIC Pro
    Replies: 46
    Last Post: - 11th December 2008, 15:23
  2. confused problem with interrupt in a working program
    By illuminator4 in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 14th November 2008, 17:01
  3. problem with PWM
    By mimmmis in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 12th September 2008, 13:36
  4. Microcontroller with 2 way paging application problem
    By oneohthree in forum mel PIC BASIC Pro
    Replies: 30
    Last Post: - 20th April 2007, 17:27
  5. 4-line LCD Help - using PortA instead of B
    By Tom Gonser in forum mel PIC BASIC Pro
    Replies: 28
    Last Post: - 31st March 2005, 03:14

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts