Odd analog readings [SOLVED]

So I finally collected enough data to visualise and I’m still seeing massive variation on readings. The graph below shows readings over nearly 24 hours and whilst the trend is correct it’s measuring 2-3 degrees above what I’d expect (this is probably easily explained) however its’s the odd variations that are puzzling me…

1 Like

Adding capacitance to the analog input is not the right answer because unless your also adding some significant resistor ahead of the cap to create a low pass filter in hardware… the cap is doing basically nothing except filtering some very high frequency (and low in power) noise that you wouldn’t see in your ADC reading anyways. 50uA drive current is fine using the highest sampling speed of the ADC as long as your aren’t adding additional resistance in the analog connection between the sensor and A0.

Having the RF couple back in to the analog circuit is possible… but unlikely to cause this much of a deviation in the reading. The coupling would have to be severe and there’s just not enough power there to make a difference.

The problem is most likely ground bounce when the CC3000 turns on its transmitter and starts drawing 150mA of current for a fraction of a second at the same time your sampling the analog value.

The spark core makes an attempt at providing a filtered VDDA, but does not isolate (filter) the digital ground from the analog ground. This is also highly dependent on how the board is layed out, where the high current path to and from the CC3000 is routed in relation to VSSA, etc - the schematic calls out no special handling for VSSA - its just tied to GND. (To be fair, I did not actually look at the gerbers to tell if analog ground routing was taken into consideration or not)

The decoupling capacitor on VDDA is also too large (C13), ST recommends a 10nF cap in addition to your bulk capacitance. Unless you are using a really expensive ultra low ESR 100nF cap for C13, I would change to the 10nF to improve your analog noise floor.

To test for ground bounce on VSSA, solder a jumper wire as close to VSSA is possible (STM32 Pin 8) and put on a scope probe with its GND reference connected near your temperature sensor. I bet you’ll find a 100mV or so bounce every so often with the wifi on.

All valid points @mattande, but if it were ground bounce due to I x R drop from the CC3000 powering up… adding a cap to to the input (A0 to GND) should not make any difference. Actually it should make it worse due to the cap holding voltage well and pushing the A0 pin up with respect to VSSA due to the addition of Vbounce. Yet for many people the cap is helping.

A sketch so we can talk about ground bounce… this is how I’m envisioning your description of it. I have no idea if the layout looks anything like this in reality.

If it is ground bounce, it won’t necessarily be as easy as you describe to measure it. Measuring two ground points that far apart creates a loop antenna which is perfect for picking up electromagnetic radiation (i.e., from the antenna). When you are looking for noise, it’s easy to be fooled when you see it… especially with crappy uncalibrated scope probes. Probably easier just to look at the layout and see if looks like above, and could have up to 1 ohm between the Wifi GND and uC VSSA.

Also, could add a 100k / 100k resistor divider in place of the TMP36, and see what the effect is with and without a 10k ohm in series with a 0.01uF cap directly across A0 input and VSSA on the uC, vs. 10k ohm in series with 0.01uF cap on external A0 and GND pins. If they both look the same, I would not suspect ground bounce.

2 Likes

I don't have one of these sensors but I have used the original versions some years ago. The Analog Devices datasheet says:

Note the 0.1 μF bypass capacitor on the [power] input. This capacitor should be a ceramic type, have very short leads (surface-mount is preferable), and be located as close as possible in physical proximity to the temperature sensor supply pin. Because these temperature sensors operate on very little supply current and may be exposed to very hostile electrical environments, it is important to minimize the effects of radio frequency interference (RFI) on these devices. The effect of RFI on these temperature sensors specifically and on analog ICs in general is manifested as abnormal dc shifts in the output voltage due to the rectification of the high frequency ambient noise by the IC. When the devices are operated in the presence of high frequency radiated or conducted noise, a large value tantalum capacitor (±2.2 μF) placed across the 0.1 μF ceramic capacitor may offer additional noise immunity.

I also don't think a cap on the output is the right idea. Has anyone tried putting the sensor in a small Faraday cage (aluminum foil works) for radiated RFI and using both 0.1 uF and 2.2 uF bypass caps for conducted RFI close to the TMP36? I would try that.

Ok, adding a new theory here on these odd analog readings...

Over in this thread:

@avidan has been having some problems with a Thermistor set up on one of the analog inputs. It's basically a resistor divider from 3.3V to GND. After going around and round on that thread I realized I have a crappy meat probe that I wouldn't mind Sparkulating :spark: (action verb?), so I set off last night to make it happen. To my surprise I found our old friend "odd analog readings" and recalled all of the things that we've come up with in this thread.

I was getting readings that were about 0.24V lower than they should be, but that makes a huge problem with thermistors.

Adding a 0.1uF cap from the A3 input to GND (and not very cleanly I might add) solved the problem and my readings were very consistently close to expected.

Going back to the ADC setup... Odd analog readings [SOLVED] - #21 by BDub - Troubleshooting - Particle

My new theory is that adding a 0.1uF cap to the A3 input (which in this thermistor circuit has a higher impedance than is expected for the ADC setup) effectively lowers the impedance enough that the sample and hold cap inside the STM32's ADC charges up completely. I suspect that if I changed the ADC setup to allow for higher impedances, the readings would be closer to expected... but some small level of capacitance to GND on each analog input should help in all ADC setup cases. Keep in mind the ADC's sample and hold capacitance is only 8pF, so it doesn't take much to charge it up, but the STM32 does need to allow enough time for that to happen as well. When it doesn't allow enough time, lowering the impedance effectively reduces the RC time constant that governs the speed at which a capacitor charges up.

