Firmware for BLE Tags
Dependencies: BLE_API MMA8452_tag_private mbed nRF51822
Fork of cow_beacon_adxl345 by
main.cpp@2:eb47002f16b5, 2016-06-14 (annotated)
- Committer:
- luisbc92
- Date:
- Tue Jun 14 00:42:00 2016 +0000
- Revision:
- 2:eb47002f16b5
- Parent:
- 1:1c14c1d3ce09
Initial;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
luisbc92 | 0:4c7b37b8faad | 1 | #include "mbed.h" |
luisbc92 | 0:4c7b37b8faad | 2 | #include "BLEDevice.h" |
luisbc92 | 1:1c14c1d3ce09 | 3 | #include "MMA8452.h" |
luisbc92 | 1:1c14c1d3ce09 | 4 | |
luisbc92 | 1:1c14c1d3ce09 | 5 | // Configuration |
luisbc92 | 2:eb47002f16b5 | 6 | #define BLE_ADV_INTERVAL 1000 // Interval between each advertising packet (in MS) |
luisbc92 | 2:eb47002f16b5 | 7 | #define ACC_RATE 8 // Accelerometer sampling rate (in Hz) |
luisbc92 | 2:eb47002f16b5 | 8 | #define ACC_BUFFER_SIZE 8 // Accelerometer history size (DON'T CHANGE) |
luisbc92 | 0:4c7b37b8faad | 9 | |
luisbc92 | 1:1c14c1d3ce09 | 10 | // Objects |
luisbc92 | 1:1c14c1d3ce09 | 11 | BLEDevice ble; // BLE |
luisbc92 | 1:1c14c1d3ce09 | 12 | DigitalOut led(P0_2); // LED (Active Low) |
luisbc92 | 1:1c14c1d3ce09 | 13 | InterruptIn btn(P0_3); // Button Interrupt (Active Low) |
luisbc92 | 1:1c14c1d3ce09 | 14 | MMA8452 acc(P0_22, P0_20, 100000); // Accelerometer |
luisbc92 | 1:1c14c1d3ce09 | 15 | Ticker acc_tick; // Ticker for the accelerometer |
luisbc92 | 1:1c14c1d3ce09 | 16 | Ticker led_tick; // Ticker for led |
luisbc92 | 1:1c14c1d3ce09 | 17 | Ticker alg_tick; // Ticker for algorithm |
luisbc92 | 1:1c14c1d3ce09 | 18 | |
luisbc92 | 1:1c14c1d3ce09 | 19 | // Data |
luisbc92 | 1:1c14c1d3ce09 | 20 | struct acc_ring { |
luisbc92 | 1:1c14c1d3ce09 | 21 | double data[3][ACC_BUFFER_SIZE]; |
luisbc92 | 2:eb47002f16b5 | 22 | int8_t data_int[3][ACC_BUFFER_SIZE]; |
luisbc92 | 1:1c14c1d3ce09 | 23 | int head; |
luisbc92 | 1:1c14c1d3ce09 | 24 | } acc_ring; |
luisbc92 | 1:1c14c1d3ce09 | 25 | |
luisbc92 | 1:1c14c1d3ce09 | 26 | // Prototypes |
luisbc92 | 1:1c14c1d3ce09 | 27 | void onError(); |
luisbc92 | 1:1c14c1d3ce09 | 28 | void onAccTick(); |
luisbc92 | 1:1c14c1d3ce09 | 29 | void onButton(); |
luisbc92 | 1:1c14c1d3ce09 | 30 | void onLedTick(); |
luisbc92 | 1:1c14c1d3ce09 | 31 | void ledBlink(int, float); |
luisbc92 | 1:1c14c1d3ce09 | 32 | void ledStop(); |
luisbc92 | 1:1c14c1d3ce09 | 33 | double getAccLast(int); |
luisbc92 | 1:1c14c1d3ce09 | 34 | double getAccMean(int); |
luisbc92 | 1:1c14c1d3ce09 | 35 | void setPayload(uint8_t*, uint8_t); |
luisbc92 | 1:1c14c1d3ce09 | 36 | |
luisbc92 | 1:1c14c1d3ce09 | 37 | // Events |
luisbc92 | 1:1c14c1d3ce09 | 38 | void onError() { |
luisbc92 | 1:1c14c1d3ce09 | 39 | led = 1; |
luisbc92 | 1:1c14c1d3ce09 | 40 | wait(0.25); |
luisbc92 | 1:1c14c1d3ce09 | 41 | led = 0; |
luisbc92 | 1:1c14c1d3ce09 | 42 | wait(0.25); |
luisbc92 | 1:1c14c1d3ce09 | 43 | } |
luisbc92 | 0:4c7b37b8faad | 44 | |
luisbc92 | 1:1c14c1d3ce09 | 45 | void onAccTick() { |
luisbc92 | 1:1c14c1d3ce09 | 46 | // Read accelerometer |
luisbc92 | 1:1c14c1d3ce09 | 47 | acc.readXGravity(&acc_ring.data[0][acc_ring.head]); |
luisbc92 | 1:1c14c1d3ce09 | 48 | acc.readYGravity(&acc_ring.data[1][acc_ring.head]); |
luisbc92 | 1:1c14c1d3ce09 | 49 | acc.readZGravity(&acc_ring.data[2][acc_ring.head]); |
luisbc92 | 2:eb47002f16b5 | 50 | |
luisbc92 | 2:eb47002f16b5 | 51 | // Convert to integer |
luisbc92 | 2:eb47002f16b5 | 52 | acc_ring.data_int[0][acc_ring.head] = (int8_t)(acc_ring.data[0][acc_ring.head] * 100); |
luisbc92 | 2:eb47002f16b5 | 53 | acc_ring.data_int[1][acc_ring.head] = (int8_t)(acc_ring.data[1][acc_ring.head] * 100); |
luisbc92 | 2:eb47002f16b5 | 54 | acc_ring.data_int[2][acc_ring.head] = (int8_t)(acc_ring.data[2][acc_ring.head] * 100); |
luisbc92 | 2:eb47002f16b5 | 55 | |
luisbc92 | 2:eb47002f16b5 | 56 | // Increment head |
luisbc92 | 2:eb47002f16b5 | 57 | acc_ring.head++; |
luisbc92 | 2:eb47002f16b5 | 58 | if (acc_ring.head >= ACC_BUFFER_SIZE) { |
luisbc92 | 2:eb47002f16b5 | 59 | acc_ring.head = 0; |
luisbc92 | 2:eb47002f16b5 | 60 | setPayload((uint8_t*)acc_ring.data_int, sizeof(acc_ring.data_int)); |
luisbc92 | 2:eb47002f16b5 | 61 | } |
luisbc92 | 1:1c14c1d3ce09 | 62 | } |
luisbc92 | 1:1c14c1d3ce09 | 63 | |
luisbc92 | 1:1c14c1d3ce09 | 64 | void onButton() { |
luisbc92 | 1:1c14c1d3ce09 | 65 | ledBlink(3, 1); |
luisbc92 | 1:1c14c1d3ce09 | 66 | } |
luisbc92 | 1:1c14c1d3ce09 | 67 | |
luisbc92 | 1:1c14c1d3ce09 | 68 | int led_blink; |
luisbc92 | 1:1c14c1d3ce09 | 69 | void onLedTick() { |
luisbc92 | 1:1c14c1d3ce09 | 70 | led = !led; // Invert LED state |
luisbc92 | 0:4c7b37b8faad | 71 | |
luisbc92 | 1:1c14c1d3ce09 | 72 | if (led == 1) // If led was turned off |
luisbc92 | 1:1c14c1d3ce09 | 73 | led_blink--; // Decrement blink counter |
luisbc92 | 1:1c14c1d3ce09 | 74 | |
luisbc92 | 1:1c14c1d3ce09 | 75 | if (led_blink == 0) |
luisbc92 | 1:1c14c1d3ce09 | 76 | led_tick.detach(); |
luisbc92 | 1:1c14c1d3ce09 | 77 | } |
luisbc92 | 1:1c14c1d3ce09 | 78 | |
luisbc92 | 1:1c14c1d3ce09 | 79 | // Functions |
luisbc92 | 1:1c14c1d3ce09 | 80 | void setPayload(uint8_t * data, uint8_t size) { |
luisbc92 | 1:1c14c1d3ce09 | 81 | ble.clearScanResponse(); |
luisbc92 | 1:1c14c1d3ce09 | 82 | ble.accumulateScanResponse(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, data, size); |
luisbc92 | 1:1c14c1d3ce09 | 83 | ble.setAdvertisingPayload(); |
luisbc92 | 1:1c14c1d3ce09 | 84 | } |
luisbc92 | 1:1c14c1d3ce09 | 85 | |
luisbc92 | 1:1c14c1d3ce09 | 86 | void ledBlink(int num, float period) { |
luisbc92 | 1:1c14c1d3ce09 | 87 | led = 0; |
luisbc92 | 1:1c14c1d3ce09 | 88 | led_blink = num; |
luisbc92 | 1:1c14c1d3ce09 | 89 | led_tick.attach(&onLedTick, period/2); |
luisbc92 | 1:1c14c1d3ce09 | 90 | } |
luisbc92 | 1:1c14c1d3ce09 | 91 | |
luisbc92 | 1:1c14c1d3ce09 | 92 | void ledStop() { |
luisbc92 | 1:1c14c1d3ce09 | 93 | led_blink = 0; |
luisbc92 | 1:1c14c1d3ce09 | 94 | led_tick.detach(); |
luisbc92 | 1:1c14c1d3ce09 | 95 | } |
luisbc92 | 1:1c14c1d3ce09 | 96 | |
luisbc92 | 1:1c14c1d3ce09 | 97 | double getAccMean(int axis) { |
luisbc92 | 1:1c14c1d3ce09 | 98 | double mean = 0; |
luisbc92 | 1:1c14c1d3ce09 | 99 | for (int i = 0; i < ACC_BUFFER_SIZE; i++) { |
luisbc92 | 1:1c14c1d3ce09 | 100 | mean += acc_ring.data[axis][i]; |
luisbc92 | 1:1c14c1d3ce09 | 101 | } |
luisbc92 | 1:1c14c1d3ce09 | 102 | return (mean / (float)ACC_BUFFER_SIZE); |
luisbc92 | 1:1c14c1d3ce09 | 103 | } |
luisbc92 | 1:1c14c1d3ce09 | 104 | |
luisbc92 | 1:1c14c1d3ce09 | 105 | |
luisbc92 | 0:4c7b37b8faad | 106 | int main(void) { |
luisbc92 | 1:1c14c1d3ce09 | 107 | // Initialize LED and Button |
luisbc92 | 1:1c14c1d3ce09 | 108 | led = 1; |
luisbc92 | 1:1c14c1d3ce09 | 109 | btn.mode(PullUp); |
luisbc92 | 1:1c14c1d3ce09 | 110 | btn.fall(&onButton); |
luisbc92 | 0:4c7b37b8faad | 111 | |
luisbc92 | 0:4c7b37b8faad | 112 | // Initialize BLE |
luisbc92 | 0:4c7b37b8faad | 113 | uint8_t tagAddress[6]; |
luisbc92 | 0:4c7b37b8faad | 114 | uint8_t tagName[8]; |
luisbc92 | 0:4c7b37b8faad | 115 | ble.init(); // Initialize BLE stack |
luisbc92 | 0:4c7b37b8faad | 116 | ble.setTxPower(4); // Set power level (in dB) |
luisbc92 | 0:4c7b37b8faad | 117 | ble.setAddress(Gap::ADDR_TYPE_RANDOM_STATIC, NULL); // Static random address |
luisbc92 | 0:4c7b37b8faad | 118 | ble.getAddress(NULL, tagAddress); // Get random address from stack |
luisbc92 | 0:4c7b37b8faad | 119 | sprintf((char*)tagName, "TAG_%2X%2X", tagAddress[1], tagAddress[0]); |
luisbc92 | 0:4c7b37b8faad | 120 | ble.accumulateAdvertisingPayload( // Advertise as BLE |
luisbc92 | 0:4c7b37b8faad | 121 | GapAdvertisingData::BREDR_NOT_SUPPORTED | |
luisbc92 | 0:4c7b37b8faad | 122 | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); |
luisbc92 | 0:4c7b37b8faad | 123 | ble.accumulateAdvertisingPayload( // Set name |
luisbc92 | 0:4c7b37b8faad | 124 | GapAdvertisingData::COMPLETE_LOCAL_NAME, |
luisbc92 | 0:4c7b37b8faad | 125 | tagName, |
luisbc92 | 0:4c7b37b8faad | 126 | sizeof(tagName)); |
luisbc92 | 1:1c14c1d3ce09 | 127 | ble.setAdvertisingInterval((uint16_t)((float)BLE_ADV_INTERVAL / 0.625)); // Advertising interval |
luisbc92 | 0:4c7b37b8faad | 128 | ble.startAdvertising(); // Start advertising |
luisbc92 | 0:4c7b37b8faad | 129 | |
luisbc92 | 1:1c14c1d3ce09 | 130 | // Initialize accelerometer |
luisbc92 | 1:1c14c1d3ce09 | 131 | char acc_id; |
luisbc92 | 1:1c14c1d3ce09 | 132 | acc.getDeviceID(&acc_id); // Check if accelerometer succesfully comunicates |
luisbc92 | 1:1c14c1d3ce09 | 133 | if (acc_id != 0x2A) onError(); |
luisbc92 | 1:1c14c1d3ce09 | 134 | acc.standby(); // Put into standby mode before configuration |
luisbc92 | 1:1c14c1d3ce09 | 135 | acc.setDataRate(acc.RATE_12_5); // Set hardware data rate to 12.5Hz |
luisbc92 | 1:1c14c1d3ce09 | 136 | acc.setDynamicRange(acc.DYNAMIC_RANGE_2G); // Set dynamic range up to 2G |
luisbc92 | 1:1c14c1d3ce09 | 137 | acc.setBitDepth(acc.BIT_DEPTH_12); // Set bit depth to 12bits for resolution |
luisbc92 | 1:1c14c1d3ce09 | 138 | acc.activate(); // Activate accelerometer |
luisbc92 | 1:1c14c1d3ce09 | 139 | acc_tick.attach(&onAccTick, (1.0 / (float)ACC_RATE)); // Setup periodic reads |
luisbc92 | 0:4c7b37b8faad | 140 | |
luisbc92 | 1:1c14c1d3ce09 | 141 | while (1) { |
luisbc92 | 1:1c14c1d3ce09 | 142 | ble.waitForEvent(); |
luisbc92 | 0:4c7b37b8faad | 143 | } |
luisbc92 | 0:4c7b37b8faad | 144 | } |