store accel_z and sallen key signal

Dependencies:   mbed tsi_sensor FreescaleIAP MMA8451Q MPL3115A2

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

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 }