![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
CAN to BLE translator - and back
Dependencies: BLE_API CANnucleo X_NUCLEO_IDB0XA1 mbed
main.cpp@5:9f30eba41c77, 2016-04-08 (annotated)
- Committer:
- filippomontano
- Date:
- Fri Apr 08 14:30:50 2016 +0000
- Revision:
- 5:9f30eba41c77
- Parent:
- 4:8c2cd88d2545
- Child:
- 6:f85bc6e59111
ble senza can;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
filippomontano | 0:345c72cbcd60 | 1 | #include "mbed.h" |
filippomontano | 0:345c72cbcd60 | 2 | #include "ble/BLE.h" |
filippomontano | 0:345c72cbcd60 | 3 | #include "CAN.h" |
filippomontano | 0:345c72cbcd60 | 4 | |
filippomontano | 3:5bce2e8d2797 | 5 | #define TARGET_NUCLEO_F072RB 1 |
filippomontano | 0:345c72cbcd60 | 6 | #define LED_PIN PA_5 |
filippomontano | 0:345c72cbcd60 | 7 | |
filippomontano | 3:5bce2e8d2797 | 8 | #define BLE_GATT_CHAR_PROPERTIES_NOTIFY 0x10 |
filippomontano | 3:5bce2e8d2797 | 9 | |
filippomontano | 5:9f30eba41c77 | 10 | //void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params); |
filippomontano | 3:5bce2e8d2797 | 11 | void writeCharCallback(const GattWriteCallbackParams *params); |
filippomontano | 3:5bce2e8d2797 | 12 | void bleInitComplete(BLE::InitializationCompleteCallbackContext *params); |
filippomontano | 3:5bce2e8d2797 | 13 | void onBleInitError(BLE &ble, ble_error_t error); |
filippomontano | 3:5bce2e8d2797 | 14 | void initBLE(void); |
filippomontano | 0:345c72cbcd60 | 15 | |
filippomontano | 5:9f30eba41c77 | 16 | void periodicCallback(void); |
filippomontano | 5:9f30eba41c77 | 17 | static volatile bool triggerSensorPolling = false; |
filippomontano | 5:9f30eba41c77 | 18 | |
filippomontano | 0:345c72cbcd60 | 19 | |
filippomontano | 3:5bce2e8d2797 | 20 | DigitalOut led(LED_PIN),CAN_show(PC_12); |
filippomontano | 3:5bce2e8d2797 | 21 | |
filippomontano | 3:5bce2e8d2797 | 22 | |
filippomontano | 3:5bce2e8d2797 | 23 | const static char DEVICE_NAME[] = "STNucleo - RGM - FM"; |
filippomontano | 3:5bce2e8d2797 | 24 | static const uint16_t uuid16_list[] = {0xFFFF}; |
filippomontano | 3:5bce2e8d2797 | 25 | |
filippomontano | 0:345c72cbcd60 | 26 | //const unsigned int RX_ID = 0x10; |
filippomontano | 0:345c72cbcd60 | 27 | //const unsigned int TX_ID = 0x11; |
filippomontano | 0:345c72cbcd60 | 28 | |
filippomontano | 0:345c72cbcd60 | 29 | char shareddata[64][8]= { }; |
filippomontano | 5:9f30eba41c77 | 30 | Ticker ticker; |
filippomontano | 3:5bce2e8d2797 | 31 | |
filippomontano | 3:5bce2e8d2797 | 32 | Timer timerA; //questo contatoro serve solo per dire: appena è passato un po' di tempo -> esegui |
filippomontano | 0:345c72cbcd60 | 33 | |
filippomontano | 3:5bce2e8d2797 | 34 | BLE ble; |
filippomontano | 3:5bce2e8d2797 | 35 | |
filippomontano | 3:5bce2e8d2797 | 36 | uint16_t customServiceUUID = 0xA000; // service UUID |
filippomontano | 3:5bce2e8d2797 | 37 | uint16_t readCharUUID = 0xA001; // read characteristic UUID |
filippomontano | 3:5bce2e8d2797 | 38 | uint16_t writeCharUUID = 0xA002; // write characteristic UUID |
filippomontano | 3:5bce2e8d2797 | 39 | |
filippomontano | 3:5bce2e8d2797 | 40 | static uint8_t readValue[128] = {0}; |
filippomontano | 3:5bce2e8d2797 | 41 | |
filippomontano | 3:5bce2e8d2797 | 42 | //static uint8_t readValue[6]="HELLO"; |
filippomontano | 3:5bce2e8d2797 | 43 | |
filippomontano | 3:5bce2e8d2797 | 44 | |
filippomontano | 3:5bce2e8d2797 | 45 | ReadOnlyArrayGattCharacteristic<uint8_t, sizeof(readValue)> readChar(readCharUUID, readValue, BLE_GATT_CHAR_PROPERTIES_NOTIFY , NULL,0); //aggiunto il BLE_GATT_CHAR_PROPERTIES_NOTIFY => appena arriva lo rimanda |
filippomontano | 3:5bce2e8d2797 | 46 | |
filippomontano | 3:5bce2e8d2797 | 47 | static uint8_t writeValue[128] = {0}; |
filippomontano | 3:5bce2e8d2797 | 48 | WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(writeValue)> writeChar(writeCharUUID, writeValue); |
filippomontano | 3:5bce2e8d2797 | 49 | |
filippomontano | 3:5bce2e8d2797 | 50 | GattCharacteristic *characteristics[] = {&readChar, &writeChar}; |
filippomontano | 3:5bce2e8d2797 | 51 | GattService customService(customServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *)); |
filippomontano | 3:5bce2e8d2797 | 52 | uint8_t retry=1; |
filippomontano | 3:5bce2e8d2797 | 53 | uint8_t readdata[20]= {}; |
filippomontano | 3:5bce2e8d2797 | 54 | char symbol=' '; |
filippomontano | 0:345c72cbcd60 | 55 | volatile bool CANmsgAvailable = false; |
filippomontano | 3:5bce2e8d2797 | 56 | volatile bool BLExmit = false; |
filippomontano | 3:5bce2e8d2797 | 57 | float stopTimer=2.0; |
filippomontano | 5:9f30eba41c77 | 58 | uint8_t j=0,k=1; |
filippomontano | 5:9f30eba41c77 | 59 | |
filippomontano | 0:345c72cbcd60 | 60 | int main() |
filippomontano | 0:345c72cbcd60 | 61 | { |
filippomontano | 3:5bce2e8d2797 | 62 | // printf("\r\nBoard started\r\n"); |
filippomontano | 0:345c72cbcd60 | 63 | led = 1; // turn LED on |
filippomontano | 5:9f30eba41c77 | 64 | BLE::Instance().init(bleInitComplete); |
filippomontano | 5:9f30eba41c77 | 65 | /* |
filippomontano | 5:9f30eba41c77 | 66 | while (true) { |
filippomontano | 5:9f30eba41c77 | 67 | // check for trigger from periodicCallback() |
filippomontano | 5:9f30eba41c77 | 68 | if (triggerSensorPolling && ble.getGapState().connected) { |
filippomontano | 5:9f30eba41c77 | 69 | triggerSensorPolling = false; |
filippomontano | 3:5bce2e8d2797 | 70 | |
filippomontano | 5:9f30eba41c77 | 71 | // Do blocking calls or whatever is necessary for sensor polling. |
filippomontano | 5:9f30eba41c77 | 72 | // In our case, we simply update the HRM measurement. |
filippomontano | 3:5bce2e8d2797 | 73 | |
filippomontano | 5:9f30eba41c77 | 74 | } else { |
filippomontano | 5:9f30eba41c77 | 75 | ble.waitForEvent(); // low power wait for event |
filippomontano | 5:9f30eba41c77 | 76 | } |
filippomontano | 5:9f30eba41c77 | 77 | }*/ |
filippomontano | 5:9f30eba41c77 | 78 | |
filippomontano | 5:9f30eba41c77 | 79 | |
filippomontano | 0:345c72cbcd60 | 80 | timerA.start(); |
filippomontano | 5:9f30eba41c77 | 81 | // can.attach(&onMsgReceived, CAN::RxIrq); // attach 'CAN receive-complete' interrupt handler |
filippomontano | 3:5bce2e8d2797 | 82 | |
filippomontano | 3:5bce2e8d2797 | 83 | while(true) { |
filippomontano | 5:9f30eba41c77 | 84 | // if(ble.getGapState().connected) { |
filippomontano | 5:9f30eba41c77 | 85 | if(triggerSensorPolling && ble.getGapState().connected) |
filippomontano | 5:9f30eba41c77 | 86 | { |
filippomontano | 5:9f30eba41c77 | 87 | triggerSensorPolling=false; |
filippomontano | 5:9f30eba41c77 | 88 | // printf("^"); |
filippomontano | 5:9f30eba41c77 | 89 | } |
filippomontano | 5:9f30eba41c77 | 90 | else { |
filippomontano | 5:9f30eba41c77 | 91 | // printf("v"); |
filippomontano | 5:9f30eba41c77 | 92 | ble.waitForEvent(); |
filippomontano | 5:9f30eba41c77 | 93 | } |
filippomontano | 5:9f30eba41c77 | 94 | |
filippomontano | 5:9f30eba41c77 | 95 | if(ble.gap().getState().connected) { |
filippomontano | 3:5bce2e8d2797 | 96 | stopTimer=0.2; |
filippomontano | 3:5bce2e8d2797 | 97 | symbol='!'; |
filippomontano | 3:5bce2e8d2797 | 98 | } else { |
filippomontano | 3:5bce2e8d2797 | 99 | stopTimer=3; |
filippomontano | 5:9f30eba41c77 | 100 | // ble.waitForEvent(); |
filippomontano | 3:5bce2e8d2797 | 101 | symbol='.'; |
filippomontano | 3:5bce2e8d2797 | 102 | } |
filippomontano | 3:5bce2e8d2797 | 103 | |
filippomontano | 3:5bce2e8d2797 | 104 | if(timerA.read()>=stopTimer) { |
filippomontano | 5:9f30eba41c77 | 105 | // BLExmit=ble.getGapState().connected; |
filippomontano | 5:9f30eba41c77 | 106 | BLExmit=ble.gap().getState().connected; |
filippomontano | 0:345c72cbcd60 | 107 | timerA.stop(); |
filippomontano | 0:345c72cbcd60 | 108 | timerA.reset(); |
filippomontano | 0:345c72cbcd60 | 109 | led=!led.read(); |
filippomontano | 3:5bce2e8d2797 | 110 | printf("%c\r\n",symbol); |
filippomontano | 0:345c72cbcd60 | 111 | timerA.start(); |
filippomontano | 3:5bce2e8d2797 | 112 | |
filippomontano | 0:345c72cbcd60 | 113 | } |
filippomontano | 5:9f30eba41c77 | 114 | |
filippomontano | 3:5bce2e8d2797 | 115 | if(BLExmit) { |
filippomontano | 3:5bce2e8d2797 | 116 | BLExmit=false; |
filippomontano | 3:5bce2e8d2797 | 117 | retry++; |
filippomontano | 5:9f30eba41c77 | 118 | if(retry==0xff) ble.gap().startAdvertising(); |
filippomontano | 5:9f30eba41c77 | 119 | printf ("%#x ",retry); |
filippomontano | 3:5bce2e8d2797 | 120 | printf("@"); |
filippomontano | 3:5bce2e8d2797 | 121 | k++; |
filippomontano | 5:9f30eba41c77 | 122 | if(k>1) |
filippomontano | 5:9f30eba41c77 | 123 | k=1; |
filippomontano | 3:5bce2e8d2797 | 124 | readValue[0]=k; |
filippomontano | 3:5bce2e8d2797 | 125 | for(int i=1; i<8; i++) { |
filippomontano | 3:5bce2e8d2797 | 126 | readValue[i]=shareddata[k][i]; |
filippomontano | 0:345c72cbcd60 | 127 | } |
filippomontano | 5:9f30eba41c77 | 128 | for(int i=0; i<8; i++) { |
filippomontano | 5:9f30eba41c77 | 129 | printf ("%x",readValue[i]); |
filippomontano | 5:9f30eba41c77 | 130 | } |
filippomontano | 3:5bce2e8d2797 | 131 | ble.updateCharacteristicValue(readChar.getValueHandle(), readValue,9); |
filippomontano | 0:345c72cbcd60 | 132 | } |
filippomontano | 0:345c72cbcd60 | 133 | } |
filippomontano | 0:345c72cbcd60 | 134 | } |
filippomontano | 3:5bce2e8d2797 | 135 | |
filippomontano | 5:9f30eba41c77 | 136 | void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) |
filippomontano | 5:9f30eba41c77 | 137 | { |
filippomontano | 5:9f30eba41c77 | 138 | (void)params; |
filippomontano | 5:9f30eba41c77 | 139 | printf("\r\nTarget loss... wait for reconnection \r\n"); |
filippomontano | 5:9f30eba41c77 | 140 | |
filippomontano | 5:9f30eba41c77 | 141 | BLE::Instance().gap().startAdvertising(); // restart advertising |
filippomontano | 5:9f30eba41c77 | 142 | } |
filippomontano | 3:5bce2e8d2797 | 143 | void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) |
filippomontano | 0:345c72cbcd60 | 144 | { |
filippomontano | 3:5bce2e8d2797 | 145 | BLE& ble = params->ble; |
filippomontano | 3:5bce2e8d2797 | 146 | ble_error_t error = params->error; |
filippomontano | 3:5bce2e8d2797 | 147 | |
filippomontano | 3:5bce2e8d2797 | 148 | if (error != BLE_ERROR_NONE) { |
filippomontano | 3:5bce2e8d2797 | 149 | onBleInitError(ble, error); |
filippomontano | 3:5bce2e8d2797 | 150 | return; |
filippomontano | 3:5bce2e8d2797 | 151 | } |
filippomontano | 3:5bce2e8d2797 | 152 | |
filippomontano | 3:5bce2e8d2797 | 153 | if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { |
filippomontano | 3:5bce2e8d2797 | 154 | return; |
filippomontano | 3:5bce2e8d2797 | 155 | } |
filippomontano | 5:9f30eba41c77 | 156 | |
filippomontano | 3:5bce2e8d2797 | 157 | ble.gap().onDisconnection(disconnectionCallback); |
filippomontano | 3:5bce2e8d2797 | 158 | |
filippomontano | 3:5bce2e8d2797 | 159 | /* Setup primary service. */ |
filippomontano | 3:5bce2e8d2797 | 160 | |
filippomontano | 3:5bce2e8d2797 | 161 | /* Setup advertising. */ |
filippomontano | 3:5bce2e8d2797 | 162 | printf("Setup of Advertising\r\n"); |
filippomontano | 3:5bce2e8d2797 | 163 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); |
filippomontano | 3:5bce2e8d2797 | 164 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); |
filippomontano | 3:5bce2e8d2797 | 165 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); |
filippomontano | 3:5bce2e8d2797 | 166 | ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
filippomontano | 3:5bce2e8d2797 | 167 | ble.gap().setAdvertisingInterval(1000);// 1000ms |
filippomontano | 3:5bce2e8d2797 | 168 | ble.gap().startAdvertising(); |
filippomontano | 3:5bce2e8d2797 | 169 | ble.onDataWritten(writeCharCallback); |
filippomontano | 3:5bce2e8d2797 | 170 | ble.addService(customService); |
filippomontano | 5:9f30eba41c77 | 171 | ticker.detach(); |
filippomontano | 5:9f30eba41c77 | 172 | ticker.attach(periodicCallback, 1); // blink LED every second |
filippomontano | 3:5bce2e8d2797 | 173 | |
filippomontano | 3:5bce2e8d2797 | 174 | printf("Starting Loop\r\n"); |
filippomontano | 5:9f30eba41c77 | 175 | |
filippomontano | 3:5bce2e8d2797 | 176 | } |
filippomontano | 3:5bce2e8d2797 | 177 | void onBleInitError(BLE &ble, ble_error_t error) |
filippomontano | 3:5bce2e8d2797 | 178 | { |
filippomontano | 3:5bce2e8d2797 | 179 | (void)ble; |
filippomontano | 3:5bce2e8d2797 | 180 | (void)error; |
filippomontano | 3:5bce2e8d2797 | 181 | printf(" ### BLE init error ###\r\n"); |
filippomontano | 3:5bce2e8d2797 | 182 | |
filippomontano | 3:5bce2e8d2797 | 183 | |
filippomontano | 3:5bce2e8d2797 | 184 | /* Initialization error handling should go here */ |
filippomontano | 0:345c72cbcd60 | 185 | } |
filippomontano | 5:9f30eba41c77 | 186 | void periodicCallback(void) |
filippomontano | 0:345c72cbcd60 | 187 | { |
filippomontano | 5:9f30eba41c77 | 188 | led = !led; /* Do blinky on LED1 while we're waiting for BLE events */ |
filippomontano | 5:9f30eba41c77 | 189 | /* Note that the periodicCallback() executes in interrupt context, so it is safer to do |
filippomontano | 5:9f30eba41c77 | 190 | * heavy-weight sensor polling from the main thread. */ |
filippomontano | 5:9f30eba41c77 | 191 | if(!ble.getGapState().connected) { |
filippomontano | 5:9f30eba41c77 | 192 | printf("? "); |
filippomontano | 5:9f30eba41c77 | 193 | ticker.attach(periodicCallback, 1); // blink LED every 5 second |
filippomontano | 5:9f30eba41c77 | 194 | } else |
filippomontano | 5:9f30eba41c77 | 195 | ticker.attach(periodicCallback, 0.1); // blink LED every second |
filippomontano | 5:9f30eba41c77 | 196 | |
filippomontano | 5:9f30eba41c77 | 197 | triggerSensorPolling = true; |
filippomontano | 0:345c72cbcd60 | 198 | } |
filippomontano | 3:5bce2e8d2797 | 199 | void writeCharCallback(const GattWriteCallbackParams *params) |
filippomontano | 3:5bce2e8d2797 | 200 | { |
filippomontano | 3:5bce2e8d2797 | 201 | |
filippomontano | 3:5bce2e8d2797 | 202 | uint8_t j=0; |
filippomontano | 3:5bce2e8d2797 | 203 | |
filippomontano | 3:5bce2e8d2797 | 204 | // check to see what characteristic was written, by handle |
filippomontano | 5:9f30eba41c77 | 205 | /* if(params->handle == writeChar.getValueHandle()) { |
filippomontano | 3:5bce2e8d2797 | 206 | BLESlot2CANId(params->data[0]); |
filippomontano | 3:5bce2e8d2797 | 207 | printf("\n\r Data received: length = %d, data = ",params->len); |
filippomontano | 3:5bce2e8d2797 | 208 | if(canRdPointer != j && canRdPointer != j+1) { |
filippomontano | 3:5bce2e8d2797 | 209 | bleWrPointerA=j; |
filippomontano | 3:5bce2e8d2797 | 210 | bleWrPointerB=j+1; |
filippomontano | 3:5bce2e8d2797 | 211 | for(int x=0; x < 9; x++) { |
filippomontano | 3:5bce2e8d2797 | 212 | printf("%c",params->data[x]); |
filippomontano | 3:5bce2e8d2797 | 213 | shareddata[j][x]=params->data[x]; |
filippomontano | 3:5bce2e8d2797 | 214 | } |
filippomontano | 3:5bce2e8d2797 | 215 | for(int x=9; x < 18; x++) { |
filippomontano | 3:5bce2e8d2797 | 216 | printf("%c",params->data[x]); |
filippomontano | 3:5bce2e8d2797 | 217 | shareddata[j+1][x-9]=params->data[x]; |
filippomontano | 3:5bce2e8d2797 | 218 | } |
filippomontano | 3:5bce2e8d2797 | 219 | bleWrPointerA=255; |
filippomontano | 3:5bce2e8d2797 | 220 | bleWrPointerB=255; |
filippomontano | 3:5bce2e8d2797 | 221 | } |
filippomontano | 5:9f30eba41c77 | 222 | }*/ |
filippomontano | 3:5bce2e8d2797 | 223 | } |