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

Committer:
qaz
Date:
2019-10-24
Revision:
81:b8ef2a762318
Parent:
80:caccea4da07b
Child:
82:f01379c0f435

File content as of revision 81:b8ef2a762318:

/* BlueCrutch. mbed Microcontroller Library yada */
// Cloned from mbed-os-example-ble-HeartRate (after main.cpp was reverted to 14 Dec 2018), because for example where's ble/BLE.h
// Taking stuff across from Niall's project bit by bit, starting with the includes.
#include <events/mbed_events.h>
#include <mbed.h>
#include "mbed.h"
#include "ble/BLE.h"
#include "ble/Gap.h"
#include "ble/services/HeartRateService.h"
#include "max32630fthr.h"
#include "HX711.h"
#include "bmi160.h"
//#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
// I have another SD card library, under FTHR_USBMSD_BD, which at least compiled - 24/10/19
#include "SDBlockDevice.h"
#include "USBMSD_BD.h"
#include "FATFileSystem.h" // Put in, aping what was in the FTHDR_USBMSD_BD example

DigitalOut led1(LED1, 1);

const static char     DEVICE_NAME[] = "HRM";
static const uint16_t uuid16_list[] = {GattService::UUID_HEART_RATE_SERVICE};

static uint8_t hrmCounter = 100; // init HRM to 100bps
static HeartRateService *hrServicePtr;

static EventQueue eventQueue(/* event count */ 16 * EVENTS_EVENT_SIZE);

/* These are all the initializations from the crutch project  - about the next 50 lines */
void dumpImuRegisters(BMI160 &imu);
void printRegister(BMI160 &imu, BMI160::Registers reg);
void printBlock(BMI160 &imu, BMI160::Registers startReg, BMI160::Registers stopReg);
MAX32630FTHR pegasus(MAX32630FTHR::VIO_3V3);

InterruptIn button(P2_3);
DigitalOut rLED(LED1, LED_OFF);
DigitalOut gLED(LED2, LED_OFF);
DigitalOut bLED(LED3, LED_OFF);
void button_callback(void);

I2C i2cBus(P5_7, P6_0);

BMI160_I2C imu(i2cBus, BMI160_I2C::I2C_ADRS_SDO_LO);
BMI160::SensorData accData;
BMI160::SensorData gyroData;
BMI160::SensorTime sensorTime;
BMI160::SensorTime startTime;
float imuTemperature;

BMI160::AccConfig accConfig;
BMI160::GyroConfig gyroConfig;

//SDFileSystem sd(P0_5, P0_6, P0_4, P0_7, "sd");  // mosi, miso, sclk, cs
// 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
// Trying this as a replacement:
// Physical block device, can be any device that supports the BlockDevice API
// HeapBlockDevice bd(512*BLOCK_SIZE, BLOCK_SIZE);
SDBlockDevice bd(P0_5, P0_6, P0_4, P0_7); // Compiled into the program 24/10/19, so success to that extent at least.
FATFileSystem fs("fs"); // File system declaration 
USBMSD_BD msd(&bd);  // USB MSD

DigitalIn sd_detect(P2_2);

Serial pc(USBTX, USBRX);    // USB Serial Terminal
int calibration_factor = 9500; //-7050 worked for my 440lb max scale setup
int epoch_time = 1570547100; // 1570547100 = 3:05 on 08/10/19. Will be overwritten
float zero_factor = 2.0781, weight;
int averageSamples = 100;
int seconds_to_blink_if_sd_mount_fails = 5;
char epoch_string[11];
char topline[200];
HX711 scale(P3_4, P3_5);
unsigned char button_pressed=0; 
bool waittimeexpired=false, debugging=false;
Ticker tick;

void tick_timer() {
    waittimeexpired = true;
    //pc.putc('x');
}
/* End of the initializations from the crutch project */

void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
{
    BLE::Instance().gap().startAdvertising(); // restart advertising
}

void updateSensorValue() {
    // Do blocking calls or whatever is necessary for sensor polling.
    // In our case, we simply update the HRM measurement.
    hrmCounter++;

    //  100 <= HRM bps <=175
    if (hrmCounter == 175) {
        hrmCounter = 100;
    }

    hrServicePtr->updateHeartRate(hrmCounter);
}

void periodicCallback(void)
{
    led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */

    if (BLE::Instance().getGapState().connected) {
        eventQueue.call(updateSensorValue);
    }
}

void onBleInitError(BLE &ble, ble_error_t error)
{
    (void)ble;
    (void)error;
   /* Initialization error handling should go here */
}

void printMacAddress()
{
    /* Print out device MAC address to the console*/
    Gap::AddressType_t addr_type;
    Gap::Address_t address;
    BLE::Instance().gap().getAddress(&addr_type, address);
    printf("DEVICE MAC ADDRESS: ");
    for (int i = 5; i >= 1; i--){
        printf("%02x:", address[i]);
    }
    printf("%02x\r\n", address[0]);
}

void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
{
    BLE&        ble   = params->ble;
    ble_error_t error = params->error;

    if (error != BLE_ERROR_NONE) {
        onBleInitError(ble, error);
        return;
    }

    if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
        return;
    }

    ble.gap().onDisconnection(disconnectionCallback);

    /* Setup primary service. */
    hrServicePtr = new HeartRateService(ble, hrmCounter, HeartRateService::LOCATION_FINGER);

    /* Setting up GAP mostly has to do with configuring connectability and the payload contained in the advertisement packets.*/
    /* Setup advertising. */
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble.gap().setAdvertisingInterval(1000); /* 1000ms */
    ble.gap().startAdvertising();
    /* The first line (above) is mandatory for Bluetooth Smart, and says that this device only supports Bluetooth low energy. The 'general discoverable'
    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
    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,
    timing values are typically multiples of 625 us. */
    printMacAddress();
}

void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
    BLE &ble = BLE::Instance();
    eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
}

int main()
{
    eventQueue.call_every(500, periodicCallback);

    BLE &ble = BLE::Instance();
    ble.onEventsToProcess(scheduleBleEventsProcessing);
    ble.init(bleInitComplete);

    eventQueue.dispatch_forever();

    return 0;
}

//*****************************************************************************
void dumpImuRegisters(BMI160 &imu) {
    printRegister(imu, BMI160::CHIP_ID);
    printBlock(imu, BMI160::ERR_REG,BMI160::FIFO_DATA);
    printBlock(imu, BMI160::ACC_CONF, BMI160::FIFO_CONFIG_1);
    printBlock(imu, BMI160::MAG_IF_0, BMI160::SELF_TEST);
    printBlock(imu, BMI160::NV_CONF, BMI160::STEP_CONF_1);
    printRegister(imu, BMI160::CMD);
    //printf("\n");
}

//*****************************************************************************
void printRegister(BMI160 &imu, BMI160::Registers reg) {
    uint8_t data;
    if(imu.readRegister(reg, &data) == BMI160::RTN_NO_ERROR) {
        //printf("IMU Register 0x%02x = 0x%02x\n", reg, data);
    } else {
        //printf("Failed to read register\n");
    }
}


//*****************************************************************************
void printBlock(BMI160 &imu, BMI160::Registers startReg, BMI160::Registers stopReg) {
    uint8_t numBytes = ((stopReg - startReg) + 1);
    uint8_t buff[numBytes];
    uint8_t offset = static_cast<uint8_t>(startReg);

    if(imu.readBlock(startReg, stopReg, buff) == BMI160::RTN_NO_ERROR) {
        for(uint8_t idx = offset; idx < (numBytes + offset); idx++) {
            //printf("IMU Register 0x%02x = 0x%02x\n", idx, buff[idx - offset]);
        }
    } else {
        //printf("Failed to read block\n");
    }
}
void button_callback() {

    button_pressed++; // changed to allow detection of double presses

}