Converting ADC Value to Voltage Readout On a Picaxe

Goeytex

Senior Member
This code takes advantage of the FVRSETUP and ADCCONFIG commands to provide good accuracy and good resolution when reading a voltage via ADC and displaying the Voltage on a PE Terminal. Of course the output could be sent instead to an LED or OLED display.

The FVRSETUP Command is available on M2 Chips and on the 28X2 and 40X2

In this code the FVRSETUP and ADCCONFIG commands are used to set the internal ADC reference to 2.048V. This gives .002v per step using ADC10. It also means that a change in the Picaxe supply voltage will not affect the ADC value or accuracy. So, for example, in a battery powered system the ADC reading will remain accurate as the battery voltage changes over time. The Picaxe can be operated down to about 2.4v with no effect on the ADC readings.

The only extra hardware required is a two resistor voltage divider to bring the input to the appropriate range. I used a 20K / 10K divider (1%) that gives a range from 0 to 6 volts to allow some head room if the input voltage is a bit higher than 5 volts. There is no odd math needed because the 2.048 reference is precisely 2 times the 10 bit range of 0 - 1023. Change the resistor divider to change the voltage range.

The reading is stable and the accuracy is excellent and is within about 20 mV as read by a TEK THS730A ( DMM)

Below is the code that I used for a 0 - 6 V range. A simple schematic is attached to show the voltage divider.

Code:
=================
#Picaxe 08M2
#No_Data
Pause 100
'=====================

FVRSETUP FVR2048  [COLOR="#008000"] 'Set Fixed Voltage Reference = 2.048 Volts [/COLOR]
ADCCONFIG %011    [COLOR="#008000"] 'Set ADC to FVR  [/COLOR]

do
      readadc10 C.2, W5 
      w5 = w5  * 6 / 10          [COLOR="#008000"]'Scale/MAP [/COLOR]
      bintoascii w5,b0,b0,b1,b2,b3
      sertxd (b0,b1,".",b2,b3," Volts DC",cr,lf)
      pause 2000

loop
Addendum.

To calculate a voltage range.

Use a resistor divider calculator such as PotDesign, to select the resistors so that the voltage is 2.00v at the center tap when max voltage is applied. Then change the code so that:

w5 = w5 * max_volts / 10

For example: The range needs to be from 0 - 24V:

For 2v at the center tap with 24v applied , the voltage divider resistors will be 12K and 1.5K
Then change the mapping code line to w5 = w5 * 24 / 10

Have Fun

Goeytex
 

Attachments

Last edited:

Snowghost

New Member
Mate!! this is the best thing since bread came sliced!!!!
ive been looking for something to do just this for ages!! (looking, because im not cleaver enough to work it out by my lonesome)
dropped right into the rest of my code,
the code and explanation are GOLD

thanks
Snowy
 

crazynight

Senior Member
Sorry for the daft question but is the "20K / 10K divider" referenced just a 10k and a 20k resistors wired as per the diagram or something different.
 

AllyCat

Senior Member
Hi,

An excellent description that is well worth a "bump" after 5+ years. :)

Just a minor point about the Addendum; I wonder how many people in the 4000+ views so far have noticed that "12K and 1.5K" will not give the correct ratio for a full-scale input of 24 volts ! The required values are, for example, 11K and 1k.

11K is an "E24" (5% range) value, but in practice you'd probably want 12K anyway to give some tolerance for a "nominal" 24 volt supply (and minor errors in the resistor and FVR values). In that case the calibration multiplier becomes 26. Or for a 24 volt battery (lead acid), use 15K with a multiplier of 32 for 32 volts (or strictly 32.75 volts) nominal full-scale.

Cheers, Alan.
 

Speddo

New Member
This looks like what I need.
But 2 questions so I can fully understand the code
What does the command [COLOR"#008000"] mean or do?
In the bintoasci line, there are two b0
in the sertxt line, there is only one b0
Why is this?
Please pardon my ignorance.
Thanks, Bill
 

AllyCat

Senior Member
Hi,

The COLOR commands are a "bug" because the forum software has been changed since that post was written. I believe it can be fixed by (the original author or a moderator) changing the [ code] tag to [ code = rich] , but basically you can just ignore any/all text within square braces [brackets].

The BINTOASCII instruction converts a word value (w5 in this case) into a string of its separate digits, in preparation for "printing" (SERTXD) onto the display (terminal). A word value can need up to 5 characters to represent it (e.g. 12345 becomes "1" "2" "3" "4" "5") but the program-writer knew that here the value would fit into only four characters. In practice, I think BINTOASCII w5 , b0 , b1 , b2 , b3 does work, but the "command syntax" says that 5 variables should be declared, so, rather than use another variable (e.g. b4) which he "knew" would be loaded with a zero, the programmer declared b0 twice, so that the first "0" is immediately overwritten with the second digit.

Cheers, Alan.
 

Speddo

