PDA

View Full Version : ADCIN & 16F870 - how to avoid non linear conversion?



CuriousOne
- 19th March 2014, 16:31
Hello.

I've built a simple circuit, with 16F870 and MAX6126 as reference voltage supply.

The problem is that I can't write a code that will properly convert read data into voltage.

By using external multimeter, I've determined that with 678 read by ADC, voltage is 3 volts. Based on this, I've created a conversion formula, but it does not appears to work correctly, for example, when input is 4.1v, it reads as 4.35 volts. And when input is 1.4V, it reads as 1V. The code is as follows (based on :



Include "modedefs.bas" ' Include serial modes
TRISA = %11111111 ' Set PORTA to all input
ADCON1 = %10000001 ' Set PORTA analog and right justify result

DEFINE LCD_DREG PORTB
DEFINE LCD_DBIT 4
DEFINE LCD_RSREG PORTB
DEFINE LCD_RSBIT 0
DEFINE LCD_EREG PORTB
DEFINE LCD_EBIT 1
DEFINE LCD_BITS 4
DEFINE LCD_LINES 2
DEFINE LCD_COMMANDUS 1500
DEFINE LCD_DATAUS 44
DEFINE OSC 4

Define ADC_BITS 10 ' Set number of bits in result
Define ADC_CLOCK 3 ' Set clock source (3=rc)
Define ADC_SAMPLEUS 50 ' Set sampling time in uS

adval Var word ' Create adval to store result
droebiti var word 'temporal value

mainloox:
ADCIN 0, adval ' Read channel 0 to adval
droebiti=adval*44 'convert to volts

Lcdout $fe,$c0, "Value: ", DEC adval, " " ' Display the decimal value
Lcdout $fe,$80, "Voltage: ", DEC (droebiti / 10000), ".", DEC4 droebiti, " V "
Pause 100 ' Wait .1 second
Goto mainloox ' Do it forever


What I'm doing wrong?

I'm using 10k pot with middle pin tied to RA0, one pin tied to Vss and another to voltage reference output. This might be the issue?

HenrikOlsson
- 19th March 2014, 19:35
Hi,
The MAX6126 comes in various versions but I suspect you're using the 5V one, since you're feeding in voltages above 4.096V I'm guessing you're using the 5V version of the MAX6126 - is that correct?

Your numbers don't quite add up.... With a VRef of 5V an input of 3V should give you a reading of (1024/5) * 3 = 614, you're getting 678. Have you followed the datasheet for the voltage reference regarding supply and output bypassing and have you verified that the VRef voltage actually IS what you expect it to be?

/Henrik.

mark_s
- 19th March 2014, 22:29
You have ADCON1 set to use porta.3 as an input for a positive reference. Without a reference connected its floating

Change ADCON1 to this


ADCON1 = %10000000


then your references will be +Vref = vdd and -Vref = vss. Or you can connect porta.3 to +5v without changing adcon1

CuriousOne
- 20th March 2014, 03:24
I'm using MAX6126 with output voltage of 4.098v and it outputs that voltage - verified with precision multimeter.
The +Vref is tied to MAX6126 output and +Vref is tied to GND. So this is why I have ADCON1=%10000001
When I tie RA0 directly to MAX6126 output, the raw output reads 1023, when I connect it to GND, it reads 0.

HenrikOlsson
- 20th March 2014, 06:34
Hi,
OK, that's a great value because then each bit in the ADC result equals exactly 4mV but your numbers still doesn't add up....

If you input exactly 3V you should get a value of 750 +/- a couple of bits - not 678 as you're apparently getting.

Have you checked the VRef voltage with a scope? Perhaps it oscillates or have a lot of noise?

What if you replace the 10k pot with a 1k pot, and put a 10nF capacitor between the ADC input and GND. Or, what if you increas the sampling time? (I'll admit, I don't really have this sampling time and Tad stuff clear in my head at the moment, need to do a little reading)

Once you get a correct ADC result for the voltage you're feeding it you can increase the resolution by oversampling. If you take 40 samples, add them together and divide the result by 10 you have a value reading in mV (well, almost - there's 4mV "missing" at the top).

adval = 0
For i = 0 to 39
ADCIN 0, adval
Voltage = Voltage + adval
PAUSEUS 100
NEXT

LCDOUT $FE, 1, DEC Voltage/10000, ".", DEC3 Voltage // 10000

/Henrik.

CuriousOne
- 20th March 2014, 10:36
Ok I've double checked wiring and so on. When getting 1023, I was connecting the upper end of pot to +5V, not to MAX output. Now, when I connected it to MAX output, it reads 987, instead of 1023, so I assume, there might be some more register settings required?

CuriousOne
- 20th March 2014, 15:28
Vin Raw Delta

0.1 10
0.5 88 78
1 213 125
1.5 335 122
2 460 125
2.5 580 120
3 700 120
3.5 807 107
4 927 120
4.1 960 33


These are raw ADC reads according to different input voltage.

HenrikOlsson
- 20th March 2014, 15:49
Hi,
First of all. With a VRef of 4.096 you can not input a voltage HIGHER than that, so the 4.1V (although very close) isn't a valid test. With that said something is seriously wrong - either with the code, the setup, or the hardware.

And again, have you actually looked at the reference voltage AND at the input voltage with a scope to verify that they are clean? Simply measuring them with a voltmeter may not show the error.

Instead of using the pot across the reference voltage, try using a low impedance source, ie a variable DC supply, to feed the ADC and put a 10nF capacitor from the PIC pin to GND to act as a noise filter. See if that makes it any better. Also, take a couple of readings and average them to further clean any noise.

If the above doesn't help then try another channel on the ADC or try another PIC. It's possible, but not likely, that something got damaged when you overloaded the input.

/Henrik.

CuriousOne
- 20th March 2014, 16:25
It is NOT 4.1V, it is 4.096v, I just wrote 4.1 to save space.

Yes, looked with scope and precision (3 digits after decimal point) multimeter.

Will try another channel and another pic, as well as another voltage supply.

CuriousOne
- 20th March 2014, 16:53
Set scope to 50mV resolution and AC input. Found an 120mv max noise pulses, with 3.35hz following frequency.

HenrikOlsson
- 20th March 2014, 17:13
Where?
On the power rail, at the output of the voltage reference, at the ADC input or all of the above?

If the noise is only present at the ADC input of the PIC then the problem is probably too high source impedance (that 10k pot you're using) and the 3.35Hz you're seeing is how often the ADC is sampling the input. Or is this with a low impedance source?

CuriousOne
- 20th March 2014, 19:09
Yes it was with 10k pot, measured at ADC input. no other tests so far.

Actually, I went with ADC route because I was not able to make BH1750 light sensor to work with picbasic, and since I badly need light measurement, I've decided to do a circuit with photoresistor and ADC, but it appears to have it's own bunch of problems.

CuriousOne
- 21st March 2014, 08:02
Yes, these pulses were from ADC. If turn ADC off, pulses are gone.

Problem is solved, but it was weird.

Since PIC has two Vss pins, I was using one Vss for GND, and to other Vss pin I've tied LCD gnd pin. So current going trough the PIC was causing the troubles. After I've added jumper to feed Vss directly to LCD, problem had gone and linearity improved.