Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <Wire.h>
- #define PI 3.14159265358979323846
- #define ACCEL (0x53) //ADXL345 device address
- #define TO_READ (6) //num of bytes we are going to read each time (two bytes for each axis)
- #define g0 9.812865328
- #define ACCELEROMETER_GAIN (0.004 * g0)
- //MIDI Presets
- #define CC = 176
- #define DEFAULT_CHANNEL = 12
- //Accelerometer
- #define R_INT_ENABLE = 46
- #define R_INT_MAP = 47
- #define R_THRESH_TAP = 29
- #define R_DUR = 33
- #define R_TAP_AXES 42
- // Gyroscope ITG3200
- #define GYRO (0x68) // gyro address, binary = 11101001 when AD0 is connected to Vcc (see schematics of your breakout board)
- #define G_SMPLRT_DIV 0x15
- #define G_DLPF_FS 0x16
- #define G_INT_CFG 0x17
- #define G_PWR_MGM 0x3E
- #define G_TO_READ 8 // 2 bytes for each axis x, y, z
- #define G_X_OFFSET 14
- #define G_Y_OFFSET 47
- #define G_Z_OFFSET 10
- char str[512]; //string buffer to transform data before sending it to the serial port
- int CALIBRATION_SAMPLES = 128;
- int reads = 0;
- int x, y, z;
- volatile double a_x, a_y, a_z;
- double a_xBias, a_yBias, a_zBias;
- volatile double a_x_stack = 0;
- volatile double a_y_stack = 0;
- volatile double a_z_stack = 0;
- volatile double g_x, g_y, g_z;
- volatile double turn;
- volatile double prev_turn = 64;
- volatile double prev_a_z = 0;
- volatile int last_pitch = 0;
- volatile int last_roll = 0;
- volatile int last_rotation = 0;
- boolean noteon = false;
- int last_note = 36;
- int BASE_NOTE = 36;
- int TRIGGER_CHANNEL = 13;
- int SHAKE_TOLERANCE = 0;
- int notes[7] = {0,2,4,5,7,9,11}; //1-octave scale
- int last_pan = 0;
- boolean toggle = false;
- void setup()
- {
- Wire.begin(); // join i2c bus (address optional for master)
- Serial.begin(115200); // start serial for output
- initAccel();
- initGyro();
- delay(22);
- }
- void loop()
- {
- getAccelGyro();
- /* Flat chip orientation
- double roll = atan2(a_y, sqrt( a_x * a_x + a_z * a_z));
- double pitch = atan2(a_x, sqrt( a_y * a_y + a_z * a_z));
- */
- //Wheel orientation - Calculate the angle in RADs to the ground
- double pitch = atan2(a_z, sqrt( a_y * a_y + a_x * a_x));
- double roll = atan2(a_y, sqrt( a_z * a_z + a_x * a_x));
- //Map the resulting values to a 7bit range
- int pitch_range = (int)map(constrain(pitch * 180/PI, -90, 90), -90, 90, 0, 127);
- int roll_range = (int)map(constrain(roll * 180/PI, -90, 90), -90, 90, 0, 127);
- int leftPot = map(constrain(analogRead(3), 490, 1023),490,1023,0,6);
- int rightPot = map(constrain(analogRead(2), 515, 1017), 515,1017,0,127);
- //Lock the gyro turn to 90degrees in each direction
- turn = constrain(turn,-90,90);
- //Map the turn value to 7bit range
- int rotation_range = map((int)constrain(turn,-90,90),-90,90,0,127);
- //Add the selected note to middle C
- int this_note = BASE_NOTE + notes[leftPot];
- //If there is contact on the leftPot engage the note
- if ((analogRead(3) > 0)) {
- if ((this_note != last_note) || (this_note == last_note && !noteon)) {
- sendMIDI(144, last_note, 0);
- sendMIDI(144, this_note, 127);
- }
- noteon = true;
- last_note = this_note;
- } //Turn notes off if there is no contact
- else if ((analogRead(3) == 0) && noteon) {
- sendMIDI(144, last_note, 0);
- noteon=false;
- }
- /* Some gesture detection
- if ((prev_a_z < -10.0) && (a_z > 0.0)) {
- sendMIDI(144, last_note, 0);
- noteon = false;
- }
- prev_a_z = a_z;
- */
- //When the change in values per cycle is greater than 0 (in this case) send the new midi command
- if (abs(pitch_range - last_pitch) > SHAKE_TOLERANCE){
- sendMIDI(176, 10, pitch_range);
- }
- if (abs(roll_range - last_roll) > SHAKE_TOLERANCE){
- sendMIDI(176, 11, roll_range);
- }
- if (abs(rotation_range - last_rotation) > SHAKE_TOLERANCE) {
- sendMIDI(176, 12, rotation_range);
- }
- if (leftPot != 0) {
- //sendMIDI(176, 13, leftPot);
- }
- //Control the pan with right pot
- if (rightPot != last_pan && rightPot != 0) {
- sendMIDI(176, 13, rightPot);
- last_pan = rightPot;
- } //Return to middle if no contact
- else if (rightPot != last_pan && rightPot == 0) {
- sendMIDI(176, 13, 64);
- last_pan = rightPot;
- }
- last_pitch = pitch_range;
- last_roll = roll_range;
- last_rotation = rotation_range;
- }
- void initAccel(){
- //Turning on the ADXL345
- writeTo(ACCEL, 0x2D, 0);
- writeTo(ACCEL, 0x2D, 16);
- writeTo(ACCEL, 0x2C, 0x0C); // Set BW 200hz
- writeTo(ACCEL, 0x31, 0x0B); // Set BW 200hz
- //TODO:TAP DETECTION
- /*
- writeTo(ACCEL, R_INT_MAP, 0); // send all interrupts to ADXL345's INT1 pin
- writeTo(ACCEL, R_DUR, 0x1F); // 625us/LSB
- writeTo(ACCEL, R_THRESH_TAP, 48); // 62.5mg/LSB <==> 3000mg/62.5mg = 48 LSB as datasheet suggestion
- writeTo(ACCEL, R_TAP_AXES, 6); // enable tap detection on x,y,z axes
- writeTo(ACCEL, R_INT_ENABLE, 96); // enable signle and double tap, activity, inactivity and free fall detection
- */
- writeTo(ACCEL, 0x2D, 8); //set power mode
- }
- void initGyro()
- {
- /*****************************************
- * ITG 3200
- * power management set to:
- * clock select = internal oscillator
- * no reset, no sleep mode
- * no standby mode
- * sample rate to = 125Hz
- * parameter to +/- 2000 degrees/sec
- * low pass filter = 5Hz
- * no interrupt
- ******************************************/
- writeTo(GYRO, G_PWR_MGM, 0x00);
- writeTo(GYRO, G_SMPLRT_DIV, 0x07); // EB, 50, 80, 7F, DE, 23, 20, FF
- writeTo(GYRO, G_DLPF_FS, 0x1E); // +/- 2000 dgrs/sec, 1KHz, 1E, 19
- writeTo(GYRO, G_INT_CFG, 0x00);
- }
- //Read the accelerometer and gyro values to buffer
- void getAccelGyro(){
- int gyroRegAddress = 0x1B;
- byte gyroBuff[G_TO_READ];
- int accelRegAddress = 0x32;
- byte accelBuff[TO_READ] ;
- int samples = 10;
- double LSB = 14.375;
- int sample_rate = 125;
- //Smoothing loop for accel, and sampling loop for gyro
- for(int i = 0; i < 10; i++){
- readFrom(ACCEL, accelRegAddress, TO_READ, accelBuff); //read the acceleration data from the ADXL345
- //each axis reading comes in 10 bit resolution, ie 2 bytes. Least Significat Byte first!!
- //thus we are converting both bytes in to one int
- a_x_stack += (((int)accelBuff[1]) << 8) | accelBuff[0];
- a_y_stack += (((int)accelBuff[3])<< 8) | accelBuff[2];
- a_z_stack += (((int)accelBuff[5]) << 8) | accelBuff[4];
- readFrom(GYRO, gyroRegAddress, G_TO_READ, gyroBuff); //read the gyro data from the ITG3200
- g_x = ((int)(gyroBuff[2] << 8) | gyroBuff[3]) - G_X_OFFSET;
- g_y = ((int)(gyroBuff[4] << 8) | gyroBuff[5]) - G_Y_OFFSET;
- g_z = ((int)(gyroBuff[6] << 8) | gyroBuff[7]) - G_Z_OFFSET;
- turn += g_x / LSB / sample_rate; //Integrate the turn value assuming 1 sample every 8ms
- delay(5); //stretch the sampling interval so that we're at about 8ms
- }
- //Calculate the smoothed acceleration data into m/s/s
- a_x = ((a_x_stack / samples) - a_xBias) * ACCELEROMETER_GAIN;
- a_y = ((a_y_stack / samples) - a_yBias) * ACCELEROMETER_GAIN;
- a_z = ((a_z_stack / samples) - a_zBias) * ACCELEROMETER_GAIN;
- a_x_stack = 0;
- a_y_stack = 0;
- a_z_stack = 0;
- }
- //Method to calibrate accelerometer offset
- void calibrateAccelerometer(void) {
- int regAddress = 0x32;
- byte buff[TO_READ] ; //6 bytes buffer for saving data read from the device
- a_x_stack = 0;
- a_y_stack = 0;
- a_z_stack = 0;
- //Take a number of readings and average them
- //to calculate the zero g offset.
- for (int i = 0; i < CALIBRATION_SAMPLES; i++) {
- readFrom(ACCEL, regAddress, TO_READ, buff); //read the acceleration data from the ADXL345
- //each axis reading comes in 10 bit resolution, ie 2 bytes. Least Significat Byte first!!
- //thus we are converting both bytes in to one int
- a_x_stack += (((int)buff[1]) << 8) | buff[0];
- a_y_stack += (((int)buff[3])<< 8) | buff[2];
- a_z_stack += (((int)buff[5]) << 8) | buff[4];
- delay(5);
- }
- a_x_stack /= CALIBRATION_SAMPLES;
- a_y_stack /= CALIBRATION_SAMPLES;
- a_z_stack /= CALIBRATION_SAMPLES;
- //At 4mg/LSB, 250 LSBs is 1g.
- a_xBias = (a_x_stack - 250);
- a_yBias = a_y_stack;
- a_zBias = a_z_stack;
- a_x_stack = 0;
- a_y_stack = 0;
- a_z_stack = 0;
- }
- //Writes val to address register on device
- void writeTo(int device, byte address, byte val) {
- Wire.beginTransmission(device); //start transmission to device
- Wire.send(address); // send register address
- Wire.send(val); // send value to write
- Wire.endTransmission(); //end transmission
- }
- //reads num bytes starting from address register on device in to buff array
- void readFrom(int device, byte address, int num, byte buff[]) {
- Wire.beginTransmission(device); //start transmission to device
- Wire.send(address); //sends address to read from
- Wire.endTransmission(); //end transmission
- Wire.beginTransmission(device); //start transmission to device
- Wire.requestFrom(device, num); // request 6 bytes from device
- int i = 0;
- while(Wire.available()) //device may send less than requested (abnormal)
- {
- buff[i] = Wire.receive(); // receive a byte
- i++;
- }
- Wire.endTransmission(); //end transmission
- }
- void sendMIDI(unsigned char MESSAGE, unsigned char CONTROL, unsigned char VALUE) //pass values out through standard Midi Command
- {
- Serial.print(MESSAGE);
- Serial.print(CONTROL);
- Serial.print(VALUE);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement