Teensy 4.1 Analog Noise

Status
Not open for further replies.

csl239

New member
Hello all,

First time posting here. I am currently having an issue with reading an analog signal from an off-axis rotary encoder sensor using the Teensy 4.1. The issue is that the signal that I get is fairly noisy; with 10 bit resolution, the signal fluctuates by around plus or minus 5.

My hardware setup consists of a 12V lipo battery powering a MCIGICM LM2596 Buck Converter, which produces the 5V that power the encoder. All of these components and the teensy share a common ground. I am currently powering the teensy via USB.

I have done some troubleshooting:
- I looked at the analog signal noise when all of the above electronics were disconnected from the teensy and the voltage signal was the 3.3V teensy power supply, ground, or a voltage obtained through a voltage divider between 3.3V and ground. The obtained signals were almost noiseless.

- I measured the sensor and buck converter voltages with a multimeter. These voltages did not appear to fluctuate at all on my multimeter (no noise observed with plus or minus 1 mV resolution), but I'm not sure whether or not my multimeter contains any low pass filtering elements which may have eliminated the noise observed with the teensy.

- Connected the teensy analog pin directly to the buck converter Vout+ terminal with the buck converter output voltage set to ~2.7 V. I observed noise of plus or minus 2 (out of 1024) with this setup.

- Connected the teensy analog pin directly to a DC power supply set to 2.7 V. I also continued to observe noise of plus or minus 1 or 2 with this setup.

My test code is as follows:
Code:
const int encPin = 9;

float pinVal;


void setup() {
  Serial.begin(9600);
  delay(1000);


}

void loop() {
  pinVal = analogRead(encPin);

  Serial.println(pinVal);
  delay(500);

}

Does anyone have any ideas regarding where the analog signal noise is coming from and how I can get rid of it? I am a mechanical engineering student and am relatively new to microcontrollers/mechatronics, so I may be missing something simple here. Thanks in advance.

The encoder sensor documentation can be found here: http://www.team221.com/robotopen/product.php?id=155
I purchased the buck converter through Amazon here: https://www.amazon.com/MCIGICM-step...keywords=buck+converter&qid=1613515325&sr=8-4
 
Most multimeters are incapable of showing the kind of relatively high frequency noises that are likely the issue here. A typical ADC method they use is of integrating type, which in itself works as low-pass filter. Oscilloscope could be better tool in this case.

That sensor's documentation is, to put politely, quite "light". Couldn't even find specification of its expected level of noise, or pretty much any decent parameters at all. Or what those SPI pins are used for. Or what that FIR filter mentioned on the page is meant for. Is it so noisy they had to implement some kind of built-in filter?

What to do about the noises? You could try adding a bit of filtering on the analog output, though at such frequency point that it won't affect the values of interest. Also, noises spread around and their noise power can add up, so adding some power supply filtering for that buck converter may help a bit. Or you can accept that noisy ADC data and filter it in digital, assuming the original data rate is many times higher than needed.
 
Last edited:
Switchmode power supplies can have poor noise figure when lightly loaded and worse if input is noisy. Generally a load of around 20% of the rated capacity shuts them up considerably. Try loading it with some R and see if that changes anything. Ok, won't be good for battery run-time but may help find where the noise is coming from. A multimeter set for AC mV may give some idea if noise is present although actual values displayed are unlikely to offer any accuracy.
 
Last edited:
AC millivolt settings on a multimeter may be severely band-limiting to a few 100 Hz or low kHz - AC on a multimeter
is designed for mains, definitely not for measuring broadband noise.

Noise increases with bandwidth, so the faster the ADC the more noise you'd expect to see, but if you then
low-pass filter you can throw away all the higher noise frequencies - its not a good idea to alias all the
high frequency noise down over your signal.

In general a switching supply can be a source of loads of analog noise, and would not be used for analog
circuitry (particularly audio and RF) without first checking that the noise is within suitable limits for the application.
 
Your description is a bit confusing to me.

First, are you reading a quadrature encoder via an ADC? That's not how I would do it but each to their own. Got Datasheet?

When you say "fluctuates by around plus or minus 5", I believe you mean the ADC reading occurs in 10 count range - say 1000 to 1009. That is about 3.5 LSB of variation. You mention fewer bits of variation in other readings you take.

Yes, there is filtering going on in your multimeter. Quite a lot, I am sure. You need an oscilloscope to see the noise. Well, some interpretation of it. Everything has bandwidth limitations to some extent.

Now, microcontroller ADC circuitry is a compromise. The microcontroller generates a lot of digital noise and you will see that even when measuring something super stable such as battery voltage. You can do things like sleep the processor to read the ADC and reduce digital noise. Low pass filters help a lot at the cost of a slower rate of change. Good layout can keep your analog sources away from digital logic or other noise generators and thus lower noise.

If you want rock solid ADC readings, use an external I2C or SPI ADC. Move the ADC close to the source.

I would guess your encoder signals enter the microcontroller via a set of wires - aka EMI antennas. Shielded cables may help.

As to your encoder. Why not read it as digital switches and not worry about noise. If mechanical, then you are probably seeing contact bounce as noise. If it is optical, you won't have contact bounce to worry about. You say off-axis so I assume it is for some sort of motor. Going fully digital from the source is the way to go here.
 
Some quadrature encoders have sin/cos analog output between the digital counts for much finer
precision and smoother velocity sensing.
 
So the actual device is some distance (300-400mm??) from the ADC? I would definitely use shielded wires. If filtering (hw or sw) isn't enough to deal with the noise, I'd use an external ADC as close to the source as possible.

By the way, the device you linked to also supports PWM and UART output. Using either of those would allow you to avoid the analog noise issue.
 
Code:
  pinVal = analogRead(encPin);
  Serial.println(pinVal);
  delay(500);

You should combine samples to reduce high frequency noise. Here is good code to do this:

Code:
// take mean of samples on each side of the median - adjustable,  no dither

double trimmed_mean(const uint16_t array[], const unsigned count, const unsigned n)
{
  qsort(array, count, sizeof(array[0]), compare_u16);

  unsigned sum = 0;
  unsigned n2 = 0;

#if 0
  // classic method is to trim n of the most extreme samples from each end - try n = 20% of count
  for (unsigned i = n; i < (count - n); ++i) {
    sum += array[i];
    ++n2;
  }
#else
  // weight each side method - try n = 1 for a tight histogram
  const int median = array[count / 2];

  for (unsigned i = 0; i < count; ++i) {
    if (((int)array[i] >= median - (int)n) && ((int)array[i] <= median + (int)n)) {
      sum += array[i];
      ++n2;
    }
  } // for
#endif

  //Serial.printf("med %d,n2 %d  %g\n", median, n2,(double)sum / n2);

  return (double)sum / n2;
}
 
Status
Not open for further replies.
Back
Top