Combines a working system to save force, acceleration and gyro data to an SD card in a MAX32630 with BLE_Heartrate taken from the mbed site.

Dependencies:   USBMSD_BD BMI160 HX711 max32630fthr USBDevice

Revision:
82:f01379c0f435
Parent:
81:b8ef2a762318
Child:
83:b67e4bb6a087
--- a/source/main.cpp	Thu Oct 24 12:58:23 2019 +0000
+++ b/source/main.cpp	Fri Oct 25 10:33:47 2019 +0000
@@ -16,6 +16,8 @@
 #include "USBMSD_BD.h"
 #include "FATFileSystem.h" // Put in, aping what was in the FTHDR_USBMSD_BD example
 
+Thread ble_thread;
+
 DigitalOut led1(LED1, 1);
 
 const static char     DEVICE_NAME[] = "HRM";
@@ -59,7 +61,7 @@
 FATFileSystem fs("fs"); // File system declaration 
 USBMSD_BD msd(&bd);  // USB MSD
 
-DigitalIn sd_detect(P2_2);
+//DigitalIn sd_detect(P2_2);
 
 Serial pc(USBTX, USBRX);    // USB Serial Terminal
 int calibration_factor = 9500; //-7050 worked for my 440lb max scale setup
@@ -71,7 +73,7 @@
 char topline[200];
 HX711 scale(P3_4, P3_5);
 unsigned char button_pressed=0; 
-bool waittimeexpired=false, debugging=false;
+bool waittimeexpired=false, debugging=false, ble_call, blecallcontinuously /* Idea is to return BLE operation to original if true */= false;
 Ticker tick;
 
 void tick_timer() {
@@ -98,12 +100,15 @@
     hrServicePtr->updateHeartRate(hrmCounter);
 }
 
