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
source/main.cpp@81:b8ef2a762318, 2019-10-24 (annotated)
- Committer:
- qaz
- Date:
- Thu Oct 24 12:58:23 2019 +0000
- Revision:
- 81:b8ef2a762318
- Parent:
- 80:caccea4da07b
- Child:
- 82:f01379c0f435
This version compiles with all of what's in crutch_project_final, outside of main(), copied into the code from BLE_Heartrate. BLE_Heartrate itself had to be reverted to the 14 Dec 2018 version, to get BLE working on the MAX32630.
Who changed what in which revision?
User | Revision | Line number | New 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 | 80:caccea4da07b | 19 | DigitalOut led1(LED1, 1); |
mbed_official | 1:72c60abef7e7 | 20 | |
qaz | 80:caccea4da07b | 21 | const static char DEVICE_NAME[] = "HRM"; |
qaz | 80:caccea4da07b | 22 | static const uint16_t uuid16_list[] = {GattService::UUID_HEART_RATE_SERVICE}; |
qaz | 80:caccea4da07b | 23 | |
qaz | 80:caccea4da07b | 24 | static uint8_t hrmCounter = 100; // init HRM to 100bps |
qaz | 80:caccea4da07b | 25 | static HeartRateService *hrServicePtr; |
qaz | 80:caccea4da07b | 26 | |
qaz | 80:caccea4da07b | 27 | static EventQueue eventQueue(/* event count */ 16 * EVENTS_EVENT_SIZE); |
mbed_official | 1:72c60abef7e7 | 28 | |
qaz | 81:b8ef2a762318 | 29 | /* These are all the initializations from the crutch project - about the next 50 lines */ |
qaz | 81:b8ef2a762318 | 30 | void dumpImuRegisters(BMI160 &imu); |
qaz | 81:b8ef2a762318 | 31 | void printRegister(BMI160 &imu, BMI160::Registers reg); |
qaz | 81:b8ef2a762318 | 32 | void printBlock(BMI160 &imu, BMI160::Registers startReg, BMI160::Registers stopReg); |
qaz | 81:b8ef2a762318 | 33 | MAX32630FTHR pegasus(MAX32630FTHR::VIO_3V3); |
qaz | 81:b8ef2a762318 | 34 | |
qaz | 81:b8ef2a762318 | 35 | InterruptIn button(P2_3); |
qaz | 81:b8ef2a762318 | 36 | DigitalOut rLED(LED1, LED_OFF); |
qaz | 81:b8ef2a762318 | 37 | DigitalOut gLED(LED2, LED_OFF); |
qaz | 81:b8ef2a762318 | 38 | DigitalOut bLED(LED3, LED_OFF); |
qaz | 81:b8ef2a762318 | 39 | void button_callback(void); |
qaz | 81:b8ef2a762318 | 40 | |
qaz | 81:b8ef2a762318 | 41 | I2C i2cBus(P5_7, P6_0); |
qaz | 81:b8ef2a762318 | 42 | |
qaz | 81:b8ef2a762318 | 43 | BMI160_I2C imu(i2cBus, BMI160_I2C::I2C_ADRS_SDO_LO); |
qaz | 81:b8ef2a762318 | 44 | BMI160::SensorData accData; |
qaz | 81:b8ef2a762318 | 45 | BMI160::SensorData gyroData; |
qaz | 81:b8ef2a762318 | 46 | BMI160::SensorTime sensorTime; |
qaz | 81:b8ef2a762318 | 47 | BMI160::SensorTime startTime; |
qaz | 81:b8ef2a762318 | 48 | float imuTemperature; |
qaz | 81:b8ef2a762318 | 49 | |
qaz | 81:b8ef2a762318 | 50 | BMI160::AccConfig accConfig; |
qaz | 81:b8ef2a762318 | 51 | BMI160::GyroConfig gyroConfig; |
qaz | 81:b8ef2a762318 | 52 | |
qaz | 81:b8ef2a762318 | 53 | //SDFileSystem sd(P0_5, P0_6, P0_4, P0_7, "sd"); // mosi, miso, sclk, cs |
qaz | 81:b8ef2a762318 | 54 | // 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 | 55 | // Trying this as a replacement: |
qaz | 81:b8ef2a762318 | 56 | // Physical block device, can be any device that supports the BlockDevice API |
qaz | 81:b8ef2a762318 | 57 | // HeapBlockDevice bd(512*BLOCK_SIZE, BLOCK_SIZE); |
qaz | 81:b8ef2a762318 | 58 | 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 | 59 | FATFileSystem fs("fs"); // File system declaration |
qaz | 81:b8ef2a762318 | 60 | USBMSD_BD msd(&bd); // USB MSD |
qaz | 81:b8ef2a762318 | 61 | |
qaz | 81:b8ef2a762318 | 62 | DigitalIn sd_detect(P2_2); |
qaz | 81:b8ef2a762318 | 63 | |
qaz | 81:b8ef2a762318 | 64 | Serial pc(USBTX, USBRX); // USB Serial Terminal |
qaz | 81:b8ef2a762318 | 65 | int calibration_factor = 9500; //-7050 worked for my 440lb max scale setup |
qaz | 81:b8ef2a762318 | 66 | int epoch_time = 1570547100; // 1570547100 = 3:05 on 08/10/19. Will be overwritten |
qaz | 81:b8ef2a762318 | 67 | float zero_factor = 2.0781, weight; |
qaz | 81:b8ef2a762318 | 68 | int averageSamples = 100; |
qaz | 81:b8ef2a762318 | 69 | int seconds_to_blink_if_sd_mount_fails = 5; |
qaz | 81:b8ef2a762318 | 70 | char epoch_string[11]; |
qaz | 81:b8ef2a762318 | 71 | char topline[200]; |
qaz | 81:b8ef2a762318 | 72 | HX711 scale(P3_4, P3_5); |
qaz | 81:b8ef2a762318 | 73 | unsigned char button_pressed=0; |
qaz | 81:b8ef2a762318 | 74 | bool waittimeexpired=false, debugging=false; |
qaz | 81:b8ef2a762318 | 75 | Ticker tick; |
qaz | 81:b8ef2a762318 | 76 | |
qaz | 81:b8ef2a762318 | 77 | void tick_timer() { |
qaz | 81:b8ef2a762318 | 78 | waittimeexpired = true; |
qaz | 81:b8ef2a762318 | 79 | //pc.putc('x'); |
qaz | 81:b8ef2a762318 | 80 | } |
qaz | 81:b8ef2a762318 | 81 | /* End of the initializations from the crutch project */ |
qaz | 81:b8ef2a762318 | 82 | |
qaz | 80:caccea4da07b | 83 | void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) |
qaz | 80:caccea4da07b | 84 | { |
qaz | 80:caccea4da07b | 85 | BLE::Instance().gap().startAdvertising(); // restart advertising |
qaz | 80:caccea4da07b | 86 | } |
mbed_official | 1:72c60abef7e7 | 87 | |
qaz | 80:caccea4da07b | 88 | void updateSensorValue() { |
qaz | 80:caccea4da07b | 89 | // Do blocking calls or whatever is necessary for sensor polling. |
qaz | 80:caccea4da07b | 90 | // In our case, we simply update the HRM measurement. |
qaz | 80:caccea4da07b | 91 | hrmCounter++; |
mbed_official | 1:72c60abef7e7 | 92 | |
qaz | 80:caccea4da07b | 93 | // 100 <= HRM bps <=175 |
qaz | 80:caccea4da07b | 94 | if (hrmCounter == 175) { |
qaz | 80:caccea4da07b | 95 | hrmCounter = 100; |
mbed_official | 1:72c60abef7e7 | 96 | } |
mbed_official | 1:72c60abef7e7 | 97 | |
qaz | 80:caccea4da07b | 98 | hrServicePtr->updateHeartRate(hrmCounter); |
qaz | 80:caccea4da07b | 99 | } |
mbed_official | 1:72c60abef7e7 | 100 | |
qaz | 80:caccea4da07b | 101 | void periodicCallback(void) |
qaz | 80:caccea4da07b | 102 | { |
qaz | 80:caccea4da07b | 103 | led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */ |
mbed_official | 1:72c60abef7e7 | 104 | |
qaz | 80:caccea4da07b | 105 | if (BLE::Instance().getGapState().connected) { |
qaz | 80:caccea4da07b | 106 | eventQueue.call(updateSensorValue); |
qaz | 80:caccea4da07b | 107 | } |
qaz | 80:caccea4da07b | 108 | } |
mbed_official | 1:72c60abef7e7 | 109 | |
qaz | 80:caccea4da07b | 110 | void onBleInitError(BLE &ble, ble_error_t error) |
qaz | 80:caccea4da07b | 111 | { |
qaz | 80:caccea4da07b | 112 | (void)ble; |
qaz | 80:caccea4da07b | 113 | (void)error; |
qaz | 80:caccea4da07b | 114 | /* Initialization error handling should go here */ |
qaz | 80:caccea4da07b | 115 | } |
mbed_official | 1:72c60abef7e7 | 116 | |
qaz | 80:caccea4da07b | 117 | void printMacAddress() |
qaz | 80:caccea4da07b | 118 | { |
qaz | 80:caccea4da07b | 119 | /* Print out device MAC address to the console*/ |
qaz | 80:caccea4da07b | 120 | Gap::AddressType_t addr_type; |
qaz | 80:caccea4da07b | 121 | Gap::Address_t address; |
qaz | 80:caccea4da07b | 122 | BLE::Instance().gap().getAddress(&addr_type, address); |
qaz | 80:caccea4da07b | 123 | printf("DEVICE MAC ADDRESS: "); |
qaz | 80:caccea4da07b | 124 | for (int i = 5; i >= 1; i--){ |
qaz | 80:caccea4da07b | 125 | printf("%02x:", address[i]); |
qaz | 80:caccea4da07b | 126 | } |
qaz | 80:caccea4da07b | 127 | printf("%02x\r\n", address[0]); |
qaz | 80:caccea4da07b | 128 | } |
mbed_official | 43:fb2855f7754b | 129 | |
qaz | 80:caccea4da07b | 130 | void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) |
qaz | 80:caccea4da07b | 131 | { |
qaz | 80:caccea4da07b | 132 | BLE& ble = params->ble; |
qaz | 80:caccea4da07b | 133 | ble_error_t error = params->error; |
mbed_official | 1:72c60abef7e7 | 134 | |
qaz | 80:caccea4da07b | 135 | if (error != BLE_ERROR_NONE) { |
qaz | 80:caccea4da07b | 136 | onBleInitError(ble, error); |
qaz | 80:caccea4da07b | 137 | return; |
mbed_official | 1:72c60abef7e7 | 138 | } |
mbed_official | 1:72c60abef7e7 | 139 | |
qaz | 80:caccea4da07b | 140 | if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { |
qaz | 80:caccea4da07b | 141 | return; |
mbed_official | 1:72c60abef7e7 | 142 | } |
mbed_official | 1:72c60abef7e7 | 143 | |
qaz | 80:caccea4da07b | 144 | ble.gap().onDisconnection(disconnectionCallback); |
mbed_official | 1:72c60abef7e7 | 145 | |
qaz | 80:caccea4da07b | 146 | /* Setup primary service. */ |
qaz | 80:caccea4da07b | 147 | hrServicePtr = new HeartRateService(ble, hrmCounter, HeartRateService::LOCATION_FINGER); |
mbed_official | 1:72c60abef7e7 | 148 | |
qaz | 81:b8ef2a762318 | 149 | /* Setting up GAP mostly has to do with configuring connectability and the payload contained in the advertisement packets.*/ |
qaz | 80:caccea4da07b | 150 | /* Setup advertising. */ |
qaz | 80:caccea4da07b | 151 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); |
qaz | 80:caccea4da07b | 152 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); |
qaz | 80:caccea4da07b | 153 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR); |
qaz | 80:caccea4da07b | 154 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); |
qaz | 80:caccea4da07b | 155 | ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
qaz | 80:caccea4da07b | 156 | ble.gap().setAdvertisingInterval(1000); /* 1000ms */ |
qaz | 80:caccea4da07b | 157 | ble.gap().startAdvertising(); |
qaz | 81:b8ef2a762318 | 158 | /* 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 | 159 | 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 | 160 | 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 | 161 | timing values are typically multiples of 625 us. */ |
qaz | 80:caccea4da07b | 162 | printMacAddress(); |
qaz | 80:caccea4da07b | 163 | } |
mbed_official | 1:72c60abef7e7 | 164 | |
qaz | 80:caccea4da07b | 165 | void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) { |
qaz | 80:caccea4da07b | 166 | BLE &ble = BLE::Instance(); |
qaz | 80:caccea4da07b | 167 | eventQueue.call(Callback<void()>(&ble, &BLE::processEvents)); |
mbed_official | 1:72c60abef7e7 | 168 | } |
mbed_official | 1:72c60abef7e7 | 169 | |
mbed_official | 1:72c60abef7e7 | 170 | int main() |
mbed_official | 1:72c60abef7e7 | 171 | { |
qaz | 80:caccea4da07b | 172 | eventQueue.call_every(500, periodicCallback); |
mbed_official | 1:72c60abef7e7 | 173 | |
qaz | 80:caccea4da07b | 174 | BLE &ble = BLE::Instance(); |
qaz | 80:caccea4da07b | 175 | ble.onEventsToProcess(scheduleBleEventsProcessing); |
qaz | 80:caccea4da07b | 176 | ble.init(bleInitComplete); |
qaz | 80:caccea4da07b | 177 | |
qaz | 80:caccea4da07b | 178 | eventQueue.dispatch_forever(); |
mbed_official | 1:72c60abef7e7 | 179 | |
mbed_official | 1:72c60abef7e7 | 180 | return 0; |
mbed_official | 1:72c60abef7e7 | 181 | } |
qaz | 81:b8ef2a762318 | 182 | |
qaz | 81:b8ef2a762318 | 183 | //***************************************************************************** |
qaz | 81:b8ef2a762318 | 184 | void dumpImuRegisters(BMI160 &imu) { |
qaz | 81:b8ef2a762318 | 185 | printRegister(imu, BMI160::CHIP_ID); |
qaz | 81:b8ef2a762318 | 186 | printBlock(imu, BMI160::ERR_REG,BMI160::FIFO_DATA); |
qaz | 81:b8ef2a762318 | 187 | printBlock(imu, BMI160::ACC_CONF, BMI160::FIFO_CONFIG_1); |
qaz | 81:b8ef2a762318 | 188 | printBlock(imu, BMI160::MAG_IF_0, BMI160::SELF_TEST); |
qaz | 81:b8ef2a762318 | 189 | printBlock(imu, BMI160::NV_CONF, BMI160::STEP_CONF_1); |
qaz | 81:b8ef2a762318 | 190 | printRegister(imu, BMI160::CMD); |
qaz | 81:b8ef2a762318 | 191 | //printf("\n"); |
qaz | 81:b8ef2a762318 | 192 | } |
qaz | 81:b8ef2a762318 | 193 | |
qaz | 81:b8ef2a762318 | 194 | //***************************************************************************** |
qaz | 81:b8ef2a762318 | 195 | void printRegister(BMI160 &imu, BMI160::Registers reg) { |
qaz | 81:b8ef2a762318 | 196 | uint8_t data; |
qaz | 81:b8ef2a762318 | 197 | if(imu.readRegister(reg, &data) == BMI160::RTN_NO_ERROR) { |
qaz | 81:b8ef2a762318 | 198 | //printf("IMU Register 0x%02x = 0x%02x\n", reg, data); |
qaz | 81:b8ef2a762318 | 199 | } else { |
qaz | 81:b8ef2a762318 | 200 | //printf("Failed to read register\n"); |
qaz | 81:b8ef2a762318 | 201 | } |
qaz | 81:b8ef2a762318 | 202 | } |
qaz | 81:b8ef2a762318 | 203 | |
qaz | 81:b8ef2a762318 | 204 | |
qaz | 81:b8ef2a762318 | 205 | //***************************************************************************** |
qaz | 81:b8ef2a762318 | 206 | void printBlock(BMI160 &imu, BMI160::Registers startReg, BMI160::Registers stopReg) { |
qaz | 81:b8ef2a762318 | 207 | uint8_t numBytes = ((stopReg - startReg) + 1); |
qaz | 81:b8ef2a762318 | 208 | uint8_t buff[numBytes]; |
qaz | 81:b8ef2a762318 | 209 | uint8_t offset = static_cast<uint8_t>(startReg); |
qaz | 81:b8ef2a762318 | 210 | |
qaz | 81:b8ef2a762318 | 211 | if(imu.readBlock(startReg, stopReg, buff) == BMI160::RTN_NO_ERROR) { |
qaz | 81:b8ef2a762318 | 212 | for(uint8_t idx = offset; idx < (numBytes + offset); idx++) { |
qaz | 81:b8ef2a762318 | 213 | //printf("IMU Register 0x%02x = 0x%02x\n", idx, buff[idx - offset]); |
qaz | 81:b8ef2a762318 | 214 | } |
qaz | 81:b8ef2a762318 | 215 | } else { |
qaz | 81:b8ef2a762318 | 216 | //printf("Failed to read block\n"); |
qaz | 81:b8ef2a762318 | 217 | } |
qaz | 81:b8ef2a762318 | 218 | } |
qaz | 81:b8ef2a762318 | 219 | void button_callback() { |
qaz | 81:b8ef2a762318 | 220 | |
qaz | 81:b8ef2a762318 | 221 | button_pressed++; // changed to allow detection of double presses |
qaz | 81:b8ef2a762318 | 222 | |
qaz | 81:b8ef2a762318 | 223 | } |