Probably still helps the noisiness of the breadboard as well.

2 Likes

Are you sure the max input impedance spec isn't being violated? It's pretty low.

Not sure what you mean by that, but I'm pretty sure the max impedance currently is 600 ohms.

Assuming that that max allowed impedance is 600 ohms (from the link you gave), then the spec is probably being violated. In the adafruit thermistor tutorial, they're using a 10K resistor with the thermistor, and the thermistor data sheet gives the resistance in the range of 25K-1M. So, at best, the lowest input impedance is around 7.1K (which is larger than 600 :smiley: ).

Edit: however, if so, this should be easily reproducible using a couple of 100K resistors, but I think that has oddly worked for people.

I found this PDF which seems to discuss the issue in detail: http://www.ti.com/lit/an/spna061/spna061.pdf

At this point I’m really just trying to follow along and learn.

Agreed Raldus, but the “spec” is really whatever you set it to. I’ve already gave my recommendation as to what it “should” be set to… but so far no one has really agreed or disagreed. Just got put on the backlog. Some testing was done previously, but results were not positive. Not really sure how to comment on it because I didn’t run the test with the new sampling rates.

That said, my theory about why the cap helps still holds true in my head… not sure what you think about it :smile:

I do want to try various resistor dividers hooked up to each of the 8 analog inputs and my scope, with and without caps, etc… and do a bunch of logging… I think I need to start my own backlog! Hah.

@amanfredi BINGO! Thanks for the link :wink:

Generally, most designers place a large capacitor (Block 3) from the ADC pin to ground (Cext
in Figure 3). This capacitor is used to lower the source impedance of the channel as seen by the
ADC so that the internal 20 pF sample capacitor can be charged quickly.

I like it. :slight_smile: The only (minor) issue is with the TMP36, where we need to keep the cap as small as possible (while still getting good results).

If I have the time, I'll play around with some 100K resistors and an LM358. @amanfredi brought up an interesting point: could we be seeing some weird crosstalk with the other ADC inputs, caused by the analog mux? (My guess is, no, but it's a thought.)

I was having the above problem as well. My 3.3V rail reads 3.29, and at the temperature in my apartment, I was getting 666mV which works out to 16.6 degC using the formula: Temp in °C = [(Vout in mV) - 500] / 10. This is about 1 deg difference from my not so accurate meat thermometer. The ADC values were too high, working out to around 40 degC. I tried the bypass cap suggested in this thread, but the values then seemed too low. In my experience with this sensor on an Arduino, the readings were accurate without the need of any other components. The main difference I see between the code that Adafruit uses in her tutorial and the one for the spark core is measurement frequency. There’s no delay in the spark core example, so the sensor is being read as fast as possible. I think there has to be some time in between readings to allow things to settle. I put in a 1sec delay, and my numbers are now OK. Also, wouldn’t dividing by 4096 be more accurate?

Adafruit’s nice tutorial on using the TMP36 sensor is here:

There's no need for this sensor to settle... it just outputs a voltage continuously based on temperature. So assuming your temperature is not changing any fluctuation in reading is based on noise, ground bounce, or ADC issues.

Kinda can't really compare the Arduino to the Spark Core for performance or features exactly. For the most part the Core is compatible with Arduino software, and most of the hardware.. but there are a bunch of little differences.

Dividing by 4095 is most accurate because 4095 is the code that the ADC outputs when it sees it's reference voltage, i.e. the 3V3* rail (3.29V in your case). Dividing by 4096 would give you a tiny less amount of voltage per bit, which would make your results lower.. but not by much. I see Adafruit's example uses 1024 in their formula... that's wrong :smile: Should be 1023.

Now if you are talking about measuring time and using 12 bit counters that wrap at 4095 back to 0, you would divide results typically by 4096 because 4095 is not the MAX... there is one more tick when the counter wraps from 4095 to 4096 (i.e. 0).

The way to figure it out is ask how many steps do I have between 0 and full scale (3.3V), and each one of those steps is the smallest granularity in your ADC measurement.

Definitely use the 0.01uF cap on your Analog input to GND, and try to keep your wiring short. Use your 3.29V measured value and 4095 for best accuracy.

If all that still gives you much different readings as compared to measuring every 1 second, I would say there is probably something still wrong with the way the ADC is set up.

1 Like

Thank you for that - the capacitor rescued my efforts to measure the resistance of a thermistor.
I had strange but consistent behaviour with a 100k thermistor and the same strange behaviour with pairs of resistors.Adding a 0.1uf capacitor gave sensible results so thank you.
All is still not plain sailing. I originally thought I could avoid using a pullup resistor with the thermistor by using the line:
pinMode(A6, INPUT_PULLUP);
in setup()
This works well on an Arduino, but on my Spark Cores the line doesn’t do anything. If I try to pull up against a 40k resistor to ground the analogue value is 0 (not around 2000 as you’d expect with a 40k pullup resistor).

If you are trying to create any kind of reliable resistor divider to measure a voltage, I would not try to use internal pullups. They are “weak” pullups at best and not really known resistance values. On something like a Arduino or PIC microcontroller they are maybe around 10k… but not always spec’d as such.

@giantmolecules fyi I did a lot of testing today with the ADC on the Spark Core and I did see that long delays with the TMP36 and no capacitor does help… but I still see values off by 10 degrees, and on average it was off by 5 degrees. I’m not exactly sure why that happens, but there are better ways to fix the bad readings. Look out for a post soon about this.

2 Likes

@BDub did you by any chance figure this out?

I did this and mine is off by about 3 degrees. It should read 16 ish but reads 13.xxxx

resurrecting an old thread, …

Yep, check out this thread: