Problem with voltage

mas11

Member
I am once again having trouble measuring voltage. I have had good success with 20 volts but am having trouble with 9 volts. Code is enclosed below. I have search the forum for answers but I can't seem to get any of them to work right. Probably my fault because I am very poor at math. I am trying to read a 9 volt battery to one decimal place. (9.0 volts) If that is possible. I can get one number with no problem, its getting the decimal place that I am struggling with at this time. Any help would be appreciated.
Code:
init:

pause 2000
serout C.2,N2400, (254,1)			'Clear display
serout C.2,N2400,(254,%00111000)		'Set ASCII Characters

main:
	readadc C.4, b2 'read voltage on pin
	b4=b2*9/255     'calculated offset. 
	sertxd (#b3,".",#b4,"volts") 'change to ascii and display of screen
	serout C.2,N2400,(254,128,#b3,".",#b4,"volts") 'display on LCD
	debug
	goto main
I am using a 08m2 chip for testing.
Thank you,

mas11
 
Last edited by a moderator:

mas11

Member
I am using a voltage divider to feed the picaxe. So the max voltage the chip would see is 4.95 volts.

mas11
 

SAborn

Senior Member
b4=b2*9/255 'calculated offset.
This may be giving you an overflow problem.
Try w6 =b2*9/255

You need to use "Debug" to see what the "Raw" adc value is for the 9 volts then you can do some scaling to calibrate the displayed voltage, as b2 at present could be any value.

Try running this

main:
readadc C.4, b2 'read voltage on pin
b4=b2*9/255
Debug
pause 500
goto main

And see what the actual values are for b2 and b4 then you will have some raw values to work with.

Better still would be to use "Readadc10" and a word variable as this will give a adc reading of 0 to 1024 (compared to 0 to 255) and will help the resolution of your readings.
 

mas11

Member
When using w6=b2*9/255 and applying 4.8 volts, w6=5 and b2 = 143. I can get the whole number, just not the decimal and I don't know how going about getting it. Also, not sure how to use the readadc10 correctly. I can't fully comprehend the use of the variables. I struggle with the math. I understand that w0 is the two byte b0,b1.And that a byte is 255 and a word is 1023. But don't know why when you use a word variable, like w6, only b12 shows the same number and nothing in b11. I think that is right. I guess you can't teach an old dog new tricks. .... I can see the b2 value change as I vary the voltage from 0 -9 volts. It changes from 0 to 255. Any suggestions would be of value. Mean while I will plug away at trying different variables and seeing the results..


mas11
 

westaust55

Moderator
Some assumptions here (please confirm):
1. The PICAXE is powered from a regulated 5V supply
2. Your 9V battery has an input voltage of 4.95 at the ADC input giving a READADC value of 252


Try this (untested) code:

Code:
SYMBOL PicAxeVolts = 5      ; PICAXE supply voltage
SYMBOL ADC_FSV	  = 255	; ADC Full scale value
SYMBOL VoltsFactor = 184   ; calculated from 20 * PicAxeVolts * 9 / 4.95 and adjusted up to suit

SYMBOL BatterySens = b2
SYMBOL Integer = b3
SYMBOL Decimal = b4

Init:

	pause 2000
	serout C.2,N2400, (254,1)			'Clear display
	serout C.2,N2400,(254,%00111000)		'Set ASCII Characters

Main:
	readadc C.4, BatterySens ; read voltage on pin

	Integer = BatterySens * VoltsFactor / ADC_FSV / 2

	Decimal = Integer // 10
	Integer = Integer / 10 


	sertxd (#Integer,".",#Decimal,"volts") 'change to ascii and display of screen



	serout C.2,N2400,(254,128,#Integer,".",#Decimal,"volts") 'display on LCD
	debug
	goto main
 

SAborn

Senior Member
In all due respect Westy i feel your code might be a little complicated for the OP at this stage.

Can i make a couple of suggestions here, and back step for a bit.

To demonstrate how a word variable works can you run this code and watch w0 count up.

Main:

inc w0
debug
pause 50
goto main

b0 will advance up to 255 and then b1 will clock over and b0 will reset to zero again and so on, in debug also click on the arrow to expand the screen to show w0 as well.
A word variable will count to 65535 (16 bit value) (not 1024 as you thought) before it overflows back to zero.

Now try this to show how readadc10 works.

Main:

Readadc10 c.4, w0
debug
pause 50
goto main

Now adjust your voltage as before and you will see w0 count from 0 to 1024 (10 bit value) as the value is greater than 255 we need to use a word variable to fit it into.

You can not get decimal points with a picaxe only whole numbers, the way we would show 4.8 in picaxe is as 48, with no decimal point (the decimal point can be added when you write the value to screen )

One way to get a result close to 4.8 volt from the 143 reading you currently have is

143 x 100 / 298 = 48.

Now break the 48 into hundreds, tens and units with bintoascii and write tens to screen then "." then units and on the display you will show 4.8

I guess you can't teach an old dog new tricks. ....
Correct, but you can kick his butt or chew his ear till he understands.
 

mas11

Member
Thank you for your responses. To answer Westaust55 question first, yes your are correct in your assumptions. I will study your code and see if I can understand it. Then I wil try it. And once again I thank you for your help and patiences. Thank you SAborn for your suggestions. I will do what you suggest and see if I can understand how the variables work. Just one question. Where did you get the 298 from in the equation: 143 x 100 / 298 = 48? Thanks again and please keep kicking and chewing...now back to the breadboard and program editor.


mas11
 

SAborn

Senior Member
Just one question. Where did you get the 298 from in the equation: 143 x 100 / 298 = 48?
Kick, Kick, Chew, Chew.

ADC value / actual voltage = calibration value

143 / 4.8 = 29.79 (rounded to 29.8)

As we can not use a decimal point in picaxe, we move the decimal point in the 29.8 over 1 position to 298, if we times the 143 by 10 and divide by 298 we will get 4.8.

Because we want 48 and not 4.8 (as picaxe will round 4.8 to 5.0) we times by 100 and divide by 298 to get 48.

Hence.......... 143 x 100 / 298 = 48.

You should sit down with a calculator and do the sums to get a clear picture of the math in your mind.
It really is quite simple stuff and then you can kick yourself for not seeing it. (save me putting my boots back on)
 

mas11

Member
Thanks SAborn. You can keep your boots on. I will play around with the numbers until I get a much clearer picture. I understand where the calibration value comes from now and the whole numbers. Thanks again,

mas11
 

mas11

Member
After studying Westaust55 code. I have a couple of questions. The codes does work..but….1) Where does the 20 come from in the equation: SYMBOL VoltsFactor = 184 ; calculated from 20 * PicAxeVolts * 9 / 4.95 and adjusted up to suit. 2) Why divide by two: Integer = BatterySens * VoltsFactor / ADC_FSV / 2. I understand the rest of the code, just not these two lines. Can you please explain these two lines?

And to SAborn, thank you for the tips. I am studying them and still playing with the math. I do have a better understanding of how to obtain the calibration values. I am wondering if I should have stuck to values that were multiples of 5 volts…….

mas11
 

westaust55

Moderator
After studying Westaust55 code. I have a couple of questions. The codes does work..but….
1) Where does the 20 come from in the equation: SYMBOL VoltsFactor = 184 ; calculated from 20 * PicAxeVolts * 9 / 4.95 and adjusted up to suit.
To retain 1 decimal place, we need to multiply the value by 10 so that say 12.3 is held as 123 - an integer number that the PICAXE can handle. To keep the number as large as possible without overflow (ie not exceeding 65536) I used a multiplier of 20 with a view to maximising accuracy since we must divide later by 255 – being the highest READADC value. Consider that the READADC value can be as high as 255 so another number approaching 255 is the highest we can allow without overflow in the internal math which can handle 16-bit values (0 to 65536).
2) Why divide by two: Integer = BatterySens * VoltsFactor / ADC_FSV / 2. I understand the rest of the code, just not these two lines. Can you please explain these two lines?
Because I multiplied by 20 instead of just 10 as discussed in response to question 1, my final number is double the actual answer hence we must now divide by 2.


In considering the 1 decimal place involved, for this application you could just stay with a multiplier of 10 and then remove the divide by 2 part.
 

mas11

Member
Thank you westaust55 for the explianation. That clears up a lot of other questions. So its just the matter of how the math is used to come up with the whole integer that the picaxe can handle. I get it now. Thanks again for your help and patience.

mas11
 
Top