Created Tue, 26 Aug 2014 07:26:57 +0000 by dominicfhk
Tue, 26 Aug 2014 07:26:57 +0000
Hey guys!
I am using the MAX32 ADC with external voltage reference to digitize a signal, but I noticed the existent of several deadbands on the digitized signal after plotting them (Picture 1). Each of them are EXACTLY 32 counts apart (~0.103V, 480/448/416 etc on my sample).
The code I used as follows: void setup(){ analogReference(EXTERNAL); Serial.begin(115200); } void loop(){ Serial.print(analogRead(A0)); delay(1); }
As for the circuit, I use a 12V battery stepped down to 5V using a switch supply and split it into two ways. 1st way goes to the Vin pin for powering up the MAX32, 2nd way goes to a 3v3 linear regulator and goes to the Aref pin as well as powering up my analog sensors.
I tried all three of my MAX32 but still got the same result. No issue with a regular Arduino nor by using internal reference on the same MAX32 instead of external reference though (Picture 2).
Had anyone run into the same issue? Maybe I happen to have a bunch of faulty MAX32? Or a bug in the IDE? Thank you!!
Tue, 26 Aug 2014 08:51:12 +0000
So, to clarify, you only see this effect when using the external ARef? All other situations it works fine?
Tue, 26 Aug 2014 16:07:28 +0000
That is correct :) ps just ignore the lack of smoothness for the first picture. The period of the signal was shorting so I zoomed to a little bit more than the second picture. What is concerning is deadbands at certain voltage range, and for some reason, exactly 32 apart.
Tue, 26 Aug 2014 20:04:10 +0000
You're right about something strange happening here.
Here's me charging a 3300µF capacitor through a 1KΩ resistor using the internal reference: [attachment=1]int.png[/attachment]
Beautiful and smooth.
Now, I switch to the external Vref, and: [attachment=0]ext.png[/attachment]
Now I don't know if that's hardware or software causing that. It may be the settings of the ADC in software, or it may be some bug in the silicon. I hope it's the former...
Tue, 26 Aug 2014 20:17:37 +0000
Oh man, that's weird... When these types of issue come up don't you just feel like "Could I be the only one who has used this feature up until now?"
Personally, I have never not had a reason to use an external reference on a PIC32 yet.
I don't seen anything in the errata for the chip:
http://ww1.microchip.com/downloads/en/DeviceDoc/80000480N.pdf
However, I did see some other disturbing things in the errata that were hard to read.
Jacob
Tue, 26 Aug 2014 20:44:02 +0000
Just tried it on a Fubarino SD which doesn't have any of the protection diodes etc on the Vref+ pin, and it's exactly the same, so that rules out those.
I have also tried tweaking analogRead() to do 4 successive readings after the switch of the Aref+ pin to give it a chance to settle, but that's no different either.
Again, I have never had call to use an external Aref with the internal ADC. I use them with external high resolution ADCs, but not the internal one.
Tue, 26 Aug 2014 20:55:07 +0000
Oooh, I may have a workaround.
How does this look? [attachment=0]extgood.png[/attachment]
I have changed the conversion clock from 6 TPB (~13MHz) to 512 TPB (around 156KHz). Makes the sampling take longer, but gets more accurate results. 512 TPB is the slowest it goes - now to back-tweak to find the fastest I can have it and still have clean results. It's odd though, as the manual specifically states that you should use the external Vref when doing high speed conversions...
Tue, 26 Aug 2014 21:06:51 +0000
Ok, a TPB of 22 (~3.6MHz) seems to be good. I think I'll submit that as a patch to the core.
For now you can find the file wiring_analog.h (hardware/pic32/cores/pic32/wiring_analog.c) and find the line:
AD1CON3 = 0x0002; //Tad = internal 6 Tpb
and change it to:
AD1CON3 = 0x000B; //Tad = internal 22 Tpb
Tue, 26 Aug 2014 21:42:39 +0000
Oooh, I may have a workaround. How does this look?
Looks like you need to make an example sketch for measure the value of a capacitor.
Jacob
Fri, 29 Aug 2014 02:58:31 +0000
Thank you so much!! Glad to know it's not just me and probably found a potential bug :D
Fri, 29 Aug 2014 17:50:08 +0000
Hmmm sorry I am a complete newbie and was trying to understand the AD1CON3 register, please correct me if I am wrong. I was looking at the manual and it says that it is one of the three ADC control registers. You recommended setting AD1CON3 as 0xB in order to achieve the optimal result using external reference. Now, setting ADRC<0:0> and SAMC<4:0> as 0 basically means that we are using the system clock as our ADC clock instead of its own imprecise, un-calibrated RC oscillator typically only used during sleep mode, and that we are not doing auto sampling. Whereas ADCS<7:0> setups the prescaler relative to the ADC clock, which in this case I assume is 80MHz for the MAX32. Finally, 0xB=0b1011=12Tcy=12(80*10^6)^-1=150ns.
I am wondering... (1) Is my interpretation correct? (3) I am not sure what it means by "Tpb", as the manual never used this term. 150ns=22Tpb, 1Tpb=6.818ns, which I still couldn't guess what it is. (3) The manual also says that setting auto sampling bit as 0 is not recommended, but did not explain further. Well... why? I seems to me that auto-sampling is a hardware feature that samples prior to calling the ADC function such that we don't need to wait for an additional 150ns before getting our data from the ADC result buffer?
Thanks in advance! I am sure this will also help other newbie out :) http://ww1.microchip.com/downloads/en/DeviceDoc/39705b.pdf
Fri, 29 Aug 2014 19:33:57 +0000
Firstly TPB is the Time period of the Peripheral Bus, or, 1/FPB. FPB is usually (though not always - it depends on the bootloader you have on your board) 1:1 with the system clock (some bootloaders are set to 1:8), so usually 80MHz. So TPB is typically 1/80000000 or 0.000000013s (13ns).
Setting ADRC to 0 for the peripheral bus clock ties in with that setting, as TPB is linked to the peripheral bus clock.
SAMC set to 0 is "not allowed", but only has any meaning when auto-sampling is turned on (AD1CON1.ASAM=1), but we do manual sampling (AD1CON1.SAMP=1, delay, AD1CON1.SAMP=0, wait for AD1CON1.DONE==1).
Personally I don't like that method of sampling and prefer a more free-running sampling arrangement where it just samples all the time in the background and you just retrieve the latest result from the buffer - or better still use DMA to fill a buffer in memory with samples over a given time, but this method is pretty much how the Arduino does it, so we have to stick close to that.