Hi guys,
I’m working on creating a virtual 3D cube which should follow the movements of a physical 3D cube which has an ADXL330 inside of it which is connected to the Arduino board. The program which displays the virtual cube is a Processing sketch.
I think I’m pretty near implementing this but somehow I’m stuck… the virtual cube rotates fine when I just rotate one axis and I comment out the rotations on the other 2 axes, this for all 3 axes.
But, when I’m using rotations on all of the 3 axes it displays a spin when an axis is passing from - to + … when it just shouldn’t.
Note that instead of hardcoding sensitivity, voltages inside the program I preferred to use a calibration process.
Now, this is the Arduino code:
/**
* Reads from a 3 axis accelerometer and send values to serial
*/
// CONSTANTS
#define SAMPLES 64
// INPUTS
#define Y 0
#define Z 1
#define X 2
#define RESET 2
// board inputs variables
int x = 0;
int y = 0;
int z = 0;
int reset = 0;
void setup() {
analogReference(EXTERNAL);
pinMode(RESET, INPUT);
digitalWrite(RESET, HIGH); // enable pullup resitor
Serial.begin(9600);
}
void loop() {
delay(10); // debounces switches
x = 0;
y = 0;
z = 0;
for(int i=0; i<SAMPLES; i++) {
x += analogRead(X);
y += analogRead(Y);
z += analogRead(Z);
reset = digitalRead(RESET);
}
x = x / SAMPLES;
y = y / SAMPLES;
z = z / SAMPLES;
Serial.print(x, HEX);
Serial.print(',');
Serial.print(y, HEX);
Serial.print(',');
Serial.print(z, HEX);
Serial.print(',');
Serial.print(reset, HEX);
Serial.println(',');
//delay(100);
}
and this is the Processing code:
/**
* Displays values coming from an accelerometer connected to Arduino
*/
import processing.serial.*;
Serial myPort; // Create object from Serial class
int [] a = {0, 0, 0}; // accelerations x,y,z
int [] zero = {0, 0, 0}; // values for no acceleration
int [] gmax = {0, 0, 0}; // values when applied full positive g acc
int [] gmin = {0, 0, 0}; // values when applied full negative g acc
float Xrot;
float Yrot;
float Zrot;
int reset = 1;
int oldreset = 1;
final int VIEW_SIZE_X = 600, VIEW_SIZE_Y = 600;
int lf = 10; // 10 is '\n' in ASCII
final int BUFFLEN = 100;
byte[] inBuffer = new byte[BUFFLEN];
boolean calibrated = false;
final int ACCTHRESHOLD = 3;
void setup()
{
size(VIEW_SIZE_X, VIEW_SIZE_Y, P3D);
myPort = new Serial(this, "/dev/ttyUSB0", 9600);
}
void draw() {
if(!calibrated) {
calibrate();
}
int [] values = readAccelerometer();
for(int i = 0; i<3; i++) {
/*if(values.length < 4) {
printArr(values); exit();
}*/
int newacc = zero[i] - values[i];
a[i] = (abs(newacc - a[i]) > ACCTHRESHOLD) ? newacc : a[i];
}
float g = (0.3 * 3) / 1024; // sensitivity V/g : max volt = g : max digital sesitivity
//println(g);
background(#000000);
translate(VIEW_SIZE_X / 2, VIEW_SIZE_Y / 2, -400);
//println(((float) a[0] * 3.0 / 1024.0 - 1.5) / 0.3);
pushMatrix();
scale(6,6,14);
Xrot = -atan2(a[1], a[2]);
Yrot = atan2(a[0], a[2]); // OK
Zrot = atan2(a[0], a[1]); // OK
rotateX(Xrot); // OK
rotateY(Zrot); // OK
rotateZ(Yrot); // OK
buildBoxShape();
popMatrix();
fill(#ffffff);
translate(-VIEW_SIZE_X/2, -VIEW_SIZE_Y/2, 0);
PFont font;
// The font must be located in the sketch's
// "data" directory to load successfully
font = loadFont("CourierNew36.vlw");
textFont(font);
String debug = a[0] + " " + a[1] + " " + a[2] + "\n" + degrees(Xrot) + " " + degrees(Yrot) + " " + degrees(Zrot)/*+ "\n" + xmin + " " + ymin + " " + zminhx + " " + hy + " " + hz */;
text(debug, 20, 0);
}
void buildBoxShape() {
//box(60, 10, 40);
noStroke();
beginShape(QUADS);
//Z+ (to the drawing area)
fill(#00ff00);
vertex(-30, -5, 20);
vertex(30, -5, 20);
vertex(30, 5, 20);
vertex(-30, 5, 20);
//Z-
fill(#0000ff);
vertex(-30, -5, -20);
vertex(30, -5, -20);
vertex(30, 5, -20);
vertex(-30, 5, -20);
//X-
fill(#ff0000);
vertex(-30, -5, -20);
vertex(-30, -5, 20);
vertex(-30, 5, 20);
vertex(-30, 5, -20);
//X+
fill(#ffff00);
vertex(30, -5, -20);
vertex(30, -5, 20);
vertex(30, 5, 20);
vertex(30, 5, -20);
//Y-
fill(#ff00ff);
vertex(-30, -5, -20);
vertex(30, -5, -20);
vertex(30, -5, 20);
vertex(-30, -5, 20);
//Y+
fill(#00ffff);
vertex(-30, 5, -20);
vertex(30, 5, -20);
vertex(30, 5, 20);
vertex(-30, 5, 20);
endShape();
}
void calibrate() {
println("Put accelerometer with Z pointing down, then press reset button");
int [] values = getCalibration();
zero[0] = values[0]; // X doesn't get any acceleration
zero[1] = values[1]; // Y doesn't get any acceleration
gmax[2] = values[2]; // store g value when Z pointing down
println("Put accelerometer with Z pointing up, then press reset button");
values = getCalibration();
gmin[2] = values[2]; // store g value when Z pointing up
println("Put accelerometer with X pointing up, then press reset button");
values = getCalibration();
gmin[0] = values[0]; // store g value when Z pointing up
zero[2] = values[2]; // Z doesn't get any acceleration
println("Put accelerometer with X pointing down, then press reset button");
values = getCalibration();
gmax[0] = values[0]; // store g value when Z pointing up
println("Put accelerometer with Y pointing up, then press reset button");
values = getCalibration();
gmin[1] = values[1]; // store g value when Z pointing up
println("Put accelerometer with Y pointing down, then press reset button");
values = getCalibration();
gmax[1] = values[1]; // store g value when Z pointing up
println("zero: ");
printArr(zero);
println("gmax: ");
printArr(gmax);
println("gmin: ");
printArr(gmin);
calibrated = true;
}
/**
* Returns values read from accelerometer only when reset button released
*/
int [] getCalibration() {
int oldreset = 1;
int [] values = {0, 0, 0, 1};
while(values == null || !(values[3] == 1 && oldreset == 0)) { // cycle until we are not releasing button
if(values != null) {
oldreset = values[3];
//println(values[3] + " " + oldreset);
}
values = readAccelerometer();
}
return values;
}
/**
* Get x,y,z and reset values coming from Serial interface.
*/
int [] readAccelerometer() {
int [] values = null;
if(myPort.available() > 0 && myPort.readBytesUntil(lf, inBuffer) > 0) {
values = new int[4];
String inputString = new String(inBuffer);
String [] inputStringArr = split(inputString, ',');
values[0] = unhex(inputStringArr[0]); // x
values[1] = unhex(inputStringArr[1]); // y
values[2] = unhex(inputStringArr[2]); // z
values[3] = unhex(inputStringArr[3]); // reset
return values;
}
else {
delay(10);
return readAccelerometer();
}
}
void printArr(int [] arr) {
for(int i = 0; i < arr.length; i++) {
print(arr[i] + " ");
}
println("");
}
Thanks for your help,
Fabio Varesano