The week's assignment is to write an application that interfaces with an input and/or output device that I made. I wanted to start using accelerometer data to influence patterns of light in a meaningful (controlled) way. Accelerometers sense movement; so because gravity is pulling on the object, it senses that and we can then determine orientation, as well as many actions like walking, throwing, or jumping -- which have particular motions associated with them, and a profile can be designed (with some insane math skillz) to recognize these movements. ADXL343 is an I2C 3-axis accelerometer with user seletable sensitivity and 10-13 bit resolution (depending on sensitivity). I2C is a 2-wire serial connection, so you just need to connect the SDA (data) and SCL (clock) lines to your microcontroller. Make sure both VCC and the CS pins on the sensor are connected to 3.3V, to tell the sensor we will be using it as an I2C device and not SPI (3- or 4-wire).
Neil's 3D acceleration C code does the dirty work of sending a pair of octets (bytes) per axis, so there 6 char total going over serial. Checking the raw data coming in, the values appeared to be very laggy... adding a 10 millisecond delay at the end of the main loop to lower the sampling resolution seemed to help. X, Y, and Z accelerations are now responsive.
_delay_ms(10);
Without parsing, the serior monitor will display a bunch of gibberish. This is because we need to convert a single character to its corresponding ASCII value!
//ord returns int from chr
x0 = ord(ser.read())
x1 = ord(ser.read())
//this will concatenate 2 single bytes into 1 number (cuz sensor reports 10 bit values)
x = x0+255*x1
if (0x8000 & x):
x = -(0x10000-x)
//this will smooth our results!
xfilt = (1-0.1)*xfilt+0.1*x
I have translated this to Processing, because I am not so versed in Python. In order to derive the sensor's angle, you need to know how the values are changing with a little bit of trigonometry. Imagine the X and Y values as sides of a right triangle, so the angle you want is the arctangent of the opposite divided by the adjacent side.
pitch = atan( xFilt / sqrt( pow(yFilt,2) + pow(zFilt,2) ) );
pitch *= 180/PI;
roll = atan( yFilt / sqrt( pow(xFilt,2) + pow(zFilt,2) ) );
roll *= 180/PI;
Ugh, something is really wrong with my accelerometer data parsing in Processing. Just for kicks I made some aliens... that move and rotate around according to the accelerometer... which is not accurate at all...
Ah ha! Because there are multiple bytes coming over, we need to check if our data is starting from the right spot. Are we receiving from X, Y, or Z's high/low bytes? On the microcontroller side, you can send some framing bytes and check them in your software for reference:
while(true){
byte1 = myPort.read();
byte2 = myPort.read();
byte3 = myPort.read();
byte4 = myPort.read();
println("byte4 = "+byte4);
if ( (byte1 == 1) & (byte2 == 2) & (byte3 == 3) & (byte4 == 4) ) {
println("found framing!");
break;
}
}