Searching \ for '[PIC]: Frequency Scaling - remapping' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/devices.htm?key=pic
Search entire site for: 'Frequency Scaling - remapping'.

Exact match. Not showing close matches.
PICList Thread
'[PIC]: Frequency Scaling - remapping'
2000\06\06@094036 by Peter Betts

picon face
Hello,

I'm Pete and I'm a recent convert to the PIC chip.

I am trying to build a project at home which measures the frequency of a
digital signal, modifies the frequency value and uses this to generate a new
frequency output.

e.g.  1kHz in gets scaled by 2/3 say and frequency output is 666.66Hz

Firstly I wanted to just get the reading of the frequency working (exact
frequency is not important just the relative scaling)
So I set up a timer at a rate of approx 3.9ms which I used to call an
interrupt routine. The interrupt routine then tested/checked the input
signal level (hi or lo) and then incremented a counter. This gave me a
resolution from 1Hz to 256Hz using a 5MHz XTAL. (Just using a single 8 bit
counter)

The counter was used to count the time between successive high pulses (this
was to ensure if I had an input which was not a 50:50 duty cycle I could
still scale it and generate a 50:50 duty cycle output.) The counter value/2
was the hi or lo period respectively.

First: Does anybody have a better way of measuring the period of an
incomming signal in order to generate a scaled frequency output.

Second: My output signal seems to gitter quite a bit and I don't know why.

Third: (and finally) I ideally want to remap the input so I guess I could
use a 256 element look up table and for every frequency input value I can
look up a new output value so I can have my own user defined mapping. Good
or bad?

I have a basic system working but it doesn't look at all elegant so I would
appreciate new ideas.

Thanks

Pete

2000\06\06@100109 by M. Adam Davis

flavicon
face
There are chips (which are less expensive) which do frequency scaling for you.
Is there a special reason why this must be done in PIC (aside from learning
about the PIC, which is a very good reason)?

Assuming you are using a 16f84, there is an input to a counter on it which
allows you to count pulses as well.  You may want to look into this.

The jitter depends on your program.  If you can show us the program we might be
able to point it out.  Otherwise we can give general ideas, but nothing
specific.

Is the ratio input/ouput set, or are you trying to change it while it is
operating?  What is the ratio range (ie, 1:256 - 1:1)?  What is the highest
frequency you are likely to use?

-Adam

Peter Betts wrote:
{Quote hidden}

2000\06\06@102853 by stouchton

flavicon
face
I use the RTCC (TMR) for frequency counter duty.  You can change the
prescale, and shift the main oscillator freq externally under command of the
PIC to give more flexibility.  Multiple counts and averaging gives more
stable results.

You can use the RTCC to determine duty cycle by comparing count and overflow
times once frequency  is narrowed in on.

Lookup table is the quickest way to handle divides.  You can have multiple
tables on multiple top halves of memory pages.


.... or just use an LO and a mixer/bandpass... but that wouldn't be as
fun!!!!!!!!!

{Original Message removed}

2000\06\06@104623 by Peter Betts

picon face
> There are chips (which are less expensive) which do frequency
> scaling for you.

Are there? Do you have any part numbers?


> Is there a special reason why this must be done in PIC (aside
> from learning
> about the PIC, which is a very good reason)?

Mainly to learn from it and to expand the features in the future would be
easier in SW. O.K. I admit.. sounded like a good idea to try a multitude of
elements of PIC design out on.


> Assuming you are using a 16f84, there is an input to a
> counter on it which
> allows you to count pulses as well.  You may want to look into this.

Yes I've used the 12C508, the 16F84 and now starting to use the 16F873
I used the sampling method of data capture, you're suggesting having a known
capture period and counting the number of pulses during that period?


> The jitter depends on your program.  If you can show us the
> program we might be
> able to point it out.  Otherwise we can give general ideas,
> but nothing
> specific.

It's at home so I'll bring it in tomorrow. Thanks.


