Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10201
Posted: 01:44am 25 Jul 2015
Copy link to clipboard
Print this post
This was discussed a week or two ago.
The attached code (tested on 4.7b23) allows you to read the ADC but optionally use the external reference voltage inputs to improve accuracy. The code does not run on the MM+ (MX470). Each call to the readADC routine takes nine readings and averages the last 8 to improve accuracy.
There are 4 modes of operation of the ADC:
mode=0, Vref+ is AVdd and Vref- is AVss
mode=1, Vref+ external and Vref- is AVss
mode=2, Vref+ AVdd and Vref- external
mode=3, both Vref+ and Vref- are external
mode 0 is the normal way it operates in the Micromite Firmware. Modes 1-3 require reference voltages applied to one or both external inputs.
28-pin VREF+ is on pin 2, VREF- is on pin 3
44-pin VREF+ is on pin 19, VREF- is on pin 20
The readADC routine takes two parameters, the pin number to read and the mode.
All relevant pins (pin to read and reference pins) must previously be set as analogue inputs using SETPIN n,AIN
The routine returns the actual ADC count (0-1023), you then need to convert this to a voltage based on the actual values of Vref+ and/or Vref- and/or AVdd as applicable.
So if Vref+ is 2.048V and Vref- is 1.024V and readADC returns 255 in mode-3 then the voltage is 1.024+ 255/1023*(2.048-1.024) = 1.279V
setpin 19,ain
SETPIN 20,AIN
SETPIN 21,AIN
do
? readADC(21,3)
pause 1000
loop
end
'
' Function readADC
'
' Parameters:
' pin number, must be a valid analogue input pin that has been set up with SETPIN n,AIN
' conversion mode
' mode=0, A/D Voltage reference configuration Vref+ is AVdd and Vref- is AVss
' mode=1, A/D Voltage reference configuration Vref+ external and Vref- is AVss
' mode=2, A/D Voltage reference configuration Vref+ AVdd and Vref- external
' mode=3, A/D Voltage reference configuration both Vref+ and Vref- are external
'
' Pin Usage
' 28-pin VREF+ is on pin 2, VREF- is on pin 3
' 44-pin VREF+ is on pin 19, VREF- is on pin 20
'
'
' NB reference pins must be previously set as analogue inputs using SETPIN refpin,AIN
'
CFunction readADC
00000000
27bdffc0 afbf003c afbe0038 afb70034 afb60030 afb5002c afb40028 afb30024
afb20020 afb1001c afb00018 8c820000 8ca40000 24050001 10850007 24032000
24050002 10850004 24034000 38840003 24036000 0004180b 3c04bf81 8c85f220
7ca5d800 3c040661 24840053 10a40007 3c04bf81 8c85f220 7ca5d800 3c040660
24840053 14a4002c 2404000a 24040002 10440007 24040003 1044000b 24040004
1044000d 3c120002 10000002 3c12000e 00009021 24040005 5044000c 3c120003
10000003 24040006 3c120001 24040006 5044000b 3c120004 24040007 5044000d
3c120005 10000002 24040017 24040017 5044000d 3c12000c 10000002 24040018
24040018 50440044 3c12000b 10000002 24040019 24040019 5044003f 3c12000a
10000002 3842001a 3842001a 3c040009 10000039 0082900a 10440007 2404000b
1044000b 2404000e 1044000d 3c12000a 10000002 3c12000e 3c12000c 2404000f
5044000c 3c120009 10000003 24040013 3c12000b 24040013 5044000b 00009021
24040014 5044000d 3c120001 10000002 24040015 24040015 5044000d 3c120002
10000002 24040016 24040016 5044000d 3c120003 10000002 24040017 24040017
5044000d 3c120004 10000002 24040018 24040018 5044000d 3c120005 10000002
24040019 24040019 5044000b 3c120006 10000002 2404001a 2404001a 50440006
3c120007 10000002 3842001b 3842001b 3c040008 0082900a 3c041000 3c02bf88
ac441064 3c02bf88 ac401068 34048000 3c02bf81 ac449004 24100001 00008821
3c13bf81 3c14bf88 3c15bf88 3c16bf81 3c17ffff 3c1ebf81 34630003 10000002
afa30010 26100001 ae729040 ae806118 aea06108 aed79050 34028f00 afc29020
8fa20010 3c03bf81 ac629010 240200e4 3c03bf81 ac629000 34028000 3c03bf81
ac629008 3c04bf88 3c031000 8c821030 00431024 1040fffd 3c02bf81 8c429070
02228821 24020001 12020020 3c031000 3c02bf88 ac431034 3c029d00 8c420004
0040f809 24040064 2e020009 1440ffde 26100001 3c031000 3c02bf88 ac431064
3c02bf88 ac401068 34038000 3c02bf81 ac439004 001110c2 00001821 8fbf003c
8fbe0038 8fb70034 8fb60030 8fb5002c 8fb40028 8fb30024 8fb20020 8fb1001c
8fb00018 03e00008 27bd0040 3c02bf88 ac431034 3c029d00 8c420004 0040f809
24040064 1000ffbf 00008821
End CFunction 'MIPS32 M4K
Edited by matherp 2015-07-26
MolsonB Regular Member Joined: 25/01/2015 Location: CanadaPosts: 48
Posted: 05:31pm 01 Aug 2015
Copy link to clipboard
Print this post
I'm assuming this still can only go to a max of 3.3V? Most of my sensors are 5V, does it makes sense to do +2.5V (VREF+) and -2.5V (VREF-) ?MkII 44pin - v5.0
ColorMax 2 - v4.5
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10201
Posted: 09:14pm 01 Aug 2015
Copy link to clipboard
Print this post
VREF+ and VREF- must be between GND and VCC. Use a potential divider to scale the input.Edited by matherp 2015-08-03
isochronic Guru Joined: 21/01/2012 Location: AustraliaPosts: 689
Posted: 09:26pm 01 Aug 2015
Copy link to clipboard
Print this post
[ Yay !! can see again :)) or maybe .)) !!]
Uh, I think the AD reference inputs are limited to be within
0.3 v of the AD power levels ?
EDIT - (sort of but not quite) The "Electrical Characteristics" section has an AD blurb, looks like the 10 bit AD has specific limits ( 2 V reference range min ) Edited by chronic 2015-08-03
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10201
Posted: 05:11am 03 Aug 2015
Copy link to clipboard
Print this post
The blurb also says:
I assume this is a..e covering to say that you may not get 10-bit accuracy if VREF+ - VREF- is less than 2V but "actually we haven't got a clue"
Setting VREF+ at 2.048V and VREF- at 1.024V certainly works fine in practice and using a 10-turn pot on the analogue input the ADC counts move up a digit at a time
HankR Senior Member Joined: 02/01/2015 Location: United StatesPosts: 209
Posted: 08:54am 04 Aug 2015
Copy link to clipboard
Print this post
What kind of variation did you see in the separate A/D readings?
What kind of reference did you use and how stable was the measured
voltage if you know?
The A/D averaging is a nice touch, but wondering just how badly it
was needed. Perhaps you did it just based on general experience
and not on recent specific testing.
Hank
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10201
Posted: 09:21pm 04 Aug 2015
Copy link to clipboard
Print this post
PIC ADCs are in my experience pretty poor and subject to lots of "noise" effects, anything that can help improve accuracy is an advantage. Geoff also does multiple readings in the MM firmware so I just did the same with one change, I always eliminate the first reading, this reduces charge effects of the ADC capacitance.
For my testing I just used two 10 turn pots off VCC/GND
Here is my C source:
#define _SUPPRESS_PLIB_WARNING
#include <plib.h>
#define FAM
#include "APIDefs.h"
#define DEVID (*(volatile unsigned int *)0xBF80F220)
#define PIC32MX170F256B_DEVID 0x06610053
#define PIC32MX270F256B_DEVID 0x06600053
#define PIC32MX170F256D_DEVID 0x0661A053
#define PIC32MX270F256D_DEVID 0x0660A053
#define HAS_28PINS ((DEVID & 0xfffffff) == PIC32MX170F256B_DEVID || (DEVID & 0xfffffff) == PIC32MX270F256B_DEVID)
long long readADC(long long *chan, long long *mode){
unsigned int anChan,i,cmode,pin=*chan,m=*mode,val=0;
if(m==0)cmode=ADC_VREF_AVDD_AVSS;/* A/D Voltage reference configuration Vref+ is AVdd and Vref- is AVss */
if(m==1)cmode=ADC_VREF_EXT_AVSS;/* A/D Voltage reference configuration Vref+ external and Vref- is AVss */
if(m==2)cmode=ADC_VREF_AVDD_EXT;/* A/D Voltage reference configuration Vref+ AVdd and Vref- external */
if(m==3)cmode=ADC_VREF_EXT_EXT;/* A/D Voltage reference configuration both Vref+ and Vref- are external */
if(HAS_28PINS) {
if(pin== 0) anChan = ADC_CH0_POS_SAMPLEA_AN14;
if(pin== 2) anChan = ADC_CH0_POS_SAMPLEA_AN0;
if(pin== 3) anChan = ADC_CH0_POS_SAMPLEA_AN1;
if(pin== 4) anChan = ADC_CH0_POS_SAMPLEA_AN2;
if(pin== 5) anChan = ADC_CH0_POS_SAMPLEA_AN3;
if(pin== 6) anChan = ADC_CH0_POS_SAMPLEA_AN4;
if(pin== 7) anChan = ADC_CH0_POS_SAMPLEA_AN5;
if(pin== 23)anChan = ADC_CH0_POS_SAMPLEA_AN12;
if(pin== 24)anChan = ADC_CH0_POS_SAMPLEA_AN11;
if(pin== 25)anChan = ADC_CH0_POS_SAMPLEA_AN10;
if(pin== 26)anChan = ADC_CH0_POS_SAMPLEA_AN9;
} else {
if(pin== 0) anChan = ADC_CH0_POS_SAMPLEA_AN14;
if(pin== 10)anChan = ADC_CH0_POS_SAMPLEA_AN12;
if(pin== 11)anChan = ADC_CH0_POS_SAMPLEA_AN11;
if(pin== 14)anChan = ADC_CH0_POS_SAMPLEA_AN10;
if(pin== 15)anChan = ADC_CH0_POS_SAMPLEA_AN9;
if(pin== 19)anChan = ADC_CH0_POS_SAMPLEA_AN0;
if(pin== 20)anChan = ADC_CH0_POS_SAMPLEA_AN1;
if(pin== 21)anChan = ADC_CH0_POS_SAMPLEA_AN2;
if(pin== 22)anChan = ADC_CH0_POS_SAMPLEA_AN3;
if(pin== 23)anChan = ADC_CH0_POS_SAMPLEA_AN4;
if(pin== 24)anChan = ADC_CH0_POS_SAMPLEA_AN5;
if(pin== 25)anChan = ADC_CH0_POS_SAMPLEA_AN6;
if(pin== 26)anChan = ADC_CH0_POS_SAMPLEA_AN7;
if(pin== 27)anChan = ADC_CH0_POS_SAMPLEA_AN8;
}
CloseADC10();
for(i=0;i<=8;i++){
SetChanADC10( ADC_CH0_NEG_SAMPLEA_NVREF | anChan );
OpenADC10( ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON , \
cmode | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_1| ADC_ALT_BUF_ON | ADC_ALT_INPUT_ON , \
ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_15 , \
0 /* anInput */ , \
SKIP_SCAN_ALL \
);
EnableADC10(); // Enable the ADC
while ( ! mAD1GetIntFlag()) ;
val+= ReadADC10(0); // read the result of the conversion
if(i==0)val=0; //scrap the first reading
mAD1ClearIntFlag();
uSec(100);
}
CloseADC10(); // turn off the ADC so that it does not add to the power drain (particularly in sleep)
return val>>3;
}
Edited by matherp 2015-08-06
Chris Roper Senior Member Joined: 19/05/2015 Location: South AfricaPosts: 280
Posted: 06:26am 06 Aug 2015
Copy link to clipboard
Print this post
You can also use a separate power source, isolated from the digital supply and feed into pin 28 AVdd
I haven't personally had the need to try it but every board I have designed I include a jumper so that AVdd can be disconnected from Vdd and feed separately.
Cheers
Chris
http://caroper.blogspot.com/
redrok Senior Member Joined: 15/09/2014 Location: United StatesPosts: 209
Posted: 04:36pm 15 May 2016
Copy link to clipboard
Print this post
Thanks chronic and matherp;
I was trying to get about 1mV/count for a a resolution of about 1/2 degree C with diode type temperature measurement. I had hoped to do this without the use of an op-amp.
Apparently, as chronic says, the spec doesn't allow this.
I'm sum what heartened, matherp, to see if I can get a bit better than the 2mV/count that your C function may allow.
I will try it and see. If I can get it to work from 0V to 1.024V I can get the 1/2 C resolution. Better yet if .0512V to 1.024V I get 1/4 C resolution.
Anyway, a floating A2D is useful and should have better noise response than one connected to digital lines. And very useful in Bridge circuits.