cancel
Showing results for 
Search instead for 
Did you mean: 

Strangely accurate ADC noise

EThom.3
Senior II

I've been struggling with a strange ADC problem for a while, and have now made some interesting observations.

The scenario

I'm using an STM32G474, where HRTIM directly controls a peltier driver for temperature regulation. Temperatures are measured by ADC4 (12 bit resolution), running in DMA circular mode, triggered by TIM7, at 1 kHz. This works. Temperatures are coming in, and are being used for PID regulation.

The problem

Quite often – perhaps always – some of the temperature readings are being disturbed, but only at certain temperatures. At first, I thought that it was random noise, but in a graph the noise looks strange. Not random at all.

After monitoring the raw ADC values that the DMA has thrown into memory, I discovered something that might be a clue – or it might just be a source of confusion. Every time a noisy sequence occurs, the ADC readout jumps to a lower nearby value where the five least significant bits are all 1, i.e. xxxx xxx1 1111. This is not random noise. It is if as the values are rounded down to nearest 0x001F.

A single spurious readout once in a while can be handled. But when this occurs, it happens so much that the PID regulation is disturbed.

The disturbances are visible in this chart. The orange trace are raw ADC samples, copied directly from the array that the DMA dumps the ADC values in. ADC values are on the right hand axis (decimal). The blue trace is the converted temperature readout, which is where I first noticed the problem.

Big chart 1.png

The disturbing ADC values in this example are 0x073F, 0x07BF, 0x083F and 0x08BF. All ending with the 11111 bit pattern, and exactly 128 ADC counts apart. I have also run tests where the spacing was 64 counts. This also tells me that this isn't random noise.

Some zoomed-in examples:

83F - 1.png

73F - 1.png

Apparently, it doesn't matter if the temperature is slowly moving up or down:

7BF - 1.png

83F - 2.png

During other tests, I have observed this behaviour at other values – but always with the xxxx xxx1 1111 pattern in the ADC value. I have watched the sampled values in RAM, by using STM32Programmer through the SWD interface. This is where I first spotted the recurring bit pattern.

I've checked my code (obviously), to see that the ADC value array isn't overwritten before is is handled in the interrupt function. The only thing that overwrites this array is the DMA channel.

What does the errata sheet say about this? The only section I've found that might be relevant, is this one:

EThom3_0-1778226117224.png

I'm using all five ADCs for different purposes, all using the same clock source, with prescalers set to 1. Perhaps ADC4 is being disturbed by one of the other ADCs. If this is the case, I may be able to make a work-around.

But again, these aren't random disturbances. They only happen in certain windows, hitting very specific values.

I am unsure about what to show you, regarding setup and code. There is a lot of code in this project. But here is how ADC4 is setup in CubeMX:

EThom3_1-1778226575722.png

Sampling time and offset is the same for all channels.

The function that initialises DMA, and starts ADC4:

void adcInitADC4(void)
{
  ADC4Handle->Instance->CR = ADC_CR_ADVREGEN; // ADC disable
  ADC4Handle->Instance->CR |= ADC_CR_ADCAL; // Start calibration

  ADC4DMAHandle->Instance->CCR &=~ DMA_CCR_EN;              // DMA channel off
  ADC4DMAHandle->Instance->CCR |= DMA_CCR_TCIE;             // Turn on DMA interrupt
  ADC4DMAHandle->Instance->CNDTR = 10;                       // Ten transfers to memory
  ADC4DMAHandle->Instance->CPAR = (uint32_t)&ADC4->DR;      // Set peripheral address (ADC data register)
  ADC4DMAHandle->Instance->CMAR = (uint32_t)&ADC4Buffer[0];   // Set memory address
  ADC4DMAHandle->Instance->CCR |= DMA_CCR_EN;               // Enable DMA

  while (ADC4Handle->Instance->CR & ADC_CR_ADCAL) __asm("NOP");

  ADC4Handle->Instance->CFGR |= ADC_CFGR_DMAEN; // DMA transfer enable

  ADC4Handle->Instance->ISR = ADC_ISR_ADRDY; // Clear ADC ready Flag
  ADC4Handle->Instance->CR |= ADC_CR_ADEN;  // Enable ADC
  while (!(ADC4Handle->Instance->ISR & ADC_ISR_ADRDY)); // Wait for ADC ready
  ADC4Handle->Instance->CR |= ADC_CR_ADSTART;  // Start ADC

  TIM7->CR1 |= TIM_CR1_CEN;
}

Can anyone help shed some light on this weirdness?

4 REPLIES 4
Ozone
Principal III

> During other tests, I have observed this behaviour at other values – but always with the xxxx xxx1 1111 pattern in the ADC value.

I tend to agree, this sounds like a systematic issue.
Have you been able to reproduce it on different boards/PCBs, or is it just one ?

The xxx1.1111 pattern is just one bit short of a carry-over to to the next MSB, so I would not exclude a problem of the individual MCU. 
Although I don't have any G4xx board, to add that.


@Ozone wrote:

Have you been able to reproduce it on different boards/PCBs, or is it just one ?


All the prototype boards of this batch exhibit this behaviour.

Well, that sounds very systematic.
I can't comment on G4xx internals, as mentioned.
Perhaps there is some silicon issue, and ST staff can comment.

Peltier elements are usually quite power-hungry.
Can you exclude power supply / VDDA / VREF issues caused by this external sources ?


@Ozone wrote:

 

Peltier elements are usually quite power-hungry.
Can you exclude power supply / VDDA / VREF issues caused by this external sources ?


This was my first hunch – that the switching circuits were inducing noise into the temperature signals. Other ADC inputs are unaffected, so I've ruled out VDDA and VREF noise. (How do you make subscript, by the way?)

I have also ruled out induced noise, as the issue seems to be tied to specific ADC values, rather than how much power the TECs are consuming. In my test setup, they don't eat much anyway. Typically a few W in the tests that I've shown. There is only the ambient air to fight them.

My next test will be connecting a potentiometer in place of a thermistor, so I can adjust the "temperature" without relying on the peltier drivers.