Broadcasts raw accelerometer values

Dependencies:   BLE_API MMA8452_tag_private mbed nRF51822

Fork of tag_final by Luis Bañuelos Chacon

main.cpp

Committer:
luisbc92
Date:
2016-06-14
Revision:
2:eb47002f16b5
Parent:
1:1c14c1d3ce09

File content as of revision 2:eb47002f16b5:

#include "mbed.h"
#include "BLEDevice.h"
#include "MMA8452.h"

// Configuration
#define BLE_ADV_INTERVAL    1000        // Interval between each advertising packet (in MS)
#define ACC_RATE            8          // Accelerometer sampling rate (in Hz)
#define ACC_BUFFER_SIZE     8          // Accelerometer history size (DON'T CHANGE)

// Objects
BLEDevice   ble;                        // BLE
DigitalOut  led(P0_2);                  // LED (Active Low)
InterruptIn btn(P0_3);                  // Button Interrupt (Active Low)
MMA8452     acc(P0_22, P0_20, 100000);  // Accelerometer
Ticker      acc_tick;                   // Ticker for the accelerometer
Ticker      led_tick;                   // Ticker for led
Ticker      alg_tick;                   // Ticker for algorithm

// Data
struct acc_ring {
    double data[3][ACC_BUFFER_SIZE];
    int8_t data_int[3][ACC_BUFFER_SIZE];
    int head;
} acc_ring;

// Prototypes
void onError();
void onAccTick();
void onButton();
void onLedTick();
void ledBlink(int, float);
void ledStop();
double getAccLast(int);
double getAccMean(int);
void setPayload(uint8_t*, uint8_t);

// Events
void onError() {
    led = 1;
    wait(0.25);
    led = 0;
    wait(0.25);
}

void onAccTick() {
    // Read accelerometer
    acc.readXGravity(&acc_ring.data[0][acc_ring.head]);
    acc.readYGravity(&acc_ring.data[1][acc_ring.head]);
    acc.readZGravity(&acc_ring.data[2][acc_ring.head]);
    
    // Convert to integer
    acc_ring.data_int[0][acc_ring.head] = (int8_t)(acc_ring.data[0][acc_ring.head] * 100);
    acc_ring.data_int[1][acc_ring.head] = (int8_t)(acc_ring.data[1][acc_ring.head] * 100);
    acc_ring.data_int[2][acc_ring.head] = (int8_t)(acc_ring.data[2][acc_ring.head] * 100);
    
    // Increment head
    acc_ring.head++;
    if (acc_ring.head >= ACC_BUFFER_SIZE) {
        acc_ring.head = 0;
        setPayload((uint8_t*)acc_ring.data_int, sizeof(acc_ring.data_int));
    }
}

void onButton() {
    ledBlink(3, 1);
}

int led_blink;
void onLedTick() {
    led = !led;         // Invert LED state
    
    if (led == 1)       // If led was turned off
        led_blink--;    // Decrement blink counter
        
    if (led_blink == 0)
        led_tick.detach();
}

// Functions
void setPayload(uint8_t * data, uint8_t size) {
    ble.clearScanResponse();
    ble.accumulateScanResponse(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, data, size);
    ble.setAdvertisingPayload();
}

void ledBlink(int num, float period) {
    led = 0;
    led_blink = num;
    led_tick.attach(&onLedTick, period/2);
}

void ledStop() {
    led_blink = 0;
    led_tick.detach();
}

double getAccMean(int axis) {
    double mean = 0;
    for (int i = 0; i < ACC_BUFFER_SIZE; i++) {
        mean += acc_ring.data[axis][i];
    }
    return (mean / (float)ACC_BUFFER_SIZE);
}


int main(void) {
    // Initialize LED and Button
    led = 1;
    btn.mode(PullUp);
    btn.fall(&onButton);
    
    // Initialize BLE
    uint8_t tagAddress[6];
    uint8_t tagName[8];
    ble.init();                                             // Initialize BLE stack
    ble.setTxPower(4);                                      // Set power level (in dB)
    ble.setAddress(Gap::ADDR_TYPE_RANDOM_STATIC, NULL);     // Static random address
    ble.getAddress(NULL, tagAddress);                       // Get random address from stack
    sprintf((char*)tagName, "TAG_%2X%2X", tagAddress[1], tagAddress[0]);
    ble.accumulateAdvertisingPayload(                       // Advertise as BLE
        GapAdvertisingData::BREDR_NOT_SUPPORTED |
        GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
    ble.accumulateAdvertisingPayload(                       // Set name
        GapAdvertisingData::COMPLETE_LOCAL_NAME,
        tagName,
        sizeof(tagName));
    ble.setAdvertisingInterval((uint16_t)((float)BLE_ADV_INTERVAL / 0.625));    // Advertising interval
    ble.startAdvertising();                                 // Start advertising
    
    // Initialize accelerometer
    char acc_id;
    acc.getDeviceID(&acc_id);                               // Check if accelerometer succesfully comunicates
    if (acc_id != 0x2A) onError();
    acc.standby();                                          // Put into standby mode before configuration
    acc.setDataRate(acc.RATE_12_5);                         // Set hardware data rate to 12.5Hz
    acc.setDynamicRange(acc.DYNAMIC_RANGE_2G);              // Set dynamic range up to 2G
    acc.setBitDepth(acc.BIT_DEPTH_12);                      // Set bit depth to 12bits for resolution
    acc.activate();                                         // Activate accelerometer
    acc_tick.attach(&onAccTick, (1.0 / (float)ACC_RATE));   // Setup periodic reads
    
    while (1) {
        ble.waitForEvent();
    }
}