Searching \ for 'Info on Fixed Point Math [+freq. metering]' 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/method/math.htm?key=math
Search entire site for: 'Info on Fixed Point Math [+freq. metering]'.

Truncated match.
PICList Thread
'Info on Fixed Point Math [+freq. metering]'
1996\09\22@225723 by Steve Hardy

flavicon
face
> From: "Richard A. Smith" <spam_OUTras2TakeThisOuTspamTANT.COM>
>
> Non-PIC-topic:
>
> I am looking for some references on doing fixed point math (16.16 or
> possibly 32.16 and maybe even 32.32 ) with an 8-bit MC.  I have to
> implement Newtons divided difference polynomial interpolation, 2nd order
> for an optical sensor I am working on.
>[cut]

D.E.Knuth 'The Art of Computer Programming' Vol 2 Chapter 4 will point
you in the right direction, for sure.

{Quote hidden}

'Cheapness' would imply an '84 or a '5X.  Probably the '84 is the choice
these days because of the EEPROM, and also it supports interrupts.

'Interrupt driven' implies an '84 or 'XX part.  However, the very minimum
number of cycles swallowed by your interrupt routine is about 12 cycles
(saving and restoring W and status without doing anything else) so,
depending on the method chosen, this may well limit your accuracy.

Assuming a clock speed of 10MHz, your basic time quantum is 400ns (or
possibly 100ns if using certain CCP functions of the 'XX part).

Looking at your spec, one can do some arithmetic to determine how accurately
one can measure period or, equivalently, frequency.

If you sample for a fixed time of 100ms then you sample f/10 cycles.  If
the total time for f/10 cycles is quantised to units of T (seconds) then
the uncertainty in period is 10T/f and uncertainty in frequency is
10Tf/(1+10T).

Using a 10MHz 16C84 as an example (because I am a minimalist), without
interrupts for simplicity, a 16-bit counter would be used to count
cycles and the 8-bit TMR0 would be used to gate the sampling interval.
Using the prescaler and TMR0 makes a maximum gate period of
400ns*256*256 = 26.2144ms.  This comes a bit short of 100ms, but let's
see how it goes.  Shorter gating times reduce accuracy.

The following code keeps track of the gate period by looking for on-off
transitions of the TMR0 clock MSB.  It also counts on-off transitions of the
signal to be measured; at each of these transitions it also records the
timestamp relative to the first transition.  The timestamp is maintained in
a 16-bit counter.

Note that this code is off the top of my head (and probably won't assemble
let alone run).  It has the advantage (?) of constant percentage error
which is not obtained with a simple frequency/period counter.  However,
this assumes that you do the 16-bit fixed point divisions optimally.  That
task is 'left as an exercise for the reader'.

       cblock
; registers
       cych            ; high word of cycle count
       cycl            ; low word of CC
       timeh           ; current time high
       timel           ; current time low
       stmph           ; high time stamp of last transition
       stmpl           ; low ditto
       flags           ; Flags (see below)
       endc
#define INPUT   porta,0 ; test input bit

F_CLKHI equ     0       ; Bit set when TMR0 MSB goes high
F_INBIT equ     1       ; Previous state of input

; On return, cyc and stmp contain number of cycles (c) and total time (t) for
; those cycles measured.  Frequency is computed by
; f = xt/c  where x is a scale factor.  The division should be performed
; using fixed-point arithmetic.  It turns out that the unit of time is
; 10.4us, given the following code.

measure equ     $
; Init counters etc to zero
       clrf    cych
       clrf    cycl
       clrf    timeh
       clrf    timel
       clrf    flags
; Wait for 1st 1->0 transition of input
       btfss   INPUT
       goto    $-1
       btfsc   INPUT
       goto    $-1
; Reset timer (chich also clears invisible prescaler)
       clrf    tmr0
; main loop.  Inside loop, check for 1->0 transition of TMR0 and exit
; if found.  Then check for 1->0 transition of input.  If found, increment
; cycle count and transfer timestamp.  Finally increment the timestamp.
; Everything must be isochronous i.e. exactly same number of cycles must
; happen in the loop no matter which branch is taken.  Hence the time-
; wasting instructions.  Instructions after ';==' are isochronous points.
; This loop is amenable to optimisation (I can see how to save 2 cycles
; but can't be bothered re-doing my arithmetic!)
;==
loop    btfss   flags,F_CLKHI   ; Clock MSB set previously?
       goto    cont1           ; No, skip next
       btfss   tmr0,7          ; Check current MSB
       return                  ; Exit loop since MSB now 0
       goto    cont2
cont1   btfsc   tmr0,7          ; Clock MSB gone high?
       bsf     flags,F_CLKHI   ; Yes, set flag indicating this.
       nop                     ; Total 6 instruction cycles
;==
cont2   btfss   INPUT           ; Check input
       goto    cont3           ; Currently 0 (go see if changed)
       bsf     flags,F_INBIT   ; Currently 1, reflect in flags
       goto    cont4
cont3   btfss   flags,F_INBIT   ; Previous bit 1?
       goto    cont5           ; No, no change
       bcf     flags,F_INBIT   ; Reflect new state in flags
       incfsz  cycl            ; Increment 16-bit cycle counter (low)
       goto    $+2             ; Skip next if no carry
       incf    cych            ; Inc high
       movf    timel,w         ; Move time stamp hi and low
       movwf   stmpl
       movf    timeh,w
       movwf   stmph
       goto    cont6           ; Total 15 instr. cyc.
cont4   nop
cont5   nop
       goto    $+1             ; Waste time (10 instr max)
       goto    $+1
       goto    $+1
       goto    $+1
;==
cont6   incfsz  timel           ; Increment timer
       goto    $+2
       incf    timeh           ; Total 3 instr. cyc.
;==
       goto    loop
; Total loop time is 6 + 15 + 3 + 2 = 26 intructions.  This is 26*400ns =
; 10.4us (quantisation error).  The maximum frequency which
; could be measured (assuming 50% duty) is 1/(2*10.4us) = 48KHz.
; The frequency measurement error is then (10.4/26214.4)*100% = 0.04%.
; For 20KHz this is a 8Hz error, but for 1KHz is 0.4Hz error.


Note that this code requires interrupts to be disabled.  Since the conversion
time is only 26ms (instead of the nominated 100ms) perhaps the 'other tasks'
mentioned could be slotted into the remaining time???

Of course, the CCP modules in the 16CXX series could be used to advantage
since there is also a 16-bit timer etc.  This would enhance accuracy.


Regards,
SJH

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