Measuring small voltages with 20x2

depeet

New Member
I would like to measure small voltages without the need of an OpAmp. I read that READADC10 has a resolution of 1023 bits and I calculated that 5Volt divided by 1023 is about 4,9mV. Whatever I tried, I could only display 1, 2, 3, 4 or 5 volt. Is there any way to measure the smallest voltages and display them like 0.053
 

inglewoodpete

Senior Member
Remember that PICAXEs only use integers, so you need to manipulate the result of a ReadADC10 to print out a number to 3 decimal places. I presume you are using a word variable to store the ADC result.

Assuming you are using a regulated 5v supply, if you use a formula like Voltage = ADCValue * 49 / 10, this will give the result in millivolts. If you need to display the result as a decimal, like "3.275", use the BinToASCII command. If logging to the terminal program or LCD, insert a decimal point in the appropriate location.
 

hippy

Technical Support
Staff member
The PICAXE is a positive integer only chip so you are probably losing decimal fractions when dividing. You can usually gain additional resolution by scaling and positioning the decimal point when printing the result. For example "ReadAdc10 pin,w0" with a 5V supply -
Code:
w1 = w0 / 1023 * 5
SerTxd( #w1 )         ; Only ever gives "0" or "5"
Code:
w1 = w0 * 5 / 1023
SerTxd( #w1 )         ; Gives "0", "1", "2", "3", "4" or "5"
Code:
w1 = w0 * 50 / 1023
SerTxd( #w1 )         ; Gives "0" through "50", representing 0.0 through 5.0
Wanting to go to greater than one decimal place gets more tricky as the maths involved will cause overflow. That is "w1 = w0 * 500 / 1023" initially seems to work for low values but soon fails to deliver correct results.
 

depeet

New Member
Thanks, it was really simple. For some reason (don't ask me why) I divided by 1023 instead of 10. I did it the right why earlier this week but the values where way of what was expected and started fooling with the code. Apparantly the poweradapter wasn't stable because it seems to work better with a desktop powersupply
 

depeet

New Member
The PICAXE is a positive integer only chip so you are probably losing decimal fractions when dividing. You can usually gain additional resolution by scaling and positioning the decimal point when printing the result. For example "ReadAdc10 pin,w0" with a 5V supply -
Code:
w1 = w0 / 1023 * 5
SerTxd( #w1 )         ; Only ever gives "0" or "5"
Code:
w1 = w0 * 5 / 1023
SerTxd( #w1 )         ; Gives "0", "1", "2", "3", "4" or "5"
Code:
w1 = w0 * 50 / 1023
SerTxd( #w1 )         ; Gives "0" through "50", representing 0.0 through 5.0
Wanting to go to greater than one decimal place gets more tricky as the maths involved will cause overflow. That is "w1 = w0 * 500 / 1023" initially seems to work for low values but soon fails to deliver correct results.
This was the approach I ended up with. And indeed multiplying with 500 gives more then 65535 (word). Ingelwood solved my stupid problem
 

hippy

Technical Support
Staff member
To ten decimal places ...
Code:
#Macro Add(n1,n2,n3,n4,n5)
  w1 = w1 + n1
  w2 = w2 + n2
  w3 = w3 + n3
  w4 = w4 + n4
  w5 = w5 + n5
#EndMacro

Do
  ReadAdc10 C.1, w0
  w1 = 0 : w2 = 0 : w3 = 0 : w4 = 0 : w5 = 0
  If bit9 = 1 Then Add( 2,500,000,000,000 ) End If
  If bit8 = 1 Then Add( 1,250,000,000,000 ) End If
  If bit7 = 1 Then Add( 0,625,000,000,000 ) End If
  If bit6 = 1 Then Add( 0,312,500,000,000 ) End If
  If bit5 = 1 Then Add( 0,156,250,000,000 ) End If
  If bit4 = 1 Then Add( 0,078,125,000,000 ) End If
  If bit3 = 1 Then Add( 0,039,062,500,000 ) End If
  If bit2 = 1 Then Add( 0,019,531,250,000 ) End If
  If bit1 = 1 Then Add( 0,009,765,625,000 ) End If
  If bit0 = 1 Then Add( 0,004,882,812,500 ) End If
  w4 = w5 / 1000 + w4
  w3 = w4 / 1000 + w3
  w2 = w3 / 1000 + w2
  w1 = w2 / 1000 + w1
  SerTxd( #w1, "." )
  BinToAscii w2, b25,b24,b23,b22,b21 : SerTxd( b23,b22,b21, " " )
  BinToAscii w3, b25,b24,b23,b22,b21 : SerTxd( b23,b22,b21, " " )
  BinToAscii w4, b25,b24,b23,b22,b21 : SerTxd( b23,b22,b21, " " )
  BinToAscii w5, b25,b24,b23,b22,b21 : SerTxd( b23, CR, LF )
Loop
That's not quite right, because 1023 doesn't give 5.0 volts, but could be adjusted.
 

BESQUEUT

Senior Member
To ten decimal places ...
Code:
#Macro Add(n1,n2,n3,n4,n5)
  w1 = w1 + n1
  w2 = w2 + n2
  w3 = w3 + n3
  w4 = w4 + n4
  w5 = w5 + n5
#EndMacro

Do
  ReadAdc10 C.1, w0
  w1 = 0 : w2 = 0 : w3 = 0 : w4 = 0 : w5 = 0
  If bit9 = 1 Then Add( 2,500,000,000,000 ) End If
  If bit8 = 1 Then Add( 1,250,000,000,000 ) End If
  If bit7 = 1 Then Add( 0,625,000,000,000 ) End If
  If bit6 = 1 Then Add( 0,312,500,000,000 ) End If
  If bit5 = 1 Then Add( 0,156,250,000,000 ) End If
  If bit4 = 1 Then Add( 0,078,125,000,000 ) End If
  If bit3 = 1 Then Add( 0,039,062,500,000 ) End If
  If bit2 = 1 Then Add( 0,019,531,250,000 ) End If
  If bit1 = 1 Then Add( 0,009,765,625,000 ) End If
  If bit0 = 1 Then Add( 0,004,882,812,500 ) End If
  w4 = w5 / 1000 + w4
  w3 = w4 / 1000 + w3
  w2 = w3 / 1000 + w2
  w1 = w2 / 1000 + w1
  SerTxd( #w1, "." )
  BinToAscii w2, b25,b24,b23,b22,b21 : SerTxd( b23,b22,b21, " " )
  BinToAscii w3, b25,b24,b23,b22,b21 : SerTxd( b23,b22,b21, " " )
  BinToAscii w4, b25,b24,b23,b22,b21 : SerTxd( b23,b22,b21, " " )
  BinToAscii w5, b25,b24,b23,b22,b21 : SerTxd( b23, CR, LF )
Loop
That's not quite right, because 1023 doesn't give 5.0 volts, but could be adjusted.
Why make simple when you know how to make complicated ?
For the fun...
My proposal (not tested : see post #10) V1 :
Code:
Do
  ReadAdc10 C.1, w0
  w1=w0*25+9/10*23+9/10*17+9/10  ' WARNING : to be improved by Picaxe simulation
loop
or V2 :
Code:
Do
  ReadAdc10 C.1, w0
  w1=w0**64063+1/2
  BinToAscii w1, b25,b24,b23,b22,b21
  SerTxd( b24,".",b23,b22,b21 )         ' WARNING : to be improved by Picaxe simulation
loop
Results :
w0IngleWoodV1V2
1023​
5013​
50000​
5000​
1022​
5008​
49950​
4995​
1021​
5003​
49902​
4990​
1020​
4998​
49852​
4985​
1019​
4993​
49804​
4980​
1018​
4988​
49755​
4975​
1017​
4983​
49706​
4970​
 
Last edited:

AllyCat

Senior Member
Hi,

To "scale" by any value from zero up to 2, to an accuracy of better than 0.01%, you can easily use the PICaxe ** operator. For values of 1 and above, just add "the number you started with" (and, within reason, could add multiple times if desired) at the end, otherwise use only the ** part :
Code:
scaled_word = initial_word ** FRACTIONAL_SCALE_FACTOR + initial_word
Where FRACTIONAL_SCALE_FACTOR is the fractional ("decimaL") part, multiplied by 65536 (which may need to be done on a pocket calculator).

Cheers, Alan.
 

BESQUEUT

Senior Member
Hi,

To "scale" by any value from zero up to 2, to an accuracy of better than 0.01%, you can easily use the PICaxe ** operator. For values of 1 and above, just add "the number you started with" (and, within reason, could add multiple times if desired) at the end, otherwise use only the ** part :
Code:
scaled_word = initial_word ** FRACTIONAL_SCALE_FACTOR + initial_word
Where FRACTIONAL_SCALE_FACTOR is the fractional ("decimaL") part, multiplied by 65536 (which may need to be done on a pocket calculator).

Cheers, Alan.
so :
FRACTIONAL_SCALE_FACTOR=500/1023=0.488 758 553
FRACTIONAL_SCALE_FACTOR*65536=32031.3754
w1=w0**32032

w0IngleWoodExcelV1V2Allycat
1 023​
5,013​
5,000 000 000 0​
5,000 0​
5,000​
5,00​
1 022​
5,008​
4,995 112 414 5​
4,995 0​
4,995​
4,99​
1 021​
5,003​
4,990 224 828 9​
4,990 2​
4,990​
4,99​
1 020​
4,998​
4,985 337 243 4​
4,985 2​
4,985​
4,98​
1 019​
4,993​
4,980 449 657 9​
4,980 4​
4,980​
4,98​
1 018​
4,988​
4,975 562 072 3​
4,975 5​
4,975​
4,97​
1 017​
4,983​
4,970 674 486 8​
4,970 6​
4,970​
4,97​
1 016​
4,978​
4,965 786 901 3​
4,965 7​
4,965​
4,96​
1 015​
4,974​
4,960 899 315 7​
4,960 9​
4,960​
4,96​
1014​
4,969​
4,956 011 730 2​
4,955 9​
4,955​
4,95​

6​
0,029​
0,029 325 513 2​
0,029 3​
0,025​
0,02​
5​
0,025​
0,024 437 927 7​
0,024 5​
0,020​
0,02​
4​
0,020​
0,019 550 342 1​
0,019 5​
0,015​
0,01​
3​
0,015​
0,014 662 756 6​
0,014 7​
0,010​
0,01​
2​
0,010​
0,009 775 171 1​
0,009 8​
0,005​
0,00​
1​
0,005​
0,004 887 585 5​
0,004 9​
0,000​
0,00​
0​
0,000​
0,000 000 000 0​
0,000 0​
0,000​
0,00​
NB1 : not tested with Picaxe : Excel calculated

NB2 :Hippy's results :

4,995 117 187 5 for w0=1023

If you add one, you can get
5,000 000 000 0 for w0=1023
but you'll get :
0,004 882 812 5 for w0=0...
 
Last edited:

BESQUEUT

Senior Member
Improved version, with Picaxe simulation :
Code:
#simspeed 1

#Macro Add(n1,n2,n3,n4,n5)
  w1 = w1 + n1
  w2 = w2 + n2
  w3 = w3 + n3
  w4 = w4 + n4
  w5 = w5 + n5
#EndMacro

sertxd (CR,LF," w0 ; Hippy 01; Hippy 02 ; JYB 01 ; JYB 02",CR, LF)
for w0=0 to 5
    sertxd(#w0," ; ")
    gosub hippy01
    gosub hippy02
    gosub JYB01
    gosub JYB02
    sertxd (CR,LF)
next w0
sertxd (CR,LF)
for w0=1017 to 1023
    sertxd(#w0," ; ")
    gosub hippy01
    gosub hippy02
    gosub JYB01
    gosub JYB02
    sertxd (CR,LF)
next w0
end

Hippy01:
  w1 = 0 : w2 = 0 : w3 = 0 : w4 = 0 : w5 = 0
  If bit9 = 1 Then Add( 2,500,000,000,000 ) End If
  If bit8 = 1 Then Add( 1,250,000,000,000 ) End If
  If bit7 = 1 Then Add( 0,625,000,000,000 ) End If
  If bit6 = 1 Then Add( 0,312,500,000,000 ) End If
  If bit5 = 1 Then Add( 0,156,250,000,000 ) End If
  If bit4 = 1 Then Add( 0,078,125,000,000 ) End If
  If bit3 = 1 Then Add( 0,039,062,500,000 ) End If
  If bit2 = 1 Then Add( 0,019,531,250,000 ) End If
  If bit1 = 1 Then Add( 0,009,765,625,000 ) End If
  If bit0 = 1 Then Add( 0,004,882,812,500 ) End If
  w4 = w5 / 1000 + w4
  w3 = w4 / 1000 + w3
  w2 = w3 / 1000 + w2
  w1 = w2 / 1000 + w1
  SerTxd( #w1, "." )
  BinToAscii w2, b25,b24,b23,b22,b21 : SerTxd( b23,b22,b21, " " )
  BinToAscii w3, b25,b24,b23,b22,b21 : SerTxd( b23,b22,b21, " " )
  BinToAscii w4, b25,b24,b23,b22,b21 : SerTxd( b23,b22,b21, " " )
  BinToAscii w5, b25,b24,b23,b22,b21 : SerTxd( b23, " ; " )
return

Hippy02:
  w1 = 0 : w2 = 0 : w3 = 0 : w4 = 0 : w5 = 0
  ' scale factor = 5.000 000 000 0 * 1024/1023
  If bit9 = 1 Then Add( 2,502,443,792,766 ) End If
  If bit8 = 1 Then Add( 1,251,221,896,383 ) End If
  If bit7 = 1 Then Add( 0,625,610,948,192 ) End If
  If bit6 = 1 Then Add( 0,312,805,474,096 ) End If
  If bit5 = 1 Then Add( 0,156,402,737,048 ) End If
  If bit4 = 1 Then Add( 0,078,201,368,524 ) End If
  If bit3 = 1 Then Add( 0,039,100,684,262 ) End If
  If bit2 = 1 Then Add( 0,019,550,342,131 ) End If
  If bit1 = 1 Then Add( 0,009,775,171,065 ) End If
  If bit0 = 1 Then Add( 0,004,887,585,533 ) End If
  w4 = w5 / 1000 + w4
  w3 = w4 / 1000 + w3
  w2 = w3 / 1000 + w2
  w1 = w2 / 1000 + w1
  SerTxd( #w1, "." )
  BinToAscii w2, b25,b24,b23,b22,b21 : SerTxd( b23,b22,b21, " " )
  BinToAscii w3, b25,b24,b23,b22,b21 : SerTxd( b23,b22,b21, " " )
  BinToAscii w4, b25,b24,b23,b22,b21 : SerTxd( b23,b22,b21, " " )
  BinToAscii w5, b25,b24,b23,b22,b21 : SerTxd( b23, " ; " )
return

JYB01:
  w1=w0*23+5/10*17+2/4*5
  BinToAscii w1, b25,b24,b23,b22,b21
  SerTxd( b25,".",b24,b23,b22," ",b21, " ; " )
RETURN


JYB02:
   w1=w0**64063*5+bit0
  BinToAscii w1, b25,b24,b23,b22,b21
  SerTxd( b24,".",b23,b22,b21)
  RETURN
Results :
Code:
w0 ; Hippy 01       ; Hippy 02        ; JYB 01  ; JYB 02
0 ; 0.000 000 000 0 ; 0.000 000 000 0 ; 0.000 0 ; 0.000
1 ; 0.004 882 812 5 ; 0.004 887 585 5 ; 0.004 5 ; 0.001
2 ; 0.009 765 625 0 ; 0.009 775 171 0 ; 0.010 5 ; 0.005
3 ; 0.014 648 437 5 ; 0.014 662 756 5 ; 0.015 0 ; 0.011
4 ; 0.019 531 250 0 ; 0.019 550 342 1 ; 0.019 0 ; 0.015
5 ; 0.024 414 062 5 ; 0.024 437 927 6 ; 0.025 5 ; 0.021

1017 ; 4.965 820 312 5 ; 4.970 674 486 8 ; 4.970 5 ; 4.971
1018 ; 4.970 703 125 0 ; 4.975 562 072 3 ; 4.974 5 ; 4.975
1019 ; 4.975 585 937 5 ; 4.980 449 657 8 ; 4.981 0 ; 4.981
1020 ; 4.980 468 750 0 ; 4.985 337 243 4 ; 4.985 5 ; 4.985
1021 ; 4.985 351 562 5 ; 4.990 224 828 9 ; 4.989 5 ; 4.991
1022 ; 4.990 234 375 0 ; 4.995 112 414 4 ; 4.996 0 ; 4.995
1023 ; 4.995 117 187 5 ; 5.000 000 000 0 ; 5.000 0 ; 5.001
 
Last edited:

hippy

Technical Support
Staff member
Correct to 30 decimal places ...
Code:
w0=1023 : 5.000 000 000 000 000 000 000 000 000 000
w0=0    : 0.000 000 000 000 000 000 000 000 000 000
Code:
#Macro Add(n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13)
  w1  = w1  + n1
  w2  = w2  + n2
  w3  = w3  + n3
  w4  = w4  + n4
  w5  = w5  + n5
  w6  = w6  + n6
  w7  = w7  + n7
  w8  = w8  + n8
  w9  = w9  + n9
  w10 = w10 + n10
  w11 = w11 + n11
  w12 = w12 + n12
  w13 = w13 + n13
#EndMacro

Do
  ReadAdc10 C.1, w0
  w1  = 0 : w2  = 0 : w3  = 0 : w4  = 0
  w5  = 0 : w6  = 0 : w7  = 0 : w8  = 0
  w9  = 0 : w10 = 0 : w11 = 0 : w12 = 0
  w13 = 0
  ;                     1 2   3   4   5   6   7   8   9   10  11  12  13
  If bit9 = 1 Then Add( 2,502,443,792,766,373,411,534,701,857,282,500,000 ) End If
  If bit8 = 1 Then Add( 1,251,221,896,383,186,705,767,350,928,641,300,000 ) End If
  If bit7 = 1 Then Add( 0,625,610,948,191,593,352,883,675,464,320,630,000 ) End If
  If bit6 = 1 Then Add( 0,312,805,474,095,796,676,441,837,732,160,310,000 ) End If
  If bit5 = 1 Then Add( 0,156,402,737,047,898,338,220,918,866,080,160,000 ) End If
  If bit4 = 1 Then Add( 0,078,201,368,523,949,169,110,459,433,040,078,000 ) End If
  If bit3 = 1 Then Add( 0,039,100,684,261,974,584,555,229,716,520,039,000 ) End If
  If bit2 = 1 Then Add( 0,019,550,342,130,987,292,277,614,858,260,020,000 ) End If
  If bit1 = 1 Then Add( 0,009,775,171,065,493,646,138,807,429,130,009,800 ) End If
  If bit0 = 1 Then Add( 0,004,887,585,532,746,823,069,403,714,565,004,900 ) End If
  w12 = w13 / 1000 + w12
  w11 = w12 / 1000 + w11
  w10 = w11 / 1000 + w10
  w9  = w10 / 1000 + w9
  w8  = w9  / 1000 + w8
  w7  = w8  / 1000 + w7
  w6  = w7  / 1000 + w6
  w5  = w6  / 1000 + w5
  w4  = w5  / 1000 + w4
  w3  = w4  / 1000 + w3
  w2  = w3  / 1000 + w2
  w1  = w2  / 1000 + w1
  SerTxd( #w1, "." )
  BinToAscii w2,  b45,b44,b43,b42,b41 : SerTxd( b43,b42,b41, " " )
  BinToAscii w3,  b45,b44,b43,b42,b41 : SerTxd( b43,b42,b41, " " )
  BinToAscii w4,  b45,b44,b43,b42,b41 : SerTxd( b43,b42,b41, " " )
  BinToAscii w5,  b45,b44,b43,b42,b41 : SerTxd( b43,b42,b41, " " )
  BinToAscii w6,  b45,b44,b43,b42,b41 : SerTxd( b43,b42,b41, " " )
  BinToAscii w7,  b45,b44,b43,b42,b41 : SerTxd( b43,b42,b41, " " )
  BinToAscii w8,  b45,b44,b43,b42,b41 : SerTxd( b43,b42,b41, " " )
  BinToAscii w9,  b45,b44,b43,b42,b41 : SerTxd( b43,b42,b41, " " )
  BinToAscii w10, b45,b44,b43,b42,b41 : SerTxd( b43,b42,b41, " " )
  BinToAscii w11, b45,b44,b43,b42,b41 : SerTxd( b43,b42,b41, CR, LF )
Loop
 

BESQUEUT

Senior Member
Correct to 30 decimal places ...
;):ROFLMAO:(y):coffee::coffee::coffee:
Only 11, but less code and one more digit than Hippy 02...

Code:
Hippy03:
    w1 = 0 : w2 = 0 : w3 = 0 : w4 = 0
  ' scale factor = 5.000 000 000 0 * 1024/1023
  If bit9 = 1 Then Addd( 250,244,379,277 ) End If
  If bit8 = 1 Then Addd( 125,122,189,638 ) End If
  If bit7 = 1 Then Addd( 062,561,094,819 ) End If
  If bit6 = 1 Then Addd( 031,280,547,410 ) End If
  If bit5 = 1 Then Addd( 015,640,273,705 ) End If
  If bit4 = 1 Then Addd( 007,820,136,852 ) End If
  If bit3 = 1 Then Addd( 003,910,068,426 ) End If
  If bit2 = 1 Then Addd( 001,955,034,213 ) End If
  If bit1 = 1 Then Addd( 000,977,517,107 ) End If
  If bit0 = 1 Then Addd( 000,488,758,553 ) End If

  w3 = w4 / 1000 + w3
  w2 = w3 / 1000 + w2
  w1 = w2 / 1000 + w1
  BinToAscii w1, b25,b24,b23,b22,b21 : SerTxd( b23,".",b22,b21 )
  BinToAscii w2, b25,b24,b23,b22,b21 : SerTxd( b23," ",b22,b21 )
  BinToAscii w3, b25,b24,b23,b22,b21 : SerTxd( b23," ",b22,b21 )
  BinToAscii w4, b25,b24,b23,b22,b21 : SerTxd( b23," ",b22,b21, " ; " )
return
Results :
Code:
w0 ; Hippy 01       ; Hippy 02        ; Hippy 03         ; JYB 01  ; JYB 02
0 ; 0.000 000 000 0 ; 0.000 000 000 0 ; 0.000 000 000 00 ; 0.000 0 ; 0.000
1 ; 0.004 882 812 5 ; 0.004 887 585 5 ; 0.004 887 585 53 ; 0.004 5 ; 0.001
2 ; 0.009 765 625 0 ; 0.009 775 171 0 ; 0.009 775 171 07 ; 0.010 5 ; 0.005
3 ; 0.014 648 437 5 ; 0.014 662 756 5 ; 0.014 662 756 60 ; 0.015 0 ; 0.011
4 ; 0.019 531 250 0 ; 0.019 550 342 1 ; 0.019 550 342 13 ; 0.019 0 ; 0.015
5 ; 0.024 414 062 5 ; 0.024 437 927 6 ; 0.024 437 927 66 ; 0.025 5 ; 0.021

1017 ; 4.965 820 312 5 ; 4.970 674 486 8 ; 4.970 674 486 80 ; 4.970 5 ; 4.971
1018 ; 4.970 703 125 0 ; 4.975 562 072 3 ; 4.975 562 072 34 ; 4.974 5 ; 4.975
1019 ; 4.975 585 937 5 ; 4.980 449 657 8 ; 4.980 449 657 87 ; 4.981 0 ; 4.981
1020 ; 4.980 468 750 0 ; 4.985 337 243 4 ; 4.985 337 243 40 ; 4.985 5 ; 4.985
1021 ; 4.985 351 562 5 ; 4.990 224 828 9 ; 4.990 224 828 93 ; 4.989 5 ; 4.991
1022 ; 4.990 234 375 0 ; 4.995 112 414 4 ; 4.995 112 414 47 ; 4.996 0 ; 4.995
1023 ; 4.995 117 187 5 ; 5.000 000 000 0 ; 5.000 000 000 00 ; 5.000 0 ; 5.001
my favorite is JYB01:
w1=w0*23+5/10*17+2/4*5

Scale factor is : 50 000 000/1023=48 875.85
25*23*17*5 = 48875
 
Last edited:

inglewoodpete

Senior Member
Meanwhile, back in reality, we are using a 10-bit ADC. Digital representation of analogue values is always +/- 1 bit, since the analogue value may teeter on the transition of the LSB between 0 and 1. So a 10-bit ADC cannot reliably return a value better than 1/512 or 0.2% without oversampling and careful hardware design.

The simpler formula that I suggested: Voltage = ADCValue * 49 / 10 seems to deliver the simplest realistic solution (<0.26%) with the lowest processing overhead.

11, 30 decimal places? Surely we need a PICAXE humour forum group! :)
 

BESQUEUT

Senior Member
Meanwhile, back in reality, we are using a 10-bit ADC. Digital representation of analogue values is always +/- 1 bit, since the analogue value may teeter on the transition of the LSB between 0 and 1. So a 10-bit ADC cannot reliably return a value better than 1/512 or 0.2% without oversampling and careful hardware design.

The simpler formula that I suggested: Voltage = ADCValue * 49 / 10 seems to deliver the simplest realistic solution (<0.26%) with the lowest processing overhead.

11, 30 decimal places? Surely we need a PICAXE humour forum group! :)
If using bin2ascii you can even shorter it to V=ADC*49
Your formula add an error to the ADC error.
Mines are only one or two more operators and show 5.000 0 V or 5.001 for 1023... 🤗
 
Last edited:

marks

Senior Member
two decimal places are usually enough for me but I guess a few more can be handy for calibrations sometimes
Code:
#picaxe 18M2
#terminal 19200
SETFREQ M16
SYMBOL ADCvalue = W3
SYMBOL Volts         = W4
Main:
'ReadADC10 C.0,ADCvalue
' ReadADC10 C.0,Volts
' IF ADCvalue = Volts THEN ConvertV ' display equal ADCvalues
'GOTO main
ADCvalue=1023 ; test

ConvertV:
Volts = ADCvalue *64 **50049   '  **50049 for 5.0000v reference

' if your voltage reference is slightly out you can calculate a new high word
' ie measured 5.03v/5.0000 x 50049 +1 =50350
' ie measured 4.97v/5.0000 x 50049 +1 =49749
DisplayV:
BinTOASCII Volts, b5,b4,b3,b2,b1
Sertxd (13,10,b5,".",b4,b3,b2,b1," Volts") ' 5.0000 v
 

AllyCat

Senior Member
Hi,
11, 30 decimal places? Surely we need a PICAXE humour forum group! :)
Indeed, I don't see much need to be able to report the age of the universe to the nearest picosecond (i.e. 30 significant figures). ;)

However, I have posted code snippets (mainly for M2s) to measure the supply rail RESOLUTION to nearly 16 bits (~1mV, or 0.02%) using the on-chip hardware, and perhaps REPEATABILITY nearly that good. But with most normal components and DMMs, etc., you'll have to work hard to get a genuine ABSOLUTE ACCURACY much better than +/- 1%. But normally I just display the Vdd directly in mV (i.e. 4 digits, not necessarily all significant), to KISS and avoid all the messy formatting of DP and leading zeros, etc. :)

It's not clear from the OP #1 what is his definition of "small voltages", but the sensitivity of the PICaxe ADC can be increased (without using an Op Amp) by reducing the ADC reference voltage. For example, using FVR2048 will improve the resolution to 2mV per lsb (and simplify those pesky maths) and in practice FVR1024 can give raw 1mV resolution (before oversampling), even though not "recommended" by Microchip.

Cheers, Alan.
 

inglewoodpete

Senior Member
It's not clear from the OP #1 what is his definition of "small voltages", but the sensitivity of the PICaxe ADC can be increased (without using an Op Amp) by reducing the ADC reference voltage. For example, using FVR2048 will improve the resolution to 2mV per lsb (and simplify those pesky maths) and in practice FVR1024 can give raw 1mV resolution (before oversampling), even though not "recommended" by Microchip.
Actually, the 20X2 is very limited on super-small voltages. ADCConfig and FVRSetup are not available, although CalibADC is.
 

AllyCat

Senior Member
Hi,

As I've said before, I don't use (any) X2s myself, but I have just taken a look at the 20X2 base PIC data sheet. The hardware is indeed quite "skinny" compared with the 20M2 data sheet, which has 6 more sections ("modules"). However, the block diagrams (in section 20) do appear to show a fully-functional FVR which can be used as a reference to the ADC (as well as the DAC and Comparators).

It's worth noting that some of the PICaxe "Config" and "Setup" commands are little more than POKESFR commands in disguise. So it may well be possible to do much the same as the snippets which I've posted for the M2s, using only SFR commands, (but I have found a few Microchip features that don't always work entirely "as expected"). Also, I did eventually give up on the PICaxe M2s "readinternaltemp" command (which internally makes use of the ADC and FVR modules) and replaced it entirely with POKE/PEEKSFR commands in my alternative "CHIPTEMP" code snippet.

Cheers, Alan.
 

fernando_g

Senior Member
Very interesting thread a tour of force which shows clever ways to achieve surprising results with the limited integer arithmetic.

Having said this, and on the practical side; nowadays that all Picaxe chips support I2C, I tend to use external ADCs instead whenever high accuracy is required.

For a pair of simple reasons:

--12, 14 and even 16 bit converters have become relatively inexpensive.
--They come in single, dual and quad, freeing Picaxe ports for other things. Using a smaller Picaxe might fully offset the cost of the ADC.
--Some have programmable gain amplifiers, which really helps when reading small voltages.
--The internal reference in these converters (when so equipped) is an order of magnitude far more stable with respect to temperature stability and aging, as compared to a voltage regulator which typically powers a Picaxe.
 
Top