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:

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
waiting2
goto	waiting2
movwf	pulseb

movlw	0x0d
waiting
goto	waiting
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
goto	$+1 goto$+1
goto	$+1 goto$+1
goto	$+1 goto$+1
goto	$+1 goto$+1
goto	$+1 goto$+1
goto	$+1 goto$+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
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:

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.

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.

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

• 11.9 KB Views: 256

Nigel Goodwin

Super Moderator
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.