Fitness Wearable

Published by Edumcg in the blog Edumcg's blog. Views: 609


Introduction
My goal is to create a Fitness Wearable gathering data from the BMI160 IMU. From the data collected I'm going to filter it to get linear movement using the Fourier Transform then save the data in the microSD and finally use the PAN136B module to connect wirelessly to an Android app in order to count the reps made by the user.

BOM
-MAX32630FTHR
-WRL-12577 Bluetooth Module

Schematics
-

Instructions
My first goal was to use the PAN136B module but after trying for several weeks I gave up on it and used the module listed in the BOM.
My attempt to use the PAN136B was the following:
Code (Text):
  1.  
  2.      //Bluetooth Config
  3.     DigitalOut bReset(P1_6,0); //First Low
  4.     There are two bits that control whether the RTC timer and 32768Hz oscillator are enabled.
  5.     The PWRSEQ_REG0.pwr_rtcen_run bit must be set to 1.
  6.     set PWRSEQ_REG4.pwr_pseq_32k_en to 1
  7.  
  8.     uint32_t myPwrseqReg0 = MXC_PWRSEQ->reg0;
  9.     myPwrseqReg0 &= ~(MXC_F_PWRSEQ_REG0_PWR_RTCEN_RUN);
  10.     myPwrseqReg0 |= (1 << MXC_F_PWRSEQ_REG0_PWR_RTCEN_RUN_POS);
  11.      MXC_PWRSEQ->reg0 = myPwrseqReg0;
  12.  
  13.     uint32_t myPwrseqReg4 = MXC_PWRSEQ->reg4;
  14.     myPwrseqReg4 &= ~(MXC_F_PWRSEQ_REG4_PWR_PSEQ_32K_EN);
  15.     myPwrseqReg4 |= (1 << MXC_F_PWRSEQ_REG4_PWR_PSEQ_32K_EN_POS);
  16.     MXC_PWRSEQ->reg4 = myPwrseqReg4;
  17.     wait(0.10);
  18.     bReset.write(1); //Initiate
  19.  
I managed to gather data from the IMU and saved it on the SDCard, also I already have the FFT. Currently I'm still filtering it in order to work properly with the workouts.
Android App

Here are screeshots of how the Android app looks right now:
0.PNG 1.PNG
Video
*Not yet*

