cancel
Showing results for 
Search instead for 
Did you mean: 

Noise levels in ADC in STM32L4?

Dave Jones
Associate III
Posted on September 19, 2017 at 23:41

I have a custom board using an STM32L452. I'm doing some testing of the ADC and am finding pretty high levels of noise.

I have a rail-to-rail op amp driving the ADC pin with a 300 ohm resistor from the amp to the pin and a .047uF cap to ground at the pin. The board is laid out well, with lots of ground under and around the chip, and bypass caps on every power pin, right next to the pins. Plus a bulk 10uF ceramic on the Vdd. The Vaa has it's own .1uF and 10uF right next to the pin. The Vdd and the Vaa each have a ferrite separating them from the main board power source (and therefore from each other).

In addition, to try and reduce external noise during my tests I added several extra caps on top of the cap on the ADC pin. A .1uF, a 1uF, and a 10uF ceramic, all stacked on top of the original cap. I did the same series on top of the bypass cap for the Vaa. (these extra caps will be removed after the tests) Those caps are all X7R and progressively larger physical packages to overcome the DC Bias issue ceramic caps have.

The input signal is a constant DC biased in the middle of the input range.

In the DMA interrupt routine I look at each result from that one channel and compare it to a previously stored high and low value. If the new one is higher than the old high, it replaces it. If lower than the old low value, it replaces it. After 100,000 conversions I save that high and low value in another pair of variables and reset the pair used in the comparison. Those saved values are then read via I2C by an external device that displays them and the difference between them. So that LCD shows me the high and low value for the past 100,000 conversions plus the difference between them.

In an ideal ADC that difference would be zero. In my previous version of this board (same op amp driving the ADC) I had a PIC24 chip, and with 12 bit conversions (and no additional caps) I saw typical conversions that fluctuated by about 4-6 numbers. With this board and its STM32L452 I am seeing typical variations in the range of about 13 to 22 numbers. About 4 times more noise than the PIC.

I tried various settings for the ADC clock prescaler, both synchronous and asynchronous, divided by 1, 2, and 4. And  tried all the different sampling times. There were small changes at different settings, but not a large amount. The results ranged from 13-16 numbers different up to 19-22 numbers different. So varying from about 3.5 to 4.5 bits worth of noise instead of the 2 to 2.5 bits worth of noise I had with the PIC.

That means that at 12 bit conversions I'm really only seeing 7 to 8 bits of clean signal.

I tried the oversampling, and it does help. But I need conversions at a decent rate and it would take 256 times oversampling to recover about 4 bits. That would reduce the speed far too much for my application. This is going to process control voltages in the audio frequency range, not extremely slow sensors, where I could get by with excessive filtering in both the hardware and software.

Has anybody else done an extensive test of the ADC on an L4 (or other STM32)? And are you seeing similar amounts of noise in the raw conversions?

14 REPLIES 14
Posted on September 23, 2017 at 22:16

I'm a little confused by your charts. When it says 'unbuffered' are you talking about the A-D input pin coming from a passive source vs coming from the output of an op-amp? If so, I would expect the noise to be much higher if not being driven by an op-amp. If that's the case, then your chart shows that the buffered version had only about 1 digit of noise on it. (even during the time that the PL2303TA was cranking away) I'm driving the ADC input with an op amp through a 300 ohm resistor and cap to ground, as an LPF. The op amp is powered from the VAA rail. (and for these tests, the signals into the op amps are all flat DC)

The troubling part for me is 'I tried to use SysTick for triggering. For that I had to keep up the CPU running. The results were so bad that I even did not record them ☹.'

I can't run the ADC very slowly, and can't shut down the MCU during conversion. I have 5 channels that must be converted constantly, and at as high a speed as possible. The MCU is busy all the time doing other things. I have a 10Megabaud SPI port transmitting about 70% of the time, two I2C ports (100K) reading and writing several hundred times per second, several signals coming in at between 100Hz and 30KHz causing interrupts, several signals going to and from a CPLD. And I haven't even activated the SDMMC port yet, which will be needed.

I did manage to reduce the noise a little bit last night (about 1/2 a bit) by playing with the clocks. I originally tried either the MSI or HSI going into the PLL to make an 80MHz Sysclk, and the ADC using either that or the equivalent signal generated by the PLLSAI1 (set for the same 80 MHz output). With those I was getting about 16-17 digits fluctuation. I then tried using the HSI, but dividing it by 2 before the PLLs, and then multiplying it back up in both PLLs to 80MHz. Using Sysclk at that point for the ADC gave the same 16-17 digits, but using the PLLSAI1 for the ADC gave more like 11-12 digits.

Posted on September 23, 2017 at 22:28

Thanks for the suggestion. I just tried disabling prefetch. It made no difference at all.

Posted on September 23, 2017 at 23:33

“Unbuffered�? refers to the ADC input. The signal impedance is about 100 kΩ and I used one of the internal OpAms (powered from VDDA) as an input buffer. Without it, the edges of the ADC are fed back into the network. This was quite helpful when I tried to analyze the timing.

In fact, the RMS noise of the “buffered�? system is not higher than about one digit. Note that I am always talking about RMS noise and not about peak-to-peak noise.

I must admit that I cannot recall the additional amount of noise introduced by the CPU. But is performed so poor that I did not consider that design.

Posted on September 24, 2017 at 00:27

That's a good point about RMS calculations. I don't find RMS values of noise to be useful when debugging how noisy an A-D is. If I were converting a known bandwidth signal, like audio, it might make sense as a way of understanding the average amount of noise being added. But when converting a fixed DC value it doesn't do that.

My inputs can be anywhere from DC to a high frequency. Any measurable noise at a fixed DC level can be assumed to exist on all other frequency input signals. So for me p-p noise is the indicator of a noise problem with an A-D. An 'ideal' A-D, when fed a stable fixed DC voltage would put out a specific number, and never change that number. If that number fluctuates then there is 'noise' in the conversion. Even if that change in value only happens once  in a million samples, it is still an indication of noise in the system. So I look at the amount of fluctuation over a long period of time. I'm not looking for an average of how much noise there is. Rather what is the worst case. I can only trust the conversion as far as how accurate it is in the worst case. That one bad sample might be the one I use for setting something critical within the system.

Generally the RMS to p-p factor used for noise is 6 or 6.6, though sometimes as high as 8. So one digit RMS would equal between 6 and 8 digits p-p. At 6, it's about 1/2 what I'm seeing. At 8 it's closer to 3/4 of what I'm seeing. So, considering that I'm running the conversion at 80MHz, and running a number of other processes and peripherals at the same time, I guess it's not too bad. Though it's still more than twice the amount of change I used to get on my previous board using the PIC24. (but that part used 8 times more power than the L4)

Posted on September 24, 2017 at 00:35

Thanks. I did find that document a while ago, and in fact went through it again before starting this thread. I think I'm already doing all that I can in hardware (and the above two posts I made today, I think,  would back that up). And I am well aware of software methods to improve the noise. I do use a combination of methods to do that. But the cleaner the input signal, the cleaner and more reliable the filtered result. Plus the wider the bandwidth of the result.

So my goal is to get the raw data as clean as possible. Then add filtering afterwards to clean it up further.