Page 1 of 1

Need Advice

Posted: 17 Jun 2007 10:03
by arunkish
I'm using PIC16F73 for the below program and I'm trying to measure small voltages. The program shows the correct voltage but often it fluctuates.. For eg when measured in the ADC input the Voltage is 0.037 but at the same time the text I get on the LCD is 00025 , 000022 , 00019 etc. The question is why it does not hold the value. But the multimeter shows the correct constant voltage. Is there any calculation to give the right output??

program AdcOnLcd2

dim CurrentValue as float
dim Text as char[10]
dim rrrr as word

main:

INTCON = 0
OPTION_REG = $80
ADCON1 = $82
TRISA = $FF

Lcd_Init(PORTB)
Lcd_Cmd( LCD_CURSOR_OFF)
Lcd_Cmd(LCD_CLEAR)


while true
CurrentValue = ADC_read(2)
CurrentValue = CurrentValue*(5000.0 div 255.0)
rrrr=CurrentValue
WordToStrWithZeros(rrrr, Text)
Lcd_Out(2, 8, text)
delay_ms(1000)
wend
end.

Posted: 17 Jun 2007 13:20
by alsopb
With 5 volts divided into 255 bins, the resolution is 0.019 volts.

I'm suprised that you get anything but mulitples of 0.019 volts.
Most a/d's have a +/- one count inaccuracy.

+/-1 one count is +/- .019 volts so if voltage 0.037, you should get readings of 0.038 +/- .019.

You need to either go to a PIC with 10 bit A/D or amplify the input voltage. I'd also replace the (5000 div 255) by a constant of 0.019. Since you're outputting integers perhaps you just want a long integer of CurrentValue*19. Eliminates all floats and mixed type math.

Brian
Henderson, NC

Thank you

Posted: 17 Jun 2007 13:36
by arunkish
Sir
Thank you very much for your reply and I understood it. As I said sometimes the output I get on the LCD is 0 , 19 etc.... I'm measuring very small changes (millivolt) but that shows a big variation. Is there any solution to solve this without amplification ? Or If I use PIC16F877 will this issue be cleared? But how does multimeters displays the correct output ?

Thanks

Posted: 17 Jun 2007 14:01
by jpc
multimeter is very slow , it is averaging voltage where PIC ADC takes a very short sample and next makes a fast conversion. You gan improve the quality of yourt measurement by integrating many samples. As you need only 1 hz output you can take as many samples as your PIC can do in this second . I would start accumulating some 10000 samples and then scale the result to whatever you prefer. This approach will give you both better stability and accuracy. If you want to learn more search on 'oversampling ' , will guide you to http://www.atmel.com/dyn/resources/prod ... oc8003.pdf

Posted: 17 Jun 2007 14:09
by arunkish
Thank you JPC, I'm going to check it out with PIC16F877. I will let you know what happens.

Posted: 17 Jun 2007 14:28
by dejan_mrtt
Hi arunkish,

All that Brian said is correct!
In the world of ADC's, devices are built with usually more powerfull ADC's than it appears in the result. For example, if you want to display result variable between 0-10000 counts you'll use at least 16bit ADC, wich has 65535 counts. This is becouse you'll eliminate a great deal of noise and fluctuations - as in your case. So if you get to use an ADC module on 16F877,
with 10bit resolution ( 1024 counts ), you will have to divide the result getting it in range of 0-512 or even 0-100, and this is if you want to get rid of fluctuations (noise). ( NOT Multiplying it! )

Anyway this can be improved...if you plan to use a better coding techniques.
For example:
If you still want to get yours 1024 counts - out of 10bit ADC, you'll need to experiment a little with extracting an average value from a series of stored results:
- Declare an array of word variables, lets say...

Code: Select all

Dim My_result as word[20]
- Then use a counter, storing each result in this array;

Code: Select all

i=0
For i = 0 to 19
My_result[i] = ADC_Read(2)
delay_ms(2)
Next i
-Then sum all of those word numbers, and divide them by 20.

Code: Select all

i=0
For i = 0 to 19
Final_result = Final_result + My_result[i]
Next i 

Final_Result = Final_result div 20
This will be done every 50ms, so the refresh of your value will be every 50ms.

Sorry if I missed something in this quick tip but....
I think you'll get the idea.

Oh and if you calculate the time for sampling to be exactly long as your halfperiod of the 50/60Hz hum coming via power lines, you'll get just fine ADC results.

