Truncated match.
PICList
Thread
'3 PWMs'
1998\05\19@123942
by
Justin Lipton
Hi,
I am new to the PIC device family and am looking to program a PIC16C74.
My application requires 3 PWM outputs (all with adjustable duty cycles).
Obviously I will use CCP1 for one PWM output leaving me bothered about
the remaining two.
The other two outputs have frequencies of 30Hz and 70Hz respectively and
need duty cycles (which will not change very often) of 50% or 10%.
Can anyone suggest a neat method for implementing these outputs?
Note that the processor is also required to be an I2C bus master (I found
these routines) and other than monitoring the bus has very little else to
do.
Thanks in advance,
Justin.
~^~^~^~^~^~^~^~^~^~^~^~^~^~
Justin Lipton
Oridion Medical Ltd.
P.O. Box 45025
91450 Jerusalem ISRAEL
Phone 972 2 589 9124
Fax 972 2 582 8868
spam_OUTjustin.liptonTakeThisOuT
oridion.com
~^~^~^~^~^~^~^~^~^~^~^~^~^~
1998\05\19@151030
by
Andrew Warren
|
Justin Lipton <.....PICLISTKILLspam
@spam@MITVMA.MIT.EDU> wrote:
> I am new to the PIC device family and am looking to program a
> PIC16C74.
>
> My application requires 3 PWM outputs (all with adjustable duty
> cycles). Obviously I will use CCP1 for one PWM output leaving me
> bothered about the remaining two.
>
> The other two outputs have frequencies of 30Hz and 70Hz respectively
> and need duty cycles (which will not change very often) of 50% or
> 10%.
>
> Can anyone suggest a neat method for implementing these outputs?
>
> Note that the processor is also required to be an I2C bus master (I
> found these routines) and other than monitoring the bus has very
> little else to do.
Justin:
How precise do those two frequencies have to be? If a 1% error is
ok, you could do something like this:
Setup TMR0 to generate an overflow interrupt in 90 microseconds.
Initialize a register called TIME30 to 37; 37 is the number of
90-microsecond periods in 3330 microseconds (approximately
one-tenth of a 30Hz signal's period).
Initialize a register called TIME70 to 16; 16 is the number of
90-microsecond periods in 1440 microseconds (approximately
one-tenth of a 70Hz signal's period).
Two other registers, called DUTY30 and DUTY70, set the duty
cycle of each waveform. Set them to 1 for a 10% duty cycle, or
to 5 for a 50% duty cycle... Your main program can modify them
as needed during its execution.
Initialize two more registers, called COUNT30 and COUNT70, to 10.
When the TMR0-overflow interrupt occurs:
Reset the TMR0 register to generate another interrupt in 90
microseconds.
Decrement TIME30. If it's at 0, reset it to 37 and:
Decrement COUNT30. If it's less than DUTY30, pull the
30Hz output pin high; otherwise, pull that pin low.
If COUNT30 is at 0, reset it to 10.
Decrement TIME70. If it's at 0, reset it to 16 and:
Decrement COUNT70. If it's less than DUTY70, pull the
70Hz output pin high; otherwise, pull that pin low.
If COUNT30 is at 0, reset it to 10.
This'll produce a 30.03Hz signal on one pin and a 69.44Hz signal on
the other, with the duty cycle of each signal independently
adjustable in 10% steps from 0 to 100%.
A couple of notes:
1. When your main program changes DUTY30 or DUTY70, there may
be a brief glitch on the corresponding output pin.
2. All the numbers above are in decimal.
3. All of this is just off the top of my head, so no
guarantees... But it's pretty simple; I'm confident that
it'll work just fine.
-Andy
=== Andrew Warren - fastfwd
KILLspamix.netcom.com
=== Fast Forward Engineering - Vista, California
=== http://www.geocities.com/SiliconValley/2499 (personal)
=== http://www.netcom.com/~fastfwd (business)
1998\05\19@170801
by
Harold Hallikainen
|
On Tue, 19 May 1998 18:27:00 +0200 Justin Lipton
<.....Justin.liptonKILLspam
.....ORIDION.COM> writes:
>Hi,
>
>I am new to the PIC device family and am looking to program a
>PIC16C74.
>
>My application requires 3 PWM outputs (all with adjustable duty
>cycles).
>Obviously I will use CCP1 for one PWM output leaving me bothered about
>the remaining two.
>
>The other two outputs have frequencies of 30Hz and 70Hz respectively
>and
>need duty cycles (which will not change very often) of 50% or 10%.
>
>Can anyone suggest a neat method for implementing these outputs?
>
I've gotten four 50/60 Hz PWM outputs by letting a timer run and
generating an interrupt on a CCP compare match. The interrupt set (or
clears) the appropriate output bit, then checks to see which channel is
supposed to go on next, loads the CCP with the new value, and returns.
On a timer roll-over, all outputs (other than the 100% duty cycle) are
turned off. You may have to switch on/off to get the duty cycle going
the way you want, but that should give a start...
This is used for light dimming phase control in the Shoebox
dimmer at http://www.dovesystems.com (sorry, no code or schematics posted
there..., just product info).
Harold
_____________________________________________________________________
You don't need to buy Internet access to use free Internet e-mail.
Get completely free e-mail from Juno at http://www.juno.com
Or call Juno at (800) 654-JUNO [654-5866]
1998\05\19@170812
by
Scott Newell
>My application requires 3 PWM outputs (all with adjustable duty cycles).
>Obviously I will use CCP1 for one PWM output leaving me bothered about
>the remaining two.
The 74 has two hardware PWM outputs, right?
>The other two outputs have frequencies of 30Hz and 70Hz respectively and
>need duty cycles (which will not change very often) of 50% or 10%.
>
>Can anyone suggest a neat method for implementing these outputs?
USART? (Send the same character continuously. You may want to use the 9
bit mode, and don't forget about the start bit!)
newell
1998\05\19@211830
by
Scott Dattalo
|
Justin Lipton wrote:
>
> Hi,
>
> I am new to the PIC device family and am looking to program a PIC16C74.
>
> My application requires 3 PWM outputs (all with adjustable duty cycles).
> Obviously I will use CCP1 for one PWM output leaving me bothered about
> the remaining two.
>
> The other two outputs have frequencies of 30Hz and 70Hz respectively and
> need duty cycles (which will not change very often) of 50% or 10%.
>
> Can anyone suggest a neat method for implementing these outputs?
Neat? That's too subjective. But here are a couple of Cool ways of
generating multiple PWM outputs. First, last week when we were talking
about PWM's I alluded to a vertical counter version. Here it is:
;------------------------------------------------------------
;vert_pwm
;
; The purpose of this routine is to generate 4 pulse width
;modulated waveforms using vertical counters. This version
;implements 5-bit counters, but other sized counters can
;easily be created.
; The algorithm consists of 8 vertical roll over counters:
;4 for the rising edge and 4 for the falling edge. Whenever
;a rising edge counter rolls over the corresponding PWM bit
;is driven high and when a falling edge counter rolls over it's
;driven low.
; The four rising edge counters are grouped together in the
;lower nibble while the falling edge counters are in the upper.
;
; The counters work on this little trick (complements to
;John Payson):
; the following two instructions propogate the carry bit in
;the W register to the next counter bit and if there is an
;underflow (the counters are down counters), generates a carry
;out.
;
; XORWF bn,F ;toggle next bit if there's a carry in
; ANDWF bn,W ;Set carry if bit went from 0 to 1
;
;RAM
; b0-b4 counters
; pwm_state - current state of the pwm outputs
; temp - temporary register.
;ROM
; 17 instructions
;
vert_pwm:
COMF b0,W ;unconditionally toggle and get the
MOVWF b0 ;'carry out' if going from 0 -> 1
;
XORWF b1,F ;
ANDWF b1,W ;
;
XORWF b2,F ;
ANDWF b2,W ;
;
XORWF b3,F ;
ANDWF b3,W ;
;
XORWF b4,F ;
ANDWF b4,W ;
;
MOVWF temp ;save the carry out results (only
;those counters that rolled over
;will generate a carry out).
;
ANDLW 00001111b ;get the rising edge counters.
;
IORWF pwm_state,F ;If a rising edge counter rolled over
;then turn that output on.
;
SWAPF temp,W ;Get the falling edge counters
XORLW 0x0f ;and toggle them. A roll over is now
;a 'zero'
;
ANDWF pwm_state,F ;If a falling edge counter rolled
;then turn that output off
MOVWF PWM_PORT
The down side with the vertical counter pwm is its initialization. Try
it.
Here's another method for 8 8-bit pwms (but uses old-fashioned
horizontal counters)
;------------------------------------------------------------
;pwm_multiple
;
; The purpose of this routine is to generate 8 pulse width
;modulated waveforms. The algorithm consists of 9 counters
;that change the state of the pwm bits whenever they roll over.
;One of the counters, rising_edge, will drive the pwm bits
;high when it rolls over. The other 8 counters pwm0-pwm7 will
;drive their corresponding bits low when they roll over.
;
;
;RAM:
; pwm0-pwm7 - pwm counters
; rising_edge - rising edge counter
; pwm_state - current state of the pwm outputs.
;ROM
; 23 instructions
;Execution time
; 23 cycles
pwm_multiple
CLRW ;Build the bit mask for turning
;off the PWM outputs. Assume that
;all of the outputs will be turned
;off.
;
DECFSZ pwm0,F ;If the first counter has not reached 0
IORLW 00000001b ;then we don't want to turn it off.
;
DECFSZ pwm1,F ;Same for the second one
IORLW 00000010b ;
;
DECFSZ pwm2,F ;and so on...
IORLW 00000100b ;
;
DECFSZ pwm3,F ;
IORLW 00001000b ;
;
DECFSZ pwm4,F ;
IORLW 00010000b ;
;
DECFSZ pwm5,F ;
IORLW 00100000b ;
;
DECFSZ pwm6,F ;
IORLW 01000000b ;
;
DECFSZ pwm7,F ;
IORLW 10000000b ;
;
;
ANDWF pwm_state,W ; Clear all of those pwm outputs
;that have reached zero.
;
XORLW 11111111b ;Toggle the current state.
INCFSZ rising_edge,F ;If the rising edge counter has not
XORLW 11111111b ;rolled over then toggle them again.
;Double toggle == no effect. However,
;if the rising edge counter does roll
;over then a single toggle will turn
;the pwm bits on, unless of course the
;pwm counter has just rolled over too.
;
MOVWF pwm_state ;Save the state
MOVWF PWM_PORT ;update the outputs
There's also a "Scenix virtual peripheral" similar to this bit-banging
code. However, the pwm frequencies are not constant (which in most cases
is not a big deal) and the code is slower (which in many cases is).
Now I realize that neither of these directly satisfy your 30Hz and 70Hz
frequency requirements (why do you need those frequencies anyways?).
However, you could set up a timer interrupt routine that interrupts at
210 Hz (or 420, 630, 210*n Hz) and every third time through run the 70Hz
PWM code and every 7th time through run the 30hz code. There was a
single pwm output version of code posted last week.
Scott
1998\05\20@125904
by
Alvaro Deibe Diaz
|
Puede que lo que te envio no te resulte interesante inmediatamente. Pero de
todas formas puede resultarte entretenido, te lo aseguro. Se trata de otra
aplicacion mas de los llamados "contadores verticales". Te aseguro que es
extremadamente inteligente, y tiene muchas ventajas (no he pensado en los
inconvenientes, pero estoy seguro que tambien tendra). Es como lo de los
algoritmos de ordenamiento, son curiosidades interesantes.
Es un poco dificil de seguir, asi que si necesitas que te ponga en
antecedentes, dimelo; (no es que me considere mas listo que tu, sino que ya
he visto otras veces el tema de los contadores verticales).
Chao.
-----Mensaje original-----
De: Scott Dattalo [SMTP:EraseMEsdattalospam_OUT
TakeThisOuTUNIX.SRI.COM]
Enviado el: miercoles 20 de mayo de 1998 3:17
Para: PICLIST
spam_OUTMITVMA.MIT.EDU
Asunto: Re: 3 PWMs
Justin Lipton wrote:
{Quote hidden}>
> Hi,
>
> I am new to the PIC device family and am looking to program a PIC16C74.
>
> My application requires 3 PWM outputs (all with adjustable duty cycles).
> Obviously I will use CCP1 for one PWM output leaving me bothered about
> the remaining two.
>
> The other two outputs have frequencies of 30Hz and 70Hz respectively and
> need duty cycles (which will not change very often) of 50% or 10%.
>
> Can anyone suggest a neat method for implementing these outputs?
Neat? That's too subjective. But here are a couple of Cool ways of
generating multiple PWM outputs. First, last week when we were talking
about PWM's I alluded to a vertical counter version. Here it is:
;------------------------------------------------------------
;vert_pwm
;
; The purpose of this routine is to generate 4 pulse width
;modulated waveforms using vertical counters. This version
;implements 5-bit counters, but other sized counters can
;easily be created.
; The algorithm consists of 8 vertical roll over counters:
;4 for the rising edge and 4 for the falling edge. Whenever
;a rising edge counter rolls over the corresponding PWM bit
;is driven high and when a falling edge counter rolls over it's
;driven low.
; The four rising edge counters are grouped together in the
;lower nibble while the falling edge counters are in the upper.
;
; The counters work on this little trick (complements to
;John Payson):
; the following two instructions propogate the carry bit in
;the W register to the next counter bit and if there is an
;underflow (the counters are down counters), generates a carry
;out.
;
; XORWF bn,F ;toggle next bit if there's a carry in
; ANDWF bn,W ;Set carry if bit went from 0 to 1
;
;RAM
; b0-b4 counters
; pwm_state - current state of the pwm outputs
; temp - temporary register.
;ROM
; 17 instructions
;
vert_pwm:
COMF b0,W ;unconditionally toggle and get the
MOVWF b0 ;'carry out' if going from 0 -> 1
;
XORWF b1,F ;
ANDWF b1,W ;
;
XORWF b2,F ;
ANDWF b2,W ;
;
XORWF b3,F ;
ANDWF b3,W ;
;
XORWF b4,F ;
ANDWF b4,W ;
;
MOVWF temp ;save the carry out results (only
;those counters that rolled over
;will generate a carry out).
;
ANDLW 00001111b ;get the rising edge counters.
;
IORWF pwm_state,F ;If a rising edge counter rolled over
;then turn that output on.
;
SWAPF temp,W ;Get the falling edge counters
XORLW 0x0f ;and toggle them. A roll over is now
;a 'zero'
;
ANDWF pwm_state,F ;If a falling edge counter rolled
;then turn that output off
MOVWF PWM_PORT
The down side with the vertical counter pwm is its initialization. Try
it.
Here's another method for 8 8-bit pwms (but uses old-fashioned
horizontal counters)
;------------------------------------------------------------
;pwm_multiple
;
; The purpose of this routine is to generate 8 pulse width
;modulated waveforms. The algorithm consists of 9 counters
;that change the state of the pwm bits whenever they roll over.
;One of the counters, rising_edge, will drive the pwm bits
;high when it rolls over. The other 8 counters pwm0-pwm7 will
;drive their corresponding bits low when they roll over.
;
;
;RAM:
; pwm0-pwm7 - pwm counters
; rising_edge - rising edge counter
; pwm_state - current state of the pwm outputs.
;ROM
; 23 instructions
;Execution time
; 23 cycles
pwm_multiple
CLRW ;Build the bit mask for turning
;off the PWM outputs. Assume that
;all of the outputs will be turned
;off.
;
DECFSZ pwm0,F ;If the first counter has not reached 0
IORLW 00000001b ;then we don't want to turn it off.
;
DECFSZ pwm1,F ;Same for the second one
IORLW 00000010b ;
;
DECFSZ pwm2,F ;and so on...
IORLW 00000100b ;
;
DECFSZ pwm3,F ;
IORLW 00001000b ;
;
DECFSZ pwm4,F ;
IORLW 00010000b ;
;
DECFSZ pwm5,F ;
IORLW 00100000b ;
;
DECFSZ pwm6,F ;
IORLW 01000000b ;
;
DECFSZ pwm7,F ;
IORLW 10000000b ;
;
;
ANDWF pwm_state,W ; Clear all of those pwm outputs
;that have reached zero.
;
XORLW 11111111b ;Toggle the current state.
INCFSZ rising_edge,F ;If the rising edge counter has not
XORLW 11111111b ;rolled over then toggle them again.
;Double toggle == no effect. However,
;if the rising edge counter does roll
;over then a single toggle will turn
;the pwm bits on, unless of course the
;pwm counter has just rolled over too.
;
MOVWF pwm_state ;Save the state
MOVWF PWM_PORT ;update the outputs
There's also a "Scenix virtual peripheral" similar to this bit-banging
code. However, the pwm frequencies are not constant (which in most cases
is not a big deal) and the code is slower (which in many cases is).
Now I realize that neither of these directly satisfy your 30Hz and 70Hz
frequency requirements (why do you need those frequencies anyways?).
However, you could set up a timer interrupt routine that interrupts at
210 Hz (or 420, 630, 210*n Hz) and every third time through run the 70Hz
PWM code and every 7th time through run the 30hz code. There was a
single pwm output version of code posted last week.
Scott
More... (looser matching)
- Last day of these posts
- In 1998
, 1999 only
- Today
- New search...