2019-2020 LIS2MDL Magnetometer Project

Dependencies:   X_NUCLEO_IKS01A3

Revision:
6:b2e247935342
Parent:
5:7c883cce2bc4
Child:
7:4a3b6202963e
diff -r 7c883cce2bc4 -r b2e247935342 main.cpp
--- a/main.cpp	Wed Jul 24 14:22:13 2019 +0000
+++ b/main.cpp	Thu Sep 05 13:49:08 2019 +0000
@@ -36,9 +36,32 @@
  ******************************************************************************
 */
 
+/*
+    LELEC2811 Magnetometer LIS2MDL Project
+    M. Lefebvre - 2019
+*/
+
 /* Includes */
+#include <stdlib.h>
 #include "mbed.h"
 #include "XNucleoIKS01A3.h"
+#include "stm32l073xx.h"
+#include "stm32l0xx_hal_flash.h"
+
+/* Defines */
+#define LIS2MDL_ODR         50.0    // Output data rate (10, 20, 50 or 100 Hz)
+#define LIS2MDL_LP          1       // Power mode (0 for high-resolution mode, 1 for low-power mode)
+#define LIS2MDL_LPF         0       // Bandwidht (0 for ODR/2, 1 for ODR/4)
+#define FS                  10.0    // Sampling frequency (Hz)      
+
+/* Serial link */
+Serial pc(SERIAL_TX, SERIAL_RX);
+
+/* Button */
+InterruptIn button1(USER_BUTTON);
+volatile bool button1_pressed = false; // Used in the main loop
+volatile bool button1_enabled = true; // Used for debouncing
+Timeout button1_timeout; // Used for debouncing
 
 /* Instantiate the expansion board */
 static XNucleoIKS01A3 *mems_expansion_board = XNucleoIKS01A3::instance(D14, D15, D4, D5, A3, D6, A4);
@@ -51,102 +74,232 @@
 static LIS2DW12Sensor *accelerometer = mems_expansion_board->accelerometer;
 static STTS751Sensor *temp = mems_expansion_board->t_sensor;
 
-/* Helper function for printing floats & doubles */
-static char *print_double(char *str, double v, int decimalDigits = 2)
+/* Erase content of Flash memory */
+bool erase_flash(bool verbose)
 {
-    int i = 1;
-    int intPart, fractPart;
-    int len;
-    char *ptr;
+    printf("Erasing Flash memory...\r\n");
+    
+    // Unlock Flash memory
+    HAL_FLASH_Unlock();
 
-    /* prepare decimal digits multiplicator */
-    for (; decimalDigits != 0; i *= 10, decimalDigits--);
-
-    /* calculate integer & fractinal parts */
-    intPart = (int)v;
-    fractPart = (int)((v - (double)(int)v) * i);
+    // Erase Flash memory
+    FLASH_EraseInitTypeDef eraser;
+    uint32_t Flash_addr = FLASH_BANK2_BASE;
+    uint32_t page_error = 0;
+    int32_t page = 1;
+    
+    while (Flash_addr < FLASH_BANK2_END) {
+        eraser.TypeErase = FLASH_TYPEERASE_PAGES;
+        eraser.PageAddress = Flash_addr;
+        eraser.NbPages = 1;
+        if(HAL_OK != HAL_FLASHEx_Erase(&eraser, &page_error)) {
+            if (verbose) {printf("Flash erase failed!\r\n");}
+            printf("Error 0x%X\r\n", page_error);
+            HAL_FLASH_Lock();
+            return false;
+        }
+        if (verbose) {printf("Erased page %d at address: 0x%X\r\n", page, Flash_addr);}
+        Flash_addr += FLASH_PAGE_SIZE;
+        page++;
+    }
+    
+    if (verbose) {printf("Flash erase succesful!\r\n");}
+    return true;
+}
 
-    /* fill in integer part */
-    sprintf(str, "%i.", intPart);
-
-    /* prepare fill in of fractional part */
-    len = strlen(str);
-    ptr = &str[len];
+/* Write Flash memory */
+bool write_flash(uint32_t Flash_addr, uint32_t Flash_wdata, bool verbose)
+{
+    // Unlock Flash memory
+    HAL_FLASH_Unlock();
+    
+    // Write Flash memory
+    if (HAL_OK != HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Flash_addr, Flash_wdata)) {
+        if (verbose) {printf("Flash write failed!\r\n");}
+        HAL_FLASH_Lock();
+        return false;
+    }
+    if (verbose) {printf("Flash write succesful!\r\n");}
+    HAL_FLASH_Lock();
+    return true;
+}
 
