
Code for the project of LELEC2811 2017
Dependencies: FreescaleIAP MMA8491Q_PG mbed
Fork of LELEC_2811_Accelerometer by
Diff: main.cpp
- Revision:
- 3:d03eae745223
- Parent:
- 2:f146ae6546b5
- Child:
- 4:2de56fc46abb
--- a/main.cpp Mon Nov 27 15:14:24 2017 +0000 +++ b/main.cpp Mon Nov 27 22:37:15 2017 +0000 @@ -5,18 +5,12 @@ #define MMA8491_I2C_ADDRESS (0x55<<1) -#define NO_JUMPER 0 -#define JUMPER_PRESENT 1 - -#define LEVEL_0 0 -#define LEVEL_1 1 +#define DISABLE_STATE 0 +#define ENABLE_STATE 1 #define LED_ON 0 #define LED_OFF 1 -#define DISABLE_STATE 0 -#define ENABLE_STATE 1 - #define REG_OUT_X_MSB 0x01 #define REG_OUT_Y_MSB 0x03 #define REG_OUT_Z_MSB 0x05 @@ -25,368 +19,280 @@ #define FLASH_ACQ_DONE 1 #define ERASE_FLASH_ERROR -1 #define WRITE_FLASH_ERROR -2 - + #define SECTOR_SIZE 1024 #define RESERVED_SECTOR 32 - -#define ACQ_TIMER_PERIOD 0.01 // Time between 2 acquisitions (here 10 mSec) + +#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 6 // Number of mvts detected +#define THRESHOLD_MVT 0.6 // threshold to validate a mvt +#define THRESHOLD_SHOCK 0.5 // threshold to detect shock -typedef struct{ - int16_t X; - int16_t Y; - int16_t Z; -} Accel_Data; +MMA8491Q my8491(PTE0, PTE1, MMA8491_I2C_ADDRESS); // Setup I2C for MMA8491 -// --- Setup I2C for MMA8491 -MMA8491Q my8491(PTE0, PTE1, MMA8491_I2C_ADDRESS); +Serial Host_Comm(USBTX, USBRX); // Set Serial Port -// --- Set Serial Port -Serial Host_Comm(USBTX, USBRX); // tx, rxSerial pc(USBTX, USBRX); // tx, rx +AnalogIn myPTE20(PTE20); +AnalogIn myPTE21(PTE21); +AnalogIn myPTE22(PTE22); -Ticker myTick_Acq; // Periodical timer for Acquisition - -DigitalOut Led_Red(LED1); // Define I/O for Leds +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(PTC9); // Used to enter/exit Acquisition mode -DigitalIn Start_Pulse_In(PTC11); // ShortPin J1_15 and J1_16 to enter in Acq_Mode +DigitalOut Start_Pulse_Out(PTC9); // Used to enter/exit Acquisition mode +DigitalIn Start_Pulse_In(PTC11); // ShortPin J1_15 and J1_16 to enter in Acq_Mode -// Globale variable -volatile bool bTimer; // 1 means a Timer tick is done +// --------------------- Structure and Enumeration --------------------- +struct Data { + int16_t accX, accY, accZ; + unsigned short Vout_IF; // 2 bytes : Analog_PTE20 + unsigned short Vout_FILT; // 2 bytes : Analog_PTE21 + unsigned short Vout_GAIN; // 2 bytes : Analog_PTE22 +}; + +struct NeuralNetwork { + float* Weights; + float* Biases; +}; + +enum Mvts { Undefined = 0, Serve, ClearOverhead, DropOverhead, SmashShot, ClearUnderarm, DropUnderarm }; + +// -------------------------- Globale variable -------------------------- +volatile bool bTimer; // 1 means a Timer tick is done int Flash_Base_Address = RESERVED_SECTOR * SECTOR_SIZE ; // Store Flash Base Adresse with 32K reserved for Application Code -int Nb_Sector; +int n_sector; uint32_t KL25_Flash_Size; -// Function Declaration - +// ------------------------ Function Declaration ------------------------ +void Init(void); void Clear_Led(void); -int Acquisition_Flash(void); -int Read_Data_Logging(void); -bool Check_Jumper(void); -void myTimer_Acq_Task(void); -void Acquisition_Task(void); -void Read_Task(void); +bool Check_Jumper(void); // if J1_15 & J1_16 connected together -> return 1 +void myTimer_Acq_Task(void); // called by the timer +Data ReadData(void); + +void Log(void); +void PrintSet(Data *data, int n); +void Print(Data data); +NeuralNetwork *InitNeuralNetwork(void); // Initialize the neural network +void FreeNeuralNetwork(NeuralNetwork *nn); // Free the allocated memory +float Sigmoid(float x); // sigmoid function (used by neural network) +Mvts SelectMvt(NeuralNetwork *nn, int16_t *AccDataLog, int index_write); extern IAPCode verify_erased(int address, unsigned int length); -int main() { +// ---------------------------------------------------------------------- +// -------------------------------- main -------------------------------- +int main() +{ + Init (); + uint8_t Count; - Start_Pulse_In.mode(PullNone); // Input Pin is programmed as floating - Accel_Enable = DISABLE_STATE; // Turn Accel Enable to disabled state - - // --- Baud rate setting - Host_Comm.baud(115200); - - Clear_Led(); - - KL25_Flash_Size = flash_size(); // Get Size of KL25 Embedded Flash - Nb_Sector = (KL25_Flash_Size / SECTOR_SIZE) - RESERVED_SECTOR; // Reserve Max 32K for App Code - - myTick_Acq.attach(&myTimer_Acq_Task, ACQ_TIMER_PERIOD); - - Host_Comm.printf("\n\rLELEC2811 Badminton Logger V1.0 Nov2017 Group G\n\r"); - - for (;;) + while(true) { - if (Check_Jumper() == JUMPER_PRESENT) + if (Check_Jumper()) { Clear_Led(); - Count = 5; while (Count !=0) { - if (Check_Jumper() == JUMPER_PRESENT) + if (Check_Jumper()) { - Led_Blue = LED_ON; // Blink to alert user "Enter in Acquisition" - wait_ms(900); + Led_Blue = LED_ON; // Blink to alert user "Enter in Logging mode" + wait_ms(500); Led_Blue = LED_OFF; - wait_ms(100); + wait_ms(500); Count --; if (Count == 0) - { - Acquisition_Task(); - } + Log(); } else - { Count = 0; - } - } - } - else - { - Read_Task(); + } } - } -} - -void Read_Task() -{ - char host_cmd; - IAPCode Flash_State; - bool bAcq_Done; - - Flash_State = verify_erased(Flash_Base_Address, KL25_Flash_Size - (RESERVED_SECTOR * SECTOR_SIZE)); - if (Flash_State == 0) // Virgin Flash ? - { - bAcq_Done = 0; - } - else - { - bAcq_Done = 1; - } - - Clear_Led(); - wait_ms(500); - - if (bAcq_Done == 1) - { - Led_Green = LED_ON; - Host_Comm.putc('1'); - } - else - { - Led_Red = LED_ON; - Host_Comm.putc('0'); - } - - if(Host_Comm.readable()) // Did we receive a char from Host ? - { - host_cmd = Host_Comm.getc(); // Get it - - if ((host_cmd == 'R') || (host_cmd == 'r')) // Read Flash Command ? - { - Read_Data_Logging(); // Read and send acquisition data - } - } - wait_ms(50); -} - -void Acquisition_Task() -{ - int Acq_Status; - - Clear_Led(); - - Acq_Status = Acquisition_Flash(); - - Clear_Led(); - - while (Check_Jumper() == JUMPER_PRESENT) - { - if (Acq_Status != FLASH_ACQ_DONE) - { - Led_Red = !Led_Red; - } - else - { - Led_Green = !Led_Green; - } - wait_ms(100); + wait_ms(500); } } +// -------------------------------- Init -------------------------------- +void Init(void) +{ + Start_Pulse_In.mode(PullNone); // Input Pin is programmed as floating + Accel_Enable = DISABLE_STATE; // Turn Accel Enable to disabled state + Clear_Led(); + + KL25_Flash_Size = flash_size(); // Get Size of KL25 Embedded Flash + n_sector = (KL25_Flash_Size / SECTOR_SIZE) - RESERVED_SECTOR; // Reserve Max 32K for App Code + + myTick_Acq.attach(&myTimer_Acq_Task, ACQ_TIMER_PERIOD); // Timer for acquisition + + Host_Comm.baud(115200); // Baud rate setting + Host_Comm.printf("\nLELEC2811 - Badminton Logger - Group G\n"); + Host_Comm.printf("Initialization done.\n"); +} + +// ----------------------------- Clear_Led ------------------------------ void Clear_Led(void) { Led_Red = LED_OFF; Led_Green = LED_OFF; - Led_Blue = LED_OFF ; // Bug on board : Turning On Blue Led decrease consumption... + Led_Blue = LED_OFF ; // Bug on board : Turning On Blue Led decrease consumption... } -bool Check_Jumper() // If J1_15 and J1_16 connected together -> return JUMPER_PRESENT +// ---------------------------- Check_Jumper ---------------------------- +bool Check_Jumper() { uint8_t i; - for (i = 0 ; i < 2 ; i ++) { - Start_Pulse_Out = LEVEL_1; + Start_Pulse_Out = 1; wait_ms(1); - if (Start_Pulse_In != LEVEL_1) - { - return NO_JUMPER; - } + if (Start_Pulse_In != 1) + return 0; - Start_Pulse_Out = LEVEL_0; + Start_Pulse_Out = 0; wait_ms(1); - if (Start_Pulse_In != LEVEL_0) - { - return NO_JUMPER; - } + if (Start_Pulse_In != 0) + return 0; } - return JUMPER_PRESENT; + return 1; } -int Acquisition_Flash(void) +// -------------------------- myTimer_Acq_Task -------------------------- +void myTimer_Acq_Task() { bTimer = 1; } + +// ------------------------------ ReadData ------------------------------ +Data ReadData() { - int Status; - int Flash_Ptr ; - uint8_t Data_Ptr; - Accel_Data myData[2]; - uint8_t Ready; - int Led_Counter; + Data data; + + // Get Accelerometer data's + Accel_Enable = ENABLE_STATE; // Rising Edge -> Start measure + + uint8_t 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 = DISABLE_STATE; - for (Flash_Ptr = Flash_Base_Address ; Flash_Ptr < KL25_Flash_Size ; Flash_Ptr += 0x400) + // Get Piezo Data's + data.Vout_IF = myPTE20.read_u16(); + data.Vout_FILT = myPTE21.read_u16(); + data.Vout_GAIN = myPTE22.read_u16(); + + return data; +} + +// -------------------------------- Log --------------------------------- +void Log() +{ + NeuralNetwork *nn = InitNeuralNetwork(); + 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 shockDetected = 0; // if shock detected + int n_sinceShock = 0; // number of ReadData() since last chock + Mvts mvts [100] = {}; // stocks history of mvts + int index_mvt = 0; + + while(Check_Jumper()) { - Status = erase_sector(Flash_Ptr); // Erase sector - - if (Status !=0) - { - return ERASE_FLASH_ERROR; - } - } - - Flash_Ptr = Flash_Base_Address; - - Led_Blue = LED_ON; - - Led_Counter = 0; - Data_Ptr = 0; - while (Flash_Ptr < KL25_Flash_Size ) // Acq Loop - { - while (bTimer == 0) // Wait Acq Tick Timer - { - - } + Led_Green != Led_Green; // LED blinks green while logging + + while (bTimer == 0) {} // Wait Acq Tick Timer bTimer = 0; - Accel_Enable = ENABLE_STATE; // Rising Edge -> Start Accel Measure + currData = ReadData(); + // Host_Comm.printf("%d ; %d ; %d ; %d ; %d ; %d\n", data.accX, data.accY, data.accZ, data.Vout_IF, data.Vout_FILT, data.Vout_GAIN); + AccDataLog[index_write*3] = currData.accX; + AccDataLog[index_write*3+1] = currData.accY; + AccDataLog[index_write*3+2] = currData.accZ; - if ((float) Led_Counter * ACQ_TIMER_PERIOD == 1.0) // Blink at 1 Hz - { - Led_Counter = 0; - Led_Blue = !Led_Blue; - } - - - Ready = 0; - while((Ready && 0x10) == 0) // Wait Accelerometer have new data's + if (currData.Vout_FILT >= THRESHOLD_SHOCK) { - Ready = my8491.Read_Status(); + shockDetected = 1; + n_sinceShock = 0; } - - myData[Data_Ptr].X = my8491.getAccAxis(REG_OUT_X_MSB); - myData[Data_Ptr].Y = my8491.getAccAxis(REG_OUT_Y_MSB); - myData[Data_Ptr].Z = my8491.getAccAxis(REG_OUT_Z_MSB); - - Led_Counter++; - - Accel_Enable = DISABLE_STATE; - - //Host_Comm.printf("\n\r%x\tX = %f", Flash_Ptr, float(myData[Data_Ptr].X)*4.0/4096.0 ); - //Host_Comm.printf("\tY = %f", float(myData[Data_Ptr].Y)*4.0/4096.0 ); - //Host_Comm.printf("\tZ = %f", float(myData[Data_Ptr].Z)*4.0/4096.0 ); - - Data_Ptr ++; - - if (Data_Ptr == 2)// Save 2 acquistions -> 2 * 3 * 2 bytes = 12 bytes + if (n_sinceShock == N_PTS/2 && shockDetected == 1) { - Data_Ptr = 0; - Status = program_flash(Flash_Ptr, (char *) &myData[0].X, 4); // Write 4 bytes in the Flash - if (Status !=0) - { - return WRITE_FLASH_ERROR; - } - - Flash_Ptr += 4; - Status = program_flash(Flash_Ptr, (char *) &myData[0].Z, 4); // Write 4 bytes in the Flash - if (Status !=0) - { - return WRITE_FLASH_ERROR; - } - - Flash_Ptr += 4; - //Status = program_flash(Flash_Ptr, (char *) &myData[1].Y, 4); // Write 4 bytes in the Flash - Status = program_flash(Flash_Ptr, (char *) &myData[0].Y, 4); // Bug corrected 23/11/2016 - if (Status !=0) - { - return WRITE_FLASH_ERROR; - } - - Flash_Ptr += 4; - - if ((Flash_Ptr & 0x3FC) == 0x3FC) - { - Flash_Ptr += 4; //170 * 6 = 1020 ---> skip 4 last bytes of each sector of 1024 bytes - } + mvts[index_mvt] = SelectMvt(nn, AccDataLog, index_write); + index_mvt ++; + shockDetected = 0; } - if (Check_Jumper() != JUMPER_PRESENT) // If Jumper remoded -> Stop Acquisition - { - return FLASH_ACQ_DONE ; - } + + index_write ++; + n_sinceShock ++; + if (index_write == N_PTS-1) + index_write = 0; } - return FLASH_ACQ_DONE ; + FreeNeuralNetwork(nn); + Clear_Led(); +} + +// ------------------------- InitNeuralNetwork -------------------------- +NeuralNetwork *InitNeuralNetwork(void) +{ + NeuralNetwork *nn = (NeuralNetwork*) malloc(sizeof(NeuralNetwork)); + nn->Weights = (float*) malloc(sizeof(float)*N_PTS*N_MVTS); + nn->Biases = (float*) malloc(sizeof(float)*N_MVTS); + return nn; } -int Read_Data_Logging() -{ - int16_t *data = (int16_t *) Flash_Base_Address; // uint16 pointer of data stored in Flash - int Flash_Ptr; - char cmd; - int Record_Counter; - float X_Val, Y_Val, Z_Val; - int16_t Raw_X, Raw_Y, Raw_Z; - int Max_Record; - - Clear_Led(); - - Max_Record = Nb_Sector * (SECTOR_SIZE / sizeof(Accel_Data)); - Record_Counter = 0; - Flash_Ptr = 0; - - //Host_Comm.printf("\n\rBegin of Data"); +// ------------------------- FreeNeuralNetwork -------------------------- +void FreeNeuralNetwork(NeuralNetwork *nn) +{ + free(nn->Weights); + free(nn->Biases); + free(nn); +} - while (Record_Counter < Max_Record) - { - Led_Green = !Led_Green; - Led_Blue = !Led_Green; - - if(Host_Comm.readable()) - { - cmd = Host_Comm.getc(); - if ((cmd == 'S') || (cmd == 's')) // Receiving 'S' or 's' means stop Read Flash - { - Clear_Led(); - return 0; - } - } - - Record_Counter ++; - - Raw_X = data[Flash_Ptr++]; - Raw_Y = data[Flash_Ptr++]; - Raw_Z = data[Flash_Ptr++]; - - if ((Raw_X == -1) && (Raw_Y == -1) && (Raw_Z == -1)) // Valid data ? (!= 0xFFFFFFFF from empty Flash sector) - { - } - else - { - X_Val = float(Raw_X) * 4.0/4096.0; - Y_Val = float(Raw_Y) * 4.0/4096.0; - Z_Val = float(Raw_Z) * 4.0/4096.0; - - Host_Comm.printf("\n\r%d\tX=%.4f\tY=%.4f\tZ=%.4f", Record_Counter, X_Val, Y_Val, Z_Val); - } - - if ((Flash_Ptr & 0x1FE) == 0x1FE) - { - Flash_Ptr +=2; // skip the last bytes at the end of a sector - } - } - //Host_Comm.printf("\n\rEnd of Data"); - Clear_Led(); - return 0; +// ------------------------------ Sigmoid ------------------------------- +float Sigmoid(float x) +{ + return 1/(1+exp(-x)); } -/* Interrupt Task */ -void myTimer_Acq_Task() -{ - bTimer = 1; +// ----------------------------- SelectMvt ------------------------------ +Mvts SelectMvt(NeuralNetwork *nn, int16_t *AccDataLog, int index_write) +{ + int i, j; + + // inputs = AccDataLog rotated of N_PTS-1-index_write + int shift_amount = N_PTS-1-index_write; + int16_t inputs [N_PTS*3]; + for(i = 0; i < N_PTS; i++) + for(j = 0; j < 3; j++) + inputs[((i+shift_amount)%N_PTS)*3+j] = AccDataLog[i*3+j]; + + /* + for(i = 0; i < N_PTS; i++) + Host_Comm.printf("%d ; %d ; %d\n", inputs[i*3],inputs[i*3+1],inputs[i*3+2]); + */ + + float selection [N_MVTS] = {}; + for (j = 0; j < N_MVTS; j++) { + for (i = 0; i < N_PTS*3; i++) + selection[j] += inputs[i] * nn->Weights[i*N_PTS*3+j]; + + selection[j] = Sigmoid(selection[j] + nn->Biases[j]); + } + + Mvts mvt = Undefined; + for (i = 0; i < N_MVTS; i++) + if (selection[i] > THRESHOLD_MVT) + mvt = static_cast<Mvts>(i); + + return mvt; }