Problem with accelerometer

I recently purchased this item http://www.pololu.com/catalog/product/1247 and hooked it all up. It sort-of works, but not really. I made this video explaining what is wrong:

Here’s the source for the arduino sketch:

const int xpin = 0,
          ypin = 1,
          zpin = 2,
          
          slp = 12;

const float vdd = 3.3,
            v0g = 1.21,
            s = 0.1175;

void setup() {
  pinMode(slp, OUTPUT);
  
  pinMode(xpin, INPUT);
  pinMode(ypin, INPUT);
  pinMode(zpin, INPUT);
  
  digitalWrite(slp, HIGH);
  
  Serial.begin(9600);
}

float x, y, z;

void set_angles() {
  float r, rx, ry, rz, ax, ay, az,
        vx, vy, vz, dx, dy, dz;
  
  // get values from pins
  ax = analogRead(xpin);
  ay = analogRead(ypin);
  az = analogRead(zpin);
  
  // convert values to voltages
  vx = ax * vdd / 1023;
  vy = ay * vdd / 1023;
  vz = az * vdd / 1023;
  
  // calculate voltage offset
  dx = (vx - 1.23);
  dy = (vy - 1.23);
  dz = (vz - 1.23);
  
  // calculate components of vector
  rx = dx / s;
  ry = dy / s;
  rz = dz / s;
  
  // calculate magnitude of vector
  r = sqrt(rx*rx + ry*ry + rz*rz);
  
  
  // get angle between axis and vector
  x = acos(rx / r);
  y = acos(ry / r);
  z = acos(rz / r);
  
  // convert to degrees
  x *= 57.29;
  y *= 57.29;
  z *= 57.29;
}

#define p(x) Serial.print(x);
#define pl(x) Serial.println(x);

void loop() {
  
  // averages for x, y, z angles
  float xa, ya, za;
  xa = ya = za = 0;
  
  int i;
  
  // get 100 readings and average them (per tick on the python graph)
  for (i = 0; i < 100; ++i) {
    set_angles();
    xa += x;
    ya += y;
    za += z;
  }
  
  xa /= i;
  ya /= i;
  za /= i;
  
  // print the angles to the serial port
  p(xa); p(",");
  p(ya); p(",");
  pl(za);
}

If anyone’s interested, here’s also the code for the visualization program you saw in the video:

import matplotlib.pyplot as plt
import numpy as np
from time import sleep
import serial, sys

# how long we want the x axis to be
xlen = 200

xs, yx, yy, zz = [], [], [], []

yx, yy = [0 for i in range(xlen)], [0 for i in range(xlen)]
zz, xs = [0 for i in range(xlen)], [i for i in range(xlen)]

fig = plt.figure()
fig.canvas.set_window_title('Accelerometer Output Visualizer')
ax = fig.add_subplot(111)

ax.grid(True)

ax.set_title("Accelerometer Readings")
ax.set_xlabel("Time (x100 ms)")
ax.set_ylabel("Rotation Angle (Degrees)")

ax.axis([0, 100, 340, 420])

l = ax.plot(xs, yx, 'r-', yx, xs, 'b-', yx, xs, 'g-')
ax.legend(('X', 'Y', 'Z'), loc = 'upper left')

manager = plt.get_current_fig_manager()

s = serial.Serial('/dev/ttyUSB1', 9600)

def gen(arg):
  # read data from serial port and make it into a float array
  d = map(float, s.readline().rstrip().split(','))
  
  # add data to the y axis arrays for each axis of the accelerometer
  yx.append(d[0])
  yy.append(d[1])
  zz.append(d[2])

def plotter(arg):
  # make the new x axis
  xs = np.arange(len(yx) - xlen, len(yx), 1)
  
  # update the y axis values
  l[0].set_data(xs, yx[-xlen:])
  l[1].set_data(xs, yy[-xlen:])
  l[2].set_data(xs, zz[-xlen:])
  
  # shift x axis
  ax.axis([min(xs), max(xs), 0, 180])
  
  manager.canvas.draw()

t1 = fig.canvas.new_timer(interval = 20)
t1.add_callback(plotter, ())

t2 = fig.canvas.new_timer(interval = 20)
t2.add_callback(gen, ())

t1.start()
t2.start()

plt.show()

You don't initialise xa, ya, za in "loop". Is that right?

AWOL: You don't initialise xa, ya, za in "loop". Is that right?

Oops I didn't notice that. But that's not what the problem is (I must have gotten rid of the initialization while commenting the code to post here).