-    /* fill in leading fractional zeros */
-    for (i /= 10; i > 1; i /= 10, ptr++) {
-        if (fractPart >= i) {
-            break;
-        }
-        *ptr = '0';
-    }
+/* Read Flash memory */
+void read_flash(uint32_t Flash_addr, uint32_t* Flash_rdata, uint32_t n_bytes)
+{
+    memcpy(Flash_rdata, (uint32_t*) Flash_addr, n_bytes);
+}
 
-    /* fill in (rest of) fractional part */
-    sprintf(ptr, "%i", fractPart);
+/* Print Flash memory info */
+void print_flash_info()
+{
+    printf("**************************************************\n\r");
+    printf("/***** Flash memory info *****/\r\n");
+    printf("Flash size: %d [B]\r\n", FLASH_SIZE);
+    printf("Flash page size: %d [B]\r\n", FLASH_PAGE_SIZE);
+    printf("Flash nb of pages: %d \r\n", FLASH_SIZE/FLASH_PAGE_SIZE);
+    printf("Flash bank 1 base address: 0x%X\r\n", FLASH_BASE);
+    printf("Flash bank 1 end address: 0x%X\r\n", FLASH_BANK1_END);
+    printf("Flash bank 2 base address: 0x%X\r\n", FLASH_BANK2_BASE);
+    printf("Flash bank 2 end address: 0x%X\r\n", FLASH_BANK2_END);
+    printf("**************************************************\n\r");
+}
 
-    return str;
+/* Enables button when bouncing is over */
+void button1_enabled_cb(void)
+{
+    button1_enabled = true;
 }
 
