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 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?

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 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 }