LELEC2811 - I&S / Mbed OS LELEC2811_LPS22HH_Altimeter

Dependencies:   X_NUCLEO_IKS01A3

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

Go to the documentation of this file.
00001 /**
00002  ******************************************************************************
00003  * @file    main.cpp
00004  * @author  SRA
00005  * @version V1.0.0
00006  * @date    5-March-2019
00007  * @brief   Simple Example application for using the X_NUCLEO_IKS01A3
00008  *          MEMS Inertial & Environmental Sensor Nucleo expansion board.
00009  ******************************************************************************
00010  * @attention
00011  *
00012  * <h2><center>&copy; COPYRIGHT(c) 2019 STMicroelectronics</center></h2>
00013  *
00014  * Redistribution and use in source and binary forms, with or without modification,
00015  * are permitted provided that the following conditions are met:
00016  *   1. Redistributions of source code must retain the above copyright notice,
00017  *      this list of conditions and the following disclaimer.
00018  *   2. Redistributions in binary form must reproduce the above copyright notice,
00019  *      this list of conditions and the following disclaimer in the documentation
00020  *      and/or other materials provided with the distribution.
00021  *   3. Neither the name of STMicroelectronics nor the names of its contributors
00022  *      may be used to endorse or promote products derived from this software
00023  *      without specific prior written permission.
00024  *
00025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00028  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00029  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00030  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00031  *  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00032  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00033  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00034  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  ******************************************************************************
00037 */
00038 
00039 /*
00040     LELEC2811 Altimeter LPS22HH Project
00041     M. Lefebvre - 2019-2020
00042 */
00043 
00044 /* Includes */
00045 #include <stdlib.h>
00046 #include <time.h>
00047 #include "mbed.h"
00048 #include "XNucleoIKS01A3.h"
00049 #include "stm32l073xx.h"
00050 #include "stm32l0xx_hal_flash.h"
00051 
00052 /* Defines */
00053 #define FS                      10.0    // Readout frequency (Hz)
00054 
00055 // LPS22HH Pressure sensor
00056 #define P0                      1013.26 // Sea level pressure (hPa)
00057 #define LPS22HH_ODR             10.0    // Output data rate (one-shot, 1, 10, 25, 50, 75, 100, 200 Hz)
00058 #define LPS22HH_LOW_NOISE_EN    1       // Low-noise (0 disabled, 1 enabled)
00059 #define LPS22HH_LPF_CFG         3       // Device bandwidth (0 for ODR/2, 2 for ODR/9, 3 for ODR/20)
00060 #define LPS22HH_DATA_SIZE       8       // Number of bytes for LPS22HH pressure sensor data
00061 
00062 /* Functions definition */
00063 bool acquisition_task(bool verbose);
00064 void read_task();
00065 void print_flash_info();
00066 bool erase_flash(bool verbose);
00067 bool write_flash(uint32_t Flash_addr, uint32_t* Flash_wdata, int32_t n_words, bool verbose);
00068 void read_flash(uint32_t Flash_addr, uint32_t* Flash_rdata, uint32_t n_bytes);
00069 void button1_enabled_cb(void);
00070 void button1_onpressed_cb(void);
00071 static char *print_double(char *str, double v);
00072 float pressure_to_altitude(double pressure);
00073 uint32_t FloatToUint(float n);
00074 float UintToFloat(uint32_t n);
00075 
00076 /* Serial link */
00077 Serial pc(SERIAL_TX, SERIAL_RX);
00078 
00079 /* Button */
00080 InterruptIn button1(USER_BUTTON);
00081 volatile bool button1_pressed = false; // Used in the main loop
00082 volatile bool button1_enabled = true; // Used for debouncing
00083 Timeout button1_timeout; // Used for debouncing
00084 
00085 /* Instantiate the expansion board */
00086 static XNucleoIKS01A3 *mems_expansion_board = XNucleoIKS01A3::instance(D14, D15, D4, D5, A3, D6, A4);
00087 
00088 /* Retrieve the composing elements of the expansion board */
00089 static LIS2MDLSensor *magnetometer = mems_expansion_board->magnetometer;
00090 static HTS221Sensor *hum_temp = mems_expansion_board->ht_sensor;
00091 static LPS22HHSensor *press_temp = mems_expansion_board->pt_sensor;
00092 static LSM6DSOSensor *acc_gyro = mems_expansion_board->acc_gyro;
00093 static LIS2DW12Sensor *accelerometer = mems_expansion_board->accelerometer;
00094 static STTS751Sensor *temp = mems_expansion_board->t_sensor;
00095 
00096 /* Main */
00097 int main()
00098 {
00099     uint8_t id;
00100     float read_reg, read_reg_1;
00101     uint8_t read_reg_int, read_reg_int_1, read_reg_int_2;
00102     
00103     bool save_data = false;
00104     uint32_t Flash_addr = FLASH_BANK2_BASE;
00105 
00106     /* Serial link configuration */
00107     pc.baud(115200);
00108     
00109     /* Button configuration */
00110     button1.fall(callback(button1_onpressed_cb)); // Attach ISR to handle button press event
00111     
00112     /* Reset message */
00113     printf("\n\r**************************************************\n\r");
00114     printf("LELEC2811 LPS22HH Altimeter Program\n\r");
00115     printf("**************************************************\n\r");
00116     
00117     /* LPS22HH pressure sensor configuration */
00118     press_temp->enable();
00119     printf("/***** LPS22HH pressure sensor configuration *****/\r\n");
00120     
00121     press_temp->read_id(&id);
00122     printf("LPS22HH pressure = 0x%X\r\n", id);
00123     
00124     press_temp->set_odr(LPS22HH_ODR, LPS22HH_LOW_NOISE_EN);
00125     press_temp->get_odr(&read_reg, &read_reg_int);
00126     printf("LPS22HH ODR = %1.1f [Hz]\r\n", read_reg);
00127     printf("LPS22HH LOW_NOISE_EN = %1d\r\n", read_reg_int);
00128     
00129     press_temp->set_lpfp_cfg(LPS22HH_LPF_CFG);
00130     press_temp->get_lpfp_cfg(&read_reg_int);
00131     printf("LPS22HH LPF_CFG = %1d\r\n", read_reg_int);
00132     
00133     /* Print Flash memory information */
00134     print_flash_info();
00135     
00136     /* Information for the user */
00137     printf("Press blue button to start data acquisition\r\n");
00138     printf("Press 'R' to read previously measured data\r\n");
00139     
00140     /* Acquisition loop */
00141     while(1) {
00142         // Start saving data when button is pushed
00143         if (button1_pressed) {
00144             button1_pressed = false;
00145             save_data = true;
00146             erase_flash(false);
00147             printf("Acquiring data...\r\n");
00148             printf("Press blue button to stop data acquisition\r\n");
00149             Flash_addr = FLASH_BANK2_BASE;
00150         }
00151         
00152         if (save_data) {
00153             // Acquisition task
00154             save_data = acquisition_task(false);
00155         }
00156         else {
00157             // Read task
00158             read_task();
00159         }
00160     }
00161 }
00162 
00163 /* Acquisition task */
00164 bool acquisition_task(bool verbose)
00165 {
00166     float pressure_value, alt_value;
00167     
00168     uint32_t buffer_size = FLASH_PAGE_SIZE/4;
00169     uint32_t data_ind = 0;
00170     uint32_t data_buffer[buffer_size];
00171     
00172     uint32_t Flash_addr = FLASH_BANK2_BASE;
00173 
00174     while (Flash_addr <= FLASH_BANK2_END-FLASH_PAGE_SIZE+1) {
00175         // Read sensors data
00176         press_temp->get_pressure(&pressure_value);
00177         alt_value = pressure_to_altitude(pressure_value);
00178         
00179         // Write page in Flash memory
00180         if (data_ind >= buffer_size) {
00181             write_flash(Flash_addr, &data_buffer[0], buffer_size, false);
00182             Flash_addr += FLASH_PAGE_SIZE;
00183             data_ind = 0;
00184         }
00185             
00186         // Write data to buffer
00187         data_buffer[data_ind] = FloatToUint(pressure_value);
00188         data_buffer[data_ind+1] = FloatToUint(alt_value);
00189         data_ind = data_ind+2;
00190         
00191         // Print data in terminal
00192         if (verbose) {
00193             printf("LPS22HH: [press/mbar] %1.6f, [alt/m] %1.6f\r\n", pressure_value, alt_value);
00194         }
00195         
00196         // Wait for acquisition period
00197         wait(1/FS);
00198         
00199         // Stop saving data when button is pushed
00200         if (button1_pressed) {
00201             button1_pressed = false;
00202             // Save remaining data to Flash memory
00203             write_flash(Flash_addr, &data_buffer[0], data_ind, false);
00204             printf("Data acquisition stopped\r\n");
00205             printf("Press 'R' to read the data\r\n");
00206             return false;
00207         }
00208     }
00209     printf("Data acquisition stopped\r\n");
00210     printf("Press 'R' to read the data\r\n");
00211     return false;
00212 }
00213 
00214 /* Read task */
00215 void read_task()
00216 {
00217     char pc_input;
00218     uint32_t Flash_rdata[2];
00219     bool flash_empty = false;
00220     
00221     // Read terminal input
00222     if (pc.readable()) {
00223         pc_input = pc.getc();
00224     }
00225     else {
00226         pc_input = ' ';
00227     }
00228     
00229     // Read Flash memory if 'R' is pressed
00230     if ((pc_input == 'r') || (pc_input == 'R')) {
00231         // Data labels
00232         printf("press\talt\r\n");
00233         
00234         // Read 1st Flash data
00235         uint32_t Flash_addr_temp = FLASH_BANK2_BASE;
00236         read_flash(Flash_addr_temp, &Flash_rdata[0], LPS22HH_DATA_SIZE);
00237         
00238         // Read Flash data
00239         while ((Flash_addr_temp <= FLASH_BANK2_END-LPS22HH_DATA_SIZE+1) && !flash_empty) {
00240             // Print read data in the terminal
00241             printf("%1.6f\t%1.6f\r\n", UintToFloat(Flash_rdata[0]), UintToFloat(Flash_rdata[1]));
00242             Flash_addr_temp += LPS22HH_DATA_SIZE;
00243             
00244             // Check if the next address is not empty (erased Flash only contains 0)
00245             if (Flash_addr_temp <= FLASH_BANK2_END-LPS22HH_DATA_SIZE+1) {
00246                 read_flash(Flash_addr_temp, &Flash_rdata[0], LPS22HH_DATA_SIZE);
00247                 if ((Flash_rdata[0] == 0) && (Flash_rdata[1] == 0)) {
00248                     flash_empty = true;
00249                 }
00250             }
00251         }
00252     }
00253 }
00254 
00255 /* Print Flash memory info */
00256 void print_flash_info()
00257 {
00258     printf("**************************************************\n\r");
00259     printf("/***** Flash memory info *****/\r\n");
00260     printf("Flash size: %d [B]\r\n", FLASH_SIZE);
00261     printf("Flash page size: %d [B]\r\n", FLASH_PAGE_SIZE);
00262     printf("Flash nb of pages: %d \r\n", FLASH_SIZE/FLASH_PAGE_SIZE);
00263     printf("Flash bank 1 base address: 0x%X\r\n", FLASH_BASE);
00264     printf("Flash bank 1 end address: 0x%X\r\n", FLASH_BANK1_END);
00265     printf("Flash bank 2 base address: 0x%X\r\n", FLASH_BANK2_BASE);
00266     printf("Flash bank 2 end address: 0x%X\r\n", FLASH_BANK2_END);
00267     printf("**************************************************\n\r");
00268 }
00269 
00270 /* Erase content of Flash memory */
00271 bool erase_flash(bool verbose)
00272 {
00273     printf("Erasing Flash memory...\r\n");
00274     
00275     // Unlock Flash memory
00276     HAL_FLASH_Unlock();
00277 
00278     // Erase Flash memory
00279     FLASH_EraseInitTypeDef eraser;
00280     uint32_t Flash_addr = FLASH_BANK2_BASE;
00281     uint32_t page_error = 0;
00282     int32_t page = 1;
00283     
00284     while (Flash_addr < FLASH_BANK2_END) {
00285         eraser.TypeErase = FLASH_TYPEERASE_PAGES;
00286         eraser.PageAddress = Flash_addr;
00287         eraser.NbPages = 1;
00288         if(HAL_OK != HAL_FLASHEx_Erase(&eraser, &page_error)) {
00289             if (verbose) {printf("Flash erase failed!\r\n");}
00290             printf("Error 0x%X\r\n", page_error);
00291             HAL_FLASH_Lock();
00292             return false;
00293         }
00294         if (verbose) {printf("Erased page %d at address: 0x%X\r\n", page, Flash_addr);}
00295         Flash_addr += FLASH_PAGE_SIZE;
00296         page++;
00297     }
00298     
00299     if (verbose) {printf("Flash erase succesful!\r\n");}
00300     return true;
00301 }
00302 
00303 /* Write Flash memory */
00304 bool write_flash(uint32_t Flash_addr, uint32_t* Flash_wdata, int32_t n_words, bool verbose)
00305 {
00306     clock_t time;
00307     if (verbose) {time = clock();}
00308     
00309     // Unlock Flash memory
00310     HAL_FLASH_Unlock();
00311     
00312     // Write Flash memory
00313     for (int i=0; i<n_words; i++) {
00314         if (HAL_OK != HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Flash_addr, Flash_wdata[i])) {
00315             if (verbose) {printf("Flash write failed!\r\n");}
00316             HAL_FLASH_Lock();
00317             return false;
00318         }
00319         Flash_addr += 4;
00320     }
00321     if (verbose) {printf("Flash write succesful!\r\n");}
00322     
00323     HAL_FLASH_Lock();
00324     
00325     if (verbose) {
00326         time = clock() - time;
00327         printf("Time to write: %1.6f [s]\r\n", (((double) time)/CLOCKS_PER_SEC));
00328     }
00329     
00330     return true;
00331 }
00332 
00333 /* Read Flash memory */
00334 void read_flash(uint32_t Flash_addr, uint32_t* Flash_rdata, uint32_t n_bytes)
00335 {
00336     memcpy(Flash_rdata, (uint32_t*) Flash_addr, n_bytes);
00337 }
00338 
00339 /* Enables button when bouncing is over */
00340 void button1_enabled_cb(void)
00341 {
00342     button1_enabled = true;
00343 }
00344 
00345 /* ISR handling button pressed event */
00346 void button1_onpressed_cb(void)
00347 {
00348     if (button1_enabled) { // Disabled while the button is bouncing
00349         button1_enabled = false;
00350         button1_pressed = true; // To be read by the main loop
00351         button1_timeout.attach(callback(button1_enabled_cb), 0.3); // Debounce time 300 ms
00352     }
00353 }
00354 
00355 /* Helper function for printing floats & doubles */
00356 static char *print_double(char *str, double v)
00357 {
00358     int decimalDigits = 6;
00359     int i = 1;
00360     int intPart, fractPart;
00361     int len;
00362     char *ptr;
00363 
00364     /* prepare decimal digits multiplicator */
00365     for (; decimalDigits != 0; i *= 10, decimalDigits--);
00366 
00367     /* calculate integer & fractinal parts */
00368     intPart = (int)v;
00369     fractPart = (int)((v - (double)(int)v) * i);
00370 
00371     /* fill in integer part */
00372     sprintf(str, "%i.", intPart);
00373 
00374     /* prepare fill in of fractional part */
00375     len = strlen(str);
00376     ptr = &str[len];
00377 
00378     /* fill in leading fractional zeros */
00379     for (i /= 10; i > 1; i /= 10, ptr++) {
00380         if (fractPart >= i) {
00381             break;
00382         }
00383         *ptr = '0';
00384     }
00385 
00386     /* fill in (rest of) fractional part */
00387     sprintf(ptr, "%i", fractPart);
00388 
00389     return str;
00390 }
00391 
00392 /* Pressure to altitude conversion */
00393 float pressure_to_altitude(double pressure)
00394 {
00395     return 44330.77 * (1-pow(pressure/P0, 0.1902632));
00396 }
00397 
00398 uint32_t FloatToUint(float n)
00399 {
00400    return (uint32_t)(*(uint32_t*)&n);
00401 }
00402  
00403 float UintToFloat(uint32_t n)
00404 {
00405    return (float)(*(float*)&n);
00406 }