PIC18F ADC

Status
Not open for further replies.

adrianvon

Member
Hi all,

I have a sensor which outputs 13mV per degree. It will be useing it to monitor a full 360 degrees. How can I set the the PIC18F ADC reference voltsge to get 13mV resoultion?
My first step is to set the ADC in 10-bit mode since I cannot get 360 degrees from an 8-bit ADC.
Multiplying 13mV by 1024 will 13.3V which exceeds the 5V limit.
Dividing 13mV by 2 to set two bits for every degrees also gets above the 5V limit ( 13mV/2 = 6.5mV .... 6.5mV * 1024 = 6.7V)

Is there a way to achieve this without reducing the sensor output voltage please?
 
You simply attenuate the incoming voltage to fit the required range, it's as simple as that - and is an absolutely standard technique (not even something you need to thing about).

If you check my PIC tutorials, the ADC tutorial hardware provides both an opamp for buffering (it's important to have a low impedance source) and a preset for setting the exact range. I also use a negative voltage generator and a 2.5V reference, to allow absolute full coverage from 0V to the required FSD voltage (in my case I used 10.23V FSD) - supposed 'rail to rail' opamps don't actual go 100% rail to rail.
 
Thanks for the reply. By attenuating the incoming voltage, what exactly do you mean? Does that mean reducing the 13.3V to fit in the ADC range (i.e. 5V). Also, where can I find your tutorial on ADC please?
 
Last edited:
If my math is OK.
13mV/degree, 360 degrees = 4.68 volts.
5 volts on the ADC Vref =4.88mV/ ADC step.
Wish you told us what sensor!
4.68V is 2.66ADC steps per degree.
If you took two resistors and divided the output down to 1.76V gives one ADC step/degree.
Divide down to 3.52V gives you two ADC steps/degree.
-------------------------------------------
That is the hardware way. Here is the software way.
------------------------------------------
connect sensor directly to ADC.
Read the voltage in 10 bit mode. (16 bit INT)
Because divide by 2.66 is hard do this; multiply by 100 and then divide by 266.
 
Hi, the sensor is just a linear 3-turn potentiometer. I can vary the pot input voltage, but I would like to keep it as high as possible. This way, if some noise is present it will not have an effect of the ADC monitoring. I can set the pot to output 9mV per degrees. That would make 2 ADC steps for every degree (4.5mV per step). But I am worried that using 9mV per degree would make it very difficult to calibrate and noise will have an effect on the reading.
 
Now we are getting more information.

3-turn pot: So it is not a sensor. A 3 turn pot will have the 5 volts spread out over 3 turns. So each turn will be 1.667 volts.

Most 1 turn pots I know only turn 75% of the way around. Both ends are not linear.
I don't know your 3-T pot but it likely is only 2.7 turns.

I think you are worrying too much about noise. You have not tried it yet. Put a capacitor from the wiper arm on the pot to ground. (0.1uf at the micro) If the noise is too high then sample 4 times and average. Twist the three pot wires together in a bundle. Keep the wires short.

I think you will find the pot is not 10 bit linear. You will have to calibrate the pot. If you are concerned about 1 bit of noise then the non linear pot will be a problem.

Have you tried putting 5V across the pot, turn 360 and read the voltage, turn 360 and read the voltage?
 
I am going to test the pot tomorrow using an oscilloscope. Instead of twisting the wires, I was going to use a shielded cable like the one in the attached photo. Will that work ? (Note: apparently it is only shielded and not twisted). Also, is there a difference between the shielded cable attached (with single strands shielding) and the one in the link below?

**broken link removed**

Thanks in advance.
 

Attachments

  • 2.jpg
    281.6 KB · Views: 200
The link looks like radio frequency coax. One wire and shield.
The picture looks like microphone cable. Shield and two or more wires. I like it.
 
Well now you've actually told us what you're trying to do, there's even less concern - simply connect the pot between the +ve reference (5V?) and ground - so you've got the absolute maximum possible spread.

Assuming there's any sort of length of cable, using twin screened would be a good idea.

A further point is the value of the pot, what is it? - higher values will make it more susceptible to stray pickup, and it also needs to be kept low to meet the maximum source impedance requirement (5K is probably about the highest to meet that, although I'm not sure on the 18F series).
 
Thanks a lot for the reply. The pot value is 2.5K. The PIC18F ADC maximum impedance is also 2.5K. Should I use a voltage follower (op-amp) at the output of the wiper?

Both you and ronsimpson suggested a twisted, shielded cable. The cable I attached in the previous post does not look like it is twisted, although it is shielded. Should I buy another cable?
 
Shielded is best.
Twisted is OK. Better than nothing.
You don't need twisted and shielded.
 
Well now you've actually told us what you're trying to do, there's even less concern - simply connect the pot between the +ve reference (5V?) and ground - so you've got the absolute maximum possible spread.

Lets assume Vref+ is 4850mV. 4850mV / 1024 = 4.736mV.
Dividing 4850mV by 360 degrees gives 13.472mV.
Since 13.472mV is not exactly divisible by 4.736mV, how can I determine the angle please?

I think the solution is to adjust the pot input voltage as below:

4.736mV = 1 ADC step
Therefore 2 ADC steps = 9.472mV

9.472mV * 360 degrees = 3410mV.

Therefore, setting the pot input voltage at 3410mV I can say that 2 ADC steps are equal to 1 degree.

Is this correct? or am I complicating matters (as always)

By the way, I am planning to set these voltages using the TLV431 shunt regulator for precise reference voltages.
 
Lets assume Vref+ is 4850mV. 4850mV / 1024 = 4.736mV.
Dividing 4850mV by 360 degrees gives 13.472mV.
Since 13.472mV is not exactly divisible by 4.736mV, how can I determine the angle please?
Post#4 "software" shows how to do the math
a linear 3-turn potentiometer
You do not understand. A three turn pot takes three turns to get from one end to the other. One turn will not get you from 0V to 5Volts.
You are thinking too much and do not understand what you have.

Connect your pot from 0 volt to 5 volts. Put a meter from 0 volts to the wiper. Turn the know and record what voltages you get. Until you know how the potentiometer works the math is never going to work out.

Sorry to yell at you.
 
I am using 360 degrees and not 1080 degrees (i.e. three turn) because the pot is connected to a reduction gear. Therefore, the pot turns 1080 degrees for every 360 degrees turn of the drive gear. Since I want to measure the angle of the drive gear and not the driver gear connected to the pot, it does not make sense calculating using 1080 degrees. Sorry for not providing this info in the first post.
 
I am using 360 degrees and not 1080 degrees
You are using 1 turn not 3 turn.
a reduction gear. Therefore, the pot turns 1080 degrees for every 360 degrees
Then there is a gear box so 1 turn is 3 turns.
it does not make sense calculating using 1080 degrees.
Numerous times you talk about putting a voltage across the pot. Then getting o to that voltage out of the pot. That make me think you are planning on using the entire pot. Yet you talk about using 1 turn not 3 turns.

Please don't explain it to me. I can't get it. While I don't know what you are doing I do under stand pot very well. I think you will be surprised.
(from post #13) Connect your pot from 0 volt to 5 volts. Put a meter from 0 volts to the wiper. Turn the know and record what voltages you get. .
 
As you are using a pic simply connect Vdd (5V) across the pot and use Vdd as Vref. Any noise on the supply will be cancelled out as both the pot and Vref see the same noise. The angle is then ADCreading*360/1023. Using a higher voltage will mean that Vref doesn't see the same variation and so your reading will be more inaccurate.

I'm assuming the pot does three revs per 360° of the shaft that you require the angle of.

Mike.
 
Adrianvon,

I was wrong. The last time I tried this the pot was not good at either end and did not make 3 turns.

I just pulled a data sheet on a pot form Vishay. Model 533.
It shows the rotation to be between 1080 degrees and 1090 degrees.
Linearity +/-0.25%
Worst case the end voltage will be less than 0.25% of the applies voltage. With a 5V supply you will not have more than 12mV at 0 degrees and less and than 4.988V at 3 turns.
Note 3 turns is somewhere between 1080 and 1090.

I think the pot will work well.

I have had trouble with "back lash" in gear boxes.
 
Is this correct? or am I complicating matters (as always)

You're overcomplicating things

Step back and think about it.

A 10 bit ADC gives approximately 0.1% resolution (as it provides roughly 1000 values) - this is likely to greatly exceed the rest of the 'system', particularly the accuracy of the pot and even more so the accuracy of the gearing you've now mentioned, where backlash is likely to be far above 0.1%.

Anything you do maths on is going to lose resolution, which is why in my tutorial I chose a 10.23V range for the ADC, this gives you 0.01V (1omV) resolution, so works perfectly. If you changed the attenuation to read 20.46V, and multiplied the result, then you still have the same 0.1% accuracy, but the last digit can only display even numbers - which makes for a really crappy display

This applies to any scaling, if you want to keep the full resolution, otherwise you can always lose the last digit, dropping to only 1% resolution, which is often as much (or more) than you need.
 
Here's what I'd try.... For every turn of the drive gear your pot turns 3 times 0~ 5v or 0~ 1023 bits

If you put a trimmer on the top of your pot.... Set the zero position of the three turn pot, rotate the drive shaft 360 degrees... set the trim pot so the output = 3.5 volts ( 720 bits)... Then your maths won't be a problem.....
 
Hi,
Thanks all for the replies. For setting the ADC for the PIC18F4550, is the initialization code below correct please? Are "16*Tosc" and "2TAD" ok for a 20MHz Xtal?

Code:
ADCON0 = 0; 
ADCON1 = 0;
ADCON2 = 0;

TRISAbits.TRISA0 = 1; 
ADCON0bits.CHS0 = 0;  
ADCON0bits.CHS1 = 0;
ADCON0bits.CHS2 = 0;
ADCON0bits.CHS3 = 0;
ADCON0bits.GO_DONE = 0; 
ADCON0bits.ADON = 0;
ADCON1bits.VCFG0 = 1;
ADCON1bits.VCFG1 = 0; 
ADCON1bits.PCFG0 = 0;  
ADCON1bits.PCFG1 = 1;
ADCON1bits.PCFG2 = 1;
ADCON1bits.PCFG3 = 1;
ADCON2bits. ADFM = 1; 
ADCON2bits. ADCS2 = 1; 
ADCON2bits. ADCS1 = 0;
ADCON2bits. ADCS0 = 1;
ADCON2bits. ACQT2 = 1; 
ADCON2bits. ACQT1 = 1;
ADCON2bits. ACQT0 = 1;
ADCON0bits.ADON = 1;

Also, can someone please tell me how to read data from the two registers used for storing the ADC value? I tried the code below. Am I missing a delay or something?Is there a way to store the value of both registers in one variable?

Code:
ADCON0bits.GO_DONE = 1; 

While (GO_DONE == 1)  { } 

Result == ADRESH;
Result == ADRESL;

THANKS IN ADVANCE.
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…