• 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.

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

Status
Not open for further replies.

Triode

Active Member
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
 

DirtyLude

Well-Known Member
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.
 

Triode

Active Member
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.
 

Leftyretro

New Member
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.
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
 

dougy83

Well-Known Member
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:
#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:

Triode

Active Member
So I suggest you do a little research on the differences between PWM and PPM before you start coding
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.
 

dougy83

Well-Known Member
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).
 

Triode

Active Member
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:

Sceadwian

Banned
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.
 

Triode

Active Member
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.
 

jeremygaughan

New Member
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:
;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:
;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
 

Triode

Active Member
Heres a part I'm confused about, on the 16F916 for example, the datasheet says

• Up to 2 Capture, Compare, PWM modules:
- 16-bit Capture, max. resolution 12.5 ns
- 16-bit Compare, max. resolution 200 ns
- 10-bit PWM, max. frequency 20 kHz
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:

Sceadwian

Banned
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.
 

dougy83

Well-Known Member
There's no requirement of PPM to have a fixed duty cycle.
Then it would be called DPPM (differential pulse position modulation), which encodes symbols using the period between pulses.
 

Sceadwian

Banned
But the signal itself is encoded in the pulse width as well, suffice to say it's a hybrid method of modulation.
 

dougy83

Well-Known Member
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.
 

Sceadwian

Banned
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.
 

dougy83

Well-Known Member
And how long is this 'idle' period? Possibly 0.5ms?
 

Attachments

Nigel Goodwin

Super Moderator
Most Helpful Member
And how long is this 'idle' period? Possibly 0.5ms?
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.
 

dougy83

Well-Known Member
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.
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:
Status
Not open for further replies.

Latest threads

EE World Online Articles

Loading
Top