Signal Processing with Moving Averages

Posted on Jul 15, 2015 in Code
james portrait
James Jacoby
Chief Technology Officer, Founder

Lately we have been experimenting with Gimbal beacons, a popular iBeacon product. The most obvious application for the technology is to affect some change in an app depending on which beacon the user is closest to. In order for this to work well, the app needs to know which beacon has the strongest signal strength.

Unfortunately, many factors influence the signal strength, not just range. We also found that even while stationary, the signal strength varies greatly and oftentimes a beacon that was farther away would register as closer. This sounds like a job for averages.

Here is the raw data from two beacons, standing slightly closer to the blue beacon.

Raw data captured from two Gimbal beacons

Everywhere you see the green beacon strength poke up above the blue line represents a point in time where the app would incorrectly report that the green beacon is closer than the blue beacon. To fix this, we apply a moving average with a sample size of five to get the following.

Smoothed Data

As you can see, relying on the moving average is a much better idea and results in both beacons correctly reporting their relative distance. The moving average of the green beacon no longer intrudes on the blue beacon.

class MovingAverage {
  var samples: Array<Double>
  var sampleCount = 0
  var period = 5
  
  init(period: Int = 5) {
    self.period = period
    samples = Array<Double>()
  }
  
  var average: Double {
    let sum: Double = samples.reduce(0, combine: +)
    
    if period > samples.count {
      return sum / Double(samples.count)
    } else {
      return sum / Double(period)
    }
  }
  
  func addSample(value: Double) -> Double {
    var pos = Int(fmodf(Float(sampleCount++), Float(period)))
    
    if pos >= samples.count {
      samples.append(value)
    } else {
      samples[pos] = value
    }
    
    return average
  }
}

Moving averages are useful for all kinds of signal processing so we created a reusable snippet of code.

Git the Gist

Building a Dynamic Form System Moby iPhone Dock