Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

ADC_Read in MikroC, HELP! How to code 0 - 1.8v only?

Status
Not open for further replies.

eebhoi01

Advanced Member level 4
Joined
Feb 22, 2012
Messages
116
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,296
Activity points
2,347
Hello Guys,

Im currently coding a project which involves reading an analog value ranging from 0 to 1.8V. How am I going to do this?

I tried this code:

float data;

void Analog()
{
data = ADC_Read(0); // adc read at AN0
data = (data/1023)*1.8; //1.8 is my maximum value
if (data > .5) { "DO SOMETHING"; }
else {DO NOTHING}
}

This is the part of my program where ADC works. My question is, is the ".5" right? or it should either be 1 or 0?
The decimal value is really important in my application, please help me out.


Best Regards,

Jay
 

The ".5" should be OK, the compiler will compile it as a float so the comparison with "data" should work. If your data result is >0.5, the DO SOMETHING will happen.

However...

Is 1.8V the maximum level of your input signal to the PIC? If so, are you amplifying it to 5V first, or using an external reference for the ADC, or is your supply voltage 1.8V? If not, then your calculation might not be what you think.
 

If your reference voltage is 1.8V, then it's fine.

Instead of using float values, why don't you use integers? If you need single decimal place accuracy (nearest 0.1V), you can use this:
Code:
data = ADC_Read(0); // adc read at AN0
data = (data/1023)*18; //1.8 is my maximum value
if (data > 5) { "DO SOMETHING"; }
else {DO NOTHING}

So, 18 means 1.8V, 5 means 0.5V. Then, you avoid using float values. The code is more efficient and executed quicker.

If all you need to do is compare for 0.5V, you can avoid converting to "5" or "0.5" as well. Compare against the value you'd obtain from the ADC with 0.5V input.

Hope this helps.
Tahmid.
 

The ".5" should be OK, the compiler will compile it as a float so the comparison with "data" should work. If your data result is >0.5, the DO SOMETHING will happen.

However...

Is 1.8V the maximum level of your input signal to the PIC? If so, are you amplifying it to 5V first, or using an external reference for the ADC, or is your supply voltage 1.8V? If not, then your calculation might not be what you think.

Thank you sir

Yes, the 1.8V is my input level to the Pin. 0 to 1.8V coming from the sensor. In other words, the output of my sensor (0-1.8V) is directly connected to the PIC adc pin.

- - - Updated - - -

If your reference voltage is 1.8V, then it's fine.

Instead of using float values, why don't you use integers? If you need single decimal place accuracy (nearest 0.1V), you can use this:
Code:
data = ADC_Read(0); // adc read at AN0
data = (data/1023)*18; //1.8 is my maximum value
if (data > 5) { "DO SOMETHING"; }
else {DO NOTHING}

So, 18 means 1.8V, 5 means 0.5V. Then, you avoid using float values. The code is more efficient and executed quicker.

If all you need to do is compare for 0.5V, you can avoid converting to "5" or "0.5" as well. Compare against the value you'd obtain from the ADC with 0.5V input.

Hope this helps.
Tahmid.


Thank you so much Sir, Im going to try this out. I never thought about this. What i know is if the value involves decimal then float should be used. Thanks again
 

The input voltage is between 0V to 1.8V. But what is the ADC reference voltage? Are you using VDD as reference? In that case, your VREF=VDD. For your code, you'd need 1.8V as ADC reference.
 
Which PIC are you using, and what is the supply voltage? I guess that you are using the internal reference for the ADC. That is the supply voltage.

If so, your calculation data = (data/1023)*1.8; will not give the correct answer. You need to use data = (data/1023)*5.0; if your supply is 5V.

Also, Tahmid is quite correct that integer arithmetic is much preferable. It is rare that floating point is really needed, and only if doing some serious calculations. Floating point libraries add a lot of excess code to your compiled program, and slow it down a lot. I've done a lot of stuff with PICs where I've needed to handle many decimal places in calculations and display, but almost never used floating point!
 
The input voltage is between 0V to 1.8V. But what is the ADC reference voltage? Are you using VDD as reference? In that case, your VREF=VDD. For your code, you'd need 1.8V as ADC reference.

Oh wait sir, this might be the problem. "ADC input value is different from my reference voltage?" I though that for this formula "data = (data/1023)*Ref" Ref is the same with ADC input in my case the 1.8. Am I wrong?
 

The ADC does not know that 1.8V is the maximum, and you cannot tell it this in your program. It is done electrically by the ADC reference.

The ADC will compare the input to the reference, and give a maximum count (1023) when the input = the reference.

The internal reference is the supply voltage for the PIC (5V?) so with a 1.8V input, the ADC will only count to 368. That is what reading the ADC will give you in this case.

So, if you multiply the ADC reading by the reference, and divide by 1024, you will get the true input:

368*5/1024=1.8 (ignore low decimal errors)

Note that you are losing a lot of potential resolution. That might not be important if you do not need it, but in this case you will never use the ADC readings above 368. You are using only 28% of the available ADC range. If you used an op-amp to multiply the 1.8V up to 5V, (i.e. op-amp multiplies by 2.78) then you could use the full range of the ADC. Or, you could use an external reference of 1.8V for the ADC, but using the op-amp is probably cheaper than buying a 1.8V reference chip.
 

MANY THANKS SIR Tahmid and SIR FoxyRick. It really helped me alot. Thank you
 

One final point - the order in which you multiply and divide.

Most important if using integer variables, multiply first, then divide, like I have done in my post above. That way, you do not lose as much resolution which can happen when you divide with integers (because any fractional part is lost). The only reason to divide first is if the multiply might make the variable overflow if done first. Even then, better to use a larger variable if possible (long long, 32 bit)
 

The internal reference is the supply voltage for the PIC
Not necessarily. It can be connected to a different reference voltage for many PIC processors. The datasheet usually specifies a minimum Vref value for correct ADC operation, e.g. 3 V for 5V supply and 1.8V for 3V.

As another point, the suggested
Code:
data = (data/1023)*5.0
should be better written as
Code:
data = data*(5.0/1023)
otherwise many embedded C compilers will perform a float division and a float multiply instead of a multiply with a calculated constant.
 
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top