> Is the ratio input/ouput set, or are you trying to change it
> while it is
> operating?  What is the ratio range (ie, 1:256 - 1:1)?  What
> is the highest
> frequency you are likely to use?

To have a fixed MAP in EEROM or RAM and use this to scale the input.

Range would be max 4:1 to 1:4, so it can increase or decrease.

Thanks

Pete

ps. Hi Scott, hope you are well. Still at Plantronics I see. You must be a
manager by now ;-)

2000\06\06@152326 by pandersn

flavicon
face
Pete....

To measure the frequency of an input signal (be it 50/50 or 60/40 duty
cycle - or whatever), you can do the following: set up the capture and
compare module (mid-range PICs) CCP1, using timer1, to sample the signal on
its rising edge (but not enable the interrupt for the CCP!), and then use
timer 2, to interrupt at a rate a bit faster than the rate of your incoming
signal, then at each interrupt save the count from the capture register (if
its flag is set) and subtract the previous value. That way you'll get a
count at 1/4 the crystal frequency that represents the time period of your
input signal.

Example: set CAP1 to gather timer1 count each rising edge. Let timer1 free
run. Use timer2 set to overflow at a count of say 250 and an interrupt on
overflow. That means you'll be sampling your "captured" signal every 1/4 ms
(250 useconds - assuming a 4 Mhz xtal). A signal of 2000 kHz would have a
count of 500 (plus or minus roughly one by jitter).

You can then map that signal to something else.

Hope that helps.

Phil.

On Tuesday, June 06, 2000 8:40 AM, Peter Betts [SMTP:spam_OUTpeter.bettsTakeThisOuTspamNOKIA.COM]
wrote:
> Hello,
>
> I'm Pete and I'm a recent convert to the PIC chip.
>
> I am trying to build a project at home which measures the frequency of a
> digital signal, modifies the frequency value and uses this to generate a
new
> frequency output.
>
> e.g.  1kHz in gets scaled by 2/3 say and frequency output is 666.66Hz
>
> Firstly I wanted to just get the reading of the frequency working (exact
> frequency is not important just the relative scaling)
> So I set up a timer at a rate of approx 3.9ms which I used to call an
> interrupt routine. The interrupt routine then tested/checked the input
> signal level (hi or lo) and then incremented a counter. This gave me a
> resolution from 1Hz to 256Hz using a 5MHz XTAL. (Just using a single 8
bit
> counter)
>
> The counter was used to count the time between successive high pulses
(this
> was to ensure if I had an input which was not a 50:50 duty cycle I could
> still scale it and generate a 50:50 duty cycle output.) The counter
value/2
> was the hi or lo period respectively.
>
> First: Does anybody have a better way of measuring the period of an
> incomming signal in order to generate a scaled frequency output.
>
> Second: My output signal seems to gitter quite a bit and I don't know
why.
>
> Third: (and finally) I ideally want to remap the input so I guess I could
> use a 256 element look up table and for every frequency input value I can
> look up a new output value so I can have my own user defined mapping.
Good
> or bad?
>
> I have a basic system working but it doesn't look at all elegant so I
would
> appreciate new ideas.
>
> Thanks
>
> Pete

2000\06\07@024001 by Peter Betts

picon face
Phil,

> Example: set CAP1 to gather timer1 count each rising edge.
> Let timer1 free
> run.

Sorry for being dumb but this means at the internal clock rate, no
prescaler. i.e. timer1 increments every 4th clock cycle?  Yes?


> Use timer2 set to overflow at a count of say 250 and an
> interrupt on
> overflow.

Doh! I must have missed that. I didn't know you could set where the overflow
would occur, I've been assuming it was always on 255->256 count! Hows that
done then?


>That means you'll be sampling your "captured"
> signal every 1/4 ms
> (250 useconds - assuming a 4 Mhz xtal). A signal of 2000 kHz
> would have a
> count of 500 (plus or minus roughly one by jitter).

So run a 16bit counter/storage to get so decent resolution.

