I'm working on a project with a joystick and I'm trying to keep everything a simple and low latency as possible. I am reading the pots with the onboard 10bit ADC on the ATmega 32u4 but may be upgrading to either a 16bit ADC or 24 bit ADC. How can I filter noise out of the signals?
-
Have you tried averaging multiple readings yet? Using ADC noise reduction mode?– Ignacio Vazquez-AbramsMar 29, 2014 at 22:27
-
will give that a try now– user862Mar 29, 2014 at 22:42
-
how do you use the built in noise reduction on the 32u4 from the arduino programming enviroment?– user862Mar 29, 2014 at 22:55
-
1Not directly. You need to drop to raw AVR code (not assembly though, just direct register manipulation).– Ignacio Vazquez-AbramsMar 29, 2014 at 22:58
-
1The datasheet has a chapter on the ADC and it talks about noise reduction. There are many aspects of noise reduction, amongst which sleep states and filtered analog power supply rails. For using 16 bit ADC (let alone 24 bit, which is pretty much state of art) to spec, you need a very well designed circuit and PCB and quality components. Otherwise it is just a waste of your money. You can start by changing the reference voltage to one of the internal band gap references. What is the exact problem you are trying to solve?– jippieMar 30, 2014 at 7:35
3 Answers
The Atmel ATmega328 datasheet, section 24.6.1, recommends that you drive the analog input pin with an output impedance of 10 KOhm or less. Also, it recommends that you remove high-frequency components with a low-pass filter. (That low-pass is sometimes called an antialiasing filter).
The simplest possible low-pass filter is a resistor and a capacitor.
+5V +5V
| |
(sensor)---resistor---+---(Arduino)
| | |
| capacitor |
| | |
GND----------------GND--------GND
Contrary to popular belief, it is not possible to make an antialiasing filter in software.
For an initial low-resolution prototype, a quick rule of thumb is to pick the RC time constant at least 10 times as long as the time between samples.
So if you are sampling at around 1000 Samples/second (i.e., a sampling interval of 1 millisecond), then 100 Ohms of resistance and (roughly) 100 uF ceramic capacitor may be adequate. (The RC time constant here is RC == 100 Ohms x 100 uF = 10 milliseconds).
Many joysticks already have a relatively high output impedance; you'll need to use a resistor with that much less resistance to compensate. (Sometimes you don't need any additional resistance; but you still need that capacitor between the Arduino analog input pin and the Arduino ground pin). (Many sensors have an output impedance more than 10 KOhm; people who use them are pretty much forced to use an op-amp chip to get clean signals).
Entire books have been written on signal filtering. In addition, there are many other techniques for getting higher resolution analog signals, higher speed data collection, and trading off between them -- but they are probably overkill for reading the position of a joystick.
One possible approach is to go for a completely software side solution.
Microsmooth is a signal processing library that I am working on that is specifically intended for low latency, low memory signal smoothing. It is still in development, but even now, most of the filters work in less than 100 microseconds per call while giving fairly good accuracy and smoothing. Also, the header file allows for simple configuration for certain filter parameters.
The noise from your joystick pots will drown out any resolution over eight bits regardless. They were designed for the very crude game port on a pc and use a copper wiper on a slab of carbon. Not a terrible recipe for a noise generator.