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

PWM controlls, best chip for several at once? AVR or PIC

Discussion in 'Microcontrollers' started by Triode, May 3, 2009.

  1. Triode

    Triode Member

    Joined:
    Feb 11, 2009
    Messages:
    925
    Likes:
    22
    Location:
    Bay Area
    I'm working on an idea for a remote controlled device that could be simplified greatly if i can get a chip that can measure the pulse width of 3 and produce 3 pwm signals simultaniously, better yet measure 3 and output 6, I'm newer at this so if that's ridiculous forgive my ignorance.

    (Sceadwian, your input could help here!) I'm considering AVRs as well as PICs because until now power was less of a concern than readily available help.

    So if anyone can suggest a good way to do this, or a good chip to do this, even if it requires several micro controllers or other chips/components that can make the task more manageable, tell me your ideas.

    Right now on hand I have:
    PIC16F917 (5)
    PIC16F877A (3)
    PIC16F88 (3)
    PIC16F690(3)
    PIC12F629(1) obviously wont do much here but I might as well mention it
     
  2. DirtyLude

    DirtyLude Well-Known Member

    Joined:
    Aug 5, 2003
    Messages:
    1,904
    Likes:
    56
    Location:
    Toronto, Canada
    You haven't given us enough information to give a reasonable suggestion. With just the general outline you've given, just about any microcontroller could do all of the above.

    How much resolution do you need for both reading and generating the PWM? If it's super high resolution, you might have a problem, otherwise PWM is not an intensive task.
     
  3. Triode

    Triode Member

    Joined:
    Feb 11, 2009
    Messages:
    925
    Likes:
    22
    Location:
    Bay Area
    The plan is to take PWM signals from an existing radio control receiver, and use the microcontroller to interpret that and control a variety of other tasks.

    for starters I would like to use it to take 2 pwm signals, which I think are only about 40Hz but I could be wrong, and control a pair of variable speed H bridges, which would, I think, require a total of 4 pwm outputs, 2 each, to allow forward and reverse at varying speed. I'm not sure what frequency would be best for that, but I don't think its very high.
     
  4. dave

    Dave New Member

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


     
  5. Leftyretro

    Leftyretro New Member

    Joined:
    Mar 11, 2007
    Messages:
    1,420
    Likes:
    13
    Location:
    Hercules, California

    Although similar, PWM signals are not the same as PPM signals used in R/C radio control equipment. While a PIC or AVR can deal with both kinds of signals very well, it is different when get down to coding your solution. So I suggest you do a little research on the differences between PWM and PPM before you start coding.

    Lefty
     
  6. dougy83

    dougy83 Well-Known Member

    Joined:
    May 18, 2008
    Messages:
    2,672
    Likes:
    215
    Location:
    Brisbane, Australia
    You can either use a hardware capture module (part of the uC timer devices) of software routine to get the servo pulse widths. The PWM should probably be done with the hardware modules as the frequency will be higher than the servo signal and require more uC effort if done in software.

    I've attached sample code for the servo pulse capture of 2 channels.
    Code (text):
    #include <pic.h>

    #define NUM_SERVO_CHANNELS 2

    // these variables store the servo pulse duration, and
    // signal when the value has changed
    uint16_t servoTime[NUM_SERVO_CHANNELS];
    uint8_t servoTimeUpdated[NUM_SERVO_CHANNELS];   // could use bit variables, if desired

    void interrupt myIsr()
    {
        static uint16_t oldPortVal = 0, oldTimer[NUM_SERVO_CHANNELS];
        uint16_t timer;
        uint8_t portVal, risingEdge, fallingEdge;

        if(RBIE && RBIF)
        {
            portVal = PORTB;
            risingEdge = (portVal ^ oldPortVal) & portVal;
            fallingEdge = (portVal ^ oldPortVal) & oldPortVal;
            oldPortVal = portVal;

            timer = TIMER1;     // get 16-bit timebase

            // check which pins changed
            if(risingEdge & (1 << SERVO_BIT0))
            {
                oldTimer[0] = timer;
            }
            else if(fallingEdge & (1 << SERVO_BIT0))
            {
                servoTime[0] = timer - oldTimer[0];
                servoTimeUpdated[0] = true;
            }

            if(risingEdge & (1 << SERVO_BIT1))
            {
                oldTimer[1] = timer;
            }
            else if(fallingEdge & (1 << SERVO_BIT1))
            {
                servoTime[1] = timer - oldTimer[1];
                servoTimeUpdated[1] = true;
            }
        }
    }
     
    Just make sure that the 16-bit timer is not used for one of the PWM outputs.
    Also, the 16-bit timer overflow period (i.e. 65536 counts) must be < servo pulse width or the captured value in the above code will be invalid.

    Alternately, an atmega48/88/168 (et al.) could be used; these have up to 6 PWM outputs (or 4 if you're using a timer for capture).
     
    Last edited: May 4, 2009
  7. Triode

    Triode Member

    Joined:
    Feb 11, 2009
    Messages:
    925
    Likes:
    22
    Location:
    Bay Area
    Thanks, sometimes you have to learn more before you know what questions to ask. I'd read a few tutorials on using pwm to controll servos, but this haden't been mentioned, or I missed it.

    dougy83, wow, thanks, I didn't actually expect example code. I'll work on this all more when I'm home.
     
  8. dougy83

    dougy83 Well-Known Member

    Joined:
    May 18, 2008
    Messages:
    2,672
    Likes:
    215
    Location:
    Brisbane, Australia
    I think you'll find that the RC servos use a type of PWM; not PPM.

    In PPM, the position of each pulse within its timeslot changes, but the pulse width may remain the same. In PWM, the width of the pulse changes (which is what happens to control the servo). Note: there is a misleading image on the PPM wikipedia page.

    All you need to do when 'decoding' the servo signal is measure the time that the pulse remains high. I think it's generally between 1-2ms (although I have heard of servos working outside this range).
     
    • Like Like x 1
  9. Triode

    Triode Member

    Joined:
    Feb 11, 2009
    Messages:
    925
    Likes:
    22
    Location:
    Bay Area
    1 to 2 with 1.5 being center is what all the tutorials I read say, though it is often noted that some servos vary from this.
     
    Last edited: May 4, 2009
  10. Sceadwian

    Sceadwian Banned

    Joined:
    Oct 27, 2006
    Messages:
    14,047
    Likes:
    141
    Location:
    Rochester, US
    There's no requirement of PPM to have a fixed duty cycle. RC signals are in fact PPM. The SERVO signals are PWM though. An RC frame starts with a sync pulse (never figured out it's width although I think it's longer or shorter than the max/min servo pulse) followed by each of the PWM signals for each servo in series (again never figured out the delay between pulses) The docoder blindly looks for the requirements of this sync pulse and then simply feeds each rising and following edge into the next output port. Servo's themselves can work on quiet an extended range of PWM frequency and duty cycles however the same can not be said of the RC signal as a whole as at some point either too much or too far the decoder is going to interpret the servo signal as a sync pulse and reset.
     
    • Like Like x 1
  11. Triode

    Triode Member

    Joined:
    Feb 11, 2009
    Messages:
    925
    Likes:
    22
    Location:
    Bay Area
    I'm not sure if there is any confusion about this, but for now I'm not working with the radio signal directly, though I would like to build my own radio controll reciever some time. I am just working with the signal that a premade hobby RC set puts out from the reciver at the plugs where you would connect the servos. It seems like the quickest way to me to make a good RC robot that isnt limited to servo motion and premade motor controllers.
     
  12. jeremygaughan

    jeremygaughan New Member

    Joined:
    Sep 26, 2007
    Messages:
    129
    Likes:
    1
    Location:
    Hot Springs, AR
    I think this is going to be easy for you to do. If you are using futaba stuff the signals are 1ms or a little less to get more range to the left, 1.5ms is dead center, and 2.0ms is right but you can make it a little longer and make the servo really go for it.
    The cool thing is the servo signals don't have to happen perfectly. The servo needs an input every once in a while and doesn't care if those times are consistent, so you can run the part of your program that reads the receiver then send your signals when you have time. They generally want a signal every 20 ms but anywhere from 10 to 30 is fine. Don't do it any faster it will freak out the servo making it jerky. Also slower will make it sleep in between inputs causing it to be jerky.
    If you want to look I wrote a program to control two servos and another to run multiple PWM's. They are here.
    I hope they can give you some ideas.

    Moving servo's using the ADC. But using the value sent by the receiver would be even easier. Just count it store it in a folder and use it later where pulse and pulseb are.

    Code (text):
    ;move a servo with ADC on a 12f675


        list P=12f675
    #include <p12f675.inc>
        __config _INTRC_OSC_NOCLKOUT & _BODEN_OFF & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _CPD_OFF & _CP_OFF
        ERRORLEVEL -302
       
        cblock      20h
        servotime, servotime2, pulse, pulse2, pulseb, timer1, timer2, timer3
        endc
       
        bsf STATUS,RP0      ;bank 1
        movlw   0x38
        movwf   ANSEL
        movlw   0x1c
        movwf   TRISIO      ;set I/O
        bcf STATUS,RP0
       
        movlw   0x07        ;turn off comparitors
        movwf   CMCON


    start
        movlw   0x09
        movwf   ADCON0
        bsf ADCON0,1
    waiting2
        btfsc   ADCON0,1
        goto    waiting2
        movf    ADRESH,0
        movwf   pulseb

        movlw   0x0d
        movwf   ADCON0
        bsf ADCON0,1
    waiting
        btfsc   ADCON0,1
        goto    waiting
        movf    ADRESH,0
        movwf   pulse
        movlw   0xfa
        movwf   pulse2
    servo
        bsf GPIO,5
        decfsz  pulse2,1                      ;turn first on and wait for 1ms
        goto    servo
    servo2
        nop
        nop
        nop
        nop
        nop
        decfsz  pulse,1                        ;count down to make value
        goto    servo2                         ;between 1 and 2 ms
        bcf GPIO,5

        movlw   0xfa
        movwf   pulse2
    servob
        bsf GPIO,1              ;turn second on and wait for 1ms
        decfsz  pulse2,1
        goto    servob
    servo3
        nop
        nop
        nop
        nop
        nop
        decfsz  pulseb,1             ;leave on for between 1-3ms
        goto    servo3
        bcf GPIO,1

        call    pause
        goto    start

    pause
        movlw   0xff                  ;wait for the rest of the 18k to pass
        movwf   timer2
        movlw   0x12   
        movwf   timer1
        decfsz  timer1,1
        goto    $-1
        decfsz  timer2,1
        goto    $-5
        return
        end
    Like the header says learning to do PWM with TMRO

    Code (text):
    ;learning to do pwm with tmro 12f675

        list P=12f675
    #include <p12f675.inc>
        __config _INTRC_OSC_NOCLKOUT & _BODEN_OFF & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _CPD_OFF & _CP_OFF
        ERRORLEVEL -302
       
        cblock      20h
        pwmcounter, channel1, channel2, period
        endc

        ORG     0000h
        goto    setup
       
        ORG     0004h
        call    pwm
        BCF INTCON,2
        RETFIE              ;reset interrupt
       
    setup
        bsf STATUS,RP0  ;bank 1
        movlw   0x3c
        movwf   ANSEL
        movlw   0x3c
        movwf   TRISIO      ;set I/O
        movlw   0xd8       
        movwf   OPTION_REG  ;set tmr0
        bcf STATUS,RP0
        movlw   0x07        ;turn off comparitors
        movwf   CMCON
        movlw   0xa0
        movwf   INTCON      ;set interrupt

    start
        movlw   0x09
        movwf   ADCON0
        goto    $+1
        goto    $+1
        goto    $+1
        goto    $+1
        goto    $+1
        goto    $+1
        goto    $+1
        goto    $+1
        goto    $+1
        goto    $+1
        goto    $+1
        goto    $+1

        bsf ADCON0,1
        btfsc   ADCON0,1
        goto  $-1
            movf    ADRESH,0
        movwf   channel1

        movlw   0x0d
        movwf   ADCON0
        goto    $+1
        goto    $+1
        goto    $+1
        goto    $+1
        goto    $+1
        goto    $+1
        goto    $+1
        goto    $+1
        goto    $+1
        goto    $+1
        goto    $+1
        goto    $+1
        bsf ADCON0,1
        btfsc   ADCON0,1
        goto    $-1
        movf    ADRESH,0
        movwf   channel2
        goto    start

    pwm
        incf    period,1
        btfss   STATUS,Z
        goto    $+2
        clrf    period
        movf    channel1,0
        addwf   period,0
        btfss   STATUS,C
        goto    $+3
        bsf GPIO,0
        goto    $+2
        bcf GPIO,0
        movf    channel2,0
        addwf   period,0
        btfss   STATUS,C
        goto    $+3
        bsf GPIO,1
        return
        bcf GPIO,1
        return
                       
        end
     
    • Like Like x 1
  13. Triode

    Triode Member

    Joined:
    Feb 11, 2009
    Messages:
    925
    Likes:
    22
    Location:
    Bay Area
    Heres a part I'm confused about, on the 16F916 for example, the datasheet says

    Doesnt this mean that It can only capture or produce two PWM signals at once, or is that not a limitation here? Also I only see CCP1 and CCP2 on the pin diagram, I don't know, but aren't those the only pins that can use those functions? It seems like this would limit my ability to capture two signals while simulatanously putting out 4.

    I'll probably be able to ask some better questions once I've been home and played around with this more. For now I didn't know where to start so I haven't even positioned a servo yet.

    edit: oops. hadent seen the helpfull post above, that explains a lot. I'll try and get a bit further before I bring you guys more questions, thanks for the help so far!
     
    Last edited: May 4, 2009
  14. Sceadwian

    Sceadwian Banned

    Joined:
    Oct 27, 2006
    Messages:
    14,047
    Likes:
    141
    Location:
    Rochester, US
    Unless you have a PCM transmitter and reciever you can 'or' the servo signals into the single capture module, the pulses never occur at the same time, but you would have to use the first channel as a trigger to reset the internal ICP flow. Again this is very much like the PPM signal is naturally transmitted, if you can tap that in the receiver you can decode it directly without all the wires.
     
  15. dougy83

    dougy83 Well-Known Member

    Joined:
    May 18, 2008
    Messages:
    2,672
    Likes:
    215
    Location:
    Brisbane, Australia
    Then it would be called DPPM (differential pulse position modulation), which encodes symbols using the period between pulses.
     
  16. Sceadwian

    Sceadwian Banned

    Joined:
    Oct 27, 2006
    Messages:
    14,047
    Likes:
    141
    Location:
    Rochester, US
    But the signal itself is encoded in the pulse width as well, suffice to say it's a hybrid method of modulation.
     
  17. dougy83

    dougy83 Well-Known Member

    Joined:
    May 18, 2008
    Messages:
    2,672
    Likes:
    215
    Location:
    Brisbane, Australia
    I don't believe it's hybrid modulation. There is a 0.5ms pulse, followed by a variable idle time, hence DPPM. Try inverting the 'PPM' signal if you can't see it.
     
  18. Sceadwian

    Sceadwian Banned

    Joined:
    Oct 27, 2006
    Messages:
    14,047
    Likes:
    141
    Location:
    Rochester, US
    The actual signal they receive is NOT a fixed .5ms pulse. It's an analog .5 to 2ms pulse followed by an idle period preceded by a frame fresh. The servo's themselves only see their own pulses because that's that what decoder does, it hides the sync pulse and sends each additional pulse that is not a sync pulse to the next available servo line. 4 channel receivers will still accept 5+ channel signals, they'll just eat everything after 4.
     
  19. dougy83

    dougy83 Well-Known Member

    Joined:
    May 18, 2008
    Messages:
    2,672
    Likes:
    215
    Location:
    Brisbane, Australia
    And how long is this 'idle' period? Possibly 0.5ms?
     

    Attached Files:

    • rc.gif
      rc.gif
      File size:
      11.9 KB
      Views:
      246
  20. Nigel Goodwin

    Nigel Goodwin Super Moderator Most Helpful Member

    Joined:
    Nov 17, 2003
    Messages:
    39,229
    Likes:
    641
    Location:
    Derbyshire, UK
    Pretty pointless knowing, as you don't ever see it.

    Your mistake appears to be that you are looking at the signal sent out of the transmitter, and not the servo pulses supplied from the receiver.

    All the servo signals are, is just a single variable width pulse, 1-2mS long, repeated every 20mS or so. That's it, nothing else.

    Personally I consider it misleading that people keep calling it PWM, it makes people think it's what the PWM module is designed for (and it's not) - however, I suppose it is a limited type of PWM.
     
  21. dougy83

    dougy83 Well-Known Member

    Joined:
    May 18, 2008
    Messages:
    2,672
    Likes:
    215
    Location:
    Brisbane, Australia
    No, your mistake. I was talking about the so-called 'PPM' signal used to modulate the RF signal.

    For a constant frame rate, the signal going to the servo is PWM.
     
    Last edited: May 5, 2009

Share This Page