ADC Noise when using Sampler Class

Has anyone run into 'noise" samples when using the sampler class on an “April” board (Sparkfun to be specific)

I am using Pin 9 configured as ANALOG IN. I get basically the same “noise” values with almost any circuit connected to the pin.

Can’t see the noise on the scope and am wondering if this has to do with noise on the reference voltage and not the signal itself.

Wednesday, March 06, 2013 21:33:01: Capture started
Wednesday, March 06, 2013 21:33:01: Sampler stopped
Wednesday, March 06, 2013 21:33:01: Value:25344
Wednesday, March 06, 2013 21:33:01: Value:62208
Wednesday, March 06, 2013 21:33:01: Value:58112
Wednesday, March 06, 2013 21:33:01: Value:49920
Wednesday, March 06, 2013 21:33:01: Value:62208
Wednesday, March 06, 2013 21:33:01: Value:45824
Wednesday, March 06, 2013 21:33:01: Value:62208
Wednesday, March 06, 2013 21:33:01: Value:17152
Wednesday, March 06, 2013 21:33:01: Value:33536
Wednesday, March 06, 2013 21:33:01: Value:17152
Wednesday, March 06, 2013 21:33:01: Buffer Size: 2000
Wednesday, March 06, 2013 21:33:01: Max:62464 Min:512 Range:61952 Avg:15867

Would love to here other experiences and suggestions.

Thanks,
Chris

Even using the basic hardware class shows a lot of variation…

`// Simple analog demo on a Sparkfun April
function sample()
{
local val = hardware.pin9.read();
server.log(format("%d",val));
imp.wakeup(1,sample);
}

hardware.pin9.configure(ANALOG_IN);
imp.configure(“Analog”, [], []);
sample();
`

Here’s what I get with the pin floating:

03/08/2013 09:34:13 AM: 3104
03/08/2013 09:34:14 AM: 3184
03/08/2013 09:34:15 AM: 3136
03/08/2013 09:34:16 AM: 3136
03/08/2013 09:34:17 AM: 3168
03/08/2013 09:34:18 AM: 3136
03/08/2013 09:34:19 AM: 3200
03/08/2013 09:34:20 AM: 3104
03/08/2013 09:34:21 AM: 3088
03/08/2013 09:34:22 AM: 3120
03/08/2013 09:34:23 AM: 3008
03/08/2013 09:34:24 AM: 3168

And here’s what I get with a pot connected between 3V3 and Gnd, wiper on pin 9:

03/08/2013 09:37:56 AM: 28374
03/08/2013 09:37:57 AM: 28214
03/08/2013 09:37:58 AM: 28582
03/08/2013 09:37:59 AM: 28326
03/08/2013 09:38:00 AM: 28150
03/08/2013 09:38:01 AM: 28214
03/08/2013 09:38:02 AM: 28646
03/08/2013 09:38:03 AM: 28967
03/08/2013 09:38:04 AM: 28855

Yes, there will be noise, as there is on any ADC. Also note that the ADC is only 12 bit and so the last 4 bits of the sample are not actual valid data.

The ADC also takes significant charge from the pin when it samples, so depending on the sampling rate and output impedance of what you’re connecting to the pin, you’ll see variation from that too. If this is a problem, you should use a unity gain buffer amp on the input.

sjm - Thanks for posting those samples. Could I ask which impee board are you using? As you can see from my samples, I have some noise source that is giving brief samples that are almost rail-to-rail making this unusable. I’m beginning to think it may be the switcher on the April board but don’t have a good enough scope to see what is really going on.

Hugo - Thanks for the guidance. Many MCU/DSP data sheets will have a section on the ADC which provides some details on the equivalent input circuit and recommendation for the holdup sampling cap. Do you have anything from your supplier that you can pass along?

Thank you both,
Chris

The first line in my code above gives you a clue as to the board :wink:

But as Hugo pointed out, these are 12 bit values left aligned (and according to the wiki, the bottom 4 bits are copies of the top 4*). With this in mind, doing a (val>>4) does improve it somewhat.

  • not sure why they did this, I would have kept it right aligned, and masked out the top 4 bits.

I suspect the ADC external input impedance will be around 50k, with a sampling switch resistance of 1k, shunted by a sample/hold cap of 8pF. External parasitic capacitance will be at least 7pF (these are typical values for a STM32F10xxx).

not sure why they did this, I would have kept it right aligned, and masked out the top 4 bits

