Skip to main content
Dave Jones
Associate III
September 19, 2017
Question

Noise levels in ADC in STM32L4?

  • September 19, 2017
  • 8 replies
  • 3921 views
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?

    This topic has been closed for replies.

    8 replies

    Rob.Riggs
    Senior
    September 20, 2017
    Posted on September 20, 2017 at 05:49

    Have you tried testing on a STM32L452RE Nucleo64 board?  Testing on a reference design would eliminate potential external issues in your board design.

    I have run into issues sourcing VDD and VDDA from the same power plane.  The LDO I had driving VDD had a fairly poor step response to load (the power supply was optimized for minimum quiescent current in standby) and the load steps were apparent on VDD and VDDA even with the recommended filtering in place.  A 10mA voltage change on VREF was enough to lose 3.5 bits.

    The solution in my case was to use a separate low noise LDO for VDDA that could be shut down in standby.

    Test against a reference design with nothing else going on and see if you still see the same amount of noise.

    Dave Jones
    Associate III
    September 20, 2017
    Posted on September 20, 2017 at 19:12

    Thanks for the reply. I don't have a Nucleo board available to test with. That's why I'm asking about other peoples experiences with this.

    Your experience, and the 3.5 bit reduction in noise is useful information. But it's not clear if you still had noticeable noise after that reduction, before doing any software filtering. If you were converting at full speed, and after adding the fix that gained you 3.5 bits, did you still have 4 bits or so of noise in the raw unfiltered, un-oversampled data? Or was it much lower?

    If you and others are using an L4 and are seeing much less than 4 bits of noise when converting at full speed, and looking at the raw conversion data (no oversampling or software filtering), then it's worth my time to rip apart the hardware and try to reduce noise on the Vaa and ADC input. But if everybody is seeing that level of noise, then it's a internal problem and doesn't require me reworking the board.

    Dave Jones
    Associate III
    September 22, 2017
    Posted on September 22, 2017 at 23:36

    So nobody else has done basic testing to see how much noise they are getting in the ADC when running at full speed, without added oversampling or software filtering?

    HermannKleier
    Associate III
    September 22, 2017
    Posted on September 23, 2017 at 01:17

    One of the nastiest problem I ever debugged was similar to yours. The hardware was Nucleo L476RG based with the application hardware on a proper designed (ground planes + decoupling + short signal lines + buffer amps, input impedance around 100 kΩ !) extension board. That way I eliminated �?just as Riggs stated�? problems with the MCU layout. During measurement, I stopped the MCU (to save power and noise) and let the DMA do the job. Upon completion I transmitted the data via UART to a PC for evaluation and started the next cycle. According to the theory the RMS noise due to discretion of a perfect A/D is 1/√ 12 (approx 0.29 digits). The measured RMS noise was between 0.36 … 0.42 digits. This met the noise level (10.5 … 10.9 bits resolution) as specified in table 65 of

    http://www.st.com/resource/en/datasheet/stm32l476je.pdf

    . But after I had replaced the HAL API by the LL API, the first half of the buffer was noisy (RMS noise about 1 digit equivalent to raising the noise power by a factor of 6) while the second half was fine (around 0.4 digits). “No problem,� I said to myself and enlarged the buffer. This let the noisy part grow as well as the clean part. Inserting a sleep before the next cycle fixed the problem.

    The solution of the puzzle was: Replacing the HAL API by LL I raised the Baud rate. LL was way faster. Doing so, the RS232/USB chip (good ole PL2303 TA) required more power. For high baud rates (1 MBaud) and big buffers (32 KBytes) the voltage converter in the PL2303TA was still running when the next conversion had started already. The interface chip was “in the cable� between the MCU board and the PC. What can we make of it?

    1. If set up properly (hardware and software) the STM32L4 has a low noise A/D converter.
    2. Even off-board components can mess up A/D conversion.
    Oleg Skydan
    Associate II
    September 23, 2017
    Posted on September 23, 2017 at 09:13

    I had a very similar problem with the STM32F407 MCU. It was the trickiest thing I ever debug. The ADC noise was dependent of the code position in the flash memory - adding some NOPs significantly changed the ADC noise. The problem appeared to be inside the MCU. Code position had influence on the flash memory prefetch operation. The solution was to disable ART Flash Prefetcher (bit FLASH_ACR_PRFTEN should be cleared in the FLASH->ACR register). You can try it with you L4 MCU, it may help.

    Dave Jones
    Associate III
    September 23, 2017
    Posted on September 23, 2017 at 22:28

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

    HermannKleier
    Associate III
    September 23, 2017
    Posted on September 23, 2017 at 11:04

    A picture is worth a thousand words. Four pictures are even better. To give you an idea of what you should possibly consider if you are facing A/D noise I browsed my old records.

    0690X00000608L1QAI.png

    This is, where I started. The PL2303TA was bustling about up to period 22 to recover from the 1 MBaud / 32 KByte transmission of the most recent cycle. The RMS noise of the unbuffered (green) system went up to about 20 digits. Keep in mind that the noise of the perfect system is ? 0.29. Buffering (using the internal OpAmp) helped a lot. To investigate the data in the idle period of the PL2303TA, I zoomed the y-scale:

    0690X00000608L6QAI.png

    Same graph as above, just enlarged. After taming the interface (reducing the transmission speed to 19200 Baud), things look much better:

    0690X00000608LVQAY.png

    Now the buffered systems approach the theoretical limit of 0.29. Though the CPU was stopped, I required the timers for triggering the ADC. I tried TIM2, TIM4, and TIM8. The following is a zoomed plot for the buffered systems:

    0690X00000608LQQAY.png

    The graph suggests that the noise could depend on the timer. But to prove that, more measurements would be required. My application used TIM2.

    Bottom line:

    1. Whenever you use the ADCs, evaluate.
    2. The data sheet tells you what you can expect if you are doing a good job.
    3. There are more parameters that I expected. I?d never thought the timers could be a factor too.
    4. 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 ?.
    5. Noise depends on the sampling time (and the input impedance). In my system the S/N did not improve for sampling times beyond 12.5 cycles.
    Dave Jones
    Associate III
    September 23, 2017
    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.

    HermannKleier
    Associate III
    September 23, 2017
    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.

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

    Since two of the suggestions pointed to issues with the voltage regulation, I decided to tack on a separate precision LDO on the Vaa. It's a regulator with 0.1% load regulation and is soldered literally on top of the bypass cap for the Vdda/Vssa, about 1mm away from the chip pins.

    No difference.

    Not entirely surprising, since the main 3.3v regulator is a larger LDO that also has 0.1% load regulation. But it now rules out the regulator.

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

    In order to eliminate noise on the input pin and op-amp as being the issue, I disconnected the pin from the op-amp and simply connected it to a 200 ohm to ground and a 200 ohm to Vaa, with the same stack of ceramic caps (0.047uF, 0.1uF, 1uF, and 10uF) to ground. All very close to the chip. So that's a 100 ohm source impedance. (less, when you count the impedance of the caps)

    It made no difference.

    So with the Vaa ruled out, and the input signal ruled out, I'm down to it being internal interference inside the MCU.

    Vangelis Fortounas
    Associate II
    September 23, 2017
    Posted on September 24, 2017 at 00:07

    Hello Dave.

    Take a look also to

    http://www.st.com/content/ccc/resource/technical/document/application_note/group0/3f/4c/a4/82/bd/63/4e/92/CD00211314/files/CD00211314.pdf/jcr:content/translations/en.CD00211314.pdf

    Has a lot of usefull info, SW and HW methods to improve accuracy and noise figure.

    Regards

    vf

    Dave Jones
    Associate III
    September 24, 2017
    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.