BLE project for PILLAR
Dependencies: BLE_API mbed simpleBLEControl
Fork of BLE_API_DEMO by
main.cpp@54:52be0aeba318, 2014-11-28 (annotated)
- Committer:
- antoniorohit
- Date:
- Fri Nov 28 08:10:25 2014 +0000
- Revision:
- 54:52be0aeba318
- Parent:
- 53:f503e75f0c94
Funnel + Base motor integrated positioning;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
antoniorohit | 51:0bf1116bca52 | 1 | // This code is for the nRF51822 that is used to provide a BLE interface to PILLar |
antoniorohit | 51:0bf1116bca52 | 2 | // There is 1 service and 1 characteristic |
antoniorohit | 51:0bf1116bca52 | 3 | // The service provides a way to write a step value from the phone to a stepper motor |
antoniorohit | 51:0bf1116bca52 | 4 | // controlled by an Arduino |
ktownsend | 0:87a7fc231fae | 5 | #include "mbed.h" |
Rohit Grover |
10:2436164b692e | 6 | #include "BLEDevice.h" |
antoniorohit | 53:f503e75f0c94 | 7 | #define RFID_BUFF_SIZE 8 // Enough to hold 7-byte UID + delimiter |
ktownsend | 0:87a7fc231fae | 8 | |
antoniorohit | 52:8e483d1199f9 | 9 | DigitalOut led1(LED1); // LED toggled on connect and write events |
antoniorohit | 52:8e483d1199f9 | 10 | DigitalOut led2(LED2); // Toggled on button press |
antoniorohit | 51:0bf1116bca52 | 11 | BLEDevice ble; // Declare the ble device |
antoniorohit | 51:0bf1116bca52 | 12 | Serial arduino(USBTX, USBRX); // serial interface to PC or Arduino controlling the stepper |
ktownsend | 0:87a7fc231fae | 13 | |
antoniorohit | 51:0bf1116bca52 | 14 | // Arbit 128-bit UIDs generated from |
antoniorohit | 51:0bf1116bca52 | 15 | // http://www.guidgenerator.com/online-guid-generator.aspx |
antoniorohit | 51:0bf1116bca52 | 16 | // We need one for each service and characteristic |
antoniorohit | 51:0bf1116bca52 | 17 | const uint8_t ARDUINO_WRITE_CHARACTERISTIC_UUID[LENGTH_OF_LONG_UUID] = { |
nebgnahz | 50:4c02add9abba | 18 | 0xfb, 0x71, 0xbc, 0xc0, 0x5a, 0x0c, 0x11, 0xe4, |
nebgnahz | 50:4c02add9abba | 19 | 0x91, 0xae, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b |
nebgnahz | 50:4c02add9abba | 20 | }; |
antoniorohit | 51:0bf1116bca52 | 21 | |
antoniorohit | 52:8e483d1199f9 | 22 | const uint8_t RFID_UUID[LENGTH_OF_LONG_UUID] = { |
antoniorohit | 52:8e483d1199f9 | 23 | 0x7a, 0x77, 0xbe, 0x20, 0x5a, 0x0d, 0x11, 0xe4, |
antoniorohit | 52:8e483d1199f9 | 24 | 0xa9, 0x5e, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b |
antoniorohit | 52:8e483d1199f9 | 25 | }; |
antoniorohit | 52:8e483d1199f9 | 26 | |
nebgnahz | 50:4c02add9abba | 27 | const uint8_t TEST_SERVICE_UUID[LENGTH_OF_LONG_UUID] = { |
nebgnahz | 50:4c02add9abba | 28 | 0xb0, 0xbb, 0x58, 0x20, 0x5a, 0x0d, 0x11, 0xe4, |
antoniorohit | 51:0bf1116bca52 | 29 | 0x93, 0xee, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}; |
nebgnahz | 50:4c02add9abba | 30 | |
antoniorohit | 51:0bf1116bca52 | 31 | const static char DEVICE_NAME[] = "mediCAL BLE"; // For Advertisement |
antoniorohit | 51:0bf1116bca52 | 32 | static volatile uint16_t writeToArduino_handler; // handler to echo data |
antoniorohit | 52:8e483d1199f9 | 33 | static volatile bool is_button_pressed = false; |
antoniorohit | 52:8e483d1199f9 | 34 | static volatile bool uid_read = false; |
antoniorohit | 52:8e483d1199f9 | 35 | |
antoniorohit | 52:8e483d1199f9 | 36 | |
antoniorohit | 52:8e483d1199f9 | 37 | // What happens on connect event - DEBUG purposes ONLY!! |
antoniorohit | 52:8e483d1199f9 | 38 | void onConnection(Gap::Handle_t handle, const Gap::ConnectionParams_t * param_ptr){ |
antoniorohit | 52:8e483d1199f9 | 39 | arduino.printf("Connection Event!\n\r"); |
antoniorohit | 52:8e483d1199f9 | 40 | ble.stopAdvertising(); // stop advertising |
antoniorohit | 52:8e483d1199f9 | 41 | led1 = !led1.read(); |
antoniorohit | 52:8e483d1199f9 | 42 | } |
nebgnahz | 48:908b4ec086ba | 43 | |
antoniorohit | 51:0bf1116bca52 | 44 | // What happens on disconnect event |
antoniorohit | 51:0bf1116bca52 | 45 | void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason){ |
antoniorohit | 52:8e483d1199f9 | 46 | arduino.printf("Disconnection Event!\n\r"); |
rgrover1 | 46:ee7c55907f36 | 47 | ble.startAdvertising(); // restart advertising |
rgrover1 | 7:daab8ba5139e | 48 | } |
Rohit Grover |
3:24e2b056d229 | 49 | |
antoniorohit | 51:0bf1116bca52 | 50 | // This function is called whenever data is written to the BLE device through the phone |
antoniorohit | 51:0bf1116bca52 | 51 | void onDatawritten(const GattCharacteristicWriteCBParams *eventDataP) { |
nebgnahz | 49:14b2df099dfc | 52 | // eventDataP->charHandle is just uint16_t |
nebgnahz | 49:14b2df099dfc | 53 | // it's used to dispatch the callbacks |
antoniorohit | 51:0bf1116bca52 | 54 | if(eventDataP->charHandle==writeToArduino_handler){ // The data is for the motor |
antoniorohit | 51:0bf1116bca52 | 55 | uint16_t bytesRead = eventDataP->len; |
antoniorohit | 54:52be0aeba318 | 56 | // What the BLE master will tell us is which funnels to dispense from |
antoniorohit | 54:52be0aeba318 | 57 | int funnel = *((int16_t *)eventDataP->data); |
antoniorohit | 54:52be0aeba318 | 58 | switch(funnel){ |
antoniorohit | 54:52be0aeba318 | 59 | case 0: |
antoniorohit | 54:52be0aeba318 | 60 | arduino.printf("%dm", 0); |
antoniorohit | 54:52be0aeba318 | 61 | arduino.printf("%dM", 25); |
antoniorohit | 54:52be0aeba318 | 62 | arduino.printf("%dM", -25); |
antoniorohit | 54:52be0aeba318 | 63 | arduino.printf("%dm", 128); |
antoniorohit | 54:52be0aeba318 | 64 | arduino.printf("%dm", -128); |
antoniorohit | 54:52be0aeba318 | 65 | arduino.printf("%dm", -0); |
antoniorohit | 54:52be0aeba318 | 66 | break; |
antoniorohit | 54:52be0aeba318 | 67 | case 1: |
antoniorohit | 54:52be0aeba318 | 68 | arduino.printf("%dm", 128); |
antoniorohit | 54:52be0aeba318 | 69 | arduino.printf("%dM", 75); |
antoniorohit | 54:52be0aeba318 | 70 | arduino.printf("%dM", -75); |
antoniorohit | 54:52be0aeba318 | 71 | arduino.printf("%dm", 128); |
antoniorohit | 54:52be0aeba318 | 72 | arduino.printf("%dm", -128); |
antoniorohit | 54:52be0aeba318 | 73 | arduino.printf("%dm", -128); |
antoniorohit | 54:52be0aeba318 | 74 | break; |
antoniorohit | 54:52be0aeba318 | 75 | case 2: |
antoniorohit | 54:52be0aeba318 | 76 | arduino.printf("%dm", 256); |
antoniorohit | 54:52be0aeba318 | 77 | arduino.printf("%dM", 125); |
antoniorohit | 54:52be0aeba318 | 78 | arduino.printf("%dM", -125); |
antoniorohit | 54:52be0aeba318 | 79 | arduino.printf("%dm", 128); |
antoniorohit | 54:52be0aeba318 | 80 | arduino.printf("%dm", -128); |
antoniorohit | 54:52be0aeba318 | 81 | arduino.printf("%dm", -256); |
antoniorohit | 54:52be0aeba318 | 82 | break; |
antoniorohit | 54:52be0aeba318 | 83 | |
antoniorohit | 54:52be0aeba318 | 84 | case 3: |
antoniorohit | 54:52be0aeba318 | 85 | arduino.printf("%dm", 384); |
antoniorohit | 54:52be0aeba318 | 86 | arduino.printf("%dM", 175); |
antoniorohit | 54:52be0aeba318 | 87 | arduino.printf("%dM", -175); |
antoniorohit | 54:52be0aeba318 | 88 | arduino.printf("%dm", 128); |
antoniorohit | 54:52be0aeba318 | 89 | arduino.printf("%dm", -128); |
antoniorohit | 54:52be0aeba318 | 90 | arduino.printf("%dm", -384); |
antoniorohit | 54:52be0aeba318 | 91 | break; |
antoniorohit | 54:52be0aeba318 | 92 | |
antoniorohit | 54:52be0aeba318 | 93 | default: |
antoniorohit | 54:52be0aeba318 | 94 | break; |
antoniorohit | 54:52be0aeba318 | 95 | } |
antoniorohit | 54:52be0aeba318 | 96 | |
antoniorohit | 53:f503e75f0c94 | 97 | led1 = !led1.read(); // debug purposes |
nebgnahz | 48:908b4ec086ba | 98 | } |
nebgnahz | 48:908b4ec086ba | 99 | } |
antoniorohit | 53:f503e75f0c94 | 100 | char read_ch; // temp var to store data from arduino |
antoniorohit | 52:8e483d1199f9 | 101 | uint8_t buff[RFID_BUFF_SIZE] = {0}; // max packet size for GATT is 20 bytes |
antoniorohit | 52:8e483d1199f9 | 102 | uint8_t ct = 0; |
antoniorohit | 52:8e483d1199f9 | 103 | |
antoniorohit | 52:8e483d1199f9 | 104 | void callback() { |
antoniorohit | 52:8e483d1199f9 | 105 | // Note: you need to actually read from the serial to clear the RX interrupt |
antoniorohit | 52:8e483d1199f9 | 106 | read_ch = arduino.getc(); |
antoniorohit | 53:f503e75f0c94 | 107 | buff[ct++] = int(read_ch); |
antoniorohit | 53:f503e75f0c94 | 108 | |
antoniorohit | 53:f503e75f0c94 | 109 | if((ct > RFID_BUFF_SIZE-1)){ // Arduino sends 8-bytes [UID][;][0 padding] |
antoniorohit | 52:8e483d1199f9 | 110 | uid_read = true; |
antoniorohit | 52:8e483d1199f9 | 111 | } |
antoniorohit | 53:f503e75f0c94 | 112 | led2 = !led2.read(); // debug purposes |
antoniorohit | 52:8e483d1199f9 | 113 | } |
antoniorohit | 52:8e483d1199f9 | 114 | |
antoniorohit | 52:8e483d1199f9 | 115 | // Button1 pressed routine - toggle is_button pressed |
antoniorohit | 52:8e483d1199f9 | 116 | void button1Pressed() { |
antoniorohit | 52:8e483d1199f9 | 117 | is_button_pressed = !is_button_pressed; |
antoniorohit | 53:f503e75f0c94 | 118 | led2 = !led2.read(); // debug |
antoniorohit | 52:8e483d1199f9 | 119 | } |
antoniorohit | 52:8e483d1199f9 | 120 | |
antoniorohit | 52:8e483d1199f9 | 121 | // Button2 pressed routine |
antoniorohit | 52:8e483d1199f9 | 122 | void button2Pressed() { |
antoniorohit | 53:f503e75f0c94 | 123 | led2 = !led2.read(); // debug |
antoniorohit | 52:8e483d1199f9 | 124 | } |
rgrover1 | 47:430545f41113 | 125 | |
ktownsend | 0:87a7fc231fae | 126 | int main(void) |
ktownsend | 0:87a7fc231fae | 127 | { |
antoniorohit | 52:8e483d1199f9 | 128 | arduino.baud(115200); |
antoniorohit | 51:0bf1116bca52 | 129 | arduino.printf("Entered main\n\r"); |
ktownsend | 0:87a7fc231fae | 130 | |
antoniorohit | 52:8e483d1199f9 | 131 | // RFID Interrupt initialization |
antoniorohit | 52:8e483d1199f9 | 132 | // button initialization |
antoniorohit | 52:8e483d1199f9 | 133 | InterruptIn button1(BUTTON1); |
antoniorohit | 52:8e483d1199f9 | 134 | button1.mode(PullUp); |
antoniorohit | 52:8e483d1199f9 | 135 | button1.rise(&button1Pressed); |
antoniorohit | 52:8e483d1199f9 | 136 | |
antoniorohit | 52:8e483d1199f9 | 137 | InterruptIn button2(BUTTON2); |
antoniorohit | 52:8e483d1199f9 | 138 | button2.mode(PullUp); |
antoniorohit | 52:8e483d1199f9 | 139 | button2.rise(&button2Pressed); |
antoniorohit | 52:8e483d1199f9 | 140 | |
antoniorohit | 53:f503e75f0c94 | 141 | arduino.attach(&callback); // callback is triggered when there is incoming serial data |
antoniorohit | 53:f503e75f0c94 | 142 | |
antoniorohit | 51:0bf1116bca52 | 143 | // You can write from the phone to control what is written to Arduino |
antoniorohit | 51:0bf1116bca52 | 144 | GattCharacteristic writeToArduino_characteristics( |
antoniorohit | 51:0bf1116bca52 | 145 | ARDUINO_WRITE_CHARACTERISTIC_UUID, NULL, sizeof(int16_t), sizeof(int16_t), |
antoniorohit | 52:8e483d1199f9 | 146 | GattCharacteristic::BLE_GATT_FORMAT_SINT16 | // 16-bit signed int |
antoniorohit | 51:0bf1116bca52 | 147 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | // has read |
antoniorohit | 51:0bf1116bca52 | 148 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE); // and write properties |
antoniorohit | 51:0bf1116bca52 | 149 | writeToArduino_handler = writeToArduino_characteristics.getValueAttribute().getHandle();// save the handler |
rgrover1 | 45:98c5a34b07a4 | 150 | |
antoniorohit | 52:8e483d1199f9 | 151 | GattCharacteristic RFID_characteristics( |
antoniorohit | 52:8e483d1199f9 | 152 | RFID_UUID, NULL, RFID_BUFF_SIZE*sizeof(uint8_t), RFID_BUFF_SIZE*sizeof(uint8_t), |
antoniorohit | 52:8e483d1199f9 | 153 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | |
antoniorohit | 52:8e483d1199f9 | 154 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY); |
antoniorohit | 52:8e483d1199f9 | 155 | |
antoniorohit | 52:8e483d1199f9 | 156 | |
antoniorohit | 52:8e483d1199f9 | 157 | GattCharacteristic *charTable[] = {&writeToArduino_characteristics, |
antoniorohit | 52:8e483d1199f9 | 158 | &RFID_characteristics}; // Characteristic table |
antoniorohit | 51:0bf1116bca52 | 159 | GattService testService(TEST_SERVICE_UUID, charTable, // Add the char(s) to this service |
nebgnahz | 49:14b2df099dfc | 160 | sizeof(charTable) / sizeof(GattCharacteristic *)); |
nebgnahz | 50:4c02add9abba | 161 | |
nebgnahz | 48:908b4ec086ba | 162 | // BLE setup, mainly we add service and callbacks |
nebgnahz | 48:908b4ec086ba | 163 | ble.init(); |
nebgnahz | 48:908b4ec086ba | 164 | ble.addService(testService); |
antoniorohit | 52:8e483d1199f9 | 165 | ble.onDataWritten(onDatawritten); |
antoniorohit | 52:8e483d1199f9 | 166 | ble.onConnection(onConnection); |
nebgnahz | 48:908b4ec086ba | 167 | ble.onDisconnection(disconnectionCallback); |
nebgnahz | 48:908b4ec086ba | 168 | |
nebgnahz | 48:908b4ec086ba | 169 | // setup advertising |
nebgnahz | 49:14b2df099dfc | 170 | ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | |
nebgnahz | 50:4c02add9abba | 171 | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); |
nebgnahz | 49:14b2df099dfc | 172 | ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, |
nebgnahz | 49:14b2df099dfc | 173 | (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); |
rgrover1 | 7:daab8ba5139e | 174 | ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
antoniorohit | 52:8e483d1199f9 | 175 | ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */ |
rgrover1 | 7:daab8ba5139e | 176 | ble.startAdvertising(); |
Rohit Grover |
3:24e2b056d229 | 177 | |
Rohit Grover |
11:1d9aafee4984 | 178 | while (true) { |
antoniorohit | 52:8e483d1199f9 | 179 | if (uid_read) { |
antoniorohit | 52:8e483d1199f9 | 180 | ble.updateCharacteristicValue(RFID_characteristics.getValueAttribute().getHandle(), |
antoniorohit | 52:8e483d1199f9 | 181 | buff, RFID_BUFF_SIZE*sizeof(uint8_t)); |
antoniorohit | 52:8e483d1199f9 | 182 | uid_read = false; |
antoniorohit | 52:8e483d1199f9 | 183 | ct = 0; |
antoniorohit | 52:8e483d1199f9 | 184 | } |
antoniorohit | 52:8e483d1199f9 | 185 | else { |
antoniorohit | 52:8e483d1199f9 | 186 | ble.waitForEvent(); |
antoniorohit | 52:8e483d1199f9 | 187 | } |
ktownsend | 0:87a7fc231fae | 188 | } |
nebgnahz | 50:4c02add9abba | 189 | } |