ADC to Voltage

Mad Professor

Senior Member
Good Day All.

I know this is a very basic question but I have been banging my head on the desk for awile now.

I just want to be able to view my ADC in volts 0-5v.

Code:
#Picaxe 18x

symbol ADC1 = w1
symbol ADC2 = w2
symbol ADC1volts = w3
symbol ADC2volts = w4

main:
readadc10 1,ADC1
readadc10 2,ADC2
ADC1volts = ADC1 *0.0048828125
ADC2volts = ADC2 *0.0048828125
sertxd (ADC1volts,"v ",ADC2volts,"v ")
pause 1000
goto main
I am not sure what is the right way I doing what I want, can someone please show me the error of my ways.

Thanks for your time.
 
Last edited:

manie

Senior Member
The Picaxe chip works with integers ONLY ! So your code would calculate to zero as you cannot use a decimal. To multiply by 0.00488 (which is 4.88mV on Readadc10 referenced to 5V supply...) you must use
ADC2volts = ADC2 * 488 / 100
which calculates to the same value as your example. I would not bother with ALL the decimals, you could probably even use 4.90 without much difference...
Manie
 

SilentScreamer

Senior Member
Might be a bit long winded but this works I think.

Code:
ADC2volts = ADC2 / 2 * 122 / 25 * 2
But then you need to divide by 1000 don't you?
 

manie

Senior Member
10 bit ADC * 488? In a Word variable.
Oooh.
Dippy: True (OOOOHHH).... I was showing the principle, I have had some occasion where I had to "pre" divide by a factor to prevent overflow errors, so yes, one must know your data range to get the calculation right. I use 10bit because its available but have found that 8bit (19.6mV/bit count - 5000mV/255) works fine, and prevents overflow erros when reading higher values. How much accuracy does one require ?

Screamer: Yes, that would work well too. Divide by 1000 if you want result in Volts, else it is mV's...

Manie
 
Last edited:

Mad Professor

Senior Member
I would like to monitor two pressure sensors.

I am going to be using Freescale MPX4250A 20-250kpa pressure sensor in this project.

020kPa = 0.204V nominal, based on a 5.1v input.
250kPa = 4.896V nominal, based on a 5.1v input.
vOut = Vs * (P*0.004) - 0.04

I want to be able to read the ADC input from the PicAxe and send the Sensor Voltage and Kpa Reading to a 16x2 LCD Display.

So the display shows somthing like.
1: 0.81v 50kpa
2: 1.83v 100kpa
 
Last edited:

Dippy

Moderator
I find the equation shown in Fig 4 of that Data Sheet a little ambiguous/unclear, so I'm not sure whether you have quoted it correctly.

If 'twer me, the first task would be to transpose it to P= ..... (which I'm not going to do as a) its badly written, and b) that's your job).

As you will know Vout will be proportional to the ADC.

Once you have done that you should be able to derive some multipliers and dividers etc. to get a reasonable conversion.
Just remember the maximum value of a Word variable. And remember you have the remaindr/modulus function.
Between them you should be able to get reasonable results.

It will take a few minutes of shuffling the equation around, but its good exercise for the noggin. But just sit back and wait a while and someone will do it for you :)
 

Mad Professor

Senior Member
Dippy: Thanks for your reply, yes your right the Fig 4 in the datasheet is unclear, as it's shown as "VOUT = Vs* (0.004 x P-0.04)".

vOut = Vs * (P*0.004) - 0.04
so
20kpa * 0.004 - 0.04 * 5.1volts = 0.204
250kpa * 0.004 - 0.04 * 5.1volts = 4.896

This above works out to the same as the two values given in the datasheet, So I think it's right. :rolleyes:
 

Dippy

Moderator
Excellent. Might be clearer to insert brackets as even your calculation examples are ambiguous to me.

Now you can transpose the equation to give:

P= ....

then insert the Vout = 'some function of ADC' into that.

Do it completely algebraically to start with. i.e. letters & numbers.
Then you can chuck in frig numbers to get over the lack of decimals and word limitations.
You may find that things can cancel out to make the final thing easier to code up.
 

westaust55

Moderator
Try these formula:

For voltage:
Vout = ReadADC10 * 50 /1023 - this to 10 time to extract 1 decimal place ie 50 = 5.0


For pressure in kPa:
Vsfactr = Vs * 88 - typical Vs = 5.1 or 5
Press = READADC10*108 / Vsfactr + 4 * 250 / 100 kPa

Keep in mind that with volts effectively only to 1 decimal place the is error introduced
likewise for the Pressure with whole/integer values of actual pressure (eg 41, 42, 45, etc) the error seems not too bad eg ~0.5% of FSD but at in between pressures (eg 41.5) the erro increases.
It is all a case of what you want/need to achieve.
 
Last edited:

hippy

