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

Committer:
qaz
Date:
Thu Jun 04 10:32:19 2020 +0000
Revision:
83:b67e4bb6a087
Parent:
82:f01379c0f435
Publishing

Who changed what in which revision?

UserRevisionLine numberNew contents of line
qaz 81:b8ef2a762318 1 /* BlueCrutch. mbed Microcontroller Library yada */
qaz 81:b8ef2a762318 2 // Cloned from mbed-os-example-ble-HeartRate (after main.cpp was reverted to 14 Dec 2018), because for example where's ble/BLE.h
qaz 81:b8ef2a762318 3 // Taking stuff across from Niall's project bit by bit, starting with the includes.
mbed_official 10:ac3615194d04 4 #include <events/mbed_events.h>
mbed_official 1:72c60abef7e7 5 #include <mbed.h>
qaz 81:b8ef2a762318 6 #include "mbed.h"
mbed_official 1:72c60abef7e7 7 #include "ble/BLE.h"
qaz 80:caccea4da07b 8 #include "ble/Gap.h"
mbed_official 1:72c60abef7e7 9 #include "ble/services/HeartRateService.h"
qaz 81:b8ef2a762318 10 #include "max32630fthr.h"
qaz 81:b8ef2a762318 11 #include "HX711.h"
qaz 81:b8ef2a762318 12 #include "bmi160.h"
qaz 81:b8ef2a762318 13 //#include "SDFileSystem.h" // Error: Class "FATFileSystem" has no member "_ffs" in "SDFileSystem/FATFileSystem/ChaN/diskio.cpp", Line: 25, Col: 37. Compile error fixed by removing the SDFileSystem library from BlueCrutch. Compile was immediately successful. 24/10/19
qaz 81:b8ef2a762318 14 // I have another SD card library, under FTHR_USBMSD_BD, which at least compiled - 24/10/19
qaz 81:b8ef2a762318 15 #include "SDBlockDevice.h"
qaz 81:b8ef2a762318 16 #include "USBMSD_BD.h"
qaz 81:b8ef2a762318 17 #include "FATFileSystem.h" // Put in, aping what was in the FTHDR_USBMSD_BD example
mbed_official 1:72c60abef7e7 18
qaz 82:f01379c0f435 19 Thread ble_thread;
qaz 82:f01379c0f435 20
qaz 80:caccea4da07b 21 DigitalOut led1(LED1, 1);
mbed_official 1:72c60abef7e7 22
qaz 80:caccea4da07b 23 const static char DEVICE_NAME[] = "HRM";
qaz 80:caccea4da07b 24 static const uint16_t uuid16_list[] = {GattService::UUID_HEART_RATE_SERVICE};
qaz 80:caccea4da07b 25
qaz 80:caccea4da07b 26 static uint8_t hrmCounter = 100; // init HRM to 100bps
qaz 80:caccea4da07b 27 static HeartRateService *hrServicePtr;
qaz 80:caccea4da07b 28
qaz 80:caccea4da07b 29 static EventQueue eventQueue(/* event count */ 16 * EVENTS_EVENT_SIZE);
mbed_official 1:72c60abef7e7 30
qaz 81:b8ef2a762318 31 /* These are all the initializations from the crutch project - about the next 50 lines */
qaz 81:b8ef2a762318 32 void dumpImuRegisters(BMI160 &imu);
qaz 81:b8ef2a762318 33 void printRegister(BMI160 &imu, BMI160::Registers reg);
qaz 81:b8ef2a762318 34 void printBlock(BMI160 &imu, BMI160::Registers startReg, BMI160::Registers stopReg);
qaz 81:b8ef2a762318 35 MAX32630FTHR pegasus(MAX32630FTHR::VIO_3V3);
qaz 81:b8ef2a762318 36
qaz 81:b8ef2a762318 37 InterruptIn button(P2_3);
qaz 81:b8ef2a762318 38 DigitalOut rLED(LED1, LED_OFF);
qaz 81:b8ef2a762318 39 DigitalOut gLED(LED2, LED_OFF);
qaz 81:b8ef2a762318 40 DigitalOut bLED(LED3, LED_OFF);
qaz 81:b8ef2a762318 41 void button_callback(void);
qaz 81:b8ef2a762318 42
qaz 81:b8ef2a762318 43 I2C i2cBus(P5_7, P6_0);
qaz 81:b8ef2a762318 44
qaz 81:b8ef2a762318 45 BMI160_I2C imu(i2cBus, BMI160_I2C::I2C_ADRS_SDO_LO);
qaz 81:b8ef2a762318 46 BMI160::SensorData accData;
qaz 81:b8ef2a762318 47 BMI160::SensorData gyroData;
qaz 81:b8ef2a762318 48 BMI160::SensorTime sensorTime;
qaz 81:b8ef2a762318 49 BMI160::SensorTime startTime;
qaz 81:b8ef2a762318 50 float imuTemperature;
qaz 81:b8ef2a762318 51
qaz 81:b8ef2a762318 52 BMI160::AccConfig accConfig;
qaz 81:b8ef2a762318 53 BMI160::GyroConfig gyroConfig;
qaz 81:b8ef2a762318 54
qaz 81:b8ef2a762318 55 //SDFileSystem sd(P0_5, P0_6, P0_4, P0_7, "sd"); // mosi, miso, sclk, cs
qaz 81:b8ef2a762318 56 // SDFileSystem sd(P0_5, P0_6, P0_4, P0_7, "sd", P2_2, SDFileSystem::SWITCH_NEG_NO, 400000); // Had to comment this out because the SDFileSystem library gave compile time errors in BlueCrutch
qaz 81:b8ef2a762318 57 // Trying this as a replacement:
qaz 81:b8ef2a762318 58 // Physical block device, can be any device that supports the BlockDevice API
qaz 81:b8ef2a762318 59 // HeapBlockDevice bd(512*BLOCK_SIZE, BLOCK_SIZE);
qaz 81:b8ef2a762318 60 SDBlockDevice bd(P0_5, P0_6, P0_4, P0_7); // Compiled into the program 24/10/19, so success to that extent at least.
qaz 81:b8ef2a762318 61 FATFileSystem fs("fs"); // File system declaration
qaz 81:b8ef2a762318 62 USBMSD_BD msd(&bd); // USB MSD
qaz 81:b8ef2a762318 63
qaz 82:f01379c0f435 64 //DigitalIn sd_detect(P2_2);
qaz 81:b8ef2a762318 65
qaz 81:b8ef2a762318 66 Serial pc(USBTX, USBRX); // USB Serial Terminal
qaz 81:b8ef2a762318 67 int calibration_factor = 9500; //-7050 worked for my 440lb max scale setup
qaz 81:b8ef2a762318 68 int epoch_time = 1570547100; // 1570547100 = 3:05 on 08/10/19. Will be overwritten
qaz 81:b8ef2a762318 69 float zero_factor = 2.0781, weight;
qaz 81:b8ef2a762318 70 int averageSamples = 100;
qaz 81:b8ef2a762318 71 int seconds_to_blink_if_sd_mount_fails = 5;
qaz 81:b8ef2a762318 72 char epoch_string[11];
qaz 81:b8ef2a762318 73 char topline[200];
qaz 81:b8ef2a762318 74 HX711 scale(P3_4, P3_5);
qaz 81:b8ef2a762318 75 unsigned char button_pressed=0;
qaz 82:f01379c0f435 76 bool waittimeexpired=false, debugging=false, ble_call, blecallcontinuously /* Idea is to return BLE operation to original if true */= false;
qaz 81:b8ef2a762318 77 Ticker tick;
qaz 81:b8ef2a762318 78
qaz 81:b8ef2a762318 79 void tick_timer() {
qaz 81:b8ef2a762318 80 waittimeexpired = true;
qaz 81:b8ef2a762318 81 //pc.putc('x');
qaz 81:b8ef2a762318 82 }
qaz 81:b8ef2a762318 83 /* End of the initializations from the crutch project */
qaz 81:b8ef2a762318 84
qaz 80:caccea4da07b 85 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
qaz 80:caccea4da07b 86 {
qaz 80:caccea4da07b 87 BLE::Instance().gap().startAdvertising(); // restart advertising
qaz 80:caccea4da07b 88 }
mbed_official 1:72c60abef7e7 89
qaz 80:caccea4da07b 90 void updateSensorValue() {
qaz 80:caccea4da07b 91 // Do blocking calls or whatever is necessary for sensor polling.
qaz 80:caccea4da07b 92 // In our case, we simply update the HRM measurement.
qaz 80:caccea4da07b 93 hrmCounter++;
mbed_official 1:72c60abef7e7 94
qaz 80:caccea4da07b 95 // 100 <= HRM bps <=175
qaz 80:caccea4da07b 96 if (hrmCounter == 175) {
qaz 80:caccea4da07b 97 hrmCounter = 100;
mbed_official 1:72c60abef7e7 98 }
mbed_official 1:72c60abef7e7 99
qaz 80:caccea4da07b 100 hrServicePtr->updateHeartRate(hrmCounter);
qaz 80:caccea4da07b 101 }
mbed_official 1:72c60abef7e7 102
qaz 82:f01379c0f435 103 void periodicCallback(void) {
qaz 82:f01379c0f435 104 if ((ble_call) || (blecallcontinuously)) {
qaz 83:b67e4bb6a087 105 led1 = /* !led1 */ LED_OFF; /* Do blinky on LED1 while we're waiting for BLE events. It's set to LED_OFF at the moment (24/10/19) because the BLE blinking can get in the way of the lights for writing data, no SD card inserted and calibration and BLE is not yet doing anything useful */
mbed_official 1:72c60abef7e7 106
qaz 82:f01379c0f435 107 if (BLE::Instance().getGapState().connected) {
qaz 82:f01379c0f435 108 eventQueue.call(updateSensorValue);
qaz 82:f01379c0f435 109 }
qaz 82:f01379c0f435 110 } else {
qaz 82:f01379c0f435 111 led1 = LED_OFF; // Don't leave the lights on
qaz 80:caccea4da07b 112 }
qaz 80:caccea4da07b 113 }
mbed_official 1:72c60abef7e7 114
qaz 80:caccea4da07b 115 void onBleInitError(BLE &ble, ble_error_t error)
qaz 80:caccea4da07b 116 {
qaz 80:caccea4da07b 117 (void)ble;
qaz 80:caccea4da07b 118 (void)error;
qaz 80:caccea4da07b 119 /* Initialization error handling should go here */
qaz 80:caccea4da07b 120 }
mbed_official 1:72c60abef7e7 121
qaz 80:caccea4da07b 122 void printMacAddress()
qaz 80:caccea4da07b 123 {
qaz 80:caccea4da07b 124 /* Print out device MAC address to the console*/
qaz 80:caccea4da07b 125 Gap::AddressType_t addr_type;
qaz 80:caccea4da07b 126 Gap::Address_t address;
qaz 80:caccea4da07b 127 BLE::Instance().gap().getAddress(&addr_type, address);
qaz 80:caccea4da07b 128 printf("DEVICE MAC ADDRESS: ");
qaz 80:caccea4da07b 129 for (int i = 5; i >= 1; i--){
qaz 80:caccea4da07b 130 printf("%02x:", address[i]);
qaz 80:caccea4da07b 131 }
qaz 80:caccea4da07b 132 printf("%02x\r\n", address[0]);
qaz 80:caccea4da07b 133 }
mbed_official 43:fb2855f7754b 134
qaz 80:caccea4da07b 135 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
qaz 80:caccea4da07b 136 {
qaz 80:caccea4da07b 137 BLE& ble = params->ble;
qaz 80:caccea4da07b 138 ble_error_t error = params->error;
mbed_official 1:72c60abef7e7 139
qaz 80:caccea4da07b 140 if (error != BLE_ERROR_NONE) {
qaz 80:caccea4da07b 141 onBleInitError(ble, error);
qaz 80:caccea4da07b 142 return;
mbed_official 1:72c60abef7e7 143 }
mbed_official 1:72c60abef7e7 144
qaz 80:caccea4da07b 145 if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
qaz 80:caccea4da07b 146 return;
mbed_official 1:72c60abef7e7 147 }
mbed_official 1:72c60abef7e7 148
qaz 80:caccea4da07b 149 ble.gap().onDisconnection(disconnectionCallback);
mbed_official 1:72c60abef7e7 150
qaz 80:caccea4da07b 151 /* Setup primary service. */
qaz 80:caccea4da07b 152 hrServicePtr = new HeartRateService(ble, hrmCounter, HeartRateService::LOCATION_FINGER);
mbed_official 1:72c60abef7e7 153
qaz 81:b8ef2a762318 154 /* Setting up GAP mostly has to do with configuring connectability and the payload contained in the advertisement packets.*/
qaz 80:caccea4da07b 155 /* Setup advertising. */
qaz 80:caccea4da07b 156 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
qaz 80:caccea4da07b 157 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
qaz 80:caccea4da07b 158 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);
qaz 80:caccea4da07b 159 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
qaz 80:caccea4da07b 160 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
qaz 80:caccea4da07b 161 ble.gap().setAdvertisingInterval(1000); /* 1000ms */
qaz 80:caccea4da07b 162 ble.gap().startAdvertising();
qaz 81:b8ef2a762318 163 /* The first line (above) is mandatory for Bluetooth Smart, and says that this device only supports Bluetooth low energy. The 'general discoverable'
qaz 81:b8ef2a762318 164 is the typical value to set when you want your device to be seen by other devices in order to connect. Next comes the ID for the heart rate sensor
qaz 81:b8ef2a762318 165 service and the name of the device. After the payload is set the code sets the advertising type and the advertising interval. In Bluetooth Smart,
qaz 81:b8ef2a762318 166 timing values are typically multiples of 625 us. */
qaz 80:caccea4da07b 167 printMacAddress();
qaz 80:caccea4da07b 168 }
mbed_official 1:72c60abef7e7 169
qaz 80:caccea4da07b 170 void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
qaz 80:caccea4da07b 171 BLE &ble = BLE::Instance();
qaz 80:caccea4da07b 172 eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
mbed_official 1:72c60abef7e7 173 }
mbed_official 1:72c60abef7e7 174
qaz 82:f01379c0f435 175 void bleheartrate() {
qaz 80:caccea4da07b 176 eventQueue.call_every(500, periodicCallback);
qaz 80:caccea4da07b 177 BLE &ble = BLE::Instance();
qaz 80:caccea4da07b 178 ble.onEventsToProcess(scheduleBleEventsProcessing);
qaz 80:caccea4da07b 179 ble.init(bleInitComplete);
qaz 82:f01379c0f435 180 eventQueue.dispatch_forever(); // https://os.mbed.com/docs/mbed-os/v5.14/tutorials/the-eventqueue-api.html
qaz 82:f01379c0f435 181 // have to do break_dispatch somewhere to stop it. Maybe inside the loop not to have BLE on all the time
qaz 82:f01379c0f435 182 }
qaz 80:caccea4da07b 183
qaz 82:f01379c0f435 184 int main() {
qaz 82:f01379c0f435 185 pegasus.init(MAX32630FTHR::VIO_3V3);
qaz 82:f01379c0f435 186 ble_thread.start(bleheartrate); // Tried to start and stop this in each iteration with break_dispatch. Now using a semaphore
qaz 82:f01379c0f435 187 ble_call = false;
qaz 82:f01379c0f435 188
qaz 82:f01379c0f435 189 // set PWRSEQ_REG0.pwr_rtcen_run to 1, PWRSEQ_REG0.pwr_rtcen_slip to 1
qaz 82:f01379c0f435 190 // 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
qaz 82:f01379c0f435 191 if (debugging) pc.printf("Starting Main Program Thread ...\n");
qaz 82:f01379c0f435 192 //bLED=LED_ON; // Just to verify program has loaded
qaz 82:f01379c0f435 193 //wait(0.5);
qaz 82:f01379c0f435 194 //bLED=LED_OFF;
qaz 82:f01379c0f435 195 gLED = LED_ON;
qaz 82:f01379c0f435 196 rLED = LED_ON;
qaz 82:f01379c0f435 197 i2cBus.frequency(400000);
qaz 82:f01379c0f435 198 scale.tare();
qaz 82:f01379c0f435 199 scale.setScale(calibration_factor); //Adjust to default calibration factor
qaz 82:f01379c0f435 200
qaz 82:f01379c0f435 201 uint32_t failures = 0;
qaz 82:f01379c0f435 202
qaz 82:f01379c0f435 203 if(imu.setSensorPowerMode(BMI160::GYRO, BMI160::NORMAL) != BMI160::RTN_NO_ERROR) {
qaz 82:f01379c0f435 204 //printf("Failed to set gyroscope power mode\n");
qaz 82:f01379c0f435 205 failures++;
qaz 82:f01379c0f435 206 }
qaz 82:f01379c0f435 207 wait_ms(100);
qaz 82:f01379c0f435 208
qaz 82:f01379c0f435 209 if(imu.setSensorPowerMode(BMI160::ACC, BMI160::NORMAL) != BMI160::RTN_NO_ERROR) {
qaz 82:f01379c0f435 210 //printf("Failed to set accelerometer power mode\n");
qaz 82:f01379c0f435 211 failures++;
qaz 82:f01379c0f435 212 }
qaz 82:f01379c0f435 213 wait_ms(100);
qaz 82:f01379c0f435 214
qaz 82:f01379c0f435 215 //example of using getSensorConfig
qaz 82:f01379c0f435 216 if(imu.getSensorConfig(accConfig) == BMI160::RTN_NO_ERROR) {
qaz 82:f01379c0f435 217 //printf("ACC Range = %d\n", accConfig.range);
qaz 82:f01379c0f435 218 //printf("ACC UnderSampling = %d\n", accConfig.us);
qaz 82:f01379c0f435 219 //printf("ACC BandWidthParam = %d\n", accConfig.bwp);
qaz 82:f01379c0f435 220 //printf("ACC OutputDataRate = %d\n\n", accConfig.odr);
qaz 82:f01379c0f435 221 } else {
qaz 82:f01379c0f435 222 //printf("Failed to get accelerometer configuration\n");
qaz 82:f01379c0f435 223 failures++;
qaz 82:f01379c0f435 224 }
qaz 82:f01379c0f435 225
qaz 82:f01379c0f435 226 //example of setting user defined configuration
qaz 82:f01379c0f435 227 accConfig.range = BMI160::SENS_4G;
qaz 82:f01379c0f435 228 accConfig.us = BMI160::ACC_US_OFF;
qaz 82:f01379c0f435 229 accConfig.bwp = BMI160::ACC_BWP_2;
qaz 82:f01379c0f435 230 accConfig.odr = BMI160::ACC_ODR_8;
qaz 82:f01379c0f435 231 if(imu.setSensorConfig(accConfig) == BMI160::RTN_NO_ERROR) {
qaz 82:f01379c0f435 232 //printf("ACC Range = %d\n", accConfig.range);
qaz 82:f01379c0f435 233 //printf("ACC UnderSampling = %d\n", accConfig.us);
qaz 82:f01379c0f435 234 //printf("ACC BandWidthParam = %d\n", accConfig.bwp);
qaz 82:f01379c0f435 235 //printf("ACC OutputDataRate = %d\n\n", accConfig.odr);
qaz 82:f01379c0f435 236 } else {
qaz 82:f01379c0f435 237 //printf("Failed to set accelerometer configuration\n");
qaz 82:f01379c0f435 238 failures++;
qaz 82:f01379c0f435 239 }
qaz 82:f01379c0f435 240
qaz 82:f01379c0f435 241 if(imu.getSensorConfig(gyroConfig) == BMI160::RTN_NO_ERROR) {
qaz 82:f01379c0f435 242 //printf("GYRO Range = %d\n", gyroConfig.range);
qaz 82:f01379c0f435 243 //printf("GYRO BandWidthParam = %d\n", gyroConfig.bwp);
qaz 82:f01379c0f435 244 //printf("GYRO OutputDataRate = %d\n\n", gyroConfig.odr);
qaz 82:f01379c0f435 245 } else {
qaz 82:f01379c0f435 246 //printf("Failed to get gyroscope configuration\n");
qaz 82:f01379c0f435 247 failures++;
qaz 82:f01379c0f435 248 }
qaz 82:f01379c0f435 249
qaz 82:f01379c0f435 250 wait(1.0);
qaz 82:f01379c0f435 251 //printf("\033[H"); //home
qaz 82:f01379c0f435 252 //printf("\033[0J"); //erase from cursor to end of screen
qaz 82:f01379c0f435 253
qaz 82:f01379c0f435 254 /*if(failures == 0)
qaz 82:f01379c0f435 255 // FORMAT_CODE_END
qaz 82:f01379c0f435 256 //{
qaz 82:f01379c0f435 257
qaz 82:f01379c0f435 258 BMI160::SensorData accData;
qaz 82:f01379c0f435 259 BMI160::SensorData gyroData;
qaz 82:f01379c0f435 260 BMI160::SensorTime sensorTime;
qaz 82:f01379c0f435 261
qaz 82:f01379c0f435 262 // }*/
qaz 82:f01379c0f435 263
qaz 82:f01379c0f435 264 rLED = LED_OFF;
qaz 82:f01379c0f435 265 gLED = LED_OFF;
qaz 82:f01379c0f435 266
qaz 82:f01379c0f435 267 button.rise(&button_callback); // attach the address of the flip function to the rising edge
qaz 82:f01379c0f435 268
qaz 82:f01379c0f435 269 button_pressed=0;
qaz 82:f01379c0f435 270
qaz 82:f01379c0f435 271 while (true) {
qaz 82:f01379c0f435 272
qaz 83:b67e4bb6a087 273 if(button_pressed>=1) { // double-pressed if for calibration (ideally). Set to triple-pressed to reduce sensitivity (see below).
qaz 82:f01379c0f435 274 tick.attach_us(&tick_timer, 1000);
qaz 82:f01379c0f435 275 gLED = LED_ON;
qaz 82:f01379c0f435 276 rLED = LED_OFF;
qaz 82:f01379c0f435 277 //float raw = scaleRaw.read();
qaz 82:f01379c0f435 278 // maybe calibrate against weighing scales reading here
qaz 82:f01379c0f435 279 float timer=0;
qaz 82:f01379c0f435 280 time_t seconds = time(NULL);
mbed_official 1:72c60abef7e7 281
qaz 82:f01379c0f435 282 char filename[40];
qaz 82:f01379c0f435 283 if (debugging) pc.printf("%s\n", filename);
qaz 82:f01379c0f435 284 rLED = LED_ON;
qaz 82:f01379c0f435 285 if (fs.mount(&bd) == 0) { // SDBlock stuff. changed from "if (sd.mount() == 0)"
qaz 82:f01379c0f435 286 if (debugging) pc.printf("Mounted SD card\n");
qaz 82:f01379c0f435 287 FILE *ft = fopen("/fs/time.txt", "r"); // changed from "/sd/"...
qaz 82:f01379c0f435 288 if(ft != NULL) {
qaz 82:f01379c0f435 289 fscanf(ft, "%d", &epoch_time);
qaz 82:f01379c0f435 290 fclose(ft);
qaz 82:f01379c0f435 291 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
qaz 82:f01379c0f435 292 seconds = time(NULL); // no idea why it seemed necessary to subtract 2^20 from the time to get the time stamping to work properly
qaz 82:f01379c0f435 293 } else if (debugging) pc.printf("Failed to open time.txt!");
qaz 82:f01379c0f435 294 strftime(filename, 40, "/fs/%a_%d_%m_%Y_%H_%M_%S.csv", localtime(&seconds)); // changed from "/sd/"...
qaz 82:f01379c0f435 295 FILE *fc = fopen("/fs/calibration.txt", "r"); // changed from "/sd/"...
qaz 82:f01379c0f435 296 if(fc != NULL) {
qaz 82:f01379c0f435 297
qaz 82:f01379c0f435 298 while (fscanf(fc, "%d", &calibration_factor) != EOF) {
qaz 82:f01379c0f435 299 //i++;
qaz 82:f01379c0f435 300 }
qaz 82:f01379c0f435 301 scale.setScale(calibration_factor); //Adjust to this calibration factor
qaz 82:f01379c0f435 302 fclose(fc);
qaz 82:f01379c0f435 303 }
qaz 82:f01379c0f435 304
qaz 82:f01379c0f435 305 if (debugging) pc.printf("-!-");
qaz 82:f01379c0f435 306 FILE *fp = fopen(filename, "w");
qaz 82:f01379c0f435 307 if(fp != NULL) {
qaz 82:f01379c0f435 308 if (debugging) pc.printf("-+-");
qaz 82:f01379c0f435 309 ble_call = true; // Turn on calling. This is read in periodicCallback(void)
qaz 82:f01379c0f435 310 sprintf(topline, "Time,Weight,ACC xAxis,ACC yAxis,ACC zAxis,GYRO xAxis,GYRO yAxis,GYRO zAxis,Calibration factor=%d\n", calibration_factor);
qaz 82:f01379c0f435 311 fprintf(fp, topline);
qaz 82:f01379c0f435 312 rLED = LED_OFF;
qaz 82:f01379c0f435 313 imu.getSensorTime(startTime);
qaz 82:f01379c0f435 314 char my_string[256];
qaz 82:f01379c0f435 315
qaz 82:f01379c0f435 316 while(timer<=20) {
qaz 82:f01379c0f435 317 imu.getGyroAccXYZandSensorTime(accData, gyroData, sensorTime, accConfig.range, gyroConfig.range);
qaz 82:f01379c0f435 318
qaz 82:f01379c0f435 319 weight = scale.getGram();
qaz 82:f01379c0f435 320 waittimeexpired = false;
qaz 82:f01379c0f435 321 if (debugging) pc.printf("Going to wait");
qaz 82:f01379c0f435 322 while (waittimeexpired&waittimeexpired==false); // Loop until another ticker sets the variable
qaz 82:f01379c0f435 323 if (debugging) pc.printf("Finished waiting");
qaz 82:f01379c0f435 324 sprintf(my_string, "%.3f,%.3f,%4.3f,%4.3f,%4.3f,%5.1f,%5.1f,%5.1f,\n"
qaz 82:f01379c0f435 325 , sensorTime.seconds-startTime.seconds
qaz 82:f01379c0f435 326 , weight
qaz 82:f01379c0f435 327 , accData.xAxis.scaled
qaz 82:f01379c0f435 328 , accData.yAxis.scaled
qaz 82:f01379c0f435 329 , accData.zAxis.scaled
qaz 82:f01379c0f435 330 , gyroData.xAxis.scaled
qaz 82:f01379c0f435 331 , gyroData.yAxis.scaled
qaz 82:f01379c0f435 332 , gyroData.zAxis.scaled);
qaz 82:f01379c0f435 333
qaz 82:f01379c0f435 334 //printf(my_string);
qaz 82:f01379c0f435 335 fprintf(fp, my_string);
qaz 82:f01379c0f435 336 timer=sensorTime.seconds-startTime.seconds;
qaz 82:f01379c0f435 337 //wait(0.01f);
qaz 82:f01379c0f435 338
qaz 82:f01379c0f435 339 } // while (timer<=20)
qaz 82:f01379c0f435 340 fclose(fp);
qaz 82:f01379c0f435 341 seconds = time(NULL);
qaz 82:f01379c0f435 342 //pc.printf("seconds %d\n", seconds);
qaz 82:f01379c0f435 343 FILE *fs = fopen("/fs/time.txt", "w"); // changed from "/sd/"...
qaz 82:f01379c0f435 344 char time_buf[11];
qaz 82:f01379c0f435 345 sprintf(time_buf, "%u", seconds);
qaz 82:f01379c0f435 346 //pc.printf("time_buf: %s\n", time_buf);
qaz 82:f01379c0f435 347 fprintf(fs, "%s", time_buf);
qaz 82:f01379c0f435 348 fclose(fs);
qaz 82:f01379c0f435 349
qaz 82:f01379c0f435 350 } else {
qaz 82:f01379c0f435 351 if (debugging) pc.printf("Failed to open csv file!");
qaz 82:f01379c0f435 352 gLED = LED_OFF;
qaz 82:f01379c0f435 353 wait(2);
qaz 82:f01379c0f435 354 rLED=LED_OFF;
qaz 82:f01379c0f435 355 }
qaz 82:f01379c0f435 356 fs.unmount(); // changed from sd.unmount()
qaz 82:f01379c0f435 357 } else { // If sd has not mounted
qaz 82:f01379c0f435 358 gLED = LED_OFF;
qaz 82:f01379c0f435 359 rLED = LED_OFF;
qaz 82:f01379c0f435 360 wait(1.0); // make plenty of time for second press
qaz 83:b67e4bb6a087 361 if (button_pressed > 2) { // If double[triple for desensitivity]-click (or more)
qaz 82:f01379c0f435 362 // blink blue once and send out a reading on the com port
qaz 82:f01379c0f435 363 bLED = LED_ON;
qaz 82:f01379c0f435 364 wait(1.0);
qaz 82:f01379c0f435 365 bLED = LED_OFF;
qaz 82:f01379c0f435 366 wait(1.0);
qaz 82:f01379c0f435 367 pc.printf("%f %d", scale.getGram(), calibration_factor);
qaz 82:f01379c0f435 368 button_pressed = 0;
qaz 82:f01379c0f435 369 } else { // indicate that there is no sd card
qaz 82:f01379c0f435 370 for (int isd = 0; isd < seconds_to_blink_if_sd_mount_fails; isd++) {
qaz 82:f01379c0f435 371 rLED = LED_ON;
qaz 82:f01379c0f435 372 wait(0.5);
qaz 82:f01379c0f435 373 rLED = LED_OFF;
qaz 82:f01379c0f435 374 wait(0.5);
qaz 82:f01379c0f435 375 }
qaz 82:f01379c0f435 376 }
qaz 82:f01379c0f435 377 rLED = LED_OFF;
qaz 82:f01379c0f435 378
qaz 82:f01379c0f435 379 }// if sd.mount == 0 ... else
qaz 82:f01379c0f435 380 gLED = LED_OFF;
qaz 82:f01379c0f435 381 button_pressed = 0;
qaz 82:f01379c0f435 382 tick.detach();
qaz 82:f01379c0f435 383 // eventQueue.break_dispatch(); // basic attempt to stop of BLE. Result was flaky.
qaz 82:f01379c0f435 384 // ble_thread.terminate();
qaz 82:f01379c0f435 385 ble_call = false; // This is read in periodicCallback(void)
qaz 82:f01379c0f435 386 } // if (button_pressed==1)
qaz 82:f01379c0f435 387 // 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."
qaz 82:f01379c0f435 388 } // while (1)
mbed_official 1:72c60abef7e7 389 }
qaz 81:b8ef2a762318 390
qaz 81:b8ef2a762318 391 //*****************************************************************************
qaz 81:b8ef2a762318 392 void dumpImuRegisters(BMI160 &imu) {
qaz 81:b8ef2a762318 393 printRegister(imu, BMI160::CHIP_ID);
qaz 81:b8ef2a762318 394 printBlock(imu, BMI160::ERR_REG,BMI160::FIFO_DATA);
qaz 81:b8ef2a762318 395 printBlock(imu, BMI160::ACC_CONF, BMI160::FIFO_CONFIG_1);
qaz 81:b8ef2a762318 396 printBlock(imu, BMI160::MAG_IF_0, BMI160::SELF_TEST);
qaz 81:b8ef2a762318 397 printBlock(imu, BMI160::NV_CONF, BMI160::STEP_CONF_1);
qaz 81:b8ef2a762318 398 printRegister(imu, BMI160::CMD);
qaz 81:b8ef2a762318 399 //printf("\n");
qaz 81:b8ef2a762318 400 }
qaz 81:b8ef2a762318 401
qaz 81:b8ef2a762318 402 //*****************************************************************************
qaz 81:b8ef2a762318 403 void printRegister(BMI160 &imu, BMI160::Registers reg) {
qaz 81:b8ef2a762318 404 uint8_t data;
qaz 81:b8ef2a762318 405 if(imu.readRegister(reg, &data) == BMI160::RTN_NO_ERROR) {
qaz 81:b8ef2a762318 406 //printf("IMU Register 0x%02x = 0x%02x\n", reg, data);
qaz 81:b8ef2a762318 407 } else {
qaz 81:b8ef2a762318 408 //printf("Failed to read register\n");
qaz 81:b8ef2a762318 409 }
qaz 81:b8ef2a762318 410 }
qaz 81:b8ef2a762318 411
qaz 81:b8ef2a762318 412
qaz 81:b8ef2a762318 413 //*****************************************************************************
qaz 81:b8ef2a762318 414 void printBlock(BMI160 &imu, BMI160::Registers startReg, BMI160::Registers stopReg) {
qaz 81:b8ef2a762318 415 uint8_t numBytes = ((stopReg - startReg) + 1);
qaz 81:b8ef2a762318 416 uint8_t buff[numBytes];
qaz 81:b8ef2a762318 417 uint8_t offset = static_cast<uint8_t>(startReg);
qaz 81:b8ef2a762318 418
qaz 81:b8ef2a762318 419 if(imu.readBlock(startReg, stopReg, buff) == BMI160::RTN_NO_ERROR) {
qaz 81:b8ef2a762318 420 for(uint8_t idx = offset; idx < (numBytes + offset); idx++) {
qaz 81:b8ef2a762318 421 //printf("IMU Register 0x%02x = 0x%02x\n", idx, buff[idx - offset]);
qaz 81:b8ef2a762318 422 }
qaz 81:b8ef2a762318 423 } else {
qaz 81:b8ef2a762318 424 //printf("Failed to read block\n");
qaz 81:b8ef2a762318 425 }
qaz 81:b8ef2a762318 426 }
qaz 81:b8ef2a762318 427 void button_callback() {
qaz 81:b8ef2a762318 428
qaz 81:b8ef2a762318 429 button_pressed++; // changed to allow detection of double presses
qaz 81:b8ef2a762318 430
qaz 81:b8ef2a762318 431 }