store accel_z and sallen key signal
Dependencies: mbed tsi_sensor FreescaleIAP MMA8451Q MPL3115A2
main.cpp
00001 /*******************************************************/ 00002 /**** LELEC_2811 Multiple sensors logger ***/ 00003 /**** P. Gerard UCL 23/11/2016 ***/ 00004 /**** M. Lefebvre UCL 09/11/2018 ***/ 00005 /*******************************************************/ 00006 00007 #include "mbed.h" 00008 #include "FreescaleIAP.h" // Library for Flash access 00009 #include "MMA8451Q.h" // Accelerometer 00010 #include "MPL3115A2.h" // Library for altimeter/temperature access 00011 00012 #define KL25Z_VDD 2.7 // !!! Value of supply voltage VDD: To be measured on board KL25Z pin 3V3 (calibration) 00013 00014 #define MMA8451_I2C_ADDRESS (0x1d<<1) 00015 #define FSR 0x02 // 0x00 for 2G, 0x01 for 4G, 0x02 for 8G 00016 #define REG_OUT_X_MSB 0x01 00017 #define REG_OUT_Y_MSB 0x03 00018 #define REG_OUT_Z_MSB 0x05 00019 00020 #define MPL3115A2_I2C_ADDRESS (0x60<<1) 00021 #define REG_ALTIMETER_MSB 0x01 00022 00023 #define DISABLE_STATE 0 00024 #define ENABLE_STATE 1 00025 00026 #define NO_JUMPER 0 00027 #define JUMPER_PRESENT 1 00028 00029 #define LEVEL_0 0 00030 #define LEVEL_1 1 00031 00032 #define LED_ON 0 00033 #define LED_OFF 1 00034 00035 #define FLASH_NO_ACQ_DONE 0 00036 #define FLASH_ACQ_DONE 1 00037 #define ERASE_FLASH_ERROR -1 00038 #define WRITE_FLASH_ERROR -2 00039 00040 #define SECTOR_SIZE 1024 00041 #define RESERVED_SECTOR 32 00042 00043 #define ACQ_TIMER_PERIOD 0.05 // Time between 2 acquisitions in seconds 00044 // f_sampling = 1 / ACQ_TIMER_PERIOD = 20Hz 00045 00046 #define N_PER_AVERAGE 20 // f_storage = f_sampling / N_PER_AVERAGE = 2Hz 00047 00048 #define BOARD_STRAIGHT 0 00049 #define BOARD_UPSIDE_DOWN 1 00050 #define ACCEL_MINIMUM_FOR_STORAGE 0 00051 00052 // Structure of sensors Data !!!!! SIZE MUST BE A MULTIPLE OF 4 bytes !!!!! 00053 typedef struct{ 00054 int16_t Accel_X; // 2 bytes 00055 int16_t Accel_Y; // 2 bytes 00056 int16_t Accel_Z; // 2 bytes 00057 float Temperature; // 4 bytes 00058 unsigned short Analog_PTE20; // 2 bytes 00059 unsigned short Analog_PTE21; // 2 bytes 00060 unsigned short Empty; // 2 bytes 00061 } Sensor_Data; // TOTAL = 16 bytes 00062 00063 typedef struct{ 00064 unsigned short Accel_Z; 00065 unsigned short Sallen_Key; 00066 // unsigned short Interface; 00067 // unsigned short Useless; 00068 } Stored_Data; 00069 00070 int Number_Stored_Points; 00071 00072 // --- Setup I2C for MMA8451 accelerometer 00073 // --- The last argument is the full scale range (FSR). 0x00 for 2G, 0x01 for 4G, 0x02 for 8G 00074 MMA8451Q my8451(PTE25, PTE24, MMA8451_I2C_ADDRESS, FSR); 00075 DigitalOut Accel_Enable(PTA13); 00076 00077 // --- Set temperature sensor 00078 MPL3115A2 myMPL3115(PTE0, PTE1, MPL3115A2_I2C_ADDRESS); 00079 00080 // --- Set serial port (for communication with PC) 00081 Serial Host_Comm(USBTX, USBRX); 00082 00083 // Analog inputs (ADCs) 00084 AnalogIn myPTE20(PTE20); 00085 AnalogIn myPTE21(PTE21); 00086 00087 // Analog output (DAC) 00088 AnalogOut myDAC(PTE30); 00089 00090 // Digital outputs 00091 DigitalOut Led_Red(LED1); // Define I/O for LEDs 00092 DigitalOut Led_Green(LED2); 00093 DigitalOut Led_Blue(LED3); 00094 DigitalOut Start_Pulse_Out(PTC9); // Used to enter/exit acquisition mode 00095 DigitalIn Start_Pulse_In(PTC11); // Short pins J1_15 and J1_16 to enter in Acq_Mode 00096 00097 // Global variables 00098 volatile bool bTimer; // 1 means a timer tick is done 00099 Ticker myTick_Acq; // Periodical timer for acquisition 00100 00101 int Flash_Base_Address = RESERVED_SECTOR * SECTOR_SIZE; // Store Flash base address with 32K reserved for application code 00102 int Nb_Sector; 00103 uint32_t KL25_Flash_Size; 00104 00105 // Functions declaration 00106 void Clear_Led(void); 00107 int Acquisition_Flash(void); 00108 int Read_Data_Logging(void); 00109 bool Check_Jumper(void); 00110 void myTimer_Acq_Task(void); 00111 void Acquisition_Task(void); 00112 void Read_Task(void); 00113 extern IAPCode verify_erased(int address, unsigned int length); 00114 00115 int main() { 00116 00117 uint8_t Count; // Count defining the number of time the LED blinks before data acquisition 00118 00119 // Set DAC output voltage 00120 float vdac; 00121 uint16_t dac_value; // Local variable in 16 bits 00122 00123 vdac = 0; // Voltage output value 00124 dac_value = (uint16_t) ((vdac * 65536) / KL25Z_VDD); // Transform desired voltage to fraction of 0xFFFF 00125 myDAC.write_u16(dac_value); // DAC value in range 0x0000 - 0xFFFF (see mbed's AnalogOut classe ref.) 00126 00127 Start_Pulse_In.mode(PullNone); // Input pin is programmed as floating 00128 Accel_Enable = DISABLE_STATE; // Turn Accel. Enable I/O to disabled state 00129 00130 // --- Baud rate setting 00131 Host_Comm.baud(115200); 00132 Clear_Led(); 00133 00134 KL25_Flash_Size = flash_size(); // Get size of KL25 embedded Flash 00135 Nb_Sector = (KL25_Flash_Size / SECTOR_SIZE) - RESERVED_SECTOR; // Reserve max 32K for app code 00136 myTick_Acq.attach(&myTimer_Acq_Task, ACQ_TIMER_PERIOD); // Initialize timer interrupt 00137 00138 Host_Comm.printf("\n\rLELEC2811 Multiple sensors logger V2.0 UCL 2018\n\r"); 00139 00140 if ((sizeof(Sensor_Data) % 4) != 0) 00141 { 00142 Host_Comm.printf("\n\rERROR! Acquisition Data Structure size is NOT a multiple of 4!!! (%d)", sizeof(Sensor_Data)); 00143 for(;;); 00144 } 00145 00146 myMPL3115.Oversample_Ratio(OVERSAMPLE_RATIO_4); 00147 myMPL3115.Barometric_Mode(); // Configure MPL3115 (used for temperature and pressure measurement) 00148 00149 for (;;) 00150 { 00151 if (Check_Jumper() == JUMPER_PRESENT) 00152 { 00153 Clear_Led(); 00154 00155 Count = 5; 00156 while (Count !=0) 00157 { 00158 if (Check_Jumper() == JUMPER_PRESENT) 00159 { 00160 Led_Blue = LED_ON; // Blink to alert user "Enter in Acquisition" after 5 seconds 00161 wait_ms(900); 00162 Led_Blue = LED_OFF; 00163 wait_ms(100); 00164 Count --; 00165 if (Count == 0) 00166 { 00167 Acquisition_Task(); 00168 } 00169 } 00170 else 00171 { 00172 Count = 0; 00173 } 00174 } 00175 } 00176 else 00177 { 00178 Read_Task(); 00179 } 00180 } 00181 } 00182 00183 void Read_Task() 00184 { 00185 char host_cmd; 00186 IAPCode Flash_State; 00187 bool bAcq_Done; 00188 00189 Flash_State = verify_erased(Flash_Base_Address, KL25_Flash_Size - (RESERVED_SECTOR * SECTOR_SIZE)); 00190 if (Flash_State == 0) // Virgin Flash ? 00191 { 00192 bAcq_Done = 0; 00193 } 00194 else 00195 { 00196 bAcq_Done = 1; 00197 } 00198 00199 Clear_Led(); 00200 wait_ms(500); 00201 00202 if (bAcq_Done == 1) 00203 { 00204 Led_Green = LED_ON; 00205 Host_Comm.putc('1'); 00206 } 00207 else 00208 { 00209 Led_Red = LED_ON; 00210 Host_Comm.putc('0'); 00211 } 00212 00213 if(Host_Comm.readable()) // Did we receive a char from Host ? 00214 { 00215 host_cmd = Host_Comm.getc(); // Get it 00216 00217 if ((host_cmd == 'R') || (host_cmd == 'r')) // Read Flash Command ? 00218 { 00219 Read_Data_Logging(); // Read and send acquisition data 00220 } 00221 } 00222 wait_ms(50); 00223 } 00224 00225 void Acquisition_Task() 00226 { 00227 int Acq_Status; 00228 00229 Clear_Led(); 00230 00231 Acq_Status = Acquisition_Flash(); 00232 00233 Clear_Led(); 00234 00235 while (Check_Jumper() == JUMPER_PRESENT) 00236 { 00237 if (Acq_Status != FLASH_ACQ_DONE) 00238 { 00239 Led_Red = !Led_Red; 00240 } 00241 else 00242 { 00243 Led_Green = !Led_Green; 00244 } 00245 wait_ms(100); 00246 } 00247 } 00248 00249 void Clear_Led(void) 00250 { 00251 Led_Red = LED_OFF; 00252 Led_Green = LED_OFF; 00253 Led_Blue = LED_OFF; // Bug on board : Turning on the blue LED decreases consumption... 00254 } 00255 00256 bool Check_Jumper() // If J1_15 and J1_16 connected together -> return JUMPER_PRESENT 00257 { 00258 uint8_t i; 00259 00260 for (i = 0 ; i < 2 ; i ++) 00261 { 00262 Start_Pulse_Out = LEVEL_1; 00263 wait_ms(1); 00264 if (Start_Pulse_In != LEVEL_1) 00265 { 00266 return NO_JUMPER; 00267 } 00268 00269 Start_Pulse_Out = LEVEL_0; 00270 wait_ms(1); 00271 if (Start_Pulse_In != LEVEL_0) 00272 { 00273 return NO_JUMPER; 00274 } 00275 } 00276 return JUMPER_PRESENT; 00277 } 00278 00279 int Acquisition_Flash(void) 00280 { 00281 int Status; 00282 int Flash_Ptr ; 00283 int Led_Counter; 00284 Sensor_Data myData; 00285 int Board_Position; 00286 int Count_Measurements; 00287 Stored_Data myStoredData; 00288 00289 double sallen_key = 0; 00290 00291 /*** Erase all Flash Page **/ 00292 for (Flash_Ptr = Flash_Base_Address ; Flash_Ptr < KL25_Flash_Size ; Flash_Ptr += 0x400) 00293 { 00294 Status = erase_sector(Flash_Ptr); // Erase sector 00295 00296 if (Status !=0) 00297 { 00298 return ERASE_FLASH_ERROR; 00299 } 00300 } 00301 00302 Flash_Ptr = Flash_Base_Address; // Begin of Storage Area in Flash 00303 00304 Led_Blue = LED_ON; 00305 Led_Counter = 0; 00306 00307 /*** Reset new variables **/ 00308 00309 myStoredData.Accel_Z= 0; 00310 // myStoredData.Interface = 0; 00311 myStoredData.Sallen_Key = 0; 00312 00313 Board_Position = BOARD_STRAIGHT; 00314 00315 Number_Stored_Points = 0; 00316 00317 00318 /***** Begin of Loop Acquisition - Write in Flash ***/ 00319 00320 while (Flash_Ptr < (KL25_Flash_Size - sizeof(Sensor_Data)) ) // Acq Loop 00321 { 00322 while (bTimer == 0) // Wait Acq Tick Timer Done 00323 { 00324 00325 } 00326 bTimer = 0; 00327 00328 if ((float) Led_Counter * ACQ_TIMER_PERIOD == 1.0) // Blink at 1Hz 00329 { 00330 Led_Counter = 0; 00331 Led_Blue = !Led_Blue; 00332 } 00333 00334 Led_Counter++; 00335 00336 // Get accelerometer data 00337 Accel_Enable = ENABLE_STATE; // Rising edge -> Start accelerometer measurement 00338 00339 // myData.Accel_X = my8451.getAccAxis(REG_OUT_X_MSB); 00340 // myData.Accel_Y = my8451.getAccAxis(REG_OUT_Y_MSB); 00341 myData.Accel_Z = my8451.getAccAxis(REG_OUT_Z_MSB); 00342 00343 Accel_Enable = DISABLE_STATE; 00344 00345 00346 /*** verify if it is upside down ***/ 00347 if (myData.Accel_Z < ACCEL_MINIMUM_FOR_STORAGE) 00348 Board_Position = BOARD_UPSIDE_DOWN; 00349 00350 if (Board_Position == BOARD_UPSIDE_DOWN){ 00351 00352 Count_Measurements ++; 00353 00354 // Get ADC values 00355 myData.Analog_PTE20 = myPTE20.read_u16(); 00356 // myData.Analog_PTE21 = myPTE21.read_u16(); 00357 00358 // add data to stored variable 00359 myStoredData.Accel_Z = myData.Accel_Z; 00360 00361 sallen_key += myData.Analog_PTE20; 00362 // myStoredData.Sallen_Key += myData.Analog_PTE20; 00363 // myStoredData.Interface += myData.Analog_PTE21; 00364 00365 Host_Comm.printf("\n\r%d %d", Count_Measurements, myStoredData.Accel_Z); 00366 00367 // after N_PER_AVERAGE measurements, take average and store 00368 if (Count_Measurements >= N_PER_AVERAGE){ 00369 00370 Count_Measurements = 0; 00371 00372 sallen_key = sallen_key/N_PER_AVERAGE; 00373 myStoredData.Sallen_Key = (short) sallen_key; 00374 // myStoredData.Sallen_Key = myStoredData.Sallen_Key / N_PER_AVERAGE; 00375 // myStoredData.Interface = myStoredData.Interface / N_PER_AVERAGE; 00376 00377 // resets the value at the average 00378 sallen_key = 0; 00379 00380 /*** Save Data in Flash ***/ 00381 Number_Stored_Points ++; 00382 Status = program_flash(Flash_Ptr, (char *) &myStoredData, sizeof(Stored_Data)); // Write in the Flash 00383 if (Status != 0) 00384 { 00385 Host_Comm.printf("\n\rFlash_Write Error = %d", Status); 00386 return WRITE_FLASH_ERROR; 00387 } 00388 Flash_Ptr += sizeof(Stored_Data); 00389 00390 // verifies if system comes back straight orientation 00391 if (myData.Accel_Z > ACCEL_MINIMUM_FOR_STORAGE) 00392 Board_Position = BOARD_STRAIGHT; 00393 00394 if (Check_Jumper() != JUMPER_PRESENT) // If jumper removed -> Stop acquisition 00395 { 00396 return FLASH_ACQ_DONE ; 00397 } 00398 } 00399 00400 } 00401 00402 else { 00403 if (Check_Jumper() != JUMPER_PRESENT) // If jumper removed -> Stop acquisition 00404 return FLASH_ACQ_DONE ; 00405 } 00406 00407 } 00408 00409 return FLASH_ACQ_DONE ; 00410 } 00411 00412 int Read_Data_Logging() 00413 { 00414 Stored_Data * data = (Stored_Data * )Flash_Base_Address; // Sensor_Data pointer of data stored in Flash 00415 int Flash_Record_Ptr; 00416 char cmd; 00417 int Record_Counter; 00418 int Max_Record; 00419 Stored_Data myRead_Data; // Data Structure used to retrieve saved value from Flash 00420 00421 float Ethanol_Sallen_Key; 00422 // float Ethanol_Interface; 00423 00424 Clear_Led(); 00425 00426 Max_Record = (Nb_Sector * SECTOR_SIZE) / sizeof(Sensor_Data); 00427 Record_Counter = 0; 00428 Flash_Record_Ptr = 0; 00429 00430 Host_Comm.printf("\n\r# AccZ Eth_SK"); 00431 00432 while (Record_Counter < Number_Stored_Points && Record_Counter < Max_Record) 00433 { 00434 Led_Green = !Led_Green; 00435 Led_Blue = !Led_Green; 00436 00437 if(Host_Comm.readable()) 00438 { 00439 cmd = Host_Comm.getc(); 00440 if ((cmd == 'S') || (cmd == 's')) // Receiving 'S' or 's' means stop Read Flash 00441 { 00442 Clear_Led(); 00443 return 0; 00444 } 00445 } 00446 00447 myRead_Data = data[Flash_Record_Ptr]; 00448 00449 Flash_Record_Ptr ++; 00450 00451 if (myRead_Data.Accel_Z == -1) // Valid data ? (!= 0xFFFFFFFF from empty Flash sector) 00452 { 00453 } 00454 else 00455 { 00456 Ethanol_Sallen_Key = ((float) myRead_Data.Sallen_Key / 0XFFFF) * KL25Z_VDD; // Convert to voltage 00457 // Ethanol_Interface = ((float) myRead_Data.Interface / 0XFFFF) * KL25Z_VDD; 00458 00459 Host_Comm.printf("\n\r%d ", Record_Counter); 00460 Host_Comm.printf("%d ", myRead_Data.Accel_Z); 00461 Host_Comm.printf("%1.3f", Ethanol_Sallen_Key); 00462 } 00463 00464 Record_Counter ++; 00465 } 00466 Clear_Led(); 00467 return 0; 00468 } 00469 00470 /* Interrupt Task */ 00471 void myTimer_Acq_Task() 00472 { 00473 bTimer = 1; 00474 }
Generated on Mon Jul 18 2022 23:05:38 by 1.7.2