1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

PIC PWM outputs?

Discussion in 'Microcontrollers' started by Andy1845c, Nov 25, 2007.

  1. Andy1845c

    Andy1845c Active Member

    Joined:
    Apr 2, 2006
    Messages:
    1,164
    Likes:
    8
    Location:
    Southern Minnesota
    I have been googling for a while now, and I haven't been able to find what I am looking for.

    What is a PWM output on a PIC? I assume any pic can do PWM, but one with a PWM output makes it easier?

    I am looking for a a program to simply fade one I/O port on and off gently. I want to use it to control christmas lights and as a starting point in learning to use PWM.

    I don't need it to be adjustible after programming (would be fun to add in the future though)

    Is somthing like this somwhat simple, or does it take a fair amount of programming know how to make work? Maybe over my head at the moment?:eek:

    All I have been able to find for the most part are motor contollers and color wash codes. And some are in C or Basic, and I only have a basic beginner knowledge of ASM.

    Anyone have any advice or know where I could find a very basic PWM program to play with?
     
  2. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    It's not too tough to do. Read the datasheet very carefully, as always, when setting something like this up.

    Here's my simple newbie PWM program for a 16F628:
    Code (text):
        processor 16f628
        include "P16F628.inc"
        __config _HS_OSC & _WDT_OFF & _LVP_OFF

        cblock  0x20        ;start of general purpose registers
        d1,d2,d3,count
        endc

        org     0x0000

    init    clrf    count
        movlw   0x07            ;turn comparators off
        movwf   CMCON
        bsf     STATUS,RP0      ;bank 1
        movlw   0x00            ;all pins outputs
        movwf   TRISA
        movwf   TRISB
        movlw   0xff            ;set period
        movwf   PR2
        bcf     STATUS,RP0      ;bank 0

    main    movlw   0x80            ;set duty cycle
        movwf   CCPR1L
        movlw   0x04            ;set timer2 prescale and enable it
        movwf   T2CON
        movlw   0x0c            ;set bottom 2 pwm bits and enable pwm
        movwf   CCP1CON
        call    delay

    mloop   movf    count,w         ;cycles msb 8 bits of pwm from 0 to 255
        movwf   CCPR1L          ;over and over
        call    delay
        incfsz  count
        goto    mloop
    reset   clrf    count
        goto    mloop  

    delay   movlw   0x2d            ;around 0.1 second or a bit less
        movwf   d1
        movlw   0xe7
        movwf   d2
        movlw   0x01
        movwf   d3
    delay_0 decfsz  d1, f
        goto    dd2
        decfsz  d2, f
    dd2 goto    dd3
        decfsz  d3, f
    dd3 goto    delay_0
        return

        end
     
    Last edited: Nov 25, 2007
  3. justDIY

    justDIY Active Member

    Joined:
    Mar 1, 2005
    Messages:
    1,723
    Likes:
    12
    Location:
    Michigan, USA
    futz's example uses the pic's internal CCP module aka hardware pwm. If you have the budget, check out the 16F737 (or 767), they have three independent CCP modules, making it nice for rgb color mixing applications. hardware pwm also offers the benefit of freeing up the CPU and not using any interrupts, so your pic can do other stuff, not having to waste cycles on generating the pulse-train.

    On the other hand, there are many asm examples out there for soft-pwm, where interrupts are used to generate a pulse-train. the advantage to soft-pwm is cheaper chips can be used, and you can get more pwm outputs. an inexpensive 12f683 has only one hard-pwm output, but can do five soft-pwm outputs.
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Andy1845c

    Andy1845c Active Member

    Joined:
    Apr 2, 2006
    Messages:
    1,164
    Likes:
    8
    Location:
    Southern Minnesota

    Thanks for the replys. Right now I don't care how I accomplish the PWM, but its interesting to know there are two ways to go about it.

    Will futz's code fade in and out, or just hold at a fixed duty cycle? I really need to spend some time learning ASM better.
     
  6. futz

    futz Active Member

    Joined:
    Sep 15, 2007
    Messages:
    2,043
    Likes:
    24
    Location:
    Vancouver, B.C.
    It's just an example. You'd have to modify it to suit your purpose. It constantly varies the PWM duty cycle from 0 (off) to 255 (full on), over and over. Tis just a demo, not supposed to be useful.
     
  7. Wingmax

    Wingmax New Member

    Joined:
    Sep 16, 2007
    Messages:
    163
    Likes:
    6
    Location:
    Australia

    If all you want is just to fade one I/O port, you don't need to use PWM. You can simply just use a delay routine. Send the port pin high, delay for certain time and send the port pin low. Just refer to Nigel's tutorial, you'll find the answer you need. But whatever you do don't use Timer0, or you'll upset him badly. :D
     
  8. Andy1845c

    Andy1845c Active Member

    Joined:
    Apr 2, 2006
    Messages:
    1,164
    Likes:
    8
    Location:
    Southern Minnesota
    Should futz's code actually output on a pin? RB3? I can't get it to work and can't get my head around how to PWM with a pic. I have been googling for over 2 hours and have seen all kinds of PWM programs, but most have more to them then just PWM and that confuses me.

    Maybe i'm just jumping too far ahead. Nothing is making any sense:mad:
     
  9. 3v0

    3v0 Coop Build Coordinator Forum Supporter

    Joined:
    Jul 14, 2006
    Messages:
    9,404
    Likes:
    227
    Location:
    OKLAHOMA USA
    I was teaching this in school today :)
    PWM in its most simple (not confusing) form. This is C but the concept is the same in any language.

    Untested off the top of the head sort of code follows....
    Code (text):

     
    int i;
    int percent;
     
    percent = 52;  //  % time on
    while(1)   // loop forever
    {
        for (i=0; i>100; i++)
        {
            if (i < percent)
            {
                  ra0 = 1; // turn bit on
            }
            else
            {
                 ra0 = 0; // turn bit off
            }
            delay_ms(1); //some sort of delay here, determines freq
    }
     
    -------------------- OR --------------------------
     
    while(1) // loop forever
    {
        ra0 = 1; // turn bit on
     
        for (i=0; i>100; i++)
        {
            if (i == percent)
            {
                  ra0 = 0; // turn bit off
            }
            delay_ms(1); // some sort of delay here, determines freq
        }
    }
     
    You can use timers and other hardware to unload the processor but the above works.
     
    Last edited: Nov 27, 2007
  10. Gayan Soyza

    Gayan Soyza Active Member

    Joined:
    Oct 23, 2006
    Messages:
    1,821
    Likes:
    19
    Location:
    Colombo
  11. Andy1845c

    Andy1845c Active Member

    Joined:
    Apr 2, 2006
    Messages:
    1,164
    Likes:
    8
    Location:
    Southern Minnesota
    I tried this one, and couldn't get the led to do anything:confused: I think i need to back up and learn some basics before I attemp PWM.
     
  12. blueroomelectronics

    blueroomelectronics Well-Known Member

    Joined:
    Jan 21, 2007
    Messages:
    12,536
    Likes:
    168
    Location:
    Toronto, Canada
    Check out the toy car project, it uses PWM to drive a toy cars motor. On the projects section of my site.
    [​IMG]
     
  13. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    Andy, what PIC device are you using Sir?
     
  14. Andy1845c

    Andy1845c Active Member

    Joined:
    Apr 2, 2006
    Messages:
    1,164
    Likes:
    8
    Location:
    Southern Minnesota
    I'm using the 16F628A. So futz's and Gayan's code should work. I'm not sure what I am doing wrong. I haven't tried Bill's code yet. I don't know if I have a 16F88 around or not.

    I think i'm just trying to run before I can walk.
     
  15. Mike - K8LH

    Mike - K8LH Well-Known Member

    Joined:
    Jan 22, 2005
    Messages:
    3,637
    Likes:
    109
    Location:
    Michigan, USA
    Ok. Are you using the 4 MHz internal oscillator? Do you have the LED connected to the RB3/CCP1 pin? If not, what pin(s)?
     
  16. Andy1845c

    Andy1845c Active Member

    Joined:
    Apr 2, 2006
    Messages:
    1,164
    Likes:
    8
    Location:
    Southern Minnesota
    I am using _HS_OSC. Would that be correct?

    I have the LED on RB3. I have tried both ways, but RB3 should be sourcing power, right?
     
  17. bananasiong

    bananasiong New Member

    Joined:
    Mar 7, 2006
    Messages:
    1,893
    Likes:
    7
    Location:
    Malaysia
    Can you post up your program? futz's program should work. Or you can first try the fixed duty cycle.
     
  18. Andy1845c

    Andy1845c Active Member

    Joined:
    Apr 2, 2006
    Messages:
    1,164
    Likes:
    8
    Location:
    Southern Minnesota
    Well, its pretty much exactly whats in the link Gayan posted

    Code (text):
    ;=======pwm.ASM=================================15/11/06==
    ;     standard crystal 4.0MHz XT
    ;------------------------------------------------------------
    ;     configure programmer
     LIST P=16F628;f=inhx8m
     #include "P16F628.INC"  ; Include header file
     __CONFIG _PWRTE_ON  & _WDT_OFF & _HS_OSC & _BODEN_ON & _LVP_OFF & _CP_OFF & _MCLRE_OFF

    ; [URL="http://sandiding.tripod.com/Bertys.html"]http://sandiding.tripod.com/Bertys.html[/URL]
    ;------------------------------------------------------------
     cblock 0x20 ; Beginn General Purpose-Register
    ;-------------------------- counters
     count1
     count2
     count3
    ;--------------------------
     endc
    ;--------------------------
    #DEFINE pwmu PORTB,3
    ;--- Reset --------------------------------------------------
     org h'00'
     goto init  ; reset -> init
    ;--- Interrupt ----------------------------------------------
     org h'04'
    ;--------------------------
    init clrf PORTA
     clrf PORTB
     movlw 0x07  ; Turn comparators off and enable pins for I/O
     movwf CMCON
     bcf STATUS,RP1
     call usi ; setari porturi
     call pause
     movlw 0xFF
     movwf PORTB
     call pause
     call set_timer
    ;-------------------------- asteapta puls de 1ms
    uu
     call pause
     movlw 0x02
     movwf CCPR1L
     call pause
     movlw 0x10
     movwf CCPR1L
     call pause
     movlw 0x40
     movwf CCPR1L
     call pause
     movlw 0x80
     movwf CCPR1L
     call pause
     movlw 0xFF
     movwf CCPR1L
     call pause
     movlw 0x80
     movwf CCPR1L
     call pause
     movlw 0x40
     movwf CCPR1L
     call pause
     movlw 0x10
     movwf CCPR1L
     goto uu
    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    set_timer
     clrf T2CON
     clrf TMR2
     clrf INTCON
     bsf STATUS,RP0
     clrf PIE1
     bcf STATUS,RP0
     clrf PIR1
     bsf STATUS,RP0
     movlw 0xFF
     movwf PR2 ; compare with 255
     bcf STATUS,RP0
     movlw 0x02
     movwf CCPR1L
     movlw 0x03
     movwf T2CON ; prescaler 1:16 and postscaler 1:1
     movlw 0x3C
     movwf CCP1CON
     bsf T2CON,TMR2ON
     return
    ;************************************************************************
    ;       Subrutine de intarziere                                         *
    ;************************************************************************
    pause movlw 0x02 ;
     movwf count3
    d3 movlw 0x3F
     movwf count1
    d1 movlw 0xFA  
     movwf count2
    d2 decfsz count2,F
     goto d2  
     decfsz count1,F
     goto d1  
     decfsz count3,F    
     goto d3          
     retlw 0x00
    ;============================================================
    usi bsf STATUS,RP0 ; Bank 1
     movlw 0xFF ; all input
     movwf TRISA
     movlw 0x00
     movwf TRISB ; all output
     bcf STATUS,RP0 ; Bank 0
     return
    ;============================================================
     end
     
    I just copied and pasted futz's as well. I assume both should output in RB3 and only RB3, correct?
     
  19. jeremygaughan

    jeremygaughan New Member

    Joined:
    Sep 26, 2007
    Messages:
    129
    Likes:
    1
    Location:
    Hot Springs, AR
    I'm not sure how much of a difference this makes but your header says 16f628 and you said that you are using a 16f628a. I'll post an alternative code in a little while.
     
  20. eng1

    eng1 New Member

    Joined:
    Apr 7, 2006
    Messages:
    951
    Likes:
    19
    Location:
    Italy
    Correct.

    If you're using a PIC16F628A you have to make little changes: the list directive and the include file. I've played with futz's code and it's ok. I've chosen the internal oscillator. The original program requires a high speed crystal.
     
  21. justDIY

    justDIY Active Member

    Joined:
    Mar 1, 2005
    Messages:
    1,723
    Likes:
    12
    Location:
    Michigan, USA
    with pwm, it will alternately sink and source, so it doesn't matter on polarity, aside from your duty cycle will going one way or the other
     

Share This Page