LELEC2811 - I&S / Mbed OS LELEC2811_IKS01A3_Multisensors

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 Multisensor IKS01A3 Project
00041     M. Lefebvre - 2019-2020
00042 */
00043 
00044 /* Includes */
00045 #include <stdlib.h>
00046 #include <time.h>
00047 #include <math.h>
00048 #include "mbed.h"
00049 #include "XNucleoIKS01A3.h"
00050 #include "stm32l073xx.h"
00051 #include "stm32l0xx_hal.h"
00052 #include "stm32l0xx_hal_flash.h"
00053 #include "main.h"
00054 #include "adc.h"
00055 #include "gpio.h"
00056 
00057 /* Defines */
00058 #define VDD                     3.3     // Supply voltage (V)
00059 #define FS                      10.0    // Readout frequency (Hz) - /!\ Must be below 19Hz
00060 #define DATA_SIZE               64      // Number of bytes to store in Flash memory
00061 #define FLASH_WRITE_TIME        0.00328 // Flash write time (s)
00062 #define TS                      (1/FS)-((DATA_SIZE/4)*FLASH_WRITE_TIME)
00063 
00064 // GPIO
00065 #define RED_LED                 GPIO_PIN_5
00066 #define IR_LED                  GPIO_PIN_6
00067 #define GREEN_LED               GPIO_PIN_7
00068 
00069 // LIS2MDL Magnetometer
00070 #define LIS2MDL_ODR             50.0    // Output data rate (10, 20, 50 or 100 Hz)
00071 #define LIS2MDL_LP              0       // Power mode (0 for high-resolution mode, 1 for low-power mode)
00072 #define LIS2MDL_LPF             0       // Bandwidth (0 for ODR/2, 1 for ODR/4)
00073 #define LIS2MDL_COMP_TEMP_EN    1       // Temperature compensation (0 disabled, 1 enabled)
00074 #define LIS2MDL_OFF_CANC        1       // Offset cancellation (0 for no offset cancellation, 1 for offset cancellation, 2 for set pulse only at power-on)
00075 #define LIS2MDL_DATA_SIZE       12      // Number of bytes for LIS2MDL magnetometer data
00076 
00077 // LPS22HH Pressure sensor
00078 #define P0                      1013.26 // Sea level pressure (hPa)
00079 #define LPS22HH_ODR             50.0    // Output data rate (one-shot, 1, 10, 25, 50, 75, 100, 200 Hz)
00080 #define LPS22HH_LOW_NOISE_EN    1       // Low-noise (0 disabled, 1 enabled)
00081 #define LPS22HH_LPF_CFG         3       // Device bandwidth (0 for ODR/2, 2 for ODR/9, 3 for ODR/20)
00082 #define LPS22HH_DATA_SIZE       8       // Number of bytes for LPS22HH pressure sensor data
00083 
00084 // LIS2DW12 Accelerometer
00085 #define LIS2DW12_ODR            4       // Output data rate (0 power down, 1 HP 12.5Hz/LP 1.6Hz, 2 for 12.5Hz, 3 for 25Hz, 4 for 50Hz, 5 for 100Hz, 6 for 200Hz, 7 for HP 400Hz/LP 200Hz, 8 for HP 800Hz/LP 200Hz, 9 for HP 1600Hz/LP 200Hz)
00086 #define LIS2DW12_FS             4       // Full-scale +-(2, 4, 8 or 16 g)
00087 #define LIS2DW12_BW_FILT        2       // Filter bandwidth (0 for ODR/2, 1 for ODR/4, 2 for ODR/10, 3 for ODR/20)
00088 #define LIS2DW12_LP_MODE        0       // Low-power modes 1 to 4 (1 gives the max. rms noise, 4 gives the min. rms noise)
00089 #define LIS2DW12_MODE           1       // Mode (0 for low-power, 1 for high-performance, 2 for single data conversion)
00090 #define LIS2DW12_LOW_NOISE      1       // Low-noise (0 disabled, 1 enabled)
00091 #define LIS2DW12_POWER_MODE     LIS2DW12_LP_MODE + (LIS2DW12_MODE << 2) + (LIS2DW12_LOW_NOISE << 4)
00092 #define LIS2DW12_DATA_SIZE      12      // Number of bytes for LIS2DW12 accelerometer sensor data
00093 
00094 // HTS221 Relative humidity and temperature sensor
00095 #define HTS221_ODR              1       // Output data rate (one-shot, 1Hz, 7Hz, 12.5Hz)
00096 #define HTS221_HEATER           0       // Heater configuration (0 disabled, 1 enabled)
00097 #define HTS221_AVGH             32      // Humidity averaging (4 to 512)
00098 #define HTS221_AVGT             16      // Temperature averaging (2 to 256)
00099 
00100 // LSM6DSO Accelerometer + gyroscope
00101 #define LSM6DSO_ODR_XL          12.5    // Accelerometer output data rate (12.5, 26, 52, 104, 208, 416, 833, 1.66k, 3.33k, 6.66kHz)
00102 #define LSM6DSO_FS_XL           4       // Accelerometer full scale (2, 4, 8, 16g)
00103 #define LSM6DSO_XL_HM_MODE      1       // Accelerometer high-performance mode (0 enabled, 1 disabled)
00104 #define LSM6DSO_XL_ULP_EN       0       // Accelerometer ultra-low-power configuration (0 disabled, 1 enabled)
00105 #define LSM6DSO_LPF2_XL_EN      1       // Accelerometer high-resolution selection (0 for 1st stage of digital filtering, 1 for 2nd stage)
00106 #define LSM6DSO_HP_SLOPE_XL_EN  0       // Accelerometer high-pass filter selection (0 for low-pass, 1 for high-pass)
00107 #define LSM6DSO_HPCF_XL         2       // Accelerometer filter configuration and cutoff setting (0 for ODR/4, 1 for ODR/10, 2 for ODR/20, 3 for ODR/45, 4 for ODR/100, 5 for ODR/200, 6 for ODR/400, 7 for ODR/800)      
00108 #define LSM6DSO_ODR_G           16      // Gyroscope output data rate (12.5, 26, 52, 104, 208, 416, 833, 1.66k, 3.33k, 6.66kHz)
00109 #define LSM6DSO_FS_G            1000    // Gyroscope full scale (250, 500, 1000, 2000dps)
00110 #define LSM6DSO_G_HM_MODE       1       // Gyroscope high-performance mode (0 enabled, 1 disabled)
00111 #define LSM6DSO_LPF1_SEL_G      1       // Gyroscope digital LPF1 enable (0 disabled, 1 enabled)
00112 #define LSM6DSO_FTYPE           3       // Gyroscope LPF1 bandwidth selection (0 ultra light, 1 very light, 2 light, 3 medium, 4 strong, 5 very strong, 6 aggressive, 7 xtreme)
00113 #define LSM6DSO_HP_EN_G         1       // Gyroscope digital HPF enable (0 HPF disabled, 1 HPF enabled)
00114 #define LSM6DSO_HPM_G           2       // Gyroscope HPF cutoff selection (0 for 16mHz, 1 for 65mHz, 10 for 260 mHz, 11 for 1.04Hz)
00115 
00116 /* Functions definition */
00117 bool acquisition_task(bool verbose);
00118 void read_task();
00119 void print_flash_info();
00120 bool erase_flash(bool verbose);
00121 bool write_flash(uint32_t Flash_addr, uint32_t* Flash_wdata, int32_t n_words, bool verbose);
00122 void read_flash(uint32_t Flash_addr, uint32_t* Flash_rdata, uint32_t n_bytes);
00123 void button1_enabled_cb(void);
00124 void button1_onpressed_cb(void);
00125 static char *print_double(char *str, double v);
00126 float pressure_to_altitude(double pressure);
00127 uint32_t FloatToUint(float n);
00128 float UintToFloat(uint32_t n);
00129 
00130 static void SystemClock_Config(void);
00131 
00132 /* ADC */
00133 uint32_t adcValue=0;
00134 
00135 /* Serial link */
00136 Serial pc(SERIAL_TX, SERIAL_RX);
00137 
00138 /* Button */
00139 InterruptIn button1(USER_BUTTON);
00140 volatile bool button1_pressed = false; // Used in the main loop
00141 volatile bool button1_enabled = true; // Used for debouncing
00142 Timeout button1_timeout; // Used for debouncing
00143 
00144 /* Instantiate the expansion board */
00145 static XNucleoIKS01A3 *mems_expansion_board = XNucleoIKS01A3::instance(D14, D15, D4, D5, A3, D6, A4);
00146 
00147 /* Retrieve the composing elements of the expansion board */
00148 static LIS2MDLSensor *magnetometer = mems_expansion_board->magnetometer;
00149 static HTS221Sensor *hum_temp = mems_expansion_board->ht_sensor;
00150 static LPS22HHSensor *press_temp = mems_expansion_board->pt_sensor;
00151 static LSM6DSOSensor *acc_gyro = mems_expansion_board->acc_gyro;
00152 static LIS2DW12Sensor *accelerometer = mems_expansion_board->accelerometer;
00153 static STTS751Sensor *temp = mems_expansion_board->t_sensor;
00154 
00155 /* Main */
00156 int main()
00157 {
00158     // Reset of all peripherals
00159     HAL_Init();
00160     
00161     // Configure the system clock
00162     SystemClock_Config();
00163     
00164     uint8_t id;
00165     float read_reg, read_reg_1;
00166     uint8_t read_reg_int, read_reg_int_1, read_reg_int_2;
00167     
00168     bool save_data = false;
00169     uint32_t Flash_addr = FLASH_BANK2_BASE;
00170 
00171     /* Serial link configuration */
00172     pc.baud(115200);
00173     
00174     /* GPIO configuration */
00175     MX_GPIO_Init();
00176     
00177     /* ADC configuration */
00178     MX_ADC_Init();
00179     HAL_ADC_Start(&hadc);
00180     
00181     /* Button configuration */
00182     button1.fall(callback(button1_onpressed_cb)); // Attach ISR to handle button press event
00183     
00184     /* Reset message */
00185     printf("\n\r**************************************************\n\r");
00186     printf("LELEC2811 IKS01A3 Multisensor Program\n\r");
00187     printf("**************************************************\n\r");
00188     
00189     /* LIS2MDL magnetometer sensor configuration */
00190     magnetometer->enable();
00191     printf("/***** LIS2MDL magnetometer configuration *****/\r\n");
00192     
00193     magnetometer->read_id(&id);
00194     printf("LIS2MDL magnetometer = 0x%X\r\n", id);
00195     
00196     magnetometer->set_m_odr(LIS2MDL_ODR);
00197     magnetometer->get_m_odr(&read_reg);
00198     printf("LIS2MDL ODR = %1.1f [Hz]\r\n", read_reg);
00199     
00200     magnetometer->set_m_lp(LIS2MDL_LP);
00201     magnetometer->get_m_lp(&read_reg_int);
00202     printf("LIS2MDL LP = %1d\r\n", read_reg_int);
00203     
00204     magnetometer->set_m_lpf(LIS2MDL_LPF);
00205     magnetometer->get_m_lpf(&read_reg_int);
00206     printf("LIS2MDL LPF = %1d\r\n", read_reg_int);
00207     
00208     magnetometer->set_m_comp_temp_en(LIS2MDL_COMP_TEMP_EN);
00209     magnetometer->get_m_comp_temp_en(&read_reg_int);
00210     printf("LIS2MDL COMP_TEMP_EN = %1d\r\n", read_reg_int);
00211     
00212     magnetometer->set_m_off_canc(LIS2MDL_OFF_CANC);
00213     magnetometer->get_m_off_canc(&read_reg_int);
00214     printf("LIS2MDL OFF_CANC = %1d\r\n", read_reg_int);
00215     
00216     /* LPS22HH pressure sensor configuration */
00217     press_temp->enable();
00218     printf("/***** LPS22HH pressure sensor configuration *****/\r\n");
00219     
00220     press_temp->read_id(&id);
00221     printf("LPS22HH pressure = 0x%X\r\n", id);
00222     
00223     press_temp->set_odr(LPS22HH_ODR, LPS22HH_LOW_NOISE_EN);
00224     press_temp->get_odr(&read_reg, &read_reg_int);
00225     printf("LPS22HH ODR = %1.1f [Hz]\r\n", read_reg);
00226     printf("LPS22HH LOW_NOISE_EN = %1d\r\n", read_reg_int);
00227     
00228     press_temp->set_lpfp_cfg(LPS22HH_LPF_CFG);
00229     press_temp->get_lpfp_cfg(&read_reg_int);
00230     printf("LPS22HH LPF_CFG = %1d\r\n", read_reg_int);
00231     
00232     /* LIS2DW12 accelerometer sensor configuration */
00233     accelerometer->enable_x();
00234     printf("/***** LIS2DW12 accelerometer sensor configuration *****/\r\n");
00235     
00236     accelerometer->read_id(&id);
00237     printf("LIS2DW12 accelerometer = 0x%X\r\n", id);
00238     
00239     accelerometer->set_x_odr(LIS2DW12_ODR);
00240     accelerometer->get_x_odr(&read_reg);
00241     printf("LIS2DW12 ODR = %1.3f [Hz]\r\n", read_reg);
00242     
00243     accelerometer->set_x_fs(LIS2DW12_FS);
00244     accelerometer->get_x_fs(&read_reg);
00245     printf("LIS2DW12 FS = %1.3f [g]\r\n", read_reg);
00246     
00247     accelerometer->set_x_bw_filt(LIS2DW12_BW_FILT);
00248     accelerometer->get_x_bw_filt(&read_reg_int);
00249     printf("LIS2DW12 BW_FILT = %1d\r\n", read_reg_int);
00250     
00251     accelerometer->set_x_power_mode(LIS2DW12_POWER_MODE);
00252     accelerometer->get_x_power_mode(&read_reg_int, &read_reg_int_1, &read_reg_int_2);
00253     printf("LIS2DW12 LP_MODE = %1d\r\n", read_reg_int);
00254     printf("LIS2DW12 MODE = %1d\r\n", read_reg_int_1);
00255     printf("LIS2DW12 LOW_NOISE = %1d\r\n", read_reg_int_2);
00256     
00257     /* HTS221 relative humidity and temperature sensor configuration */
00258     hum_temp->enable();    
00259     printf("/***** HTS221 humidity sensor configuration *****/\r\n");
00260     
00261     hum_temp->read_id(&id);
00262     printf("HTS221 humidity & temperature = 0x%X\r\n", id);
00263     
00264     hum_temp->set_odr(HTS221_ODR);
00265     hum_temp->get_odr(&read_reg);
00266     printf("HTS221 ODR = %1.3f [Hz]\r\n", read_reg);
00267     
00268     hum_temp->set_heater(HTS221_HEATER);
00269     hum_temp->get_heater(&read_reg_int);
00270     printf("HTS221 HEATER = %1d\r\n", read_reg_int);
00271     
00272     hum_temp->set_avg(HTS221_AVGH, HTS221_AVGT);
00273     hum_temp->get_avg(&read_reg, &read_reg_1);
00274     printf("HTS221 AVGH = %1.0f\r\n", read_reg);
00275     printf("HTS221 AVGT = %1.0f\r\n", read_reg_1);
00276     
00277     /* STTS751 Temperature sensor configuration */
00278     temp->enable();
00279     printf("/***** STTS751 temperature sensor configuration *****/\r\n");
00280     
00281     temp->read_id(&id);
00282     printf("STTS751 temperature = 0x%X\r\n", id);
00283     
00284     /* LSM6DSO Accelerometer and gyroscope configuration */
00285     acc_gyro->enable_x();
00286     acc_gyro->enable_g();
00287     printf("/***** LSM6DSO accelerometer and gyroscope sensor configuration *****/\r\n");
00288     
00289     acc_gyro->read_id(&id);
00290     printf("LSM6DSO accelerometer & gyroscope = 0x%X\r\n", id);
00291     
00292     acc_gyro->set_x_odr(LSM6DSO_ODR_XL);
00293     acc_gyro->get_x_odr(&read_reg);
00294     printf("LSM6DSO ODR_XL = %1.3f [Hz]\r\n", read_reg);
00295     
00296     acc_gyro->set_x_fs(LSM6DSO_FS_XL);
00297     acc_gyro->get_x_fs(&read_reg);
00298     printf("LSM6DSO FS_XL = %1.3f [g]\r\n", read_reg);
00299     
00300     acc_gyro->set_x_power_mode(LSM6DSO_XL_HM_MODE, LSM6DSO_XL_ULP_EN);
00301     acc_gyro->get_x_power_mode(&read_reg_int, &read_reg_int_1);
00302     printf("LSM6DSO XL_HM_MODE = %1d\r\n", read_reg_int);
00303     printf("LSM6DSO XL_ULP_EN = %1d\r\n", read_reg_int_1);
00304     
00305     acc_gyro->set_x_lpf2_en(LSM6DSO_LPF2_XL_EN);
00306     acc_gyro->get_x_lpf2_en(&read_reg_int);
00307     printf("LSM6DSO LPF2_XL_EN = %1d\r\n", read_reg_int);
00308     
00309     acc_gyro->set_x_filter_config(LSM6DSO_HP_SLOPE_XL_EN, LSM6DSO_HPCF_XL);
00310     acc_gyro->get_x_filter_config(&read_reg_int, &read_reg_int_1);
00311     printf("LSM6DSO HP_SLOPE_XL_EN = %1d\r\n", read_reg_int);
00312     printf("LSM6DSO HPCF_XL = %1d\r\n", read_reg_int_1);
00313     
00314     acc_gyro->set_g_odr(LSM6DSO_ODR_G);
00315     acc_gyro->get_g_odr(&read_reg);
00316     printf("LSM6DSO ODR_G = %1.3f [Hz]\r\n", read_reg);
00317     
00318     acc_gyro->set_g_fs(LSM6DSO_FS_XL);
00319     acc_gyro->get_g_fs(&read_reg);
00320     printf("LSM6DSO FS_G = %1.3f [dps]\r\n", read_reg);
00321     
00322     acc_gyro->set_g_power_mode(LSM6DSO_G_HM_MODE);
00323     acc_gyro->get_g_power_mode(&read_reg_int);
00324     printf("LSM6DSO G_HM_MODE = %1d\r\n", read_reg_int);
00325     
00326     acc_gyro->set_g_lpf_config(LSM6DSO_LPF1_SEL_G, LSM6DSO_FTYPE);
00327     acc_gyro->get_g_lpf_config(&read_reg_int, &read_reg_int_1);
00328     printf("LSM6DSO LPF1_SEL_G = %1d\r\n", read_reg_int);
00329     printf("LSM6DSO FTYPE = %1d\r\n", read_reg_int_1);
00330     
00331     acc_gyro->set_g_hpf_config(LSM6DSO_HP_EN_G, LSM6DSO_HPM_G);
00332     acc_gyro->get_g_hpf_config(&read_reg_int, &read_reg_int_1);
00333     printf("LSM6DSO HP_EN_G = %1d\r\n", read_reg_int);
00334     printf("LSM6DSO HPM_G = %1d\r\n", read_reg_int_1);
00335     
00336     /* Print Flash memory information */
00337     print_flash_info();
00338     
00339     /* Information for the user */
00340     printf("Press blue button to start data acquisition\r\n");
00341     printf("Press 'R' to read previously measured data\r\n");
00342     
00343     /* GPIO setting */
00344     HAL_GPIO_WritePin(GPIOA, RED_LED, GPIO_PIN_RESET);
00345     HAL_GPIO_WritePin(GPIOA, IR_LED, GPIO_PIN_RESET);
00346     HAL_GPIO_WritePin(GPIOA, GREEN_LED, GPIO_PIN_SET);
00347   
00348     /* Acquisition loop */
00349     while(1) {
00350         // Start saving data when button is pushed
00351         if (button1_pressed) {
00352             button1_pressed = false;
00353             save_data = true;
00354             erase_flash(false);
00355             printf("Acquiring data...\r\n");
00356             printf("Press blue button to stop data acquisition\r\n");
00357             Flash_addr = FLASH_BANK2_BASE;
00358         }
00359         
00360         if (save_data) {
00361             // Acquisition task
00362             save_data = acquisition_task(true);
00363         }
00364         else {
00365             // Read task
00366             read_task();
00367         }
00368     }
00369 }
00370 
00371 /* Acquisition task */
00372 bool acquisition_task(bool verbose)
00373 {
00374     int32_t m_axes[3];
00375     int32_t acc_axes[3];
00376     int32_t acc_axes_1[3];
00377     int32_t gyro_axes[3];
00378     float pressure_value, hum_value, temp_value, temp_value_1;
00379     int32_t data_buffer[DATA_SIZE/4];
00380     
00381     uint32_t Flash_addr = FLASH_BANK2_BASE;
00382     
00383     while (Flash_addr <= FLASH_BANK2_END-DATA_SIZE+1) {
00384         // Read sensors data
00385         magnetometer->get_m_axes(m_axes);
00386         press_temp->get_pressure(&pressure_value);
00387         accelerometer->get_x_axes(acc_axes);
00388         hum_temp->get_temperature(&temp_value);
00389         hum_temp->get_humidity(&hum_value);
00390         temp->get_temperature(&temp_value_1);
00391         acc_gyro->get_x_axes(acc_axes_1);
00392         acc_gyro->get_g_axes(gyro_axes);
00393         
00394         // Save data to Flash memory
00395         data_buffer[0] = m_axes[0];
00396         data_buffer[1] = m_axes[1];
00397         data_buffer[2] = m_axes[2];
00398         data_buffer[3] = acc_axes[0];
00399         data_buffer[4] = acc_axes[1];
00400         data_buffer[5] = acc_axes[2];
00401         data_buffer[6] = acc_axes_1[0];
00402         data_buffer[7] = acc_axes_1[1];
00403         data_buffer[8] = acc_axes_1[2];
00404         data_buffer[9] = gyro_axes[0];
00405         data_buffer[10] = gyro_axes[1];
00406         data_buffer[11] = gyro_axes[2];
00407         data_buffer[12] = (int32_t) FloatToUint(pressure_value);
00408         data_buffer[13] = (int32_t) FloatToUint(hum_value);
00409         data_buffer[14] = (int32_t) FloatToUint(temp_value);
00410         if (HAL_ADC_PollForConversion(&hadc, 5) == HAL_OK)
00411         {
00412             adcValue = HAL_ADC_GetValue(&hadc);
00413         }
00414         data_buffer[15] = (int32_t) FloatToUint(((float) adcValue)/4096 * VDD);
00415         
00416         write_flash(Flash_addr, (uint32_t*) &data_buffer[0], DATA_SIZE/4, false);
00417         
00418         // Increase Flash address
00419         Flash_addr += DATA_SIZE;
00420         
00421         // Print data in terminal
00422         if (verbose) {
00423             printf("LIS2MDL: [mag/mgauss] %6d, %6d, %6d\r\n", ((uint32_t) m_axes[0]), ((uint32_t) m_axes[1]), ((uint32_t) m_axes[2]));
00424             printf("LPS22HH: [press/mbar] %1.3f, [alt/m] %1.3f\r\n", pressure_value, pressure_to_altitude(pressure_value));
00425             printf("HTS221: [temp/deg C] %1.3f, [hum/%%] %1.3f\r\n", temp_value, hum_value);
00426             printf("STTS751 [temp/deg C] %1.3f\r\n", temp_value_1);
00427             printf("LIS2DW12: [acc/mg] %6d, %6d, %6d\r\n", ((uint32_t) acc_axes[0]), ((uint32_t) acc_axes[1]), ((uint32_t) acc_axes[2]));
00428             printf("LSM6DSO: [acc/mg] %6d, %6d, %6d\r\n", ((uint32_t) acc_axes_1[0]), ((uint32_t) acc_axes_1[1]), ((uint32_t) acc_axes_1[2]));
00429             printf("LSM6DSO: [gyro/mdps] %6d, %6d, %6d\r\n", ((uint32_t) gyro_axes[0]), ((uint32_t) gyro_axes[1]), ((uint32_t) gyro_axes[2]));
00430         }
00431         
00432         // Wait for acquisition period
00433         wait(TS);
00434         
00435         // Stop saving data when button is pushed
00436         if (button1_pressed) {
00437             button1_pressed = false;
00438             printf("Data acquisition stopped\r\n");
00439             printf("Press 'R' to read the data\r\n");
00440             return false;
00441         }
00442     }
00443     printf("Data acquisition stopped\r\n");
00444     printf("Press 'R' to read the data\r\n");
00445     return false;
00446 }
00447 
00448 /* Read task */
00449 void read_task()
00450 {
00451     char pc_input;
00452     uint32_t Flash_rdata[DATA_SIZE/4];
00453     bool flash_empty = false;
00454     
00455     // Read terminal input
00456     if (pc.readable()) {
00457         pc_input = pc.getc();
00458     }
00459     else {
00460         pc_input = ' ';
00461     }
00462     
00463     // Read Flash memory if 'R' is pressed
00464     if ((pc_input == 'r') || (pc_input == 'R')) {
00465         // Data labels
00466         printf("mag_X\tmag_Y\tmag_Z\tacc_X\tacc_Y\tacc_Z\tacc_X_1\tacc_Y_1\tacc_Z_1\tgyr_X\tgyr_Y\tgyr_Z\tpress\thum\ttemp\ttemp_1\r\n");
00467         
00468         // Read 1st Flash data
00469         uint32_t Flash_addr_temp = FLASH_BANK2_BASE;
00470         read_flash(Flash_addr_temp, &Flash_rdata[0], DATA_SIZE);
00471         
00472         // Read Flash data
00473         while ((Flash_addr_temp <= FLASH_BANK2_END-DATA_SIZE+1) && !flash_empty) {
00474             // Print read data in the terminal
00475             printf("%6d\t%6d\t%6d\t%6d\t%6d\t%6d\t%6d\t%6d\t%6d\t%6d\t%6d\t%6d\t%1.6f\t%1.6f\t%1.6f\t%1.6f\r\n", Flash_rdata[0], Flash_rdata[1], Flash_rdata[2], Flash_rdata[3], Flash_rdata[4], Flash_rdata[5], Flash_rdata[6], Flash_rdata[7], Flash_rdata[8], Flash_rdata[9], Flash_rdata[10], Flash_rdata[11], UintToFloat(Flash_rdata[12]), UintToFloat(Flash_rdata[13]), UintToFloat(Flash_rdata[14]), UintToFloat(Flash_rdata[15]));
00476             Flash_addr_temp += DATA_SIZE;
00477             
00478             // Check if the next address is not empty (erased Flash only contains 0)
00479             if (Flash_addr_temp <= FLASH_BANK2_END-DATA_SIZE+1) {
00480                 read_flash(Flash_addr_temp, &Flash_rdata[0], DATA_SIZE);
00481                 if ((Flash_rdata[0] == 0) && (Flash_rdata[1] == 0) && (Flash_rdata[2] == 0)) {
00482                     flash_empty = true;
00483                 }
00484             }
00485         }
00486     }
00487 }
00488 
00489 /* Print Flash memory info */
00490 void print_flash_info()
00491 {
00492     printf("**************************************************\n\r");
00493     printf("/***** Flash memory info *****/\r\n");
00494     printf("Flash size: %d [B]\r\n", FLASH_SIZE);
00495     printf("Flash page size: %d [B]\r\n", FLASH_PAGE_SIZE);
00496     printf("Flash nb of pages: %d \r\n", FLASH_SIZE/FLASH_PAGE_SIZE);
00497     printf("Flash bank 1 base address: 0x%X\r\n", FLASH_BASE);
00498     printf("Flash bank 1 end address: 0x%X\r\n", FLASH_BANK1_END);
00499     printf("Flash bank 2 base address: 0x%X\r\n", FLASH_BANK2_BASE);
00500     printf("Flash bank 2 end address: 0x%X\r\n", FLASH_BANK2_END);
00501     printf("**************************************************\n\r");
00502 }
00503 
00504 /* Erase content of Flash memory */
00505 bool erase_flash(bool verbose)
00506 {
00507     printf("Erasing Flash memory...\r\n");
00508     
00509     // Unlock Flash memory
00510     HAL_FLASH_Unlock();
00511 
00512     // Erase Flash memory
00513     FLASH_EraseInitTypeDef eraser;
00514     uint32_t Flash_addr = FLASH_BANK2_BASE;
00515     uint32_t page_error = 0;
00516     int32_t page = 1;
00517     
00518     while (Flash_addr < FLASH_BANK2_END) {
00519         eraser.TypeErase = FLASH_TYPEERASE_PAGES;
00520         eraser.PageAddress = Flash_addr;
00521         eraser.NbPages = 1;
00522         if(HAL_OK != HAL_FLASHEx_Erase(&eraser, &page_error)) {
00523             if (verbose) {printf("Flash erase failed!\r\n");}
00524             printf("Error 0x%X\r\n", page_error);
00525             HAL_FLASH_Lock();
00526             return false;
00527         }
00528         if (verbose) {printf("Erased page %d at address: 0x%X\r\n", page, Flash_addr);}
00529         Flash_addr += FLASH_PAGE_SIZE;
00530         page++;
00531     }
00532     
00533     if (verbose) {printf("Flash erase succesful!\r\n");}
00534     return true;
00535 }
00536 
00537 /* Write Flash memory */
00538 bool write_flash(uint32_t Flash_addr, uint32_t* Flash_wdata, int32_t n_words, bool verbose)
00539 {
00540     clock_t time;
00541     if (verbose) {time = clock();}
00542     
00543     // Unlock Flash memory
00544     HAL_FLASH_Unlock();
00545     
00546     // Write Flash memory
00547     for (int i=0; i<n_words; i++) {
00548         if (HAL_OK != HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Flash_addr, Flash_wdata[i])) {
00549             if (verbose) {printf("Flash write failed!\r\n");}
00550             HAL_FLASH_Lock();
00551             return false;
00552         }
00553         Flash_addr += 4;
00554     }
00555     if (verbose) {printf("Flash write succesful!\r\n");}
00556     
00557     HAL_FLASH_Lock();
00558     
00559     if (verbose) {
00560         time = clock() - time;
00561         printf("Time to write: %1.6f [s]\r\n", (((double) time)/CLOCKS_PER_SEC));
00562     }
00563     
00564     return true;
00565 }
00566 
00567 /* Read Flash memory */
00568 void read_flash(uint32_t Flash_addr, uint32_t* Flash_rdata, uint32_t n_bytes)
00569 {
00570     memcpy(Flash_rdata, (uint32_t*) Flash_addr, n_bytes);
00571 }
00572 
00573 /* Enables button when bouncing is over */
00574 void button1_enabled_cb(void)
00575 {
00576     button1_enabled = true;
00577 }
00578 
00579 /* ISR handling button pressed event */
00580 void button1_onpressed_cb(void)
00581 {
00582     if (button1_enabled) { // Disabled while the button is bouncing
00583         button1_enabled = false;
00584         button1_pressed = true; // To be read by the main loop
00585         button1_timeout.attach(callback(button1_enabled_cb), 0.3); // Debounce time 300 ms
00586     }
00587 }
00588 
00589 /* Helper function for printing floats & doubles */
00590 static char *print_double(char *str, double v)
00591 {
00592     int decimalDigits = 6;
00593     int i = 1;
00594     int intPart, fractPart;
00595     int len;
00596     char *ptr;
00597 
00598     /* prepare decimal digits multiplicator */
00599     for (; decimalDigits != 0; i *= 10, decimalDigits--);
00600 
00601     /* calculate integer & fractinal parts */
00602     intPart = (int)v;
00603     fractPart = (int)((v - (double)(int)v) * i);
00604 
00605     /* fill in integer part */
00606     sprintf(str, "%i.", intPart);
00607 
00608     /* prepare fill in of fractional part */
00609     len = strlen(str);
00610     ptr = &str[len];
00611 
00612     /* fill in leading fractional zeros */
00613     for (i /= 10; i > 1; i /= 10, ptr++) {
00614         if (fractPart >= i) {
00615             break;
00616         }
00617         *ptr = '0';
00618     }
00619 
00620     /* fill in (rest of) fractional part */
00621     sprintf(ptr, "%i", fractPart);
00622 
00623     return str;
00624 }
00625 
00626 /* Pressure to altitude conversion */
00627 float pressure_to_altitude(double pressure)
00628 {
00629     return 44330.77 * (1-pow(pressure/P0, 0.1902632));
00630 }
00631 
00632 uint32_t FloatToUint(float n)
00633 {
00634    return (uint32_t)(*(uint32_t*)&n);
00635 }
00636  
00637 float UintToFloat(uint32_t n)
00638 {
00639    return (float)(*(float*)&n);
00640 }
00641 
00642 static void SystemClock_Config(void)
00643 {
00644     RCC_OscInitTypeDef RCC_OscInitStruct;
00645     RCC_ClkInitTypeDef RCC_ClkInitStruct;
00646     
00647     /* Configure the main internal regulator output voltage */
00648     __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
00649     
00650     /* Initializes the CPU, AHB and APB busses clocks */
00651     RCC_OscInitStruct.OscillatorType  = RCC_OSCILLATORTYPE_HSI;
00652     RCC_OscInitStruct.HSIState        = RCC_HSI_ON;
00653     RCC_OscInitStruct.HSICalibrationValue = 16;
00654     RCC_OscInitStruct.PLL.PLLState    = RCC_PLL_NONE;
00655     if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
00656     {
00657         printf("Error in oscillator configuration\r\n");
00658     }
00659     
00660     RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
00661     RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
00662     RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
00663     RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
00664     RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
00665     if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
00666     {
00667         printf("Error in clock configuration\r\n");
00668     }
00669 }
00670 
00671 /**
00672   * @brief  Conversion complete callback in non blocking mode
00673   * @param  AdcHandle : AdcHandle handle
00674   * @note   This example shows a simple way to report end of conversion, and
00675   *         you can add your own implementation.
00676   * @retval None
00677   */
00678 void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *AdcHandle)
00679 {
00680     adcValue = HAL_ADC_GetValue(AdcHandle);
00681 }
00682 
00683 /**
00684   * @brief  This function is executed in case of error occurrence.
00685   * @param  file: The file name as string.
00686   * @param  line: The line in file as a number.
00687   * @retval None
00688   */
00689 void _Error_Handler(char *file, int line)
00690 {
00691   while(1)
00692   {
00693   }
00694 }