I was using an GY-521 accelerometer/gyroscope module in order to provide inertial tracking. The GY-521 interfaces with an Arduino which sends data over a serial connection. I convert these values into physical values (simply multiplying by a calibration constant) in a python script and then append all values to an array which I have plot into a histogram shown.
I left the sensor stationary on a table top for approximately 10 minutes to try and work out the nature of the noise.
As you can see from the histogram certain values of acceleration never had a single observation and these values appear at regular intervals. Some values also seem to be much more common than the rest of the noise.
(Main question) Is there a physical explanation for this?
(Sub-Question) What type of filtering/smoothing would you suggest to improve this? We first implemented box smoothing which worked well at preventing drift when stationary but made the system less responsive to sudden changes in rotation. I explored heavily the use of kalman filters but without a magnetometer to give measurements for attitude I could not work out how to use accelerator data for both correction of orientation and displacement tracking (since moving around with acceleration in the order of g makes the gravity vector ambiguous). Without proper smoothing of the angular velocity data the reference frame is rotated with sensor noise making drift significant after only a few seconds of running.
[EDIT]: The code running on the Arduino is from this github repository. The python script is shown below. To my knowledge the histogram is plotting raw data (multiplied by a constant).
import serial import time import matplotlib.pyplot as plt #establish serial connection to Arduino/GY521 ser = serial.Serial('COM3', 38400) #Baud rate 38400 Hz, COM port must match. ser.flushInput() for i in range(0,3): print(ser.readline(100).decode("utf-8","ignore").replace('\r\n','')) res = 2**16; # sensitivity setting a_sen = 2* 9.81; #m/s^2 g_sen = 250 ; #deg/s ax =  ay =  az =  gx =  gy =  gz =  t =  #main loop try: print("Capturing data, press ctrl+C to finish") #obtain data while 1: s = ser.readline(100) #print(s) ss = s.decode("utf-8","ignore").replace('\r\n','').split('\t') ss = ss[1:] ax.append(ss) ay.append(ss) az.append(ss) gx.append(ss) gy.append(ss) gz.append(ss) t.append(ss) except KeyboardInterrupt: print('Stopping...') #convert the read values into physical values ax = [int(i)*a_sen*2 / res for i in ax] ay = [int(i)*a_sen*2 / res for i in ay] az = [int(i)*a_sen*2 / res for i in az] gx = [int(i)*g_sen*2 / res for i in gx] gy = [int(i)*g_sen*2 / res for i in gy] gz = [int(i)*g_sen*2 / res for i in gz] t = [int(tm)/1000 for tm in t] plt.figure(1) plt.subplot(211) plt.hist(ax,"auto") plt.xlabel('Accel (m/s^2)') plt.legend(loc = 'center left',bbox_to_anchor=(0.975, 0.5)) print('Done') plt.show()