Firmware for BLE Tags
Dependencies: BLE_API MMA8452_tag_private mbed nRF51822
Fork of cow_beacon_adxl345 by
main.cpp
- Committer:
- luisbc92
- Date:
- 2016-02-09
- Revision:
- 1:1c14c1d3ce09
- Parent:
- 0:4c7b37b8faad
- Child:
- 2:eb47002f16b5
File content as of revision 1:1c14c1d3ce09:
#include "mbed.h" #include "BLEDevice.h" #include "MMA8452.h" // Configuration #define BLE_ADV_INTERVAL 500 // Interval between each advertising packet (in MS) #define ACC_RATE 10 // Accelerometer sampling rate (in Hz) #define ACC_BUFFER_SIZE 10 // Accelerometer history size // Algorithm #define ALG_PERIOD 1 // Algorithm period #define ALG_ACC_AXIS 0 // Which accelerometer axis to use #define ALG_UP_THRES 0.3 // Up State Threshold #define ALG_UP_TTCKS 10 // Up State Trigger Time #define ALG_DOWN_THRES 0.3 // Down State Threshold #define ALG_DOWN_TICKS 4 // Down State Trigger Time // 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]; int head; } acc_ring; enum AlgState { UP, DOWN }; // 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() { // Increment head acc_ring.head++; if (acc_ring.head >= ACC_BUFFER_SIZE) acc_ring.head = 0; // 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]); } 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(); } void onAlgTick() { static AlgState state = UP; static AlgState last = DOWN; static int timer; double pos = getAccMean(ALG_ACC_AXIS); switch (state) { case UP: if (pos < ALG_DOWN_THRES) { timer = 0; } else { ledBlink(1, 1); } if (timer > ALG_DOWN_TICKS) { state = DOWN; } break; case DOWN: if (pos > ALG_UP_THRES) { timer = 0; } else { ledBlink(1, 1); } if (timer > 10) { state = UP; } break; } if (state != last) { last = state; setPayload((uint8_t*)&state, 1); ledBlink(2, 0.25); } timer++; } // 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 getAccLast(int axis) { return acc_ring.data[axis][acc_ring.head]; } 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 // Setup algorithm alg_tick.attach(&onAlgTick, ALG_PERIOD); while (1) { ble.waitForEvent(); } }