I've included my PIC code in another reply to this posting so maybe you can
point out some NOVICE mistakes! Can anyone point me to some example code?

Excellent help from the list by the way, expecially the maths stuff in the
archives :-)

Pete

2000\06\07@024600 by Peter Betts

picon face
> If you can show us the program we might be able to point it out.

Here it is (hope is doesn't break the list etiquette)....
It works but it's a bit "wobbly"

;***************************************************************************
***
;                            PIC Hardware?
;***************************************************************************
***
; Use PIC16F84 and set radix system to decimal
       LIST P=16F84, R=DEC

;***************************************************************************
***
; Include header file
;***************************************************************************
***
#include "p16f84.inc"

;***************************************************************************
***
;                        Configuration Settings
;***************************************************************************
***
; Use XTAL clock, watch dog timer off and power up timer on.
       __config _XT_OSC & _WDT_OFF & _PWRTE_ON


;***************************************************************************
***
;                               equates
;***************************************************************************
***
; WORDS
count_in                equ     0x0c    ; Input Counter
count_out               equ     0x0d    ; Output Counter
new_output_counter      equ     0x0e    ; Next Output Counter Threshold
count_status            equ     0x0f    ; Status Condition of Counters
output_state            equ     0x10    ; State of the output pin

;BITS
trigger                 equ     0       ; Bit 0 of count_status
overflow                equ     1       ; Bit 1 of count_status

;GENERAL
frequency_input         equ     1       ; Bit RA1 of PortA

;***************************************************************************
***
;                            START of CODE
;***************************************************************************
***
       org     0x0                     ; reset vector
       goto    init                    ; jump over subroutines

       org     0x4                     ; Timer Interrupt Vector
       goto    timer_int               ; Goto this service routine

;***************************************************************************
***
;                              Subroutines
;***************************************************************************
***
toggle_output
       movlw   0x1
       xorwf   output_state,1          ; XOR output bit with 1 and store
back again
                                       ; This TOGGLES the state of the pin
from high to low.

       movf    new_output_counter,0    ; copy new_output_counter to 'w'
       movwf   count_out               ; Reset output counter
       goto    timer_int_end           ; Finished!

;---------------------------------------------------------------------------
---
no_toggle_output
       movlw   0x0
       movwf   output_state            ; Set output low.

       movlw   0x1                     ; else reload count_out with 1
       movwf   count_out
       goto    timer_int_end           ; Finished!

;---------------------------------------------------------------------------
---
remap_frequency
       nop                             ; Remap the input frequency value to
a new value
                                       ; Could just be a fixed ratio or..
                                       ; Use a look up table to scale it.
                                       ; Only (8bit) 256 counter values so
only 256 mapping points.
       goto    change_output_level

;***************************************************************************
***
;                       Interrupt Service Routine
;***************************************************************************
***
timer_int
       bcf     INTCON,T0IF             ; Clear pending interrupt flag

output_pulse                            ; Set output pin to correct state.
       movf    output_state,0          ; Load output_state into 'w'
       movwf   PORTB                   ; Output that bit

input_pulse                             ; "count_in = count_in + 1"
       incfsz  count_in,1              ; Increment input counter,
       goto    test_input_pin          ; If counter didn't wrap round to
zero, no_overflow

set_overflow                            ; count_in > 256 therefore a slow
input frequency
       bsf     count_status,overflow   ; Set OVERFLOW condition flag
       movlw   0x0
       movwf   new_output_counter

test_input_pin
       btfss   PORTA,frequency_input   ; Test input pin, high or low.
       goto    test_trigger            ; Is low so test if just triggered
from a high to low transition
       bsf     count_status,trigger    ; Input pin is high so set TRIGGER
condition flag and
       goto    change_output_level     ; then set next output pin state

test_trigger                            ; Test if trigger flag was set in
previous int'
       btfss   count_status,trigger    ; i.e. is a falling edge, high to
low.
       goto    change_output_level     ; If not then skip the rest and set
the condition of the next output pin state

       movlw   0x0                     ; Set 'w' to 0 incase overflow
condition is true
test_overflow                           ; Test if input counter overflowed
at any time when low or high
       btfss   count_status,overflow
       movf    count_in,0              ; No overflow so load count_in into
'w'
       movwf   new_output_counter      ; Load 'w' as the new output counter
threshold
       movlw   0x0
       movwf   count_in                ; Reset the input counter
       bcf     count_status,trigger    ; Reset the TRIGGER condition
       bcf     count_status,overflow   ; Reset the OVERFLOW condition, if
there was one!

remapping
       goto    remap_frequency

change_output_level
       decf    count_out,1             ; Decrement output counter,
"count_out = count_out - 1"
       btfss   STATUS,Z                ; Test ZERO flag is set
       goto    timer_int_end           ; count_out > 0

       movlw   0xffff
       andwf   new_output_counter,1
       btfss   STATUS,Z                ; Is new_output_counter = zero
       goto    toggle_output           ; if it isn't toggle_output
       goto    no_toggle_output

timer_int_end                           ; That's it!
       retfie                          ; Return from interrupt service
routine

;***************************************************************************
***
;                            initalisation
;***************************************************************************
***

init    clrf    PORTB                   ; set = 0
       bsf     STATUS,RP0              ; BANK1
       movlw   0ffh                    ; set porta as inputs
       movwf   TRISA
       movlw   00h                     ; set port b as outputs
       movwf   TRISB
       bcf     STATUS,RP0              ; BANK0

       movwf   count_in                ; Clear Input Counter
       movwf   count_out               ; Clear Output Counter
       movwf   new_output_counter      ; Clear Next Output Counter
Threshold
       movwf   count_status            ; Reset Counter Status
       movwf   output_state            ; Clear output pin state

       bsf     STATUS,RP0              ; BANK1
       movlw   0x0
       movwf   TMR0                    ; Reset Timer0
       movlw   b'10000011'             ; Prescaler of 1:16 (i.e. interrupt
every 3.9ms approx)
       movwf   OPTION_REG              ; Set Timer ON and use prescaler of
256
                                       ; (currently tunning from 5MHz XTAL)


;***************************************************************************
***
;                             main program
;***************************************************************************
***

main
       bcf     STATUS,RP0      ; BANK0
       bsf     INTCON,T0IE     ; Turn Timer Interrupts On
       bsf     INTCON,GIE      ; Turn Global Interrupts On

forever goto    forever

       end

2000\06\09@091714 by pandersn

flavicon
face
Right. Say xtal running at 4 Mhz. Then your instruction or "clock" rate
will be 1 Mhz. Timer2 will count once each instruction cycle. Setting a
timer2 at 250 will give you then a 4 kHz rate. Turn off the pre-scalar and
post-scalar, just set 250 in timer2 reg. Enable interrupts for timer2 of
course. Then process your flags at the capture input during each timer2
interrupt - this gives you a constant sampling rate.

You are sampling an event (a flag), so you do NOT have to sample at > twice
the freq content of the input signal (sampling theorem), that is for audio,
not freq measuring!.

Hope that helps. Hey, download (adobe) the Embedded  Micro Book from
Microchip's web site. It does a reasonable job of explaining all of the
peripherals, including the timers.

Phil Anderson....have a good day! Go kick a Tae Kwon Do bag!


On Wednesday, June 07, 2000 1:39 AM, Peter Betts
[SMTP:.....peter.bettsKILLspamspam@spam@NOKIA.COM] wrote:
{Quote hidden}

overflow
> would occur, I've been assuming it was always on 255->256 count! Hows
that
{Quote hidden}

can
> point out some NOVICE mistakes! Can anyone point me to some example code?
>
> Excellent help from the list by the way, expecially the maths stuff in
the
> archives :-)
>
> Pete

More... (looser matching)
- Last day of these posts
- In 2000 , 2001 only
- Today
- New search...