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
Diff: source/main.cpp
- Revision:
- 82:f01379c0f435
- Parent:
- 81:b8ef2a762318
- Child:
- 83:b67e4bb6a087
diff -r b8ef2a762318 -r f01379c0f435 source/main.cpp --- 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) } //*****************************************************************************