Help with pressure sensor.
Well I have to be about the dumbest person and why this eluding me on how to correct this is beyond me. Anyway I am working with a 16f877 and I've got a pressure sensor thats range is .5vdc to 4.5vdc and I am trying to get the full range of the AD but I am stuck. It works perfectly when I hook it up my AD output reads .47v which is perfect since there is some degree of percission. I don't know why they don't make these to read 0v to whatever but they don't So my quesiton is how to programatically drop that first .5v and still take advantage of the entire 1-1024 range of the AD converter or is there a better way?
Thank you.
David
It helps tremendously a few more mental blocks though....
Quote:
Originally Posted by
mackrackit
Mack, That does help allot thank you. I am an amateur at best and not a good one, but I try. I am starting to understand the math. I do read the datasheets, I don't always understand them but I read them and try none the less. The part I am having difficulty is with the settings of ADCON0 and ADCON1 and setting of VREF. I am getting readings and it seems that proportinatly it goes up as the PSI goes up. I've incorporated your suggested math into my program thanks. The problem I think I am having is the VREF is and one or more of the bits I have set in ADCON? is not correct. At a dead stop with 0 psi I get a reading and that most likely is proportinate to the
.47 vdc the voltmeter is telling me the sensor is putting out and being presented to RA0. Ok now the dumb questions: Do I need to actually present a +V and -V on RA3 and RA2 or as I understand it setting ADCON1.0 through .3 to 0000 sets it up to use the Vdd and Vss the pic is using itself?
I thought the range would be 0 to 1024 not 0 to 256 why did I think that?
I thank you for your help.
David
Baby steps gotcha.. here goes.
Mack, I acutally started my project with this example from Bruce good call. I did not completely understand it but I did in fact hook up a 5k pot to my board to see how the ADC worked.
This time I pretty much did this line for line with my pressure sensor attached to see how it would react. I am getting a reading. My volt meter is reading .47vdc from the sensor. The serout is bouncing back and fourth between 24 and 25. I would assume that the way Bruce's program is set its 0-255 analog output I would then assume that if my sensor was .5 to 4.5 then the full range of the output would be 4/255 or .0156 volts per increment of the 255 this 24*.0156 = .3744. I think my math is correct there from your previous example but since I can see/know that my sensor is putting out .47 I either did something slighlty wrong or... I've got a mistake in my program.
P.S. Thanks for the help.
David
INCLUDE "modedefs.bas"
' Hardware specific settings
@ DEVICE pic16F877, XT_OSC ' System Clock Options
@ DEVICE pic16F877, WDT_ON ' Watchdog Timer
@ DEVICE pic16F877, PWRT_ON ' Power-On Timer
@ DEVICE pic16F877, BOD_ON ' Brown-Out Detect
@ DEVICE pic16F877, LVP_ON ' Low-Voltage Programming
@ DEVICE pic16F877, CPD_OFF ' Data Memory Code Protect
@ DEVICE pic16F877, WRT_ON ' Flash Memory Word Enable
TRISA = %00000001
' Allocate variables
x var byte
SO VAR PORTC.6
BAUD CON 32
DEFINE OSC 10
ADCON1 = 0 ' Set PortA 0 to A/D inputs
Pause 100 ' Wait for LCD to start
SerOut2 SO,baud,[12,"Hello World AD Test",10,13]
pause 1000
Serout2 so,baud,[12,27,"[1;1H","Reading: "]
Goto mainloop ' Skip subroutines
' Subroutine to read a/d converter
getad:
Pauseus 50 ' Wait for channel to setup
ADCON0.2 = 1 ' Start conversion
Pauseus 50 ' Wait for conversion
Return
' Subroutine to get pot x value
getx:
ADCON0 = $41 ' Set A/D to Fosc/8, Channel 0, On
Gosub getad
x = ADRESH
Return
mainloop:
Gosub getx ' Get x value
Serout2 so,baud,[27,"[1;11H", dec3 x]
Pause 100 ' Do it about 10 times a second
Goto mainloop ' Do it forever
End
I'll take a bow... Can you check one thing for me.
Quote:
Originally Posted by
mackrackit
By George I think he has it :D
Mack,
Thank you for your help today. I can't believe I had so much trouble with that. I wrote a program in mumps a few years ago that converted a number to base 36 for this wacky interface checksum I had to write and I don't think I struggled that hard.
I was able to use my knew found logic and incoporate that same philosphy into my 10 bit program I originally started to work on but stepped back from to get the 8bit to work and understand this a little better. I know you pointed out a couple things about the high and low bits. I won't try to kid you I am not sure what you were trying to tell me there. I put this program together from bits and pieces by looking at others and their examples.
I can run this side by side with the 8 bit program and I get the same results. Is there any advatage of reading the analog value using ADCIN vs. Bruces example? Any disadvatages?
Thanks again today.
David
INCLUDE "modedefs.bas"
' Hardware specific settings
@ DEVICE pic16F877, XT_OSC ' System Clock Options
@ DEVICE pic16F877, WDT_ON ' Watchdog Timer
@ DEVICE pic16F877, PWRT_ON ' Power-On Timer
@ DEVICE pic16F877, BOD_ON ' Brown-Out Detect
@ DEVICE pic16F877, LVP_ON ' Low-Voltage Programming
@ DEVICE pic16F877, CPD_OFF ' Data Memory Code Protect
@ DEVICE pic16F877, WRT_ON ' Flash Memory Word Enable
' ADC definitions 16F877 - (8) 10bit channels
'*****************************
DEFINE ADC_BITS 10 ' (8) 10 Bit channels
DEFINE ADC_CLOCK 3 ' tell the us per osc clock tick?
DEFINE ADC_SAMPLEUS 50 ' how long to sample the pin
DEFINE OSC 10
DEFINE LOADER_USED 1
'INIT ADC
ADCON1 = %10001110 ' Just one analog input needed see page 112 of 16f877 spec
ADCON0 = %11000001 ' Analog converter Fosc/32, ADC module is ON
ADCON0.7 = 1 'I DID THAT ABOVE RIGHT DO I NEED TO RESET THIS OR
'DID MISS SOMETHING ABOUT SETTING VALUES THIS WAY?
'Varibles
SO VAR PORTC.6
ADval VAR word ' Storage for A/D result
PRESSURE VAR word
PRESS VAR word
ADavg VAR WORD[2]
READING var byte
Value VAR WORD
RES var word
'CONSTANTS
AvgCount CON 64 ' = Number of samples to average
FAspread CON 25 ' = Fast Average threshold +/-
BAUD CON 32
'**************************************
'****START OF PROGRAM*****
'**************************************
BEGIN:
SerOut2 SO,baud,[12,"Hello World 10 bit AD Test",10,13]
pause 2000
Serout2 so,baud,[27,"[2;1H","Pressure: "]
MAINLOOP:
ADCIN 0,adval ' Read A/D channel 0 to adval variable
adval = adval - 96
res = adval * 1953
adval = div32 1000
'average out press first before calcuating true pressure
READING = 1
value = adval
gosub average
press = value
Serout2 so,baud,[27,"[2;11H",DEC5 PRESS]
'PRESSURE = ( 58 * PRESS - 58 ) / 100
'pressure = ( 1464 * press - 1464 ) / 10
'value = pressure
'READING = 2
'GOSUB AVERAGE
'PRESSURE = VALUE
'Serout2 so,baud,[27,"[1;11H",DEC5 PRESSURE]
Pause 200 ' Wait period between updates
GOTO MAINLOOP
END
' -=-=-=-=-=-= Average Analog values -=-=-=-=-=-=-=-=-=-=
' compliments of Darryl Taylor
AVERAGE:
IF Value = ADavg[READING] Then NoChange
IF ABS (Value - ADavg[reading]) > FAspread OR Value < AvgCount Then FastAvg
IF ABS (Value - ADavg[reading]) < AvgCount Then RealClose
ADavg[reading] = ADavg[reading] - (ADavg[reading]/AvgCount)
ADavg[reading] = ADavg[reading] + (Value/AvgCount)
GoTo AVGok
FastAvg:
ADavg[reading] = Value
GoTo AVGok
RealClose:
ADavg[reading] = ADavg[reading] - (ADavg[reading]/(AvgCount/4))
ADavg[reading] = ADavg[reading] + (Value/(AvgCount/4))
AVGok:
Value = ADavg[reading] ' Put Average back into Value
NoChange:
Return