Searching \ for '[PIC]:Floating point on PIC16F876' in subject line. () Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/devices.htm?key=16F
Search entire site for: 'Floating point on PIC16F876'.

Exact match. Not showing close matches.
'[PIC]:Floating point on PIC16F876'
2000\11\02@045422 by  I need help on using microchip floating point routines (AN575) for a
F876 target.
Actually I4m using the A/D converter and I want to display the
conversion on a LCD module. Exactly I4m trying to build an autoranging
voltimeter.
The formula I want to obtain is (in milivolts)
mV=((ADRESH*256)+ADRESL)*5000/1024. this formula convert the result of
the A/D conversion (0 to 1023) to 0-5000 mV. The resolution I want is 3
digits: 250mV or 4.458V for readed values, for example.
Thanks.

--
http://www.piclist.com hint: To leave the PICList
piclist-unsubscribe-request mitvma.mit.edu  What about using fixed point multiply 16x16 bit. First argument from AD,
second is 4.8828125 in 8.8 fixed point representation.

Andrej

{Quote hidden}

_________________________________________________________________________
Get Your Private, Free E-mail from MSN Hotmail at http://www.hotmail.com.

Share information about yourself, create your own public profile at
http://profiles.msn.com.

--
http://www.piclist.com hint: To leave the PICList
piclist-unsubscribe-request mitvma.mit.edu  How can I do that?
I4m using the A/D conversion from F876 channel 0, who gives me a value from 0
to 1023.
I4m trying to convert it to volts or milivolts in the fixed format 1.234 and
represent it on 4  7-segments display or on LCD.
The math to do that is, I think: Volts=(((ADRESH*256)+ADRESL)*5/1024); The
problem is that Volts is an integer and the division gives me an integer. I
read the microchip AN575 appnote but I4m lost.
Can you give me an example using fixed point routines, and what I4m expect
for the result?
My intention is to build an autorranging voltimeter.
Thanks.

Andy Jancura escribis:

{Quote hidden}

--
http://www.piclist.com hint: To leave the PICList
piclist-unsubscribe-request mitvma.mit.edu  Hi,
Ramón Pérez wrote:

>I need help on using microchip floating point routines (AN575) for a
>F876 target.
>Actually I4m using the A/D converter and I want to display the
>conversion on a LCD module. Exactly I4m trying to build an autoranging
>voltimeter.
>The formula I want to obtain is (in milivolts)
>mV=((ADRESH*256)+ADRESL)*5000/1024. this formula convert the result of
>the A/D conversion (0 to 1023) to 0-5000 mV. The resolution I want is 3
>digits: 250mV or 4.458V for readed values, for example.

Hmm.. welcome to fixedpoint heaven :) you do not need floating point
for this type of scaling ( as this is 'all' you need ). Floating point
is sutitable when needing to cover a very large *dynamic* range ( i.e.
from 0.00000001 to 10000000 or similar ). For other purposes fixed point
is by far better suited ( not to mention faster ). The use of decimal
point does not dictate the use of floating point math.

Ok a quick run down:
You have a 10 bit A/D value. You need to scale it to accomplish
a more 'human' value.( note:  You understand ofcource that the accuracy
of this will be higly depedant on the reference used i.e. 5 V ) )
If you need to cater for other ( fixed ? ) reference voltages then
I suggest using an general integer 16x16 routine followed by
*two* right shifts of the top resultant top bytes ( the bottom byte can
be ignored )
Something like:

Result_32bit = AD_Value_16bit * RefmV_16bit / 1024

Resultmv = Result_32bit/(4*256) = (Result_32bit/4)/256 =
(Result_32bit>>2)/256

( which is the same as ignoring bottom byte
and shifting right the remaning bytes two steps ).

We can also save some ram/code by concluding that the advalue will only
be inside 10 bits range. And therefore do not need to full 32 bit to
store
the result.

The decimal point ( semi-fixed :) hence the term fixed point math ) will
only come into place at the conversion from binary to ASCII, where it's
placed where ever needed. Of cource the is no requirement that the
decimal
point has a fixed location, one can always change the reference voltage
by an factor ten and then also move the decimal point one step etc.

/Tony

Tony Kübek, Flintab AB
²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²
E-mail: tony.kubek flintab.com
²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²

--
http://www.piclist.com hint: To leave the PICList
piclist-unsubscribe-request mitvma.mit.edu  So you basically need to multiply a 10 bit value by
5000/1023=4.88758553274682 (1023 counts correspond to 5V).

I would recommend one of the following options:

