I recently purchased this item Pololu - MMA7341LC 3-Axis Accelerometer ±3/9g 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()