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

Use anolog input for voltmeter do I need array?

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







Use anolog input for voltmeter do I need array?
PostPosted: Sun Aug 04, 2002 10:04 pm     Reply with quote

I just got the example file ex_admm.c to work
through hyper terminal it displays
min 0c max ff
as the pot is turned the values change.
I would like to modify its output to be a digital
output may be 0.0 through 5.0
is this what a array is for?
I Imagined some thing like:
rangelow (min value= 00 hex=0.0 float )
rangehigh(max value=ff hex=5.0float
___________________________
This message was ported from CCS's old forum
Original Post ID: 6084
R.J.Hamlett
Guest







Re: Use anolog input for voltmeter do I need array?
PostPosted: Mon Aug 05, 2002 2:37 am     Reply with quote

:=I just got the example file ex_admm.c to work
:=through hyper terminal it displays
:=min 0c max ff
:=as the pot is turned the values change.
:=I would like to modify its output to be a digital
:=output may be 0.0 through 5.0
:=is this what a array is for?
:=I Imagined some thing like:
:=rangelow (min value= 00 hex=0.0 float )
:=rangehigh(max value=ff hex=5.0float

No, you don't need an array, though for certain applications an array of values can be used (this is called a 'look up table'). A look up table for all 256 possible values, using float numbers (which is implied by the existence of the decimal point), would need 1KB of memory, and is not efficient at all (a look up table is only useful really, where the 'curve' from the A/D, is mathematically complex, and hence difficult to solve in the processor). What you need is a simple bit of arithmetic. The incoming values are integers from 0 to 255. You appear to be using the 'hexadecimal' format to display these, and hence are getting 0 to FF. You can get the values 0 to 5, by simply dividing by 51.0 (255/5=51). So if the incoming number is in a integer called 'val', something like:

float result;

result=(float)val/51.0; /* you must have decimal point in the constant here to force floating point arithmetic - I am using a 'belt and braces' approach, and also 'casting' the incoming value to a float, since the CCS compiler is sometimes a little 'odd' in it's behaviour with mixed types... */
printf("\%2.1f",result);
/* This will then give you the 'floating point' display you want, but is relatively inefficient - floating point maths is slow, and printf has a lot more work to do to deal with such numbers... */

An alternative approach (better in my opinion), is instead to work the other way round. Your incoming number is 0 to 255. You want 0 to 5, but with (presumably), a couple of decimal places. If you take the incoming value and store it in a long integer, then generate val*197, you will have an integer, that ranges from 0 to 50000 as the input changes (actually 50235 with 197, or 49980 with 196). This is vastly faster to generate than the floating point maths version. Now if you sprintf this into a string, in a fixed digit format. This can then have a decimal point added where you want, and be put to the display. This is both quicker, and smaller to code than an look up table, or the floating point version, but requires more source code (where the floating point version is a 'one liner').

Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 6087
markus
Guest







Re: Use anolog input for voltmeter do I need array?
PostPosted: Tue Aug 06, 2002 4:01 pm     Reply with quote

:=:=I just got the example file ex_admm.c to work
:=:=through hyper terminal it displays
:=:=min 0c max ff
:=:=as the pot is turned the values change.
:=:=I would like to modify its output to be a digital
:=:=output may be 0.0 through 5.0
:=:=is this what a array is for?
:=:=I Imagined some thing like:
:=:=rangelow (min value= 00 hex=0.0 float )
:=:=rangehigh(max value=ff hex=5.0float
:=
:=No, you don't need an array, though for certain applications an array of values can be used (this is called a 'look up table'). A look up table for all 256 possible values, using float numbers (which is implied by the existence of the decimal point), would need 1KB of memory, and is not efficient at all (a look up table is only useful really, where the 'curve' from the A/D, is mathematically complex, and hence difficult to solve in the processor). What you need is a simple bit of arithmetic. The incoming values are integers from 0 to 255. You appear to be using the 'hexadecimal' format to display these, and hence are getting 0 to FF. You can get the values 0 to 5, by simply dividing by 51.0 (255/5=51). So if the incoming number is in a integer called 'val', something like:
:=
:= float result;
:=
:= result=(float)val/51.0; /* you must have decimal point in the constant here to force floating point arithmetic - I am using a 'belt and braces' approach, and also 'casting' the incoming value to a float, since the CCS compiler is sometimes a little 'odd' in it's behaviour with mixed types... */
:= printf("\%2.1f",result);
:= /* This will then give you the 'floating point' display you want, but is relatively inefficient - floating point maths is slow, and printf has a lot more work to do to deal with such numbers... */
:=
:=An alternative approach (better in my opinion), is instead to work the other way round. Your incoming number is 0 to 255. You want 0 to 5, but with (presumably), a couple of decimal places. If you take the incoming value and store it in a long integer, then generate val*197, you will have an integer, that ranges from 0 to 50000 as the input changes (actually 50235 with 197, or 49980 with 196). This is vastly faster to generate than the floating point maths version. Now if you sprintf this into a string, in a fixed digit format. This can then have a decimal point added where you want, and be put to the display. This is both quicker, and smaller to code than an look up table, or the floating point version, but requires more source code (where the floating point version is a 'one liner').
:=
:=Best Wishes

Here's what we came up with it work's great

#if defined(__PCM__)
#include <16f877.h>
#include <float.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NOWRT,NOBROWNOUT
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) // Jumpers: 8 to 11, 7 to 12


main() {
float big,small;

int i,value,min,max;
printf("\n\rSampling:\r\n");

setup_port_a( ALL_ANALOG );
setup_adc( ADC_CLOCK_INTERNAL );
set_adc_channel( 0 );

do {
min=255;
max=0;
for(i=0;i<=30;++i) { // run 30 passes (take 30 readings from A to D ?{
delay_ms(40);
value = Read_ADC();
if(value min=value;
if(value>max) // FIND Max value
max=value;
big=max; //Convert max to big (floating point)
small=min; //Convert min to small (floating point)
}
printf("\rMin: \%4.2f Max: \%4.2f \r\n",small/51,big/51); //print \r return min with 4 digits 2 decimal places \n new line
// small divided by 51 and big divided by 51 (255=5.00)
} while (TRUE);

}


___________________________
This message was ported from CCS's old forum
Original Post ID: 6129
SpeeDem0n
Guest







Re: Use anolog input for voltmeter do I need array?
PostPosted: Wed Aug 07, 2002 12:59 pm     Reply with quote

I constantly work with 8, 12, 14 and 16-bit A/D converters and I use a generic function to convert the A/D digital binary output into floating point voltages. You'll have to set up a few constants depending on which type of setup you have (i.e. 12 or 16 bit A/D, A/D min and max voltages and A/D offset if you A/D is bipolar). Keep in mind this code is written for accuracy in multiple situations, not raw speed. The following code is pulled from a pic running a 16-bit bipolar A/D with a voltage range of +/-10 volts.

////////////////////////////////////////////////////////////
int8 CONST A2DBITS = 16;
float CONST A2DMIN = -10.0;
float CONST A2DMAX = 10.0;
float A2DResolution, A2DOffset, Voltage;
int16 DataIn;

A2DResolution = (A2DMAX-A2DMIN) / ( pow(2.0,(float)A2DBITS) );
/* If A2DMin is 0, offset can be ignored */
A2DOffset = -1 * A2DMIN;

Voltage = ((float)DataIn * A2DResolution) - A2DOffset;
/////////////////////////////////////////////////////////////

That's what I use when dealing with A/D's. It may not help in your current situation, but hopefully it may help you sometime in the future, or even someone else now :)

Happy coding and good luck.
___________________________
This message was ported from CCS's old forum
Original Post ID: 6154
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