1) Multiply by 5000 and then divide by 1023 using fixed
point routines. (10x13 and 24/10, or any close to that)

2) Use http://www.piclist.com/codegen/constdivmul. For example:

; Temp = TEMP
; ADRES size = 10 bits
; Error = 0.090000%
; Bytes order = little endian
; Round = no

; ALGORITHM:
; Clear accumulator
; Add input * 4 to accumulator
; Add input * 1 to accumulator
; Substract input / 8 from accumulator
; Add input / 128 to accumulator
; Add input / 256 to accumulator
; Move accumulator to result
;
; Error in constant approximation : 0.017734, %

; Input:  ADRES0 .. ADRES1      (10 bits)
; Output: ADRES0 .. ADRES1      (13 bits)

cblock
TEMP0
TEMP1
endc

;copy accumulator to temporary
movwf   TEMP1
movwf   TEMP0

;shift accumulator right 1 times
clrc

;add temporary to accumulator
movf    TEMP1, w
skpnc
incfsz  TEMP1, w

;shift accumulator right 4 times
andlw   0x0F
andlw   0xF0

;substract temporary from accumulator
movf    TEMP0, w
movf    TEMP1, w
skpc
incfsz  TEMP1, w

;shift accumulator right 3 times

;add temporary to accumulator
movf    TEMP0, w
movf    TEMP1, w
skpnc
incfsz  TEMP1, w

;shift temporary left 2 times
clrc
rlf     TEMP0, f
rlf     TEMP1, f
rlf     TEMP0, f
rlf     TEMP1, f

;add temporary to accumulator
movf    TEMP0, w
movf    TEMP1, w
skpnc
incfsz  TEMP1, w

Hopefully this is much easier and quicker than using
floating point stuff.

Nikolai

---- Original Message ----
From: Ramón Pérez Hernández <monperez ULL.ES>
Sent: Wednesday, November 01, 2000 11:41:04
To: PICLIST MITVMA.MIT.EDU
Subj: [PIC]:Floating point on PIC16F876

{Quote hidden}

--
http://www.piclist.com hint: To leave the PICList
piclist-unsubscribe-request mitvma.mit.edu  On Wed, 1 Nov 2000 12:13:23 +0000, you wrote:

>How can I do that?
>I4m using the A/D conversion from F876 channel 0, who gives me a value from 0
>to 1023.
>I4m trying to convert it to volts or milivolts in the fixed format 1.234 and
>represent it on 4  7-segments display or on LCD.
>The math to do that is, I think: Volts=(((ADRESH*256)+ADRESL)*5/1024); The
>problem is that Volts is an integer and the division gives me an integer. I
>read the microchip AN575 appnote but I4m lost.
>Can you give me an example using fixed point routines, and what I4m expect
>for the result?
>My intention is to build an autorranging voltimeter.
>Thanks.
You don't need floating point - it's usually much easier to do
fixed-point - multiply it by an appropriate constant to generate a
whole a number in millivolts,  microvolts or any other decade (e.g. 1
= 10mV), display it as a whole number and stick the DP in the correct
place.

--
http://www.piclist.com hint: To leave the PICList
piclist-unsubscribe-request mitvma.mit.edu  Hi,

I wrote:
>Something like:
>
>Result_32bit = AD_Value_16bit * RefmV_16bit / 1024
>
>Resultmv = Result_32bit/(4*256) = (Result_32bit/4)/256 =
>(Result_32bit>>2)/256
>
>( which is the same as ignoring bottom byte
>and shifting right the remaning bytes two steps ).

Which is a bit 'cryptic' what I meant to write was:

Result_32bit = AD_Value_16bit * RefmV_16bit / 1024
OR
Result_mV_16bit = (AD_Value_16bit * RefmV_16bit)/(4*256) =
RefmV_16bit)>>2)/256

( which is the same as ignoring bottom byte
and shifting right the remaning bytes two steps ).

And to clarify the comment:
>We can also save some ram/code by concluding that the advalue will only
>be inside 10 bits range. And therefore do not need to full 32 bit to
>store the result.

If the range of RefmV is 0-5000 and we know the range of the advalue
is 0-1024 we can conclude that the result will never be larger than
23 bits.

/Tony

Tony Kübek, Flintab AB
²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²
E-mail: tony.kubek flintab.com
²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²

--
http://www.piclist.com hint: To leave the PICList
piclist-unsubscribe-request mitvma.mit.edu  I think your application should go through the following steps:

2) Multiply it by 5000/1023 to scale 0..1023 input value to
0..5000 output value.
3) Convert the scaled value from binary to decimal (to get 4
decimal digits)
4) Output each decimal digit to LCD, and set a point after
the first digit.

Which part of that is a problem?

You need only INTEGER arithmetics to accomplish that.
Multiplication by 5000/1023 is approximately the same as by
5005/1024 (for example, 1023*(5005/1024)=5000.1 - integer
part is 5000, which is correct). To do that, you first
multiply ADRESH:ADRESL value by 5005 using a 16 by 16 bit
multiplication routine (can be found at http://www.piclist.com or
Microchip's AN617). In result you get a 32 bit value. To
divide it by 1024, simply shift it right 10 times. It would
be more efficient to shift it first 8 times right, which is
done by moving the 3 higher bytes by one byte right to the
lower byte position. And then shift these 3 bytes 2 bits
right using right shift instruction. (Or use
http://www.piclist.com/codegen/constdivmul to do the shifts for
you, 1/1024=9.765625e-004).

At this point you get the scaled value in the 2 lower order
bytes. Convert it to decimal using for example John Payson's
routine at http://www.piclist.com in Radix conversion subdivision
of the Code Library. And then send the digits to LCD.

Good luck!
Nikolai

---- Original Message ----
From: Ramón Pérez Hernández <monperez ULL.ES>
Sent: Wednesday, November 01, 2000 14:13:23
To: PICLIST MITVMA.MIT.EDU
Subj: [PIC]:Floating point on PIC16F876

{Quote hidden}

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics  Hi,

Nicolai wrote:

>Multiplication by 5000/1023 is approximately the same as by
>5005/1024 (for example, 1023*(5005/1024)=5000.1 - integer
>part is 5000, which is correct). To do that, you first

Yes you are ofcource correct in that using 5005 and 1024 is
an more accurate way to convert the voltage. As I stated
5000/1024 will give you an linear error ( albait small one )
but that was the formula the poster descibed.

{Quote hidden}

Well thats one way to look at it, the other is to ignore the
bottom byte entirely ( 'pretend' that the result is 3 bytes wide
with msb of the 32 bit result = msb of the 24 bit value )
, and shift the remaning ( i.e. top ) three ( actually the result will
always fit into two ) bytes right two steps.

That would give you the voltage in mV.

If you want to present it as V then you just place the decimal
point three digits from the last.

>At this point you get the scaled value in the 2 lower order
>bytes. Convert it to decimal using for example John Payson's
>routine at http://www.piclist.com in Radix conversion subdivision
>of the Code Library. And then send the digits to LCD.

Yes this is a very good source, however I coded an alternative
for 24 bit result which also has true ascii output, variable
decimal point and supressing of leading zero's. It's also
posted at the same place. Maybe this one suits better.

/Tony

Tony Kübek, Flintab AB
²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²
E-mail: tony.kubek flintab.com
²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics   On Sat, 4 Nov 2000, Nikolai Golovchenko wrote:

> You need only INTEGER arithmetics to accomplish that.
> Multiplication by 5000/1023 is approximately the same as by
> 5005/1024 (for example, 1023*(5005/1024)=5000.1 - integer
> part is 5000, which is correct). To do that, you first

btw, another way to look at it is through the division approximation I post time
to time:

1 / (A + B) = 1/A * (1 - (B/A) + (B/A)^2 ...)

So, if you want to divide by `1023', then

A = 1024
B = -1

1 / 1023 = 1/1024 * (1 + 1/1024 + 1/1024/1024 + ...)

Now, division by 1024 is trivial (just shift the dividend right 10 places). So
now you have two ways to perform the multiplication:

ans = 5000 * x;

ans = (ans + ans>>10 ) >> 10;

OR as Nikolai astutely notes:

5000 * (1 + 1/1024 + 1/1024/1024) = 5004.88 ~ 5005

ans = (5005*x) >> 10

Which way you choose may depend on how you wish to optimize the
multiplication. Again, as others have noted, Nikolai's multiplication code
generator is probably the quickest way to determine which multiplication is more
efficient (5000 or 5005). If you wish to look at it for your self:

5000 = 0x1388
5005 = 0x138d

I tend to look at these a nibble at a time. So the multiplication by 5000 can be
performed:

p =  x*5000:

p = x<<12 + x<<8;
x <<= 1;
p += (x<<8);
x << = 2;
p += (x<<4) + x;

and

p = x*5005:

p = x<<12 + x<<8 + x;
x <<= 1;
p += x<<8 + x;
x <<= 2;
p += x<<8 + x;

5005 is slightly longer. However, the division by 1023 required by 5000 would
most probably make the multiplication by 5005 the quicker of the two.

Scott

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics

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