Ex-Staff (retired)
Using the ** operator and additional processing it should be possible to achieve far higher accuracy in numeric handling than when constrained to 16-bit working. It would also be possible to split numbers up into digit sequences and write routines to process those long hand to extreme accuracy, just like 4-bit calculators did, though there is effort needed to do that ( the umFPU can also do that as a bolt-on peripheral ).

Whether it's worth it in this case is a different matter.
 

Mad Professor

Senior Member
Thanks all for that info and your time.

I will incorp your code into my project, once I have sorted a clean and fixed voltage to my picaxe.
I understand that readadc10 is very senitive, besides a fixed voltage reg and some caps to smooth the input, would you recomend anything else to help keep the power in clean and stable?

As I am still quite new to picaxe I am sure I will have more question in time.

Best Regards.
 
Last edited:

BeanieBots

Moderator
One thing to remember is that the PICAXE power supply is the reference voltage. Hence, good decoupling on the power rail and well thought out track layout. Think of every track as having resistance. Trace any current flows and consider what impact a small volt-drop might have on either the voltage seen directly across the PICAXE power pins or seen directly between the PICAXE 0v pin and the analogue input pin.

Do not allow any of these connections to share current with other devices. Pay particular attention to 0v connections. Even just the current pulled by an LED can change a ReadADC10 value by a few counts due to poor layout.
 

MartinM57

Moderator
Is it going in a car (or other public road vehicle) perchance? A very common use for the MPX4250A....

In which case you need to search here for the power supply design strategies that need to be taken into account for the automotive environment

... and also be prepared for the doom-mongers that will undoubtedly say that you shouldn't even be contemplating doing this, if you're having to ask for design tips you obvioulsy don't know what you're doing so you are fundamentally unqualified to take this on etc etc

Cue the doom-mongers... :)

PS a sprinkling of fuses (wire and poly), an LM2940-T regulator, loads of low ESR caps, inline low value resistors, transorbs, zeners, reverse polarity protection diodes etc (plus automotive quality build) will see that you're OK...
 

Mad Professor

Senior Member
MartinM57: Yes this is Vehicle related, but it not going to be connected to the Vehicle power.

I will have a good long thing about the PCB design before making it, for now I am just testing on good old breadboards.
 

BeanieBots

Moderator
Even if it's not going to be connected to the power supply, don't forget that there will be a lot of electrical noise which can get in via sensor leads. Deisel engines are not too bad but petrol engines have sparks!
Temperature and vibration also need to be thought about.
All-in-all, not a nice place for sensitive electronic components:(
 

retepsnikrep

Senior Member
Using the ** operator and additional processing it should be possible to achieve far higher accuracy in numeric handling than when constrained to 16-bit working.
Hippy

Any examples of the above extra accuracy code for this simple 0-5v problem.

Thanks
 

moxhamj

New Member
Readadc is 10 bits. A word is 16 bits. So, as dippy says, go right up to the max value in a word. If you work with bits then you can work out the number to multiply by, ie 16-10=6 bits. Which is 2^6 or 64. So take your number 0-1023 and multiply by 64 to get 0-65535. That gives the best resolution.

Now you want to make 65535 display 5.00. But you need to do this in integer maths. So, make it 500 instead of 5.00 65535/500 is 131. So divide by 131 and you will get an integer number 0 to 500.

To display this, use bintoascii. Then you will need to add some leading zeros so that 3 displays as 003, 25 as 025 and 150 as 150 - ie the string is always 3 bytes long. Now print it out, but put a . after the first digit. So 3 goes to 003 which displays as 0.03. Then put a V on the end.

I think that works. I can never remember exact bits of code but I've used the theory many times when writing new code with different scaling.
 

MarkLondon

New Member
mV = ADC * 5000 /1023
= ( ADC * 5 ) - ( ADC * 115/1023 )
= ( ADC * 5 ) - ( ADC ** 7368 )

step increment dithers between 4 and 5 mV, hence convert(1022) - convert(1023) = 4mV

Code:
' ADC2VOLT.BAS
' converts 10 bit ADC to mV
' demonstrated in simulator with simulate LCD option

	symbol wrdADC = w1
	symbol wrdmV = w2

	wrdADC=0
	Gosub Convert
	sertxd(#wrdmV, " ")
	' wrdmV=0
	
	wrdADC=1
	Gosub Convert
	sertxd(#wrdmV, " ")
	' wrdmV=5
	
	wrdADC=2
	Gosub Convert
	sertxd(#wrdmV, " ")
	' wrdmV=10
	
	wrdADC=1022
	Gosub Convert
	sertxd(#wrdmV, " ")
	' wrdmV=4996
	
	wrdADC=1023
	Gosub Convert
	sertxd(#wrdmV, " ")
	' wrdmV=5000
	
	end

Convert:
	wrdmV=wrdADC**7368
	wrdmV=wrdADC*5-wrdmV
	Return
Mark
 
Top