New Member
Hi Alan.
Thanks for your reply post.
I downloaded the code and tried to run it in the simulation but error was reported on the [COLOR"#008000"] command .
I commented out (effectively removed) that command ( [COLOR"#008000"] in the three places where it was used ) and simulation ran perfectly.
Now for the real McCoy, to load it into the 20M2!
I understand your explanation of the BINTOASCI command, thanking you.
If I recall my early basic, perhaps, in the conversion to ASCI, there is a leading null which is reserved for the sign, i.e. + or -
Cheers
Bill
 

AllyCat

Senior Member
Hi Bill,

No, PICaxe Basic doesn't "support" negative numbers, i.e. bytes are defined from 0 to 255, words from 0 to 65535 and will wrap backwards between those numbers if you attempt to decrement (or subtract) past zero. In practice, the Editor/Compiler does support negative numbers to a very limited extent, for example FOR .. TO .. STEP -1 : NEXT and sometimes converts, e.g. -1 to 65535 (which may get truncated later in the calculation).

You can of course define your own "display handler" subroutine(s) to treat bytes/words as "signed" (i.e. -128 to +127 or -32768 to +32767) and some two's complement calculations (particularly addition and subtraction) will work correctly. But it's too easy to slip in an accidental "/" (division) which won't work (been there, got the T-Shirt). Actually, I rarely use BINTOASCII (which is basically a "Pre-set System Macro", because it's more efficient (less memory needed) to do the conversion yourself (mainly using /10 and //10 type operations), when you can (also) take into account factors like a negative Temperature.

Cheers, Alan.
 

Speddo

New Member
Hello Alan.
Thank you for your comments.
I take note of your comments on negative numbers
I loaded up the above code into a 20M2 and the readadc10 results are all over the place.
Connecting the pin to earth (0V) reads "00.00 Volts", but any positive voltage returns:
1.24 v instead of 1.68
1.53 v instead of 3.35
1.53v instead of 5.04 and
1.53 v when floating
Looks like it can't read above 1.53V??
I used a 3x 220ohm voltage divider chain off the 5v rail
I will try some other chips, I read somewhere the readadc is a bit erratic?
I will set up a voltage divider to generate 0-2V and see what happens there.
Regards
Bill
 

premelec

Senior Member
A picture of your setup might help as it looks like a hardware problem - unless you have a noisy power supply, environment or input READADC should be stable...
 

AllyCat

Senior Member
Hi,

No, the ADC should work much better than that, but it is configured in the code above to limit (its full scale) at 2 volts on the input pin. 220 ohm resistors are an unnecessarily low value but should still work, so I suggest you might have calculation error, or a hardware / power supply problem.

In such cases, the first test is to SERTXD the ADC value directly (i.e. #w5) in case there's an issue with the calculation (so it's worth posting the complete, exact program listing). Also, if you only want to measure the PICaxe's supply voltage, then the CALIBADC10 method is better. I've also posted several "improvements" to that command in this Code Snippets section, to give resolutions down to around 1 mV, so the ADC is certainly not fundamentally erratic (if used correctly).

Cheers, Alan.
 

Speddo

New Member
Hi,
Sorry, my ignorance and inexperience is showing.
ADC pin will only read 2v max, so anything over 2v should read 2v -a lesson learned there, except mine reads 1.53v
I have made further experiments with a 21k resistor in series with a 10k potentiometer off the common 5v rail, as per cct above.
I made a number of measurements and all made below 2v report or return approx 0.5V low.
As reported in my earlier post, 1.68v measured by a DVV on the ADC pin has the 20M2 reporting 1.24v, which is 0.44v too low.
I will try out another PicAxe and see what happens.
The code is as above, with the commands commented out as per previous post
I am not sure what the #w5 is (as mentioned by Alan)
SERTXT #w5
maybe??
To answer Premelec - I am using the dedicated PicAxe project board with components plugged into the various solderless holes.
Power supply is included with 5v regulator chip & filters.
regards
Bill
 

AllyCat

Senior Member
Hi,

It's 2 volts because that's what the FVRSETUP command in the Program tells it to be! By default it's the full supply rail.
The correct command would be SERTXD(#w5,cr,lf) plus any other formatting required, in place of (or in addition to) the SERTXD..... command in the original code.
You need to be quite careful when using "Project" Boards, because they may have additional components (e.g. pull-down resistors) that can affect how the components you think you're using will behave. That's why we often need photographs, because we probably won't actually own the appropriate project boad (and the schematic diagrams sometimes can be difficult to find).

Cheers, Alan.
 

Speddo

New Member
Hello Alan.
Yes, I have learned a lot while building what appeared to be a simple project!
I have been rewriting the code segments and following the results on the monitor.
I also learned that variables in PicAxe are not as friendly as they could be.
I can report, thanks to the forum, that I have achieved the intention of my project, at least for stage one!
Voltage reading is a slightly varying -0.03V accuracy (low reading compared to DVV), which is acceptable in my case.
I attach the final code.
 

Attachments

Top