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 CCS Technical Support

Voltage Conversion

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







Voltage Conversion
PostPosted: Wed Jun 16, 2004 2:47 pm     Reply with quote

Got my system all running.
I have a question about voltage to decimal conversion.
On the ADC input iam using .5 to 1.75V but on the display it
read decimal. I would like to know if there is a formula to convert
the incoming voltage to a readable voltage on the display.

Donnie Lee
Guest








Almost forgot.
PostPosted: Wed Jun 16, 2004 2:56 pm     Reply with quote

Unit is setup int16
it goes from 0 to decmial1023

Thanks
Ttelmah
Guest







Re: Voltage Conversion
PostPosted: Wed Jun 16, 2004 3:01 pm     Reply with quote

dlee425 wrote:
Got my system all running.
I have a question about voltage to decimal conversion.
On the ADC input iam using .5 to 1.75V but on the display it
read decimal. I would like to know if there is a formula to convert
the incoming voltage to a readable voltage on the display.

Donnie Lee

The ADC (depending on the chip involved), returns a binary value, from 0-1111111111 (for the '10bit' converter which is the commonest type), for a voltage range of 0v to Vref (in fact a voltage of Vref itself would correspond to 10000000000, but the converter stops at just 10 bits).
So the answer will depend on what Vref is being used.
If the internal nominal 2.5v reference, and a 0.5v input, you should get a value of:
0.5/(2.5/1024) = 205 (in decimal)
for 1.75v, you should get:
1.75/(2.5/1024) = 717
The last bit or two will depend on noise, the charge time allowed for the input capacitor, and some luck. To convert back for display, if you have the read voltage in a long integer called 'Vin', use:
printf("The voltage is %f/n",(float)Vin*0.0024414);
Which is the based on the inverse of the above arithmetic.

Best Wishes
Guest








PostPosted: Thu Jun 17, 2004 6:33 am     Reply with quote

I have the 16F876 Chip set for 10 bits

Thanks
Guest








Setup
PostPosted: Thu Jun 17, 2004 6:46 am     Reply with quote

Ok its the 16f876 driven by a AD8313 log chip.
I have port a setup as all_analog.
the ref is 5v
so 1.75V input would be 2.75/(5/1024)=358 decmial

What i need to do is convert the 358 decmial to read Power in mw.

Say 358 decmial = 250mw

Thanks,
Donnie Lee
SteveS



Joined: 27 Oct 2003
Posts: 126

View user's profile Send private message

PostPosted: Thu Jun 17, 2004 8:16 am     Reply with quote

If you got space and time then you could simply ( I assume a zero offset and linear sensor):

Code:

float fdata;
float factor;

   factor = 250.0 / 358.0;  // conversion - (this could be a define)
   fdata = (float) data;      // convert ADC to float (data is raw ADC value)
   fdata *= factor;            // convert to mW
   data = (int16) fdata;     // convert to int (if desired)


'course when I was a kid we had to walk to school in 2K bytes EPROM and 32 bytes of RAM so I would be tempted to use:

Code:

   data *= 45;              // data * (factor * 64)
   data = data >> 6;    // data /= 64;


Huh? Well the factor to convert counts to mW is 250/358 = 0.698. We save time and space by staying in integers and avoiding division. We avoid divison by making our division a shift ( divide by a power of 2). So we convert 0.698 to some a fraction x/(2^n). Since your ADC value can be as high as 1024, x must be less than 2^16 (int16)/1024 = 64. So .698 * 64 = 44.7 which we round to 45. This method will not be exact so it may not be accurate enough for you. You can get better accuracy by making 'n' larger, but then you need better than 16 bit math. In that case use 32 bit math and use n = 8; The shift is now a whole byte, so you just ignore the lowest byte of the multiplication result.

- SteveS
Guest








Voltage To Mw
PostPosted: Thu Jun 17, 2004 10:00 am     Reply with quote

That got it. Now I have a 4 input millwatt meter.


Thanks for all the help..


Donnie Lee
Guest








PostPosted: Thu Jun 17, 2004 11:55 am     Reply with quote

I got the system to work.

I would like a better res on the meter.
100mw = 1.400V
150mw = 1.432V
etc.
So its .00064V per mw (.032 / 50) = .00064V per mw
its there a way to read the lower 3 bits to get a higher res.

Sorry for al the dumb questions, but iam new at this and have learned a lot from you people on coding.


Thanks,
Donnie
SteveS



Joined: 27 Oct 2003
Posts: 126

View user's profile Send private message

PostPosted: Thu Jun 17, 2004 2:53 pm     Reply with quote

First, these are not dumb questions. You are making good progress each time you come up with a new question - so keep going.

Second - You should go ahead and join the list, it's nice to have a 'handle' so we know it's you each time.

Third - your question:

Looking through your posts I get the following:

1. Your input can range from 0.5 to 1.75 Volts
2. You are using a 5V reference

As Ttelmah explained, your resolution will depend on your reference. The 16F876 can have Vref+ to Vref- as low as 2.0V. With a 5V reference you are wasting a lot of teh converterd range. Your range is pretty close 2.0V that, so I would try to use a 2.0V reference - 2.048 is popular as it makes the 10 bit converter output = 2.048/1024 = 2mV per bit. Another way to get better resolution is offset and amplify the signal so it's range equals the reference, but that adds complexity and perhaps error. If 2mV per bit is good enough then I would go that way. Of course we are assuming the converter has no error, etc, but this shows you the limit as to what you can expect. 2mV resolution is ~3mW - is that ok?


- SteveS
donnie



Joined: 13 Nov 2003
Posts: 12
Location: Kissimmee Florida

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Fri Jun 18, 2004 6:41 am     Reply with quote

I still can not get .5V to display 1mw.
Here is my code, I know iam missing something but can't figure out what.
Ref Voltage is 2.41V on RA3
Inout is .5 (1mw) to 1.75 (250mw)
Code:

#include <16F876.h>
#fuses XT,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT
#DEVICE ADC=10
#use delay(clock=4000000)
#include <stdio.h>
#include <math.h>
#include <lcd1.c>
////////////////// START HERE /////////////////////////////
void main()
{
char k;
int32 data1;
int32 data2;
int32 data3;
int32 data4;
float fdata1;
float fdata2;
float fdata3;
float fdata4;
float factor1;
float factor2;
float factor3;
float factor4;
//////////////////////////////////////////////////////////
setup_counters( RTCC_INTERNAL, RTCC_DIV_256 | RTCC_8_BIT);
setup_adc_ports( A_ANALOG_RA3_REF );
setup_adc(ADC_CLOCK_INTERNAL);
CCP_OFF;
lcd_init();
do{
//////////////////////// CHANNEL 1 ////////////////////////

set_adc_channel( 0 );
delay_ms(200);
data1 = Read_ADC();
factor1 = 250.0/604.0; // Cal Point For CH1:
fdata1 = (float)data1;
fdata1 *= factor1;
data1 = (float)fdata1;
data1 *= 45;              // data * (factor * 64)
data1 = data1 >> 6;    // data /= 64;

delay_ms(200);

//////////////////////// CHANNEL 2 ///////////////////////

set_adc_channel( 1 );
delay_ms(200);
data2 = Read_ADC();

////////////////////////// MATH //////////////////////////

factor2 = 250.00/302.08; //Cal Point For CH2:
fdata2 = (float)data2;
fdata2 *= factor2;
data2 = (float)fdata2;
delay_ms(200);

///////////////////////// CHANNEL 3 //////////////////////

set_adc_channel( 2 );
delay_ms(200);
data3 = Read_ADC();

//////////////////////// MATH ////////////////////////////

factor3 = 250.00/302.08; //Cal Point For CH3:
fdata3 = (float)data3;
fdata3 *= factor3;
data3 = (int16)fdata3;
delay_ms(200);

///////////////////////// CHANNEL 4 //////////////////////

set_adc_channel( 4 );
delay_ms(200);
data4 = Read_ADC();

/////////////////////// MATH /////////////////////////////

factor4 = 250.0/ 302.08;  //Cal Point for CH4:
fdata4 = (float)data4;
fdata4 *= factor4;
data4 = (int16)fdata4;
delay_ms(200);

//////////////////// DISPLAY /////////////////////////////

//printf(lcd_putc,"\f");
printf(lcd_putc,"\fCH1:%Lumw", data1);
lcd_gotoxy(10,1);
printf(lcd_putc," CH2:%LumW\n", data2);
printf(lcd_putc,"CH3:%Lumw", data3);
lcd_gotoxy(10,2);
printf(lcd_putc," CH4:%LumW", data4);

///////////////////////// END ////////////////////////////
} while(true);

}




Last edited by donnie on Fri Jun 18, 2004 8:14 am; edited 1 time in total
donnie



Joined: 13 Nov 2003
Posts: 12
Location: Kissimmee Florida

View user's profile Send private message Send e-mail Visit poster's website

Please Help
PostPosted: Fri Jun 18, 2004 8:08 am     Reply with quote

Thanks for any help you can give a newbie..


Donnie
SteveS



Joined: 27 Oct 2003
Posts: 126

View user's profile Send private message

PostPosted: Fri Jun 18, 2004 9:08 am     Reply with quote

Ok - let's see:

1. In all the channels you use (using ch 1 as the example):

data1 = (float)fdata1;

That should be:

data1= (int16)fdata1;

It probably converts it right anyway, but might as well have the code reflect what happens.

2. I gave you two ways to do the math. One in floating point; the other using integer math. In the channel one routine you use both. I bet you were trying the two methods out, but one needs to be commented out.

3. You can move the constant factors out of the 'do' loop. You are recalculating them each time. No need. You could also declare them as constants:

const float factor1 = 250.0/604.0;

etc.

4. If you want the data to always be displayed in 3 spaces, right justified use:

%3Lu

in the printf.

5. I still haven't helped with your problem, unless it's due to #2 above...

If not, then :

.5V is 1024 * .5 / 2.41 = 212
* 250.0 / 302.08 = 175.8
(int16) = 175 - that's not 1mW

-- start from scratch:

you want .5 = 1mW and 1.75 = 250mW, reference = 2.41V
so, .5 = 212 counts (from above) , 1.75 = 1024 * 1.75 / 2.41 = 744

assume a linear sensor: the conversion from counts to mW is:

slope (m) = (250-1)/(744-212) = 0.468

offset (b) = 250 - 0.468 (744) = -98.2

so: mW = 0.468 * counts - 98.2

Try that.


- SteveS[/b]
donnie



Joined: 13 Nov 2003
Posts: 12
Location: Kissimmee Florida

View user's profile Send private message Send e-mail Visit poster's website

1mw
PostPosted: Fri Jun 18, 2004 11:52 am     Reply with quote

Got it. Looks ok so far.
Thanks for all your help..

BTW: Now at looking at the math a few things are slowly coming back. Its hell to be getting old..


Donnie Lee
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