Maybe this will help?
http://www.picbasic.co.uk/forum/show...16&postcount=2
Maybe this will help?
http://www.picbasic.co.uk/forum/show...16&postcount=2
Dave
Always wear safety glasses while programming.
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
Lets go with small steps and we will come back to the 10 bit resolution~1024.
And lets not worry about the VREF for now. That will take extra hardware to setup the reference voltage. When we get there all you will need for your application is V+.
Read through these two links, Bruce makes very nice tutorials.
This one is using your chip but does not use the ADCIN command. I like this way and it will help you to understand how the ADC works.
http://rentron.com/PICX2.htm
This one is using ADCIN and a different PIC, but will help with your understanding.
http://rentron.com/serial.htm
Get some of the above working and post the code you have. Then we will go for the 10 bit stuff.
Dave
Always wear safety glasses while programming.
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
Your reading is 24 or 25...
Try calculating 24/255*5v = 0.470v...
That's equivallent to ADCVoltage=ADCCount/ADCMaxScale*VRef
Close enough for you?
BTW... you can't use the above math in PBP as you have to scale it up a little to maintain INTEGER integrity, but I'm sure you can figure how to do that.
And in answer to a previous point you made right at the start, the reason 0-5v Sensors don't actually go 0-5v, is that by going say 0.5v-4.5v you can tell if they go open or short circuit or otherwise go defective as their output will be out of range by being too low or too high. If it actually started at 0v and somebody pulled the plug on the Sensor on your Hospitals Life Support machine, you'd never know - and just might wreck your day.
Yes, Not sure why I am getting this math all assbackwards. I think I've spent to many years as a mumps programmer. I think I get this part so far. My range of .5 to 4.5 isn't relivant... yet. the 24/25 reading is going off a REF of 5v which as you pointed out makes complete sense to me. I keep frogetting to take that into account but I am learining and willing to learn. I jsut can't seem to get past that part I think I need to programatically figure out how to factor in my range is only going to be .5 to 4.5 or 0 to 4 or I must have to give the pic a VREF. If you can point me in the right direction I would appreciate it.
With in mind and I believe I get it so far I will post the program that I have been working on with some success. I think I am close.
Here is my program and my logic/math
So if my scale is 0-1024 with an internal ref of 5v and using an earlier example form Mack I would conclude give my sensor range of 0-150psi with an proportinate output voltage of .5 to 4.5v then...
(150-0) / (4.5-.5) = 37.5 psi per volt
150/1024 at a 5v ref range is .1464 psi per reading
That part I understand completely. The next part is were I am lost.
Converting the .5 -> 4.5v with an offset somehow so that works out to
0 -> 4 then calculating out that voltage to PSI which would be easy would it not be my vdc * 37.5?
0-1024 with a 5v ref gives me .0048 volts per incrment or 204.8 increments per volt. If I leave the 5v ref as it is then I think my offset would be -102.4 so to get the PSI reading I would take:
Given ADVal = reading from the ad result
( ADVal - 102.4 ) * .1464
Let's say I know the PSI is 75 then the calc should work... Half of 1024 would be 512 so ( 512 - 102.4 ) * .1464 = 59.96
but... my reading would not be 512 for 75 psi it would be 512+102.4 right? arghhhhhhhh I'l be back I have to sweep up the last of my hair!
Thanks for your help. I am trying.
P.S. It's a beautiful day here in Pennsylvania
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?
'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
'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 AD Test",10,13]
pause 2000
Serout2 so,baud,[12,27,"[1;1H","Pressure: "]
MAINLOOP:
ADCIN 0,adval ' Read A/D channel 0 to adval variable
Serout2 so,baud,[27,"[3;11H",DEC5 adval]
'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
Do not mix up the ADCIN defines and the bit banging from Bruce's example.
Some more reading..
http://www.picbasic.co.uk/forum/showthread.php?t=2188
And a snippet for 10 bit banging..
Do a search for 10 bit ADC also..Code:ADCON1.7 = 1 gosub getAD press.highbyte = ADRESH press.lowbyte = ADRESL return
http://www.picbasic.co.uk/forum/showthread.php?t=4751
Dave
Always wear safety glasses while programming.
Bookmarks