
Code for the project of LELEC2811 2017
Dependencies: FreescaleIAP MMA8491Q_PG mbed
Fork of LELEC_2811_Accelerometer by
main.cpp
- Committer:
- ATCuriosity
- Date:
- 2017-11-30
- Revision:
- 4:2de56fc46abb
- Parent:
- 3:d03eae745223
- Child:
- 5:79b8cd191fa8
File content as of revision 4:2de56fc46abb:
/* * LELEC 2811 - BadmintonLogger - Group 5 */ #include "mbed.h" #include "FreescaleIAP.h" // Library for Flash Access #include "MMA8491Q_PG.h" // Accelerometer #include <cmath> #define MMA8491_I2C_ADDRESS (0x55<<1) #define KL25Z_VDD 2.89 // Value of VDD : To be measured on board KL25Z pin P3V3 (calibration) #define LED_ON 0 #define LED_OFF 1 #define CONSOLE 0 // print all in console #define FLASH_MVT 1 // save in flash only mvts #define FLASH_ALL 2 // save in flash mvtSets #define REG_OUT_X_MSB 0x01 #define REG_OUT_Y_MSB 0x03 #define REG_OUT_Z_MSB 0x05 #define SECTOR_SIZE 1024 // Numbers of bits by memory sector #define RESERVED_SECTOR 32 // 32K reserved for Application Code #define ACQ_TIMER_PERIOD 0.01 // Time between 2 acquisitions (here 10 mSec) #define N_PTS 50 // Number of points for each axis used to detect mvt #define N_MVTS 5 // Number of mvts detected #define THRESHOLD_MVT 0.5 // threshold to validate a mvt #define THRESHOLD_SHOCK 0.5 // threshold to detect shock MMA8491Q my8491(PTE0, PTE1, MMA8491_I2C_ADDRESS); // Setup I2C for MMA8491 Serial Host_Comm(USBTX, USBRX); // Set Serial Port AnalogIn myPTE20(PTE20); // read Vout_IF AnalogIn myPTE21(PTE21); // read Vout_FILT AnalogIn myPTE22(PTE22); // read Vout_GAIN Ticker myTick_Acq; // Periodical timer for Acquisition DigitalOut Led_Red(LED1); // Define I/O for LEDs DigitalOut Led_Green(LED2); DigitalOut Led_Blue(LED3); DigitalOut Accel_Enable(PTA13); DigitalOut Start_Pulse_Out(PTE4); // Used to enter/exit Acquisition mode DigitalIn Start_Pulse_In(PTE5); // ShortPin J1_15 and J1_16 to enter in Acq_Mode // --------------------- Structure and Enumeration --------------------- struct Data { int16_t accX, accY, accZ; float Vout_IF, Vout_FILT, Vout_GAIN; }; enum Mvt { Undefined = 0, Serve, ClearOverhead, DropOverhead, SmashShot, ClearUnderarm, DropUnderarm }; struct MvtSet { int16_t inputs [N_PTS*3]; Mvt mvt; }; // -------------------------- Globale variable -------------------------- volatile bool bTimer; // 1 means a Timer tick is done bool foundError = 0; int mode = CONSOLE; /* in flash : - [ 0x0 ; flash_base_address [ : code - flash_base_address : flash_next_address (int) - flash_base_address+4 : mode (int) - flash_base_address+8 : first address to store data */ uint32_t KL25_Flash_Size; int flash_base_address = RESERVED_SECTOR * SECTOR_SIZE ; // Store Flash Base Address int flash_next_address; // next address for saving data in flash int flash_base_address_cmd; // base address where the parameters are saved const float Weights[3*N_PTS*N_MVTS] = { #include "Weights.txt" }; const float Biases[N_MVTS] = { #include "Biases.txt" }; // ------------------------ Function Declaration ------------------------ void Init(void); void Clear_Led(void); // switch off led's bool Check_Jumper(void); // if J1_15 & J1_16 connected together -> return 1 void Check_Console(void); // detect input from user in console void myTimer_Acq_Task(void); // called by the timer void EraseAllSectors(void); // erase all sectors containing data void EraseSector(int address); // erase one sector void UpdateParamFlash(void); // update next_address_flash and mode in flash void WriteFlash(MvtSet mvtSet); // write only mvt or all set depending on 'all' void ReadFlash(void); // print memory content in console Data ReadData(void); // read data from accelerometer and piezo void Log(void); // read data, detect shock and movement void Rotate(int16_t *AccDataLog, int amount, int16_t *inputs); // inputs = AccDataLog rotated of amount void PrintSet(int16_t *inputs); // display set of data float Sigmoid(float x); // sigmoid function (used by neural network) Mvt SelectMvt(int16_t *inputs); // compute probabilities for each mvt based on the inputs // ------------------------------------------------------------------------------------------------------- // ------------------------------------------------------------------------------------------------------- // -------------------------------- main -------------------------------- int main() { Init (); int Count; while(!foundError) { if (Check_Jumper()) { Clear_Led(); Count = 5; while (Count !=0) { if (Check_Jumper()) { Led_Blue = LED_ON; // Blink to alert user "Enter in Logging mode" wait_ms(750); Led_Blue = LED_OFF; wait_ms(250); Count --; if (Count == 0) Log(); } else Count = 0; } } Led_Blue = !Led_Blue; Check_Console(); wait_ms(100); } Host_Comm.printf("\n\rProgram is exiting due to error...\n\r"); Clear_Led(); Led_Red = LED_ON; } // -------------------------------- Init -------------------------------- void Init() { Start_Pulse_In.mode(PullNone); // Input Pin is programmed as floating Accel_Enable = 0; // Turn Accel Enable to disabled state Clear_Led(); myTick_Acq.attach(&myTimer_Acq_Task, ACQ_TIMER_PERIOD); // Timer for acquisition Host_Comm.baud(115200); // Baud rate setting Host_Comm.printf("\n\rLELEC2811 - Badminton Logger - Group 5\n\r"); KL25_Flash_Size = flash_size(); // Get Size of KL25 Embedded Flash flash_base_address_cmd = KL25_Flash_Size-SECTOR_SIZE; int *base_address_ptr = (int*)flash_base_address_cmd; flash_next_address = base_address_ptr[0]; if (flash_next_address >= flash_base_address_cmd || flash_next_address < flash_base_address) { Host_Comm.printf("First run (or error with previous flash_next_address)\n\r"); EraseAllSectors(); flash_next_address = flash_base_address; mode = CONSOLE; UpdateParamFlash(); } else { // add 0xFFFF in flash to tag reset mode = base_address_ptr[1]; if (mode != CONSOLE && mode != FLASH_MVT && mode != FLASH_ALL) { mode = CONSOLE; UpdateParamFlash(); } } Host_Comm.printf("flash_next_address = %d ; mode = %d\n\r",flash_next_address, mode); Host_Comm.printf("Memory used = %f %%\n\r",(flash_next_address-flash_base_address)/(flash_base_address_cmd-flash_base_address)); Host_Comm.printf("Initialization done.\n\n\r"); Host_Comm.printf("When the jumper is removed, use the keyboard :\n\r"); Host_Comm.printf("- to erase flash : 'e' = erase flash\n\r"); Host_Comm.printf("- to change mode : 'c' = console mode ; 'm' = write_mvt mode ; 'a' = write_all mode\n\r"); Host_Comm.printf("- to read flash : 'r' = read flash ; 's' = stop reading\n\r"); } // ----------------------------- Clear_Led ------------------------------ void Clear_Led() { Led_Red = LED_OFF; Led_Green = LED_OFF; Led_Blue = LED_OFF ; } // ---------------------------- Check_Jumper ---------------------------- bool Check_Jumper() { int i; for (i = 0 ; i < 2 ; i ++) { Start_Pulse_Out = 1; wait_ms(1); if (Start_Pulse_In != 1) return 0; Start_Pulse_Out = 0; wait_ms(1); if (Start_Pulse_In != 0) return 0; } return 1; } // --------------------------- Check_Console ---------------------------- void Check_Console() { if(Host_Comm.readable()) { char cmd = Host_Comm.getc(); if ((cmd == 'E') || (cmd == 'e')) EraseAllSectors(); else if ((cmd == 'C') || (cmd == 'c')) mode = CONSOLE; else if ((cmd == 'M') || (cmd == 'm')) mode = FLASH_MVT; else if ((cmd == 'A') || (cmd == 'a')) mode = FLASH_ALL; else if ((cmd == 'R') || (cmd == 'r')) ReadFlash(); UpdateParamFlash(); } } // -------------------------- myTimer_Acq_Task -------------------------- void myTimer_Acq_Task() { bTimer = 1; } // ------------------------------------------------------------------------------------------------------- // ------------------------------------------------------------------------------------------------------- // -------------------------- EraseAllSectors --------------------------- void EraseAllSectors(void) { for (int address = flash_base_address ; address < KL25_Flash_Size ; address += SECTOR_SIZE) { EraseSector(address); if(foundError) return; } } // ---------------------------- EraseSector ----------------------------- void EraseSector(int address) { IAPCode status = erase_sector(address); if (status != Success) { Host_Comm.printf("\n\rError in EraseSector() : status = %d\n\r", status); foundError = 1; } } // -------------------------- UpdateParamFlash -------------------------- void UpdateParamFlash() { EraseSector(flash_base_address_cmd); if(foundError) return; int toWrite[2] = {flash_next_address,mode}; IAPCode status = program_flash(flash_base_address_cmd, (char *) &toWrite, 2*sizeof(int)); if (status != Success) { Host_Comm.printf("\n\rError in UpdateParamFlash() : status = %d\n\r", status); foundError = 1; } } // ----------------------------- WriteFlash ----------------------------- void WriteFlash(MvtSet mvtSet) { IAPCode status; if (mode == FLASH_ALL) // inputs (2*3*N_PTS bytes) + mvt (1 byte) { // add all bytes one behind the other : 2bytes*3*N_PTS (inputs) + 1byte (mvt) int remainder = (3*N_PTS) % 2; // modulo 2 because compacting 2bytes into 4bytes words status = program_flash(flash_next_address, (char*) &(mvtSet.inputs), 2*(3*N_PTS-remainder)); if (status != Success) { Host_Comm.printf("\n\rError in WriteFlash() (0) : status = %d\n\r", status); foundError = 1; return; } flash_next_address += 2*(3*N_PTS-remainder); int16_t toWrite[2] = {0,(int16_t) mvtSet.mvt}; if(remainder) toWrite[0] = mvtSet.inputs[3*N_PTS-1]; status = program_flash(flash_next_address, (char*) &toWrite, 4); if (status != Success) { Host_Comm.printf("\n\rError in WriteFlash() (1) : status = %d\n\r", status); foundError = 1; return; } } else // 4 mvts (4 bytes) compacted in one 32bits slot { /* int innerPosition = flash_next_address % 4; int local_base_address = flash_next_address-innerPosition; int *address_ptr = (int*)(local_base_address); int currValue = address_ptr[0]; uint8_t toWrite[4] = {(uint8_t)(currValue>>24),(uint8_t)(currValue>>16),(uint8_t)(currValue>>8),(uint8_t)currValue}; toWrite[innerPosition] = (uint8_t)mvtSet.mvt; status = program_flash(local_base_address, (char*) &toWrite, 4); if (status != Success) { Host_Comm.printf("\n\rError in WriteFlash() (2) : status = %d\n\r", status); foundError = 1; return; } flash_next_address++; */ uint8_t toWrite[4] = {0,0,0,mvtSet.mvt}; status = program_flash(flash_next_address, (char*) &toWrite, 4); if (status != Success) { Host_Comm.printf("\n\rError in WriteFlash() (2) : status = %d\n\r", status); foundError = 1; return; } } flash_next_address += 4; UpdateParamFlash(); } // ----------------------------- ReadFlash ------------------------------ void ReadFlash() { Host_Comm.printf("\n\r------ Begin Read Flash ------\n\r"); Host_Comm.printf("flash_next_address = %d ; mode = %d\n\r",flash_next_address, mode); Host_Comm.printf("Memory used = %f %%\n\r",(flash_next_address-flash_base_address)/(flash_base_address_cmd-flash_base_address)); char cmd; int *address_ptr; int remainder = (flash_next_address) % 4; int local_base_address = flash_next_address-remainder; for (int address = flash_base_address+8; address < local_base_address; address+=4) { if(Host_Comm.readable()) { cmd = Host_Comm.getc(); if ((cmd == 'S') || (cmd == 's')) return; } address_ptr = (int*)address; Host_Comm.printf("%d %d %d %d\n\r",(uint8_t)(address_ptr[0]>>24),(uint8_t)(address_ptr[0]>>16),(uint8_t)(address_ptr[0]>>8),(uint8_t)address_ptr[0]); } address_ptr = (int*)local_base_address; for (int i = 0; i < remainder; i++) Host_Comm.printf("%d ",(uint8_t)(address_ptr[0]>>(8*(3-i)))); Host_Comm.printf("\n\r------- End Read Flash -------\n\n\r"); } // ------------------------------------------------------------------------------------------------------- // ------------------------------------------------------------------------------------------------------- // ------------------------------ ReadData ------------------------------ Data ReadData() { Data data; // Get Accelerometer data's Accel_Enable = 1; // Rising Edge -> Start measure int ready = 0; while((ready && 0x10) == 0) // Wait for accelerometer to have new data's ready = my8491.Read_Status(); data.accX = my8491.getAccAxis(REG_OUT_X_MSB); data.accY = my8491.getAccAxis(REG_OUT_Y_MSB); data.accZ = my8491.getAccAxis(REG_OUT_Z_MSB); Accel_Enable = 0; // Get Piezo Data's data.Vout_IF = ((float) myPTE20.read_u16() / 0XFFFF) * KL25Z_VDD; // convert in volt data.Vout_FILT = ((float) myPTE21.read_u16() / 0XFFFF) * KL25Z_VDD; data.Vout_GAIN = ((float) myPTE22.read_u16() / 0XFFFF) * KL25Z_VDD; return data; } // -------------------------------- Log --------------------------------- void Log() { Data currData; int16_t AccDataLog [N_PTS*3] = {}; // array to save latest data read int index_write = 0; // current position to write data in AccDataLog bool enoughData = 0; bool shockDetected = 0; // if shock detected int n_sinceShock = 0; // number of ReadData() since last chock while(Check_Jumper() && !foundError) { Led_Green != Led_Green; // LED blinks green while logging while (bTimer == 0) {} // Wait Acq Tick Timer bTimer = 0; currData = ReadData(); //Host_Comm.printf("%d ; %d ; %d ; %f\n\r", currData.accX, currData.accY, currData.accZ, currData.Vout_FILT); AccDataLog[index_write*3] = currData.accX; AccDataLog[index_write*3+1] = currData.accY; AccDataLog[index_write*3+2] = currData.accZ; float amplitude = abs(currData.Vout_FILT - KL25Z_VDD/2.0); //Host_Comm.printf("amplitude = %f\n\r",amplitude); if (amplitude >= THRESHOLD_SHOCK && enoughData) { shockDetected = 1; n_sinceShock = 0; } if (n_sinceShock == N_PTS/2 && shockDetected == 1) { MvtSet mvtSet; Rotate(AccDataLog, N_PTS-1-index_write, mvtSet.inputs); mvtSet.mvt = SelectMvt(mvtSet.inputs); if (mode == CONSOLE) PrintSet(mvtSet.inputs); else WriteFlash(mvtSet); shockDetected = 0; } index_write ++; n_sinceShock ++; if (index_write == N_PTS) { enoughData = 1; index_write = 0; } } Clear_Led(); } // ------------------------------- Rotate ------------------------------- void Rotate(int16_t *AccDataLog, int amount, int16_t *inputs) { for(int i = 0; i < N_PTS; i++) for(int j = 0; j < 3; j++) inputs[((i+amount)%N_PTS)*3+j] = AccDataLog[i*3+j]; } // ------------------------------ PrintSet ------------------------------ void PrintSet(int16_t *inputs) { Host_Comm.printf("------ Begin Set ------\n\r"); for(int i = 0; i < N_PTS; i++) Host_Comm.printf("%d %d %d\n\r", inputs[i*3],inputs[i*3+1],inputs[i*3+2]); Host_Comm.printf("------- End Set -------\n\n\r"); } // ------------------------------ Sigmoid ------------------------------- float Sigmoid(float x) { return 1/(1+exp(-x)); } // ----------------------------- SelectMvt ------------------------------ Mvt SelectMvt(int16_t *inputs) { int i, j; float selection [N_MVTS] = {}; for (j = 0; j < N_MVTS; j++) { for (i = 0; i < N_PTS*3; i++) selection[j] += (float)inputs[i] * Weights[i*N_MVTS+j]; selection[j] = Sigmoid(selection[j] + Biases[j]); } Mvt mvt = Undefined; for (i = 0; i < N_MVTS; i++) { if (selection[i] > THRESHOLD_MVT) mvt = static_cast<Mvt>(i+1); Host_Comm.printf("Proba mvt %d : %f\n\r",i+1,selection[i]); } return mvt; }