Impact Sensor

Introduction
My project is to build an impact sensor using the IMU of the max32630fthr. Basically I wanted to be able to attach the sensor to an object so it could measure the impact force when the object is moved and store the readings to an sd card.

The difficulty level for this project is easy.

BOM
MAX32630FTHR
Battery or usb cable if running tethered to a pc
Micro SDCard

Schematics
All the required hardware is already on the board.

Instructions
To build the project all I had to do was load my code to the board , add a sd card and battery if you want to by itself or using the usb cable so you could watch the console output.

After doing research for the project, I found out that a couple of the sample projects for the board contain the majority of the code required. I decided to use the MAX32630FTH_IMU_Hello_World source code as my starting point. It contains all I needed to read the IMU values. I then added code to be able to enable different modes using the on board button. When the button is pressed, it executes an interrupt which will increment a variable that is used to enable and disable various functions, this also enable or disables the on board leds so you can tell which mode your in. The last step was to add code to write to a sd card.

Here is a couple of screen shots of the console. In the second image, the data is down further on the screen because I was playing around with positioning text on the screen.
1574630464826.png
1574630469369.png

upload_2017-6-16_21-1-6.png


Here is a sample of the output on the sd card:
Fields are as follows Time Temp xAcc yAcc zAcc xGyr yGyr zGyr
230.399979 24.270 -0.635 -0.489 0.593 21.2 9.8 1.4

230.887009 24.258 -0.635 -0.564 0.726 10.2 -1.6 -2.2
231.103271 24.303 -0.644 -0.559 0.753 9.2 1.9 4.9
231.319839 24.293 -0.641 -0.535 0.731 34.8 5.7 -6.3
231.536011 24.291 -0.626 -0.447 0.851 11.5 2.1 0.1
231.752533 24.303 -0.594 -0.424 0.915 62.7 -2.2 -24.8
231.968719 24.314 -0.610 -0.422 0.898 -30.3 4.6 32.4
232.183762 24.299 -0.592 -0.452 0.885 2.9 -6.4 14.5
232.395920 24.379 -0.601 -0.419 0.737 -30.9 6.8 -8.2
232.624146 24.389 -0.635 -0.488 0.827 -5.2 4.8 -6.6





The data can be easily plotted using excel or a similar program. My intent was to use processing to create an app that would be able to continuously scroll as the data came in. The app would also let you set thresholds to highlight when the force exceed the set point, but I was unable to get the serial connection to work properly which was odd because terminal programs would connect without issue.

I would of like to get bluetooth working, but I didn't find any examples until an email came out a couple of days before the due date. Since processing apps can run on a phone or tablet, bluetooth would of been the best choice to get working as I wouldn't need the usb connection to monitor the output. This setup would also be ideal for one of my test which was to mount it on the back of my sons sparing gear, so I could see how hard he was actually getting hit.

After playing around with this board, I think adding a LoRa transceiver would be a great idea too. The sensor could then be mounted in remote locations and the data could be monitored very easily. I did see someone else has already added to a board like this which looks very interesting. I think when my transceivers come in that I order, I may try to add one to see if it works.

Conclusion
I found this board rather easy to get started with. The fact it works with the mbed compiler makes great development platform. The price for the board is pretty good especially for what you get built onto the board. If I had give a con for the board, I would have to say that there isn't very many examples out there for it, but I suspect that will change as people use it


Source Code
Code:
[FONT=Courier New][SIZE=3]/**********************************************************************
* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Maxim Integrated
* Products, Inc. shall not be used except as stated in the Maxim Integrated
* Products, Inc. Branding Policy.
*
* The mere transfer of this software does not imply any licenses
* of trade secrets, proprietary technology, copyrights, patents,
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
**********************************************************************/


#include "mbed.h"
#include "max32630fthr.h"
#include "bmi160.h"
#include "SDFileSystem.h"


void dumpImuRegisters(BMI160 &imu);
void printRegister(BMI160 &imu, BMI160::Registers reg);
void printBlock(BMI160 &imu, BMI160::Registers startReg, BMI160::Registers stopReg);

void printData(BMI160::SensorData &accData, BMI160::SensorData &gyroData, BMI160::SensorTime &sensorTime, BMI160::AccRange accRange, BMI160::GyroRange gyroRange, float imuTemperature);
void saveData(BMI160::SensorData &accData, BMI160::SensorData &gyroData, BMI160::SensorTime &sensorTime, BMI160::AccRange accRange, BMI160::GyroRange gyroRange, float imuTemperature);

//Setup start/stop button
DigitalIn selectMenuBtn(P2_3, PullUp);
InterruptIn selectMenu(P2_3);
int iCase = 0;
bool save = false;
bool console = false;
bool debug = false;

void selectMenuISR()
{
    iCase++;
    if(iCase == 6){
        iCase = 0;
    }

    //Thread::wait(500);
    wait_ms(100);
}

