// ******************************************************************************************* // // // Author: Roman Lysecky // Date: November 18, 2010 // // Basic set of software routines for accessing the ADLX345 acclerometer using an SPI // interface. // // NOTE: This library of routine is incompelte, and only supports a small subset of // commands. // // ******************************************************************************************* // #include "p24fj64ga002.h" #include "adxl.h" // ******************************************************************************************* // // Initialize using SPI interface. // ******************************************************************************************* // void ADXLInitialize() { // ******************************************************************************* // // SPI1 interfaces to ADXL345. RB13 used for CS. // ******************************************************************************* // AD1PCFGbits.PCFG10 = 1; // SPI Periperhal Pin Mapping RPINR20bits.SDI1R = 14; // RP14 is SDI (Slave SD0) RPOR6bits.RP12R = 7; // RP12 is SDO (Slave SDI) (7) RPOR7bits.RP15R = 8; // RP15 is SCL (8) _TRISB13 = 0; _LATB13 = 1; SPI1CON1bits.MODE16 = 1; SPI1CON1bits.CKP = 1; SPI1CON1bits.CKE = 0; SPI1CON1bits.SMP = 0; SPI1CON1bits.MSTEN = 1; IFS0bits.SPI1IF = 0; SPI1STATbits.SPIROV = 0; SPI1STATbits.SPIEN = 1; } // ******************************************************************************************* // // Sets the operating mode to enable measurement mode. The defalt mode on power-up is a // low-power mode that does not measure acceleration. // ******************************************************************************************* // void ADXLSetMode(int mode) { int dummy; _LATB13 = 0; SPI1BUF = (SPI_WRITE|ADXL_PWR_CTL_ADDR|mode); while(IFS0bits.SPI1IF==0); SPI1STATbits.SPIROV = 0; dummy = SPI1BUF; IFS0bits.SPI1IF=0; _LATB13 = 1; } // ******************************************************************************************* // // Controls the sampling rate the ADXL accelrometer uses to take accleration measurements. // ******************************************************************************************* // void ADXLSetBandwidth(int bw) { int dummy; _LATB13 = 0; SPI1BUF = (SPI_WRITE|ADXL_BW_RATE_ADDR|bw); while(IFS0bits.SPI1IF==0); SPI1STATbits.SPIROV = 0; dummy = SPI1BUF; IFS0bits.SPI1IF=0; _LATB13 = 1; } // ******************************************************************************************* // // Reads the current 10-bit acceleration measurement for the specified axis using the // #define's for #define ADXL_X_AXIS_ADDR, ADXL_Y_AXIS_ADDR, or ADXL_Z_AXIS_ADDR. // // Returns the readins as a 16-bit signed integer. // ******************************************************************************************* // int ADXLReadAxis(int axis) { int val; val = 0; _LATB13 = 0; SPI1BUF = SPI_READ|axis|ADXL_AXIS1; while(IFS0bits.SPI1IF==0); val = (SPI1BUF & 0xFF) << 8; IFS0bits.SPI1IF=0; _LATB13 = 1; _LATB13 = 0; SPI1BUF = SPI_READ|axis|ADXL_AXIS0; while(IFS0bits.SPI1IF==0); val = val | (SPI1BUF & 0xFF); IFS0bits.SPI1IF=0; _LATB13 = 1; return val; } // ******************************************************************************************* // #define S_Shake0 0 #define S_Shake1 1 #define S_Shake2 2 #define S_Shake3 3 #define S_ShakenNotStirred 4 // ******************************************************************************************* // // Software based state machine that will detect if the accleromter is shaken in alternating // directions (with a force greater than the threshold) four times within the period // specified by the timeout. // ******************************************************************************************* // int ADXLDetectShake(int axisVal, int threshold, int timeout) { static int state = S_Shake0; static int elapsedTicks = 0; static int tick1, tick2, tick3 = 0; static int lastDir = 0; int tickAdj = 0; int shaken = 0; switch (state) { case S_Shake0: if( (axisVal >= threshold) || (axisVal <= (0 - threshold)) ) { elapsedTicks = 0; if( (axisVal >= threshold) ) lastDir = ~0; else lastDir = 0; state = S_Shake1; } break; case S_Shake1: elapsedTicks++; if( ((lastDir == 0) && (axisVal >= threshold)) || ((lastDir != 0) && (axisVal <= (0 - threshold))) ) { tick1 = elapsedTicks; lastDir = ~lastDir; state = S_Shake2; } else if( elapsedTicks > timeout ) { state = S_Shake0; } break; case S_Shake2: elapsedTicks++; if( ((lastDir == 0) && (axisVal >= threshold)) || ((lastDir != 0) && (axisVal <= (0 - threshold))) ) { tick2 = elapsedTicks; lastDir = ~lastDir; state = S_Shake3; } else if( elapsedTicks > timeout ) { tickAdj = tick1; elapsedTicks -= tickAdj; state = S_Shake1; } break; case S_Shake3: elapsedTicks++; if( ((lastDir == 0) && (axisVal >= threshold)) || ((lastDir != 0) && (axisVal <= (0 - threshold))) ) { tick3 = elapsedTicks; lastDir = ~lastDir; state = S_ShakenNotStirred; } else if( elapsedTicks > timeout ) { tickAdj = tick1; elapsedTicks -= tickAdj; tick1 = tick2 - tickAdj; state = S_Shake2; } break; case S_ShakenNotStirred: shaken = 1; elapsedTicks++; if( ((lastDir == 0) && (axisVal >= threshold)) || ((lastDir != 0) && (axisVal <= (0 - threshold))) ) { tickAdj = tick1; elapsedTicks -= tickAdj; tick1 = tick2 - tickAdj; tick2 = tick3 - tickAdj; tick3 = elapsedTicks; lastDir = ~lastDir; } else if( elapsedTicks > timeout ) { tickAdj = tick1; elapsedTicks -= tickAdj; tick1 = tick2 - tickAdj; tick2 = tick3 - tickAdj; shaken = 0; state = S_Shake3; } break; } return shaken; } // ******************************************************************************************* //