Source Code
Code (Text):
  1.  
  2. #include "mbed.h"
  3. #include "max32630fthr.h"
  4. #include "MAX14690.h"
  5. #include "cmsis.h"          // register base address definitions
  6. #include "pwrseq_regs.h"    // power sequence register definitions
  7. #include "bmi160.h"
  8. #include "SDFileSystem.h"
  9. //Setup interrupt in from imu
  10. InterruptIn imuIntIn(P3_6);
  11. static const uint32_t N = 8000; //Samples
  12. bool drdy = false;
  13. void saveData(uint32_t numSamples, float * accX,
  14.               float * accY, float * accZ, float * gyroX, float * gyroY, float * gyroZ);
  15.  
  16. void imuISR(){
  17.     drdy = true;
  18. }
  19. struct TWIDDLE {  // Structure factor for calculate fft
  20.  
  21.     float cosval [N/2];
  22.     float sinval [N/2];
  23.  
  24. };
  25. void FFT(float datos[N], int n, TWIDDLE &w); //Declaration of functions
  26. int main ()
  27. {
  28.     //Init board and set GPIO to 3.3V logic
  29.     MAX32630FTHR pegasus(MAX32630FTHR::VIO_3V3);
  30.     //Turn RGB LED off
  31.     DigitalOut rLED(LED1, LED_OFF);
  32.     DigitalOut gLED(LED2, LED_OFF);
  33.     DigitalOut bLED(LED3, LED_OFF);
  34.  
  35.     Serial BlueCOM(P3_1,P3_0,9600); //UART to the Bluetooth Module, TX,RX
  36.  
  37.     //Setup I2C bus for IMU
  38.     I2C i2cBus(P5_7, P6_0);
  39.     i2cBus.frequency(400000);
  40.     uint32_t failures = 0;
  41.     //Get IMU instance and configure it
  42.     BMI160_I2C imu(i2cBus, BMI160_I2C::I2C_ADRS_SDO_LO); //I2C_ADRS_SDO_LO = 0x68
  43.  
  44.     //Power up sensors in normal mode
  45.     if(imu.setSensorPowerMode(BMI160::GYRO, BMI160::NORMAL) != BMI160::RTN_NO_ERROR) //Differente than success
  46.     {
  47.         BlueCOM.printf("Failed to set gyroscope power mode\n");
  48.         failures++;
  49.     }else{
  50.         BlueCOM.printf("Success grysoscope");
  51.     }  
  52.     wait(0.1);
  53.     if(imu.setSensorPowerMode(BMI160::ACC, BMI160::NORMAL) != BMI160::RTN_NO_ERROR){
  54.         BlueCOM.printf("Failed to set accelerometer power mode\n");
  55.         failures++;
  56.     }else{
  57.         BlueCOM.printf("Success Accelerometer");
  58.     }
  59.     wait(0.1);
  60.     //Accelereometer configuration values
  61.     BMI160::AccConfig accConfig;
  62.     BMI160::AccConfig accConfigRead;
  63.     accConfig.range = BMI160::SENS_2G;
  64.     accConfig.us = BMI160::ACC_US_OFF;
  65.     accConfig.bwp = BMI160::ACC_BWP_2;
  66.     accConfig.odr = BMI160::ACC_ODR_11;
  67.     if(imu.setSensorConfig(accConfig) == BMI160::RTN_NO_ERROR)
  68.     {
  69.         if(imu.getSensorConfig(accConfigRead) == BMI160::RTN_NO_ERROR)
  70.         {
  71.             if((accConfig.range != accConfigRead.range) ||
  72.                     (accConfig.us != accConfigRead.us) ||
  73.                     (accConfig.bwp != accConfigRead.bwp) ||
  74.                     (accConfig.odr != accConfigRead.odr))
  75.             {
  76.                 BlueCOM.printf("ACC read data desn't equal set data\n\n");
  77.                 BlueCOM.printf("ACC Set Range = %d\n", accConfig.range);
  78.                 BlueCOM.printf("ACC Set UnderSampling = %d\n", accConfig.us);
  79.                 BlueCOM.printf("ACC Set BandWidthParam = %d\n", accConfig.bwp);
  80.                 BlueCOM.printf("ACC Set OutputDataRate = %d\n\n", accConfig.odr);
  81.                 BlueCOM.printf("ACC Read Range = %d\n", accConfigRead.range);
  82.                 BlueCOM.printf("ACC Read UnderSampling = %d\n", accConfigRead.us);
  83.                 BlueCOM.printf("ACC Read BandWidthParam = %d\n", accConfigRead.bwp);
  84.                 BlueCOM.printf("ACC Read OutputDataRate = %d\n\n", accConfigRead.odr);
  85.                 failures++;
  86.             }
  87.            
  88.         }
  89.         else
  90.         {
  91.              BlueCOM.printf("Failed to read back accelerometer configuration\n");
  92.              failures++;
  93.         }
  94.     }
  95.     else
  96.     {
  97.         BlueCOM.printf("Failed to set accelerometer configuration\n");
  98.         failures++;
  99.     }
  100.  
  101.     BMI160::GyroConfig gyroConfig;
  102.     BMI160::GyroConfig gyroConfigRead;
  103.     gyroConfig.range = BMI160::DPS_2000;
  104.     gyroConfig.bwp = BMI160::GYRO_BWP_2;
  105.     gyroConfig.odr = BMI160::GYRO_ODR_11;
  106.     if(imu.setSensorConfig(gyroConfig) == BMI160::RTN_NO_ERROR)
  107.     {
  108.         if(imu.getSensorConfig(gyroConfigRead) == BMI160::RTN_NO_ERROR)
  109.         {
  110.             if((gyroConfig.range != gyroConfigRead.range) ||
  111.                     (gyroConfig.bwp != gyroConfigRead.bwp) ||
  112.                     (gyroConfig.odr != gyroConfigRead.odr))
  113.             {
  114.                 BlueCOM.printf("GYRO read data desn't equal set data\n\n");
  115.                 BlueCOM.printf("GYRO Set Range = %d\n", gyroConfig.range);
  116.                 BlueCOM.printf("GYRO Set BandWidthParam = %d\n", gyroConfig.bwp);
  117.                 BlueCOM.printf("GYRO Set OutputDataRate = %d\n\n", gyroConfig.odr);
  118.                 BlueCOM.printf("GYRO Read Range = %d\n", gyroConfigRead.range);
  119.                 BlueCOM.printf("GYRO Read BandWidthParam = %d\n", gyroConfigRead.bwp);
  120.                 BlueCOM.printf("GYRO Read OutputDataRate = %d\n\n", gyroConfigRead.odr);
  121.                 failures++;
  122.             }
  123.          
  124.         }
  125.         else
  126.         {
  127.             BlueCOM.printf("Failed to read back gyroscope configuration\n");
  128.             failures++;
  129.         }
  130.     }
  131.     else
  132.     {
  133.         BlueCOM.printf("Failed to set gyroscope configuration\n");
  134.         failures++;
  135.     }
  136.  
  137.  
  138.     if(failures == 0)
  139.     {
  140.         BlueCOM.printf("ACC Range = %d\n", accConfig.range);
  141.         BlueCOM.printf("ACC UnderSampling = %d\n", accConfig.us);
  142.         BlueCOM.printf("ACC BandWidthParam = %d\n", accConfig.bwp);
  143.         BlueCOM.printf("ACC OutputDataRate = %d\n\n", accConfig.odr);
  144.         BlueCOM.printf("GYRO Range = %d\n", gyroConfig.range);
  145.         BlueCOM.printf("GYRO BandWidthParam = %d\n", gyroConfig.bwp);
  146.         BlueCOM.printf("GYRO OutputDataRate = %d\n\n", gyroConfig.odr);
  147.         wait(1.0);
  148.     }
  149.     DigitalIn uSDdetect(P2_2, PullUp);
  150.     uint32_t samples = 0;
  151.     float accXaxisBuff[N];
  152.     float accYaxisBuff[N];
  153.     float accZaxisBuff[N];
  154.     float gyroXaxisBuff[N];
  155.     float gyroYaxisBuff[N];
  156.     float gyroZaxisBuff[N];
  157.     char c;
  158.     //Sensor data vars
  159.     BMI160::SensorData accData;
  160.     BMI160::SensorData gyroData;
  161.     BMI160::SensorTime sensorTime;
  162.  
  163.     //Enable data ready interrupt from imu for constant loop timming, low latency
  164.     imu.writeRegister(BMI160::INT_EN_1, 0x10);
  165.     //Active High PushPull output on INT1
  166.     imu.writeRegister(BMI160::INT_OUT_CTRL, 0x0A);
  167.     //Map data ready interrupt to INT1
  168.     imu.writeRegister(BMI160::INT_MAP_1, 0x80);
  169.  
  170.      //Tie INT1 to callback fx
  171.     imuIntIn.rise(&imuISR);
  172.     while(1)
  173.     {  
  174.         if(BlueCOM.readable()){
  175.             c = BlueCOM.getc();
  176.             wait(0.25);
  177.             if(c == 's'){ //Start from Bluetooth App
  178.                 if(drdy)
  179.                 {
  180.                     //Clear data ready flag
  181.                     drdy = false;      
  182.                     //Read feedback sensors
  183.                     imu.getGyroAccXYZandSensorTime(accData, gyroData, sensorTime, accConfig.range, gyroConfig.range);
  184.                     if(samples < N)
  185.                     {
  186.                         accXaxisBuff[samples] = accData.xAxis.scaled;
  187.                         accYaxisBuff[samples] = accData.yAxis.scaled;
  188.                         accZaxisBuff[samples] = accData.zAxis.scaled;
  189.                         gyroXaxisBuff[samples] = gyroData.xAxis.scaled;
  190.                         gyroYaxisBuff[samples] = gyroData.yAxis.scaled;
  191.                         gyroZaxisBuff[samples] = gyroData.zAxis.scaled;
  192.                         samples++;
  193.                     }
  194.                     if(!uSDdetect && (samples > (N-1)))
  195.                     {
  196.                         bLED = LED_ON;
  197.                         saveData(samples, accXaxisBuff, accYaxisBuff, accZaxisBuff, gyroXaxisBuff, gyroYaxisBuff, gyroZaxisBuff);
  198.                         samples = 0;
  199.                         bLED = LED_OFF;
  200.                     }
  201.                     wait(25);
  202.                 }
  203.             }
  204.         }
  205.     }
  206. }
  207. //*****************************************************************************
  208. void saveData(uint32_t numSamples,  float * accX, float * accY, float * accZ, float * gyroX, float * gyroY, float * gyroZ)
  209. {
  210.     SDFileSystem sd(P0_5, P0_6, P0_4, P0_7, "sd");  // mosi, miso, sclk, cs
  211.     FILE *fp;
  212.  
  213.     fp = fopen("/sd/Acc&GyroData.txt", "a");
  214.     if(fp != NULL)
  215.     {
  216.         fprintf(fp, "Samples,%d\n", numSamples);
  217.  
  218.         fprintf(fp, "X-Acc\ty-Acc\tZ-Acc\tX-Gyro\tY-Gyro\tZ-Gyro\n");
  219.      
  220.         for(uint32_t idx = 0; idx < numSamples; idx++)
  221.         {
  222.             fprintf(fp, "%5.4f\t", accX[idx]);
  223.             fprintf(fp, "%5.4f\t", accY[idx]);
  224.             fprintf(fp, "%5.4f\t", accZ[idx]);
  225.             fprintf(fp, "%6.2f\t", gyroX[idx]);
  226.             fprintf(fp, "%6.2f\t", gyroY[idx]);
  227.             fprintf(fp, "%6.2f", gyroZ[idx]);
  228.             fprintf(fp, "\n");
  229.         }
  230.         fprintf(fp, "\n");
  231.         fclose(fp);
  232.     }
  233.     else
  234.     {
  235.         printf("Failed to open file\n");
  236.     }
  237. }
  238. void FFT(float datos[N], int n,TWIDDLE &w) { //Fast Fourier Transform
  239.     float temp1, temp2, temp3,temp4;   //variables needed to calculate FFT
  240.     int i,j,k,p;
  241.     int upper_leg, lower_leg;
  242.     int leg_diff;
  243.     int num_stages=0;
  244.     int index, step;
  245.     float datos_real[n], datos_imag[n]; //real and imaginary values
  246.     for (p=0; p<n; p++) {
  247.         datos_real[p]=datos[p];
  248.         datos_imag[p]=0;
  249.     }
  250.     i=1;
  251.     do {
  252.         num_stages+=1;
  253.         i=i*2;
  254.     } while (i!=n);
  255.  
  256.     leg_diff=n/2;
  257.     step=1;
  258.  
  259.     for (i=0; i<num_stages; i++) {
  260.         index=0;
  261.         for (j=0; j<leg_diff; j++) {
  262.             for (upper_leg=j; upper_leg<n; upper_leg+=(2*leg_diff)) {
  263.                 lower_leg=upper_leg+leg_diff;
  264.  
  265.                 temp1= (datos_real[upper_leg]+ datos_real[lower_leg]);
  266.                 temp2= (datos_real[upper_leg]- datos_real[lower_leg]);
  267.                 temp3= (datos_imag[upper_leg]+ datos_imag[lower_leg]);
  268.                 temp4= (datos_imag[upper_leg]- datos_imag[lower_leg]);
  269.                 datos_real[lower_leg]= (temp2*w.cosval[index])-(temp4*w.sinval[index]);
  270.                 datos_imag[lower_leg]= (temp2*w.sinval[index]+temp4*w.cosval[index]);
  271.                 datos_real[upper_leg]= temp1;
  272.                 datos_imag[upper_leg]= temp3;
  273.             }
  274.             index+=step;
  275.         }
  276.         leg_diff=leg_diff/2;
  277.         step*=2;
  278.     }
  279. //bit reversal
  280.     j=0;
  281.     for (i=1; i<(N-2); i++) {
  282.         k=n/2;
  283.         while (k<=j) {
  284.             j=j-k;
  285.             k=k/2;
  286.         }
  287.         j=j+k;
  288.  
  289.         if (i<j) {
  290.             temp1= datos_real[j];
  291.             temp2= datos_imag[j];
  292.             datos_real[j]=datos_real[i];
  293.             datos_imag[j]=datos_imag[i];
  294.             datos_real[i]=temp1;
  295.             datos_imag[i]=temp2;
  296.         }
  297.     }
  298.  
  299.     for (i=0; i<n; i++) {
  300.  
  301.         datos[i]= pow(sqrt(pow(datos_real[i],2)+pow(datos_imag[i],2)),2); //Calculate the power fft
  302.     };
  303.  
  304. }
  305.  
CAD Files
Attach or link to any CAD files if relevant to your project.
You need to be logged in to comment