-/* Simple main function */
+/* ISR handling button pressed event */
+void button1_onpressed_cb(void)
+{
+    if (button1_enabled) { // Disabled while the button is bouncing
+        button1_enabled = false;
+        button1_pressed = true; // To be read by the main loop
+        button1_timeout.attach(callback(button1_enabled_cb), 0.3); // Debounce time 300 ms
+    }
+}
+
+/* Acquisition task */
+bool acquisition_task(uint32_t* Flash_addr)
+{
+    int32_t m_axes[3];
+    
+    while (*Flash_addr < FLASH_BANK2_END) {
+        // Read magnetometer data
+        magnetometer->get_m_axes(m_axes);
+        
+        // Save data to Flash memory
+        for (int i=0; i<3; i++) {
+            //printf("Writing to address: 0x%X\r\n", *Flash_addr);
+            write_flash(*Flash_addr, (uint32_t) m_axes[i], false);
+            *Flash_addr += 4;
+        }
+        
+        // Print data in terminal
+        //printf("LIS2MDL [mag/mgauss]:  %6d, %6d, %6d\r\n", ((uint32_t) m_axes[0]), ((uint32_t) m_axes[1]), ((uint32_t) m_axes[2]));
+        
+        // Wait for acquisition period
+        wait(1/FS);
+        
+        // Stop saving data when button is pushed
+        if (button1_pressed) {
+            button1_pressed = false;
+            printf("Data acquisition stopped\r\n");
+            printf("Press 'R' to read the data\r\n");
+            
+            // Save last address in Flash memory
+            write_flash(FLASH_BANK2_BASE, *Flash_addr, false);
+            return false;
+        }
+    }
+    return false;
+}
+
+/* Read task */
+void read_task()
+{
+    char pc_input;
+    uint32_t Flash_rdata[3];
+    uint32_t Flash_addr;
+    
+    // Read terminal input
+    if (pc.readable()) {
+        pc_input = pc.getc();
+        //printf("Read character: %c\r\n", pc_input);
+    }
+    else {
+        pc_input = 'a';
+    }
+    
+    // Read Flash memory if 'R' is pressed
+    if ((pc_input == 'r') || (pc_input == 'R')) {
+        // Read last written Flash address in Flash memory
+        read_flash(FLASH_BANK2_BASE, &Flash_addr, 4);
+        
+        // Data names
+        printf("mag_X\tmag_Y\tmag_Z\r\n");
+        
+        // Read Flash data
+        uint32_t Flash_addr_temp = FLASH_BANK2_BASE + 4;
+        while (Flash_addr_temp < Flash_addr) {
+            //printf("Reading from address: 0x%X\r\n", Flash_addr_temp);
+            read_flash(Flash_addr_temp, &Flash_rdata[0], 12);
+            Flash_addr_temp += 12;
+            printf("%6d\t%6d\t%6d\r\n", Flash_rdata[0], Flash_rdata[1], Flash_rdata[2]);
+        }
+    }
+}
+
+/* Main */
 int main()
 {
     uint8_t id;
-    float value1, value2;
-    char buffer1[32], buffer2[32];
-    int32_t axes[3];
-
-    /* Enable all sensors */
-    hum_temp->enable();
-    press_temp->enable();
-    temp->enable();
-    magnetometer->enable();
-    accelerometer->enable_x();
-    acc_gyro->enable_x();
-    acc_gyro->enable_g();
+    float read_reg;
+    uint8_t read_reg_int;
+    
+    bool save_data = false;
+    uint32_t Flash_addr = FLASH_BANK2_BASE;
 
-    printf("\r\n--- Starting new run ---\r\n");
-
-    hum_temp->read_id(&id);
-    printf("HTS221  humidity & temperature    = 0x%X\r\n", id);
-    press_temp->read_id(&id);
-    printf("LPS22HH  pressure & temperature   = 0x%X\r\n", id);
-    temp->read_id(&id);
-    printf("STTS751 temperature               = 0x%X\r\n", id);
-    magnetometer->read_id(&id);
-    printf("LIS2MDL magnetometer              = 0x%X\r\n", id);
-    accelerometer->read_id(&id);
-    printf("LIS2DW12 accelerometer            = 0x%X\r\n", id);
-    acc_gyro->read_id(&id);
-    printf("LSM6DSO accelerometer & gyroscope = 0x%X\r\n", id);
+    /* Serial link configuration */
+    pc.baud(115200);
+    
+    /* Button configuration */
+    button1.fall(callback(button1_onpressed_cb)); // Attach ISR to handle button press event
+    
+    // Reset message
+    printf("\n\r**************************************************\n\r");
+    printf("LELEC2811 LIS2MDL Magnetometer Program\n\r");
+    printf("**************************************************\n\r");
 
-    while (1) {
-        printf("\r\n");
-
-        hum_temp->get_temperature(&value1);
-        hum_temp->get_humidity(&value2);
-        printf("HTS221: [temp] %7s C,   [hum] %s%%\r\n", print_double(buffer1, value1), print_double(buffer2, value2));
-
-        press_temp->get_temperature(&value1);
-        press_temp->get_pressure(&value2);
-        printf("LPS22HH: [temp] %7s C, [press] %s mbar\r\n", print_double(buffer1, value1), print_double(buffer2, value2));
-
-        temp->get_temperature(&value1);
-        printf("STTS751: [temp] %7s C\r\n", print_double(buffer1, value1));
-
-        printf("---\r\n");
-
-        magnetometer->get_m_axes(axes);
-        printf("LIS2MDL [mag/mgauss]:  %6d, %6d, %6d\r\n", axes[0], axes[1], axes[2]);
-
-        accelerometer->get_x_axes(axes);
-        printf("LIS2DW12 [acc/mg]:  %6d, %6d, %6d\r\n", axes[0], axes[1], axes[2]);
-
-        acc_gyro->get_x_axes(axes);
-        printf("LSM6DSO [acc/mg]:      %6d, %6d, %6d\r\n", axes[0], axes[1], axes[2]);
-
-        acc_gyro->get_g_axes(axes);
-        printf("LSM6DSO [gyro/mdps]:   %6d, %6d, %6d\r\n", axes[0], axes[1], axes[2]);
-
-        wait(1.5);
+    /* Enable LIS2MDL magnetometer sensor */
+    magnetometer->enable();
+    
+    /* LIS2MDL magnetometer sensor configuration */
+    printf("/***** LIS2MDL magnetometer configuration *****/\r\n");
+    
+    magnetometer->read_id(&id);
+    printf("LIS2MDL magnetometer = 0x%X\r\n", id);
+    
+    magnetometer->set_m_odr(LIS2MDL_ODR);
+    magnetometer->get_m_odr(&read_reg);
+    printf("LIS2MDL ODR = %1.1f [Hz]\r\n", read_reg);
+    
+    magnetometer->set_m_lp(LIS2MDL_LP);
+    magnetometer->get_m_lp(&read_reg_int);
+    printf("LIS2MDL LP = %1d\r\n", read_reg_int);
+    
+    magnetometer->set_m_lpf(LIS2MDL_LPF);
+    magnetometer->get_m_lpf(&read_reg_int);
+    printf("LIS2MDL LPF = %1d\r\n", read_reg_int);
+    
+    /* Print Flash memory information */
+    print_flash_info();
+    
+    /* Information for the user */
+    printf("Press blue button to start data acquisition\r\n");
+    printf("Press 'R' to read previously measured data\r\n");
+    
+    /* Acquisition loop */
+    while(1) {
+        // Start saving data when button is pushed
+        if (button1_pressed) {
+            button1_pressed = false;
+            save_data = true;
+            erase_flash(false);
+            printf("Acquiring data...\r\n");
+            printf("Press blue button to stop data acquisition\r\n");
+            Flash_addr = FLASH_BANK2_BASE + 4;
+        }
+        
+        if (save_data) {
+            // Acquisition task
+            save_data = acquisition_task(&Flash_addr);
+        }
+        else {
+            // Read task
+            read_task();
+        }
     }
-}
+}
\ No newline at end of file