Low ADC Readings

Right! I measured those voltages with the resistors connected to the Core.

I measured the resistor values with the resistors disconnected from the Core.

Forgot that part :stuck_out_tongue_winking_eye: Very tired today... was up til 1am working on my WebServer port and got it working...

FWIW: The 1st reading from the ADC is always low because it's sets up the ADC that first time through... and something something... I dunno. It's just always low.

I calculated the expected value based on the resistors and the 3V3* voltage, not the measured 2.8110V on the input.

So it seems like the ADC is correct in both cases, it's just lowering the voltage at the input somehow.

So I measured the A6 voltage with respect to GND with the Tinker app from the Sparkulator still installed... this is going to blow your mind...

Right after reset the input measures: 2.9683V

After the first reading the input meas: 2.8820V

Before the first reading the pin is set up as open (tri-state). So it makes sense that the voltage is closest to ideal (which is 2.9731V)

After that first reading it's set as an ADC input.. and puts a load on the resistors even when not performing a conversion. I guess I should have expected this... and it's interesting to keep this in mind.

Why the local master puts more load on the resistors than the sparkulator is beyond me though..

1 Like

I am pretty sure the local master is using the two ADC alternating sample technique and DMA that @satishgn set the analogRead() to do. I am not sure what the Sparkulator webIDE is setup to do–I would have to look. In the STM datasheet they have the equation for max source impedance the drive the ADC inputs and it varies considerable with the sample rate you choose, but the highest value is 50k ohm source impedance. I know that latest master slows down the rate too.

I think an LM358 for $0.95 (or less) would go along way toward improving these high impedance situations.

Hmm, so I think the last firmware push to the Sparkulator (build IDE) was about 11 days ago.

I was thinking these would be included, but they’re not yet:

#137 Fixed bug related to odd analog readings
https://github.com/spark/core-firmware/commit/b7ce24a4fb2dfe4f90e597e3a0f568f9ae098cfe

ADC sample time set to 7.5 (within specs for dual slow interleaved mode)
https://github.com/spark/core-firmware/commit/c87bc9d792517b31e958829c58e6d5305e49af54

Added setADCSampleTime() to override the default ADC Sampling Time
https://github.com/spark/core-firmware/commit/b8f55ff9483f87eda64f3841ca27ecc33866d766

You can see which fixes are on the build IDE here: https://github.com/spark/core-firmware/commits/compile-server2

Generally when you re-flash tinker from the mobile apps you’re getting the last golden build of Tinker, which would be really old at this point. We’re trying to make another golden build for this next round of manufacturing, so that should be updated in the next week or so, and we should be rolling that to the build IDE at the same time as well.

Thanks!
David

2 Likes

I would agree for actual high-impedance inputs... however Thevenin's equivalent of 22k and 220k gives you 20k of impedance (22k || 220). That's not very high at all. Also I hate to even have to add a capacitor to the input to give an accurate reading. These little "gotchas" are traps that make new users stumble and get frustrated with the Core.

We really need the Core to have a rock solid ADC. I'm not sure we can get there with the dual slow interleaved method. Correct me if I'm wrong, but it's meant more for high speed sampling than anything. I think we had a higher input impedance with the old single conversion method.

What if we switch the pins from ADC to tri-state and back to ADC before each read?

What sort of precision are we looking for here? >1%? In my experience MCU ADCs aren’t that precise due to a number if factors, clean power being the biggest. (They can be if the board is built with analog performance in mind. Most Arduino-style boards aren’t.)

If the impedance changes when the ADC is enabled, so will the voltage at the node... so I don't think that buys you anything useful.

Precision... I'd say if you measure the voltage on the input, and know the 3V3* (ADCVref) voltage, you should expect an ADC reading within +/-1% of that value.

For that to be possible input impedance should be able to handle something <50k ... higher than that and YMMV, better use an op-amp voltage follower to translate the impedance to something lower.

Total ADC Conversion time should be less than 100us. Less than 50us would be an even better goal.

The readings should be repeatable.

Anything less than this and you're just going to have people complaining all of the time about the ADC, and then why bother having one at that point? The RaspberryPi doesn't have an ADC... and it's one of the main reasons I don't use it much at all. The Spark Core is supposed to be Arduino compatible, so the ADC should be at least as good if not better than the Arduino in my opinion.

I agree with @BDub about the performance of the ADC and with the current master, I think we meet the performance goals with the exception of the very first reading.

  • Measuring voltages with source impedance in the range below 10kohm, I get +/- 1 LSB accuracy relative to a measured 3v3*
  • The +/- 1 LSB is less that 0.1% of full-scale error
  • ADC conversion times are around 40uS
  • Reading are repeatable for me to within the measured accuracy of 3v3*, which does change slightly over time

I think the only remaining software issue is reading the first value. I think the impedance issue can only be “solved” upto around 50kohm source impedance, at which point you have to add external hardware like an op-amp follower.

Not with Dual Slow Interleaved Mode... max is about 19k ohms because the max Ts that can be used is 13.5 :frowning: And I think the default in the core-firmware when set to 7.5cycles is 6.4k ohms. Which could explain why my master readings are so low. So if the purpose of converting the ADC to Dual Slow Interleaved Mode was to increase the input impedance, the goal was not achieved.

Check out my ramblings here...

More info:
http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/DM00050879.pdf

http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/CD00211314.pdf

http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/CD00258017.pdf

Somehow before I figured out that we were using a 12MHz clock for the ADC which slightly increase these numbers.

https://community.particle.io/uploads/particle/136/cbd022233addf534.png

Anyway you slice it, MAX Rain is 50k ohms:

However, I'd rather be closer to that, than 6.4k ohms.

1 Like

HI @BDub

Yes I saw this and I agree. All that I meant was that no matter how we setup the ADC in software, datasheet says that the driving impedance should be a max of 50kohm.

The current master is using Ts=7.5 cycles but is programmable by the user via setADCSampleTime() . As you pointed out, the datasheet recommends only upto 13.5 cycle for the mode it is in now. If you go slower, you might need to change the averaging (currently 20 samples) or the mode to get speed equivalent to Arduino.