-void periodicCallback(void)
-{
-    led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
+void periodicCallback(void) {
+    if ((ble_call) || (blecallcontinuously)) {
+        led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
 
-    if (BLE::Instance().getGapState().connected) {
-        eventQueue.call(updateSensorValue);
+        if (BLE::Instance().getGapState().connected) {
+            eventQueue.call(updateSensorValue);
+        }
+    } else {
+        led1 = LED_OFF; // Don't leave the lights on
     }
 }
 
@@ -167,17 +172,220 @@
     eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
 }
 
-int main()
-{
+void bleheartrate() {
     eventQueue.call_every(500, periodicCallback);
-
     BLE &ble = BLE::Instance();
     ble.onEventsToProcess(scheduleBleEventsProcessing);
     ble.init(bleInitComplete);
+    eventQueue.dispatch_forever(); // https://os.mbed.com/docs/mbed-os/v5.14/tutorials/the-eventqueue-api.html
+    // have to do break_dispatch somewhere to stop it. Maybe inside the loop not to have BLE on all the time
+}
 
-    eventQueue.dispatch_forever();
+int main() {
+    pegasus.init(MAX32630FTHR::VIO_3V3);
+    ble_thread.start(bleheartrate); // Tried to start and stop this in each iteration with break_dispatch. Now using a semaphore
+    ble_call = false;     
+
+    // set PWRSEQ_REG0.pwr_rtcen_run to 1, PWRSEQ_REG0.pwr_rtcen_slip to 1
+    // MXC_PWRSEQ->reg0 |= MXC_F_PWRSEQ_REG0_PWR_RTCEN_RUN | MXC_F_PWRSEQ_REG0_PWR_RTCEN_SLP; // needs mbed-dev, which won't load 10/19
+    if (debugging) pc.printf("Starting Main Program Thread ...\n");
+    //bLED=LED_ON; // Just to verify program has loaded
+    //wait(0.5);
+    //bLED=LED_OFF;
+    gLED = LED_ON;
+    rLED = LED_ON;
+    i2cBus.frequency(400000);
+    scale.tare();
+    scale.setScale(calibration_factor); //Adjust to default calibration factor
+
+    uint32_t failures = 0;
+
+    if(imu.setSensorPowerMode(BMI160::GYRO, BMI160::NORMAL) != BMI160::RTN_NO_ERROR) {
+        //printf("Failed to set gyroscope power mode\n");
+        failures++;
+    }
+    wait_ms(100);
+
+    if(imu.setSensorPowerMode(BMI160::ACC, BMI160::NORMAL) != BMI160::RTN_NO_ERROR) {
+        //printf("Failed to set accelerometer power mode\n");
+        failures++;
+    }
+    wait_ms(100);
+
+    //example of using getSensorConfig
+    if(imu.getSensorConfig(accConfig) == BMI160::RTN_NO_ERROR) {
+        //printf("ACC Range = %d\n", accConfig.range);
+        //printf("ACC UnderSampling = %d\n", accConfig.us);
+        //printf("ACC BandWidthParam = %d\n", accConfig.bwp);
+        //printf("ACC OutputDataRate = %d\n\n", accConfig.odr);
+    } else {
+        //printf("Failed to get accelerometer configuration\n");
+        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", accConfig.range);
+        //printf("ACC UnderSampling = %d\n", accConfig.us);
+        //printf("ACC BandWidthParam = %d\n", accConfig.bwp);
+        //printf("ACC OutputDataRate = %d\n\n", accConfig.odr);
+    } else {
+        //printf("Failed to set accelerometer configuration\n");
+        failures++;
+    }
+
+    if(imu.getSensorConfig(gyroConfig) == BMI160::RTN_NO_ERROR) {
+        //printf("GYRO Range = %d\n", gyroConfig.range);
+        //printf("GYRO BandWidthParam = %d\n", gyroConfig.bwp);
+        //printf("GYRO OutputDataRate = %d\n\n", gyroConfig.odr);
+    } else {
+        //printf("Failed to get gyroscope configuration\n");
+        failures++;
+    }
+
+    wait(1.0);
+    //printf("\033[H");  //home
+    //printf("\033[0J");  //erase from cursor to end of screen
+
+    /*if(failures == 0)
+    // FORMAT_CODE_END
+    //{
+
+        BMI160::SensorData accData;
+        BMI160::SensorData gyroData;
+        BMI160::SensorTime sensorTime;
+
+    // }*/
+
+    rLED = LED_OFF;
+    gLED = LED_OFF;
+
+    button.rise(&button_callback);  // attach the address of the flip function to the rising edge
+
+    button_pressed=0;
+
+    while (true) {
+    
+        if(button_pressed>=1) { // double-pressed if for calibration
+            tick.attach_us(&tick_timer, 1000);
+            gLED = LED_ON;
+            rLED = LED_OFF;
+            //float raw = scaleRaw.read();
+            // maybe calibrate against weighing scales reading here
+            float timer=0;
+            time_t seconds = time(NULL);
 
-    return 0;
+            char filename[40];
+            if (debugging) pc.printf("%s\n", filename);
+            rLED = LED_ON;
+            if (fs.mount(&bd) == 0) { // SDBlock stuff. changed from "if (sd.mount() == 0)"
+                if (debugging) pc.printf("Mounted SD card\n");
+                FILE *ft = fopen("/fs/time.txt",  "r"); // changed from "/sd/"...
+                if(ft != NULL) {
+                    fscanf(ft, "%d", &epoch_time);
+                    fclose(ft);
+                    set_time(epoch_time);  // handy to have this, since it allows users to take out the SD card and reset the time from graphgen.xlsx
+                    seconds = time(NULL);  // no idea why it seemed necessary to subtract 2^20 from the time to get the time stamping to work properly
+                } else if (debugging) pc.printf("Failed to open time.txt!");
+                strftime(filename, 40, "/fs/%a_%d_%m_%Y_%H_%M_%S.csv", localtime(&seconds)); // changed from "/sd/"...
+                FILE *fc = fopen("/fs/calibration.txt",  "r");  // changed from "/sd/"...
+                if(fc != NULL) {
+
+                    while (fscanf(fc, "%d", &calibration_factor) != EOF) {
+                       //i++;
+                    }
+                    scale.setScale(calibration_factor); //Adjust to this calibration factor
+                    fclose(fc);
+                }
+
+                if (debugging) pc.printf("-!-");
+                FILE *fp = fopen(filename, "w");
+                if(fp != NULL) {
+                    if (debugging) pc.printf("-+-");
+                    ble_call = true; // Turn on calling. This is read in periodicCallback(void)
+                    sprintf(topline, "Time,Weight,ACC xAxis,ACC yAxis,ACC zAxis,GYRO xAxis,GYRO yAxis,GYRO zAxis,Calibration factor=%d\n", calibration_factor);
+                    fprintf(fp, topline);
+                    rLED = LED_OFF;
+                    imu.getSensorTime(startTime);
+                    char my_string[256];
+                  
+                    while(timer<=20) {
+                        imu.getGyroAccXYZandSensorTime(accData, gyroData, sensorTime, accConfig.range, gyroConfig.range);
+
+                        weight = scale.getGram();
+                        waittimeexpired = false;
+                        if (debugging) pc.printf("Going to wait");
+                        while (waittimeexpired&waittimeexpired==false); // Loop until another ticker sets the variable
+                        if (debugging) pc.printf("Finished waiting");
+                        sprintf(my_string, "%.3f,%.3f,%4.3f,%4.3f,%4.3f,%5.1f,%5.1f,%5.1f,\n"
+                                , sensorTime.seconds-startTime.seconds
+                                , weight
+                                , accData.xAxis.scaled
+                                , accData.yAxis.scaled
+                                , accData.zAxis.scaled
+                                , gyroData.xAxis.scaled
+                                , gyroData.yAxis.scaled
+                                , gyroData.zAxis.scaled);
+
+                        //printf(my_string);
+                        fprintf(fp, my_string);
+                        timer=sensorTime.seconds-startTime.seconds;
+                            //wait(0.01f);
+
+                    } // while (timer<=20)
+                    fclose(fp);
+                    seconds = time(NULL);
+                    //pc.printf("seconds %d\n", seconds);
+                    FILE *fs = fopen("/fs/time.txt",  "w");  // changed from "/sd/"...
+                    char time_buf[11];
+                    sprintf(time_buf, "%u", seconds);
+                    //pc.printf("time_buf: %s\n", time_buf);
+                    fprintf(fs, "%s", time_buf);
+                    fclose(fs);
+
+                } else {
+                    if (debugging) pc.printf("Failed to open csv file!");
+                    gLED = LED_OFF;
+                    wait(2);
+                    rLED=LED_OFF;
+                }
+                fs.unmount(); // changed from sd.unmount()
+            } else { // If sd has not mounted
+                gLED = LED_OFF;
+                rLED = LED_OFF;
+                wait(1.0); // make plenty of time for second press
+                if (button_pressed > 1) { // If double-click (or more)
+                // blink blue once and send out a reading on the com port
+                    bLED = LED_ON;
+                    wait(1.0);
+                    bLED = LED_OFF;
+                    wait(1.0);
+                    pc.printf("%f %d", scale.getGram(), calibration_factor);
+                    button_pressed = 0;
+                } else { // indicate that there is no sd card
+                    for (int isd = 0; isd < seconds_to_blink_if_sd_mount_fails; isd++) {
+                        rLED = LED_ON;
+                        wait(0.5);
+                        rLED = LED_OFF;
+                        wait(0.5);
+                    }
+                }
+                rLED = LED_OFF;
+                
+            }// if sd.mount == 0 ... else
+            gLED = LED_OFF;
+            button_pressed = 0;
+            tick.detach();
+            // eventQueue.break_dispatch(); // basic attempt to stop of BLE. Result was flaky.
+            // ble_thread.terminate();
+            ble_call = false; // This is read in periodicCallback(void)
+        } // if (button_pressed==1)
+        // sleep(); // "Note: In most cases, you don't need to call sleep() directly. Mbed OS enters sleep mode automatically any time the system is idle. That is when all your threads are in a waiting state, for example waiting for an event or a timeout."
+    } // while (1)
 }
 
 //*****************************************************************************