int main()
{
    MAX32630FTHR pegasus(MAX32630FTHR::VIO_3V3);
 
    DigitalOut rLED(LED1, LED_OFF);
    DigitalOut gLED(LED2, LED_OFF);
    DigitalOut bLED(LED3, LED_OFF);
 
    I2C i2cBus(P5_7, P6_0);
    i2cBus.frequency(400000);
    BMI160_I2C imu(i2cBus, BMI160_I2C::I2C_ADRS_SDO_LO);
 
    printf("\033[H");  //home
    printf("\033[0J");  //erase from cursor to end of screen
 
    uint32_t failures = 0;
 
    if(imu.setSensorPowerMode(BMI160::GYRO, BMI160::NORMAL) != BMI160::RTN_NO_ERROR)
    {
        printf("Failed to set gyroscope power mode\n\r");
        failures++;
    }
    wait_ms(100);
 
    if(imu.setSensorPowerMode(BMI160::ACC, BMI160::NORMAL) != BMI160::RTN_NO_ERROR)
    {
        printf("Failed to set accelerometer power mode\n\r");
        failures++;
    }
    wait_ms(100);
 
 
    BMI160::AccConfig accConfig;
    //example of using getSensorConfig
    if(imu.getSensorConfig(accConfig) == BMI160::RTN_NO_ERROR)
    {
        printf("ACC Range = %d\n\r", accConfig.range);
        printf("ACC UnderSampling = %d\n\r", accConfig.us);
        printf("ACC BandWidthParam = %d\n\r", accConfig.bwp);
        printf("ACC OutputDataRate = %d\n\r\n\r", accConfig.odr);
    }
    else
    {
        printf("Failed to get accelerometer configuration\n\r");
        failures++;
    }
 
    //example of setting user defined configuration
    accConfig.range = BMI160::SENS_4G;
    accConfig.us = BMI160::ACC_US_OFF;
    accConfig.bwp = BMI160::ACC_BWP_2;
    accConfig.odr = BMI160::ACC_ODR_8;
    if(imu.setSensorConfig(accConfig) == BMI160::RTN_NO_ERROR)
    {
        printf("ACC Range = %d\n\r", accConfig.range);
        printf("ACC UnderSampling = %d\n\r", accConfig.us);
        printf("ACC BandWidthParam = %d\n\r", accConfig.bwp);
        printf("ACC OutputDataRate = %d\n\r\n\r", accConfig.odr);
    }
    else
    {
        printf("Failed to set accelerometer configuration\n\r");
        failures++;
    }
 
    BMI160::GyroConfig gyroConfig;
    if(imu.getSensorConfig(gyroConfig) == BMI160::RTN_NO_ERROR)
    {
        printf("GYRO Range = %d\n\r", gyroConfig.range);
        printf("GYRO BandWidthParam = %d\n\r", gyroConfig.bwp);
        printf("GYRO OutputDataRate = %d\n\r\n\r", gyroConfig.odr);
    }
    else
    {
        printf("Failed to get gyroscope configuration\n\r");
        failures++;
    }
 
    wait(1.0);
//    printf("\033[H");  //home
    printf("\033[0J");  //erase from cursor to end of screen

    selectMenu.fall(&selectMenuISR);
 
    if(failures == 0)
    {
        float imuTemperature;
        BMI160::SensorData accData;
        BMI160::SensorData gyroData;
        BMI160::SensorTime sensorTime;
     
        while(1)
        {
            switch(iCase){
            case 1:
                rLED = LED_ON;
                gLED = LED_OFF;
                bLED = LED_OFF;
                console = false;
                save = false;
                debug = false;
                break;
            case 2:
                rLED = LED_ON;
                gLED = LED_ON;
                bLED = LED_OFF;
                console = true;
                save = false;
                debug = false;
                break;
            case 3:
                rLED = LED_OFF;
                gLED = LED_ON;
                bLED = LED_OFF;
                console = false;
                save = true;
                debug = false;
                break;
            case 4:
                rLED = LED_OFF;
                gLED = LED_ON;
                bLED = LED_ON;
                console = true;
                save = true;
                debug = false;
                break;
            case 5:
                rLED = LED_OFF;
                gLED = LED_OFF;
                bLED = LED_ON;
                console = true;
                save = true;
                debug = true;
                break;
            case 6:
                rLED = LED_ON;
                gLED = LED_OFF;
                bLED = LED_ON;
                break;              
            default:
                rLED = LED_OFF;
                gLED = LED_OFF;
                bLED = LED_OFF;
                console = false;
                save = false;
                debug = false;
                printf("\033[H");
                printf("\033[0J");
                break;
        }
            imu.getGyroAccXYZandSensorTime(accData, gyroData, sensorTime, accConfig.range, gyroConfig.range);
            imu.getTemperature(&imuTemperature);  
            //if ((accData.xAxis.scaled >= 1)|(accData.yAxis.scaled >= 1)|(accData.zAxis.scaled >= 1)){      
                if (console == true)
                    printData(accData, gyroData, sensorTime, accConfig.range, gyroConfig.range, imuTemperature);
                if (save == true)
                    saveData(accData, gyroData, sensorTime, accConfig.range, gyroConfig.range, imuTemperature);
                if (debug == true)
                    dumpImuRegisters(imu);
            //}
            //gLED = !gLED;
            //rLED = !rLED;
            //bLED = !bLED;
         
        }
    }
    else
    {
        while(1)
        {
            rLED = !rLED;
            wait(0.25);
        }
    }
}


//*****************************************************************************
void dumpImuRegisters(BMI160 &imu)
{
    printRegister(imu, BMI160::CHIP_ID);
    printBlock(imu, BMI160::ERR_REG,BMI160::FIFO_DATA);
    printBlock(imu, BMI160::ACC_CONF, BMI160::FIFO_CONFIG_1);
    printBlock(imu, BMI160::MAG_IF_0, BMI160::SELF_TEST);
    printBlock(imu, BMI160::NV_CONF, BMI160::STEP_CONF_1);
    printRegister(imu, BMI160::CMD);
    printf("\n\r");
}

//*****************************************************************************
void printBlock(BMI160 &imu, BMI160::Registers startReg, BMI160::Registers stopReg)
{
    uint8_t numBytes = ((stopReg - startReg) + 1);
    uint8_t buff[numBytes];
    uint8_t offset = static_cast<uint8_t>(startReg);
 
    if(imu.readBlock(startReg, stopReg, buff) == BMI160::RTN_NO_ERROR)
    {
        for(uint8_t idx = offset; idx < (numBytes + offset); idx++)
        {
            printf("IMU Register 0x%02x = 0x%02x\n\r", idx, buff[idx - offset]);
        }
    }
    else
    {
        printf("Failed to read block\n\r");
    }
}
//*****************************************************************************
void printRegister(BMI160 &imu, BMI160::Registers reg)
{
    uint8_t data;
    if(imu.readRegister(reg, &data) == BMI160::RTN_NO_ERROR)
    {
        printf("IMU Register 0x%02x = 0x%02x\n\r", reg, data);
    }
    else
    {
        printf("Failed to read register\n\r");
    }
}
//*****************************************************************************
void printData(BMI160::SensorData &accData, BMI160::SensorData &gyroData, BMI160::SensorTime &sensorTime, BMI160::AccRange accRange, BMI160::GyroRange gyroRange, float imuTemperature)
{
    //printf("\033[H");
    //printf("\033[0J");
    printf("ACC xAxis = %s%4.3f\n\r", "\033[K", accData.xAxis.scaled);
    printf("ACC yAxis = %s%4.3f\n\r", "\033[K", accData.yAxis.scaled);
    printf("ACC zAxis = %s%4.3f\n\n\r", "\033[K", accData.zAxis.scaled);
 
    printf("GYRO xAxis = %s%5.1f\n\r", "\033[K", gyroData.xAxis.scaled);
    printf("GYRO yAxis = %s%5.1f\n\r", "\033[K", gyroData.yAxis.scaled);
    printf("GYRO zAxis = %s%5.1f\n\n\r", "\033[K", gyroData.zAxis.scaled);
 
    printf("Sensor Time = %s%f\n\r", "\033[K", sensorTime.seconds);
    printf("Sensor Temperature = %s%5.3f\n\r", "\033[K", imuTemperature);
 
    printf("\033[15;1H");
    //printf("\033[H");  //home
}
 
void saveData(BMI160::SensorData &accData, BMI160::SensorData &gyroData, BMI160::SensorTime &sensorTime, BMI160::AccRange accRange, BMI160::GyroRange gyroRange, float imuTemperature)
{
    SDFileSystem sd(P0_5, P0_6, P0_4, P0_7, "sd");  // mosi, miso, sclk, cs
    FILE *fp;
 
    fp = fopen("/sd/impact.txt", "a");
    if(fp != NULL)
    {
        fprintf(fp, "%f\t%5.3f\t%4.3f\t%4.3f\t%4.3f\t%5.1f\t%5.1f\t%5.1f\n\r",sensorTime.seconds, imuTemperature, accData.xAxis.scaled, accData.yAxis.scaled, accData.zAxis.scaled, gyroData.xAxis.scaled, gyroData.yAxis.scaled, gyroData.zAxis.scaled);
        //fprintf(fp, "\n");
        fclose(fp);
    }
    else
    {
        printf("\033[H");
        printf("\033[0J");
        printf("Failed to open file\t");
    }
}[/SIZE][/FONT]

Blog entry information

Author
cybermah
Views
1,067
Last update

More entries in General

More entries from cybermah

Share this entry

Top