2019-2020 Multisensor project using the X_NUCLEO_IKS01A3 sensor platform
Dependencies: X_NUCLEO_IKS01A3
Diff: main.cpp
- 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