This way, if a future hardware revision should contain a genuine 16-bit ADC, your code will still work.

Peter

@cnstjohn The cpu is an stm32f205, datasheet is on the ST.com website. The imp card has a shared AGND/DGND (through a connector, no less) which doesn’t help with ground noise, but it’s not been too bad in our experience.

@Hugo - Thanks for info. I’ll do my home work on the MCU details there.

@sjm - missed the impee reference ( reading too fast ). Your data shows the kind of variation I would have expected. I’d be curious to see if you get the same kind of readings with the sampler class on your April board.

I’m beginning to suspect the reference voltage. I’m feeding the board with a very clean 5v supply but there may be some switching noise from the 3v3 buck. Just haven’t had enough time to dig in more.

Thanks again for all for the help.

@cnstjohn VREF noise is quite possible. The imp module has VREF broken out separately which allows you to clean it up - the imp card has no such luxury due to the small number of pins.

I see similar results when using the sampler class. It doesn’t appear to be as “clean” as the basic read() function. As before, this is just a pot wired from 3V3 to GND, wiper on pin 9.

`// Analog test using sampler class on Sparkfun April

function DataReady(buffer, length)
{
local i;
if (length > 0)
{
for (i=0;i<length;i+=2)
server.log(format("%d",buffer[i]*256+buffer[i+1]));
}
}

function StopSampler()
{
hardware.sampler.stop();
}

buffer <- blob(2000);
imp.configure(“Sampler Demo”, [], []);
hardware.sampler.configure(hardware.pin9, 10, [buffer], DataReady);
hardware.sampler.start();
imp.wakeup(2, StopSampler);
`

03/13/2013 09:54:56 AM: 30319
03/13/2013 09:54:56 AM: 22126
03/13/2013 09:54:56 AM: 42606
03/13/2013 09:54:56 AM: 42607
03/13/2013 09:54:56 AM: 54895
03/13/2013 09:54:56 AM: 26223
03/13/2013 09:54:56 AM: 26223
03/13/2013 09:54:56 AM: 22127
03/13/2013 09:54:56 AM: 13935
03/13/2013 09:54:56 AM: 58991
03/13/2013 09:54:56 AM: 63086
03/13/2013 09:54:56 AM: 30318
03/13/2013 09:54:56 AM: 22126
03/13/2013 09:54:56 AM: 54894
03/13/2013 09:54:56 AM: 58990
03/13/2013 09:54:56 AM: 30318
03/13/2013 09:54:56 AM: 50797
03/13/2013 09:54:56 AM: 22126
03/13/2013 09:54:56 AM: 5743
03/13/2013 09:54:56 AM: 22127
03/13/2013 09:54:56 AM: 18031

And tying the input to 3V3 and GND produces some interesting results:

03/13/2013 09:57:38 AM: 65535
03/13/2013 09:57:38 AM: 61439
03/13/2013 09:57:38 AM: 65535
03/13/2013 09:57:38 AM: 65535
03/13/2013 09:57:38 AM: 61439
03/13/2013 09:57:38 AM: 61439
03/13/2013 09:57:38 AM: 65535
03/13/2013 09:57:38 AM: 65535
03/13/2013 09:57:38 AM: 65535
03/13/2013 09:57:38 AM: 65535
03/13/2013 09:57:38 AM: 57343
03/13/2013 09:57:38 AM: 65535
03/13/2013 09:57:38 AM: 65535
03/13/2013 09:57:38 AM: 65535
03/13/2013 09:57:38 AM: 65535
03/13/2013 09:57:38 AM: 65535
03/13/2013 09:57:38 AM: 65535
03/13/2013 09:57:38 AM: 61439
03/13/2013 09:57:38 AM: 65535
03/13/2013 09:57:38 AM: 65535

03/13/2013 09:58:18 AM: 0
03/13/2013 09:58:18 AM: 0
03/13/2013 09:58:18 AM: 0
03/13/2013 09:58:18 AM: 0
03/13/2013 09:58:18 AM: 0
03/13/2013 09:58:18 AM: 4096
03/13/2013 09:58:18 AM: 0
03/13/2013 09:58:18 AM: 0
03/13/2013 09:58:18 AM: 0
03/13/2013 09:58:18 AM: 0
03/13/2013 09:58:18 AM: 12288
03/13/2013 09:58:18 AM: 0
03/13/2013 09:58:18 AM: 0
03/13/2013 09:58:18 AM: 0
03/13/2013 09:58:18 AM: 0
03/13/2013 09:58:18 AM: 0
03/13/2013 09:58:18 AM: 0
03/13/2013 09:58:18 AM: 0
03/13/2013 09:58:18 AM: 4096
03/13/2013 09:58:18 AM: 0

@sjm - Thanks so much for doing that. Does look very similar to what I have seen. Both those experiments produce great data. Looks like you were running the sample much slower and still getting similar data ( I did both 4k and 8k ). I also dropped in a 1uF cap as a ADC hold up cap on pin 9 without any significant difference in the data.

@Hugo - Is there Anybody up there in the Mothership that has time to confirm these findings on an April board and maybe make some recommendations? My product concept doesn’t need a super ADC but these noise samples will make me look at an external device which would be a cost adder.

Thanks again to both.

server.log(format("%d",buffer[i]*256+buffer[i+1])); // ???

The sampler, like everything else on the imp, is little-endian. I think you meant:

server.log(format("%d",buffer[i]+buffer[i+1]*256));

That would turn your errors of 4096 or 12288 into errors of 16 or 48: that is, either one or three LSBs, which isn’t very much.

Peter

Though I see that it nowhere explicitly says in the wiki that the samples are little-endian. I’ll fix that now.

Peter

Thanks Peter, I wasn’t too clear on that myself. It’s not the first time I’ve been bitten by endian issues, and I’m sure it won’t be the last. Data looks much better when the bytes are swapped:

03/14/2013 01:36:12 PM: 28486
03/14/2013 01:36:12 PM: 28871
03/14/2013 01:36:12 PM: 28198
03/14/2013 01:36:12 PM: 28679
03/14/2013 01:36:12 PM: 28230
03/14/2013 01:36:12 PM: 28582
03/14/2013 01:36:12 PM: 28198
03/14/2013 01:36:12 PM: 28406
03/14/2013 01:36:12 PM: 28454
03/14/2013 01:36:12 PM: 28294
03/14/2013 01:36:12 PM: 28438
03/14/2013 01:36:12 PM: 28342
03/14/2013 01:36:12 PM: 28422
03/14/2013 01:36:12 PM: 28310
03/14/2013 01:36:12 PM: 28390
03/14/2013 01:36:12 PM: 28374
03/14/2013 01:36:12 PM: 28358
03/14/2013 01:36:12 PM: 28278
03/14/2013 01:36:12 PM: 28438
03/14/2013 01:36:13 PM: 28278

@Peter - You may have also hit on my issue. I am processing values from the blob as follows:
value = swap2(buffer);

The results looked reasonable but I didn’t check closely. The assumption was that this would create and MSB left justified 16bit number that I could do some math on. Sounds like this is not the case.

When you update the wiki it would really be great to see some examples of how you process the blob buffer into properly ordered 12bit values that you can use with the math class.

Thanks again.

There should be no need to call swap2(). Either read the values bytewise, like in SJM’s “DataReady” function (but corrected for endianness as per my post above), or read them as 16-bit integers directly using blob.readn():
function DataReady(buffer, length) { local i; if (length > 0) { buffer.seek(0); for (i=0; i<length; i+=2) { server.log(format("%d",buffer.readn("w"))); } } }

Either way, you end up with integers in the range 0-65535 (inclusive) that you can then do your further processing on.

Peter

Peter,

I tried modifying my code per your “readn” suggestion as follow:
local val;
buffer.seek(0);
for (local i=0; i<length; i=i+2) {
//val = swap2(buffer[i]);
val = buffer.readn(“w”);

but when it runs produces:

Saturday, March 16, 2013 10:47:59: ERROR: invalid format
Saturday, March 16, 2013 10:47:59: ERROR: at samplesReady:28

Any thoughts on what else I have not included?

Thanks!

I think the forums have mangled your code snippet… could you email or private-message me the whole thing, so I can take a look?

ta,
Peter

I think the issue is that it should be ‘w’ (single quotes) not “w” (double quotes)?

@Peter - Sorry. The code snippet is really poor now that I look at it again. Was trying to just grab the important statements. Also didn’t check the squirrel manual close on the readn() error to see the single vs double quote issue. Parser could use some more verbose error messages in this case.

All in all now if seems the ADC noise was really all about not handling the Blob data right. I used @sjm approach with Peter’s corrections for little endianess and now the readings are stable.

Would be great to see some of this flow into the manual on the sampler class with some examples.

I am able to move forward to the next phase of my project

Thanks again to all for the help.