Searching \ for '[PIC] converting C to F' in subject line. ()
Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/languages.htm?key=c
Search entire site for: 'converting C to F'.

Exact match. Not showing close matches.
'[PIC] converting C to F'
2010\05\13@083909 by

Processor is a 18F23K20

I've never had the requirement to do much math with a PIC, other than simple divide by 2 or 4 (shifts), add and subtract

So looking for a little help in implementing this

temp_F = (temp_C * 9 / 5) + 32;

The temp_C * 9 can be done with the MULLW instruction.  Just not to sure about the divide by 5 part?

Multiply by 10, then shift 1 left?

--------------------------------------------------
From: "alan smith" <micro_eng2yahoo.com>
Sent: Thursday, May 13, 2010 14:39
To: "Microcontroller discussion list - Public." <piclistmit.edu>
Subject: [PIC] converting C to F

{Quote hidden}

pls ignore previous post. Stupid.......

--------------------------------------------------
From: "Minto Witteveen" <Minto.Witteveengmail.com>
Sent: Thursday, May 13, 2010 14:51
To: "Microcontroller discussion list - Public." <piclistmit.edu>
Subject: Re: [PIC] converting C to F

{Quote hidden}

Em 13/5/2010 09:39, alan smith escreveu:
> Processor is a 18F23K20
>
> I've never had the requirement to do much math with a PIC, other than simple divide by 2 or 4 (shifts), add and subtract
>
> So looking for a little help in implementing this
>
> temp_F = (temp_C * 9 / 5) + 32;
>
> The temp_C * 9 can be done with the MULLW instruction.  Just not to sure about the divide by 5 part?
>

Use a fixed-point approach: Multiply by 65536 / 5 (which is approx.
13107) and then divide the result by 65536 (shift right 16 places).

You could speed things up by multiplying by ( 32768 * 9 / 5 == approx.
58982 ), then divide by 32768 (shift right 15 places). This method would
need just one operation.
Even the shift right by 15 may be simplified to a shift left by 1.

Of course you need to deal with 32-bit intermediate values.

Regards,

Isaac

__________________________________________________
Fale com seus amigos  de graça com o novo Yahoo! Messenger
http://br.messenger.yahoo.com/
For fixed values like this, I generally divide in one of two ways...

- Subtract 5 continuously in a loop, until the remainder is less than
5.  (Then process the remainder as required).

- Convert 1/5 (=0.2) into a value that is <integer>/256 (or even
<integer>/65536, or other depending on precision required).  Then
multiply by that integer and shift to divide by 256 etc.  To find that
integer, I generally would keep multiplying 1/5 by 2, and look for as
whole a number as possible.  For 1/5, multiplying by 256 is close to
whole at 51.2.  51/256 = 0.1992, which is 0.4% error from 0.2.  If
that's acceptable, then the code just needs to multiply by 51, then
drop the right-most byte.  You can even check the MSB of the
right-most byte and increment the next byte if required to round the
result.

FWIW, there are some divide routines in the PIClist source-code library.

BTW, I've done C to F before, and I did the math for 9/5 at once.  I
used 717/512 = 1.40039 which is 0.03% error.

Cheers,
-Neil.

Quoting alan smith <micro_eng2yahoo.com>:

{Quote hidden}

> -
Em 13/5/2010 09:51, Minto Witteveen escreveu:
> Multiply by 10, then shift 1 left?
>

Did you mean "shift 1 right" ?
__________________________________________________
Fale com seus amigos  de graça com o novo Yahoo! Messenger
http://br.messenger.yahoo.com/
alan smith wrote:
> So looking for a little help in implementing this
>
> temp_F = (temp_C * 9 / 5) + 32

Step back and ask yourself whether you really really need the temperature
representation in the PIC to be specifically in F or C.  Unless the result
will be displayed to a user directly by the PIC, the answer is most likely
"no".  Pick whatever representation has the resolution and range you need,
and is otherwise convenient inside the PIC.

I've done a lot of PIC applications that have to measure something as part
of their operation, and its very very rare these need to be converted to any
standard units.

********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.
>> So looking for a little help in implementing this
>>
>> temp_F = (temp_C * 9 / 5) + 32;
>>

How many possible input values (in deg C) do you have ?

I'm thinking "lookup-table" here... :-)

Jan-Erik.

Em 13/5/2010 10:06, Isaac Marino Bavaresco escreveu:
> Em 13/5/2010 09:51, Minto Witteveen escreveu:
>
>> Multiply by 10, then shift 1 left?
>>
>>
>
> Did you mean "shift 1 right" ?
>

Ah! Got bite by this one :) Only noticed he was multiplying twice,
missed that he was *multiplying* by 5, not dividing by 5.

__________________________________________________
Fale com seus amigos  de graça com o novo Yahoo! Messenger
http://br.messenger.yahoo.com/
Em 13/5/2010 10:02, Isaac Marino Bavaresco escreveu:
{Quote hidden}

If your input range is small and you can accept a little loss of
precision, you could use 256 and 128 instead of 65536 and 32768, then
shift right by 8 or by 7. This way you would need to deal at most with
16-bit numbers.

Regards,

Isaac

__________________________________________________
Fale com seus amigos  de graça com o novo Yahoo! Messenger
http://br.messenger.yahoo.com/
Its being displayed on an LCD, so yes.  User selects to display in C or F.
Otherwise I would agree with you...the other applications where Ive had to read a temperature, it was just comparing to setpoints to turn on or off outputs and there its typically a 10 bit value from the A/D to deal with.

--- On Thu, 5/13/10, Olin Lathrop <olin_piclistembedinc.com> wrote:

{Quote hidden}

> -
Thanks Neil...thats what I was looking for.

--- On Thu, 5/13/10, PICdude <picdude3narwani.org> wrote:

{Quote hidden}

> > --
Em 13/5/2010 10:09, Olin Lathrop escreveu:
> alan smith wrote:
>
>> So looking for a little help in implementing this
>>
>> temp_F = (temp_C * 9 / 5) + 32
>>
> Step back and ask yourself whether you really really need the temperature
> representation in the PIC to be specifically in F or C.  Unless the result
> will be displayed to a user directly by the PIC, the answer is most likely
> "no".  Pick whatever representation has the resolution and range you need,
> and is otherwise convenient inside the PIC.
>
> I've done a lot of PIC applications that have to measure something as part
> of their operation, and its very very rare these need to be converted to any
> standard units.
>

I also like this approach. Once I designed a battery charger for a very
specific product (all parameters fixed, no display, just an LED).
Internally I only dealt with ADC units, not even one conversion needed.

Isaac

__________________________________________________
Fale com seus amigos  de graça com o novo Yahoo! Messenger
http://br.messenger.yahoo.com/

alan smith wrote:

{Quote hidden}

9/5 is 1.8 so

(temp_C  * 1.8) + 32

(temp_C  * 0.8) + temp_C + 32

Using the PIC 18's mullw which is a 16 = 8 * 8 muliplier

0.8 = 204.8 / 256   (No magic it is 0.8 * 256)

0.8 ~ 205 / 256

temp_C * 205 result in PRODH is result / 256

so conversion to temp_F

(temp_C * 205)

PRODH + temp_C + 32

One mult two adds  accurate to 2 parts in 460 less than half persent

Regards

w..
--
Walter Banks
Byte Craft Limited
http://www.bytecraft.com

On Thu, May 13, 2010 at 1:39 PM, alan smith <micro_eng2yahoo.com> wrote:
> The temp_C * 9 can be done with the MULLW instruction.  Just not to sure about the divide by 5 part?

It's not actually that difficult to do a proper binary divide if you
want to. Consists of a loop with a couple of (multi-byte) left shift
operations, and a comparison/subtraction. Code for 8 bit:

MOVLW 8
MOVWF count
CLR working
CLR result
:loop
RLF orig
RLF working
MOVLW 5
SUBWF working, w
BTFSC STATUS, C
MOVWF working
RLF result
DECFSZ count
GOTO loop

PICdude wrote:

{Quote hidden}

Because the PIC18 has only a 16bit = 8bit by 8 bit multiply
change the 1.8 to a ((0.8 * 256 ) + an add) and the whole
conversion becomes a mult and two adds in 8 bits good to
256F in 8 bit calculations.

Walter..

> Processor is a 18F23K20
>
> I've never had the requirement to do much math with a PIC, other than simple divide by 2 or 4 (shifts), add and subtract
>
> So looking for a little help in implementing this
>
> temp_F = (temp_C * 9 / 5) + 32;
>
> The temp_C * 9 can be done with the MULLW instruction.  Just not to sure about the divide by 5 part?

If you don't need decimals:

temp_F = temp_C + 32      Tf=Tc*1.8+32. This line does Tf=Tc*1+32
temp_F = temp_F + HIBYTE(temp_C * 205); Add Tc*0.8 (205/256 is ~0.8)

This works only for temp_C=<0:255> for negative temp_c you could shift
temp_C to positive with adding 100 and after the conversion subtracting
180 from the result. This will give a temp_C range <-100:155>

Djula

On Thu, May 13, 2010 at 9:05 AM, PICdude <picdude3narwani.org> wrote:

> BTW, I've done C to F before, and I did the math for 9/5 at once.  I
> used 717/512 = 1.40039 which is 0.03% error.

Hmmm... 9/5 = 1.8
717/512 = 1.40039

That doesn't seem like a 0.03% error.  Am I missing something here?

Personally, I'd use 461 / 256 = 1.80078  (0.0434% error).

Bill

--
Psst...  Hey, you... Buddy...  Want a kitten?  straycatblues.petfinder.org

At 08:39 AM 13/05/2010, you wrote:
>Processor is a 18F23K20
>
>I've never had the requirement to do much math with a PIC, other
>than simple divide by 2 or 4 (shifts), add and subtract
>
>So looking for a little help in implementing this
>
>temp_F = (temp_C * 9 / 5) + 32;
>
>The temp_C * 9 can be done with the MULLW instruction.  Just not to
>sure about the divide by 5 part?

In assembly, I use fixed-point 32-bit math. I multiply by 0.9 which
is 0x7333 3333 (the way I do it), and the rest is just shifts and adds
(arithmetic shift left by 1 to get * 1.8 and add the '32').

That's for accurate instrumentation and controls-- for a single byte
value, a LUT might be easiest, as others have suggested.

Best regards,

Spehro Pefhany --"it's the network..."            "The Journey is the reward"
speffinterlog.com             Info for manufacturers: http://www.trexon.com
Embedded software/hardware/analog  Info for designers:  http://www.speff.com

>> BTW, I've done C to F before, and I did the math for 9/5 at once.  I
>> used 717/512 = 1.40039 which is 0.03% error.
>
> Hmmm... 9/5 = 1.8
>             717/512 = 1.40039
>
> That doesn't seem like a 0.03% error.  Am I missing something here?
>
> Personally, I'd use 461 / 256 = 1.80078  (0.0434% error).

The same thing but only 8 bits:

1 + 205/256 = 1.80078

What is important with this "division to multiplication" approximations
is that a small negative error is worse than a larger positive error.

i.e. 1.799999 can cause some result to be 123.99998 which is 123 for the
PIC - 1.803 would be much better. You can add rounding up but that
quickly gets complicated.

Djula

2010\05\13@110803 by

> -----Original Message-----
> From: piclist-bouncesmit.edu [piclist-bouncesmit.edu] On
Behalf
{Quote hidden}

sure
> about the divide by 5 part?

What range of input values do you need to cover?  By adding an offset
you can use a close approximation for your fractional calculation and

temp_F = ( ( (temp_C * 205) + 112 ) >> 8 ) + 32 + temp_C

This gives results accurate to within +-0.4 Fahrenheit over the range
-50 to +200 degrees Celsius

Mike

=======================================================================
This e-mail is intended for the person it is addressed to only. The
information contained in it may be confidential and/or protected by
law. If you are not the intended recipient of this message, you must
not make any use of this information, or copy or show it to any
received this e-mail, and return the original to us. Any use,
forwarding, printing or copying of this message is strictly prohibited.
No part of this message can be considered a request for goods or
services.
=======================================================================

Wow, fail on my part!  1.4 was for something else that I did recently.
I'm looking at the C-to-F code now, and I did indeed use 461/256.

BTW, for similar apps, where the sample/refresh rate is not critical,
and I'm averaging many samples, I've just added 'n' samples where 'n'
would happen to multiply the result so that the resulting math is some
power of two.

Cheers,
-Neil.

Quoting William Couture <bcouturegmail.com>:

{Quote hidden}

>

On 2010-05-13, at 5:39 AM, alan smith wrote:

> Processor is a 18F23K20
>
> I've never had the requirement to do much math with a PIC, other than simple divide by 2 or 4 (shifts), add and subtract
>
> So looking for a little help in implementing this
>
> temp_F = (temp_C * 9 / 5) + 32;
>
> The temp_C * 9 can be done with the MULLW instruction.  Just not to sure about the divide by 5 part?

In this case one can multiple by 9/5, 1.8. However, 1.8 does not fit exactly into a small number of bits in a fixed point binary number scheme. But with a limited number range, a small error could be tolerated to make the number scheme easier. For instance, multiple by 2 across a small range might work with an adjustment to the constant 32.

Since this is to be displayed to a user and not for internal calculation, where any units of you choice can and should be used (ADC counts will do), one can fudge it in all sorts of ways as the display is rendered. Without knowing the temperature range for display or the format of temp_c or the require display precision it is hard to make a suggestion.
On Thu, May 13, 2010 at 6:05 AM, PICdude <picdude3narwani.org> wrote:

>
> - Subtract 5 continuously in a loop, until the remainder is less than
> 5.  (Then process the remainder as required).
>

An astute observation here, since division is defined as repeated
subtraction.

And if all the application does is display temperature to a user, it
probably spends most of its time doing nothing.  So division done this way
would have no visible effect on the application.  Of course, if you say, "on
a battery", then that's different :)
When I first saw this thread header I thought it was a C language to
Fortran translator request.
-Josh
On Fri, May 14, 2010 at 4:46 PM, Barry Gershenfeld <gbarry42gmail.com> wrote:
> On Thu, May 13, 2010 at 6:05 AM, PICdude <picdude3narwani.org> wrote:
>
>>
>> - Subtract 5 continuously in a loop, until the remainder is less than
>> 5.  (Then process the remainder as required).
>>
>
> An astute observation here, since division is defined as repeated
> subtraction.
>
> And if all the application does is display temperature to a user, it
> probably spends most of its time doing nothing.  So division done this way
> would have no visible effect on the application.  Of course, if you say, "on
> a battery", then that's different :)

Repeated subtraction can be several times faster than software
long-division if the dividend is known to be small.  This observation
saved several milliseconds of wake time in a battery-powered
application I'm working on.

Regards,
Mark
markrages@gmail
--
Mark Rages, Engineer
Midwest Telecine LLC
markragesmidwesttelecine.com
Barry Gershenfeld wrote:
> An astute observation here, since division is defined as repeated
> subtraction.
>
> And if all the application does is display temperature to a user, it
> probably spends most of its time doing nothing.  So division done
> this way would have no visible effect on the application.  Of course,
> if you say, "on a battery", then that's different :)

This extensive discussion about how to convert from degC to degF is perhaps
interesting to some, but everyone seems to be answering the details asked
about instead of the real solution, which is not to be in this situation in
the first place.

The OP has said the PIC is directly displaying temperature to a user, so he
does have to convert whatever the internal measurement value is to standard
units for display.  But converting between display units makes no sense,
especially from integer C to integer F since the former has less resolution.
There will be quite a few degF values that will never be displayed.  Nearly
half the time the F value will jump by 2 even when the temperature is
changing slowly.  For example 20C --> 68F, 21C --> 70F.

The real question is how to convert from the internal representation to
either C or F depending on the user units switch.  The answer depends on how
the temperature is measured or communicated to the PIC in the first place.
Once you've converted to integer degC, a lot of information has already been
lost.

For example, if temperature is measured with a linear temperature to voltage
sensor, then the internal representation is probably the 10 bit A/D reading.
This needs to be converted to either degC or degF, but not both and not
between the two.  In this case I'd use a wide integer multiply routine so
that the desired result comes out with a whole number of bits below the
binary point.  The choice of F or C is just using a different multiplication
constant.

********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.
Quoting Olin Lathrop <olin_piclistembedinc.com>:

Yeah, some of us have a habit of doing that -- answering what was

{Quote hidden}

Not necessarily -- we don't know if there's some other source of the
original deg-C data.  Perhaps the data is coming from a digital
sensor.  Perhaps the OP has the deg-C data available at a higher than
1-deg-C resolution.  Perhaps he's even tapping off a 7-segment display
(and yes, I've done that in the past).

Cheers,
-Neil.

PICdude wrote:
> Yeah, some of us have a habit of doing that -- answering what was

Which is often not the best solution to the real problem.

> Not necessarily -- we don't know if there's some other source of the
> original deg-C data.

Exactly, we don't know.  This needs to be determined before useful answers
can be given.

> Perhaps the OP has the deg-C data available at a higher than
> 1-deg-C resolution.

Then most of the answers that assume degC is a integer value in a single
byte are wrong.  See what I mean?

> When I first saw this thread header I thought it was a
> C language to Fortran translator request.

Or C# to F#.
On Sat, May 15, 2010 at 4:15 PM, Marechiare <marechiaregmail.com> wrote:
>
> Or C# to F#.

Capo?
>> Or C# to F#.
>
>
> Capo?

VS 2010

Olin Lathrop wrote:
>
> Then most of the answers that assume degC is a integer value in a single
> byte are wrong.  See what I mean?

Actually the techniques remain the same independent of
the raw format be it in some recognized engineering units
or some internal format.

Many of the posts reviewed the approach to use and
some of the solutions (including mine) dealt with
the issues of minimizing the converting code size
and execution time. Almost all of them converted
the 9/5 conversion factor into fixed point.

Regards,

w..
--
Walter Banks
Byte Craft Limited
http://www.bytecraft.com
On Sat, May 15, 2010 at 4:15 PM, Marechiare <marechiaregmail.com> wrote:

> >
> > Or C# to F#.
>
> Capo?
>

Auto-Tune?
>> >
>> > Or C# to F#.
>>
>> Capo?
>>
>
> Auto-Tune?

C# and F# are two Microsoft .NET languages

-- Bob Ammerman
RAm Systems

----- Original Message -----
To: "Microcontroller discussion list - Public." <piclistmit.edu>
Sent: Thursday, May 20, 2010 12:49 AM
Subject: Re: [PIC] converting C to F

>>> >
>>> > Or C# to F#.
>>>
>>> Capo?
>>>
>>
>> Auto-Tune?
>
> C# and F# are two Microsoft .NET languages

I still like the Capo idea though..
Or just stick to C instead, far easier key to deal with :-)

>>>> > Or C# to F#.
>>>>
>>>> Capo?
>>>>
>>>
>>> Auto-Tune?
>>
>> C# and F# are two Microsoft .NET languages
>
> I still like the Capo idea though..
> Or just stick to C instead, far easier key to deal with :-)

Don't stick with that under [PIC] tag, the admin hat member will force
you back to PICs quickly :-)

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