I have built a weight scale measuring device wich uses external 16bit ADC from Analog Devices, connected to PIC18F8722 ... and I used an array of 255 word variables.... and in the end I was happy getting a stable result with range 0-5000 counts, out of 65535 !!!! As you may know this is by measuring 0-20mV levels, and its quite satisfying result - close to proffesional devices.

...And if you plan to measure this kind of low-voltage levels, you will need an amplifier for sure :wink:

Good luck...
Regards,
Dejan

Posted: 17 Jun 2007 16:15
by arunkish
Dear Dejan

Thank you very much for your code and advice. I tried it out, but nothing seems to work it shows a lots of variation even after I take the average of 20 - 40 values. I cant amplify it more using opamp becuase it comes from PT100. I think I have to move to an external 16 bit adc as you said. Is there any such devices at a low price that you know. Any amplification circuits that suits for PIC will also be good.

Regards
Arun Kishore

Posted: 17 Jun 2007 16:50
by xor
Reducing the reference voltage will also provide smaller voltage divisions. If using an RTD consider using the 8-pin MCP3551. It's essentially a 22-bit Sigma-Delta ADC with input conditioning which can manage the narrow band of voltage change for the RTD's temperature range.

Posted: 17 Jun 2007 17:41
by dejan_mrtt
Arun,

In my application I used AD7705B

http://www.datasheetcatalog.com/datashe ... 7705.shtml

Download this pdf and you'll get the idea.

AD7705 holds Software Programmable Gain Input, two differential inputs, noise filters - also configurable, and the datasheet has nice examples, so you'll see how to connect your PT100. (on page 30)

It was a long time ago but.. if you decide to use this part, feel free to post questions anytime.

Regards,
Dejan

Posted: 17 Jun 2007 17:58
by dejan_mrtt
Oh,... and as Xor said, MCP3551 is also very nice ADC part!

Good luck :wink:

Posted: 24 Jun 2007 05:03
by arunkish
Hello dejan_mrtt and Xor
I somehow managed to do it out. But the only problem I have is the flickering that happens. I even tried to reduce the ref voltage, but it keeps on flickering from 26 to 27 and then back to 26, 25 etc.. Is there a way to check if the value holds for some X seconds and if it holds then display it out ???

In short for eg. I need to check the adc value and if that value holds on for 2 seconds display it on the LCD or else display the last value that was holded for 2 seconds. How to write the coding for this?

Regards
Arun

Posted: 24 Jun 2007 11:58
by dejan_mrtt
This method will eliminate fluctuating by +/- 1 count of your display value,
and still allow you to have 1 count resolution.

The only bad thing is that you'll have an error of one count in the case of Slow Refresh. However... the visual effect will be much less frustrating :wink:

Code: Select all

 Sub procedure display_value
     wordtostr(Old_value,text)
     LCD_Out(2,5,text)        'refresh your LCD result
 End Sub
 Sub procedure Prepare_value
    If (New_value = Old_value)or      'if the result fluctuates by +/- 1
       (New_value = Old_value+1)or    'then exit the procedure
       (New_value = Old_value-1)Then  '(don't refresh the display).
    Exit
    Else
      If New_value = Old_value+2 then 'if the result is slowly increasing
         inc(Old_value)               ' or decreasing PUSH/PULL the
         display_value                'display value by one count.
         exit
         end if
      If New_value = Old_value-2 then
         dec(Old_value)
         display_value
         exit
         end if
    End If
    Old_value = New_value             'If the result is bigger then two
    display_value                     'counts or more, display the value as is.
  End Sub
 'This is where you redirect and get your New_value from ADC result
You just Call the PREPARE_VALUE procedure, after you get the NEW_VALUE from your ADC_Read method, with your callibrating math.

Maybe there is a better way of doing this but if the fluctuating is +/- 1 count, this works for me, and it's quite simple. Usually, if you dont use more proffesional software and hardvare!! methods, the ADC's are fluctuating by one count, and if you achieved this you should be satisfied. Otherwise you'll have to ease your AD converter.

Oh and...you can try advancing this code to do: +/- 2 count PUSH/PULL,
if you are not satisfied with this one.

Good luck.

Posted: 24 Jun 2007 14:52
by dejan_mrtt
I just wrote this code like an example for you.....you should work out the details and adjust the variable names.

This method worked for me in my "Wireless Weight Scale" device.

you can see some photos of it at:

http://dejanspasovski.spaces.live.com/

I had fluctuations of +/- 1 count from ADC even when it was enclosed in metal case as you can see in the photos.

Voltage signals in range of 0-20mV are not so easy to handle.

However if you are using PT100 you'll need a Super-Stable Ref.Voltage :wink: