CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Can I do this conversion without the use of floats....???

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
JAM2014



Joined: 24 Apr 2014
Posts: 138

View user's profile Send private message

Can I do this conversion without the use of floats....???
PostPosted: Fri May 02, 2014 7:06 am     Reply with quote

Hi,

I have an LM34 temperature sensor connected to my ADC input thru a 2X amplifier. I'm converting the analog input to temperature like this:

Code:

TempC[0] = (float)((ReadADCValue(0) * 5)/1023.0)/2;


'ReadADCValue' is a subroutine that returns an INT16 averaged value on the specified analog input.

The code shown is working as expected, but it's chewing up an awful lot of available ROM (in a 16F88 device). The reality is that only need the whole integer value for temp. (ie. '23', or '26'), and don't need the fractional part.

Can I do this purely with integers to save ROM space? I've seen references to 'scaled integers', but so far I haven't been able to make that work Sad My compiler is v4.050.

Thanks,

Jack
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Fri May 02, 2014 7:12 am     Reply with quote

answer -yes-
and is much simpler if you use 1024 instead of 1023 Very Happy

as in

(5*adcvalue)>>11;


i would UPDATE the compiler version
while at it.
JAM2014



Joined: 24 Apr 2014
Posts: 138

View user's profile Send private message

PostPosted: Fri May 02, 2014 9:04 am     Reply with quote

Hi,

Well, that suggestion doesn't work, and more importantly I have no idea what you are trying to accomplish with the bitwise shift. Would you care to elaborate on this technique so that I may hopefully learn something from this exercise?

Jack
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Fri May 02, 2014 9:07 am     Reply with quote

2^11 =2048

/1024/2=/2048

x>>11 =/2048

and btw

1023/1024=.1% error
alan



Joined: 12 Nov 2012
Posts: 357
Location: South Africa

View user's profile Send private message

PostPosted: Fri May 02, 2014 9:33 am     Reply with quote

asmboy,

If I look at the formula again it should probably be 1024/2.
thus 512

JAM2014

>> are divided by 2 for each right shift
thus
(5*adcvalue/1024)/2 are the same as 5*adcvalue/512
or
(5*adcvalue)>>9

2^9 are 512

Regards
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Fri May 02, 2014 9:50 am     Reply with quote

hmm lets see.....
i have to go by what the OP wrote:
as -is .the core math is screwed anyway as a simple integer value
----
scaling up by 100 would be smarter.

an example from the OP
lets go 3/4 scale on a 10 bit adc

(5*768)=3840
3840/1024=3.75="3"
3/2=1.5=1

now *100
38400/1024=37.5=37

37/2=18.5=18

lastly does the following help?

http://www.ccsinfo.com/forum/viewtopic.php?t=50354
Ttelmah



Joined: 11 Mar 2010
Posts: 19366

View user's profile Send private message

PostPosted: Fri May 02, 2014 10:47 am     Reply with quote

The old 'fencepost' argument.

The earliest ADC's, were trying to be linear from their Vref+ to Vref-. On these a 10bit ADC would give 0 to 1023 (1024 steps) and require /1023 (1024 fenceposts 1023 actual 'panels'). However quite early on in the design of ADC's manufacturers started deliberately offsetting the values, so that a binary division could be used TI introduced this about 30 years ago...). The PIC ADC, actually reaches it's full scale, one count 'early', so effectively behaves as if is has 1025 steps, and a 1024 division is the right value to use. However they also offset the conversion step points by half a bit. This results in the result always rounding down by half a bit.
The 'best fit' conversion, is to add one, and then divide by 1024.
JAM2014



Joined: 24 Apr 2014
Posts: 138

View user's profile Send private message

PostPosted: Fri May 02, 2014 1:02 pm     Reply with quote

Hi All,

OK, I understand the concept. It seems like the best strategy then is to start off with the most 'signal' I can get with my analog front end, and then scale the A/D value in my code to obtain temperature result using integer math?

The LM34 output is about 0.7V at room temperature, and I'd like to be able to measure up to about 100+ F, so it seems that the maximum scale factor I could use in hardware is about 4 to stay within the 0 - 5V range of the A/D.

Jack
newguy



Joined: 24 Jun 2004
Posts: 1903

View user's profile Send private message

PostPosted: Fri May 02, 2014 1:23 pm     Reply with quote

There are 2 avenues to explore/exploit when it comes to this type of problem (reading an analog voltage with the greatest precision you can muster over the expected output range of your sensor).

1) Using a gain stage to amplify the sensor's output to occupy the widest possible swing in A/D input. (Which you're doing)
2) Using an external precision voltage reference(s) to your PIC's A/D.

Regarding 2), you could, for instance, forego the amplifier and instead use a 2.048V reference to your A/D converter instead. At an A/D resolution of 10 bits, 1 A/D count would be precisely 2mV into your A/D. Doing something like this makes the math quite a bit easier.

It is also possible to use a different external reference for the A/D's lower voltage bound as well. Consult the PIC's data sheet for more details, but just keep in mind that the A/D on some PICs will not accept some voltages. For example (and this is from memory so it may not be entirely accurate), I believe that the 18F2680, if powered from a 5V rail, cannot accept a Vref+ of less than 3V.
gpsmikey



Joined: 16 Nov 2010
Posts: 588
Location: Kirkland, WA

View user's profile Send private message

PostPosted: Fri May 02, 2014 3:54 pm     Reply with quote

With a slight modification on #2 - some PICs have built in precision (band gap) references that you can use for the A/D. Not all have it, but some of them do 18f26k22 for example has one - from the 18(l)F2x/4xK22 data sheet for the FVR (fixed voltage reference):
Quote:
The Fixed Voltage Reference, or FVR, is a stable
voltage reference, independent of VDD, with 1.024V,
2.048V or 4.096V selectable output levels. The output
of the FVR can be configured to supply a reference
voltage to the following:
• ADC input channel
• ADC positive reference
• Comparator positive input
• Digital-to-Analog Converter (DAC)
The FVR can be enabled by setting the FVREN bit of
the VREFCON0 register.
21.1


I have not checked recently, but in the past the CCS compiler did not understand how to select the FVR correctly for the A/D so you had to set the config register yourself. Hopefully that has been fixed.
_________________
mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Fri May 02, 2014 6:23 pm     Reply with quote

Quote:

2.048V reference to your A/D

true in this instance, BUT

one needs to read the deep specs on each different pic model.
not all pics work with a vref that low.

read min ADC Vref spec in DC section of datasheet to know

if it was the popular 16F887 it would be thus:

AD06A MIN VREF Reference Voltage(3) 2.2 / 2.7
— —
Absolute minimum to ensure 1 LSb

search for AD06 in YOUR Datasheet to find what it is.


in my work, i try not to skate close to the limits .
bad for biz 2 do otherwise Very Happy
JAM2014



Joined: 24 Apr 2014
Posts: 138

View user's profile Send private message

PostPosted: Tue May 27, 2014 1:21 pm     Reply with quote

Hi All,

I've made a few changes to my hardware, and now I'm back at this problem. Unfortunately, I'm now having trouble getting my 'scaled integers' working as I expect.

Code:

int32 TestTemp = 0;
TestTemp = (Int32)(ReadADCValue(0) * 500)/4096;
fprintf(PC, "Sensor 1 Temp: %Lu\n\r", TestTemp;


ReadADCValue(0) = 640, so I expect a TestTemp result of 78. I've tried this with and without the 'Int32' casting.

The 'problem' is the value of (Int32)(ReadADCValue(0) * 500). This value is wrong even before the divide.

Compiler is PCM v4.050.

Jack
complex72



Joined: 10 May 2014
Posts: 11

View user's profile Send private message

PostPosted: Tue May 27, 2014 1:32 pm     Reply with quote

you coluld also use the abs which computes the absolute value of a number.

value = abs(x)

for instance if......
TestTemp=25.63

int16 value = abs(TestTemp)

value will be 25
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue May 27, 2014 1:41 pm     Reply with quote

You're doing 16-bit math, which generates a 16-bit (ie, wrong, truncated)
result. Then you cast it to 32 bits, but you're casting a 16-bit result.

What you want to do, is to make it do 32-bit math. Don't cast the result.
Cast one of the multiplication operands to 32 bits. Then it will work.
JAM2014



Joined: 24 Apr 2014
Posts: 138

View user's profile Send private message

PostPosted: Tue May 27, 2014 1:52 pm     Reply with quote

Hi PCM programmer,

Ugh, I had the 'right' idea to 'cast' at least one of the operands, but I mistakenly put the cast outside the (), rather than inside! It's working as expected now!

For completeness:
Code:

TestTemp = ((Int32)ReadADCValue(0) * 500)/4096;


Jack
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group