Tuesday, July 30, 2013

Oversampling, Decimation, Filtering

To convert Sharp IR Rangers to I2C, I now use an ATtiny44a for signal processing.

Sharp Range Sensor I2C Adapter prototypes.
The new approach, guided by Atmel application note AVR121 (pdf), works much better than the dedicated ADCs I was using and will form the core of my Sharp I2C adapter, after I make a few usability tweaks and finish the firmware.

Read on to see how I improved performance with oversampling and filtering.

This is what I was seeing before on both board designs using dedicated I2C ADCs.
Before: the full range is 10-bit (1024 lsb)
The resolution was 10 bits (0-1024) and the noise was high, varying by 50, or ~5-6 bits. Woefully unacceptable.

Here's the new design with signal processing prototyped on a Tiny85, configured for 13-bit resolution and mild filtering.

After: the full resolution is 13-bit (8192 lsb)

I'd say that's better, wouldn't you? The noise is 2 LSB, 2-bit out of 13-bit resolution through oversampling and filtering implemented with a so-called leaky integrator.

Signal bandwidth can keep up with me rapidly waving my hand back and forth in front of the sensor so bandwidth seems to be in the ball park.


Oversampling involves sampling a stable signal with a little bit of noise a bunch of times to arrive at a sort-of average, but with a higher resolution.

Say you have a 10-bit ADC with a range of 0 to 210 and you want to oversample to add n=2 bits of resolution (12 bit total). To do that, you have to sample it 42 (16) times. If instead you wanted n=6 bits of additional resolution (16 bit total) you would oversample 46 (4096) times.

So you take your 4n samples, during which time the signal must remain stable, yet slightly noisy, and add them up. When you're done adding, you decimate, dividing by 2n (right shift by n). For 16 bit resolution, n=6, for 12 bit, n=2 assuming a 10-bit ADC.

Frequency of sampling is important. The Nyquist-Shannon theorem says that you have to sample a signal at greater than twice its frequency. Not surprisingly, when you oversample, you have to sample at 4n times the Nyquist frequency (where n is the number of added bits of resolution).

Put another way, the more you oversample at a given sampling frequency, the lower the bandwidth of your system. My ATtiny is programmed to sample at 125kHz, far above the Sharp sensor's bandwidth, so more oversampling is possible before we fall below the bandwidth of the sensor.

Leaky Integrator

In addition to the oversampling, I also wanted to implement some filtering. I turned to my old pal, the leaky integrator. It's fast and it works great.

The idea is that you add up values while some amount of the total leaks out at each addition. It's a first order, recursive low pass filter that can be implemented with additions and shifts.

The higher the shift value, the lower the cutoff frequency and bandwidth. Here's the filter code:

#include <stdint.h>
#include "registers.h"

static uint32_t filtsum = 0;	// running sum for filter
static uint8_t shift = 3;		// leaky integrator filter shift

/** Leaky integrator filter */
uint16_t filter(uint16_t value) {
	filtsum += (value - (filtsum >> shift));

	return (filtsum >> shift);
GitHub Repository

The final version will be a similar size, with a SOIC MCU for reliable hand-assembly. I'm still deciding on the best connector.

1 comment:

  1. Hi Michael! How is your progress with this awesomw thing?
    I need to make something similar with Sharp sensors. Are your schematics and firmware sources published somewhere?


Note: Only a member of this blog may post a comment.