Geo beacon for VF.
Dependencies: MMA8452 aconno_bsp adc52832_common
main.cpp
00001 /* 00002 * 00003 * Made by Jurica Resetar @ aconno 00004 * aconno.de 00005 * All rights reserved. 00006 * 00007 */ 00008 00009 #include "mbed.h" 00010 #include "ble/BLE.h" 00011 #include "GapAdvertisingData.h" 00012 #include "acd52832_bsp.h" 00013 #include "mma8452.h" 00014 #include "AckService.h" 00015 #include "nrf52_uart.h" 00016 #include "nrf52_digital.h" 00017 #include "acn_nrf52_pwm.h" 00018 00019 #define DEBUG (0) 00020 #define DEBUG_ACC (0) 00021 #define DEBUG_PRINT_UART (0) 00022 #define DEBUG_MAC (0) 00023 #define DEBUG_CONNECTION (0) 00024 #define DEBUG_WAKEUP_BUZZER (0) 00025 00026 #define ACN_FREIGHT (1) 00027 00028 #define USE_ACC (0) 00029 00030 #define SLEEP_TIME_S (4.00) /* Sleep time (in s) */ 00031 #define ADV_TIMER_TIME_S (1.00) /* Advertising time (in s) */ 00032 #define FREE_TIME_S (0.1) /* Time between end of a scanning and sleep mode */ 00033 #define AWAKE_TIME_S (ADV_TIMER_TIME_S+FREE_TIME_S) /* Was 0.15 */ 00034 #define SHORT_SLEEP_TIME_S (0.5) /* Shorter sleep time (s) */ 00035 #define SHORT_SLEEP_TIME_PERIOD_S (10) /* Time after a last scanned advertisment. In the period, sleep time is SHORT_SLEEP_TIME */ 00036 #define BUZZER_FREQUENCY_Hz (4000) 00037 00038 #define BUZZ_TIME_S (1) /* Buzz time in s */ 00039 #define ADV_INTERVAL (100) /* Advertising interval (in ms) */ 00040 #define UUID_SIZE_B (16) 00041 00042 /* Static constants for the accelerometer */ 00043 #define WHO_AM_I 0x0D /* Type 'read' : This should return the device id of 0x2A */ 00044 #define OUT_Z_MSB 0x05 /* Type 'read' : z axis - 8 most significatn bit of a 12 bit sample */ 00045 #define ACC_POWER (p11) 00046 #define I2C_DATA (p20) 00047 #define I2C_CLK (p17) 00048 #define INT2_PIN (p15) 00049 #define BUZZER (p18) 00050 00051 #if ACN_FREIGHT 00052 #define LED_BLINK_HALF_T (0.5) 00053 #endif 00054 #define BUZZER_ON_TIME_S (0.250) 00055 #define BUZZER_OFF_TIME_S (0.050) 00056 00057 /* LEDs */ 00058 #define RED_LED (p31) 00059 #define GREEN_LED (p2) 00060 #define BLUE_LED (p3) 00061 00062 /* I2C power */ 00063 #define I2C_POWER (p5) 00064 00065 /* UART pins */ 00066 #define UART_TX (p25) 00067 #define UART_RX (p26) 00068 00069 #if DEBUG_PRINT_UART 00070 #include "nrf52_uart.h" 00071 NRF52_UART uart(UART_TX, UART_RX, Baud9600); 00072 char buffer[255]; 00073 #define SEND(...) {uint8_t len = sprintf(buffer, __VA_ARGS__); uart.send(buffer, len);} 00074 #else 00075 #define SEND(...) 00076 #endif 00077 00078 00079 #if ACN_FREIGHT 00080 00081 /* Aconno ID universal to all projects */ 00082 #define ACONNO_ID (0x69) 00083 /* Internal unique product identification. When doing new projects, just 00084 * increment old project ID by one. */ 00085 #define PRODUCT_ID (0x03) 00086 /* Version of the firmware. Start from zero and go upwards. */ 00087 #define VERSION (0x02) 00088 00089 /* Manufacturer that will sell the product. 0x0059 for general use case. */ 00090 #define MANUFACTURER_ID (0x0059) 00091 00092 struct __attribute__((packed, aligned(1))) AdvertisingFormat 00093 { 00094 uint16_t manufacturerID; 00095 uint8_t aconnoID; 00096 uint8_t productID; 00097 uint8_t version; 00098 }; 00099 00100 #endif 00101 00102 00103 uint8_t sleepFlag = true; 00104 uint8_t UUID[UUID_SIZE_B] = {0xE1, 0x61, 0x35, 0xBA, 0xC0, 0xEC, 0x47, 0x2A, 0x98, 0x00, 0xAF, 0x18, 0x43, 0xFF, 0x05, 0x00}; 00105 uint8_t startBuzz[2] = {0xBA, 0xBE}; 00106 uint8_t stopBuzz[2] = {0xDE, 0xAD}; 00107 uint8_t myMacAddress[6] = {}; 00108 uint8_t buzzer_flag = 0; 00109 00110 enum RadioState{ 00111 OFF, 00112 ADVERTISING, 00113 SCANNING, 00114 }; 00115 00116 enum RadioState radioState = OFF; 00117 00118 void GoToSleep(); 00119 void StartAdvertising(); 00120 void startScanning(); 00121 void WakeMeUp(); 00122 00123 Ticker WakeSleepT; 00124 Ticker sleepChanger; 00125 Ticker toggleBuzzer; 00126 #if ACN_FREIGHT 00127 Ticker toggleLed; 00128 #endif 00129 NRF52_PWM buzzer(NRF_PWM2); 00130 00131 #if USE_ACC 00132 DigitalOut accPower(ACC_POWER); 00133 DigitalOut i2cPower(I2C_POWER); 00134 InterruptIn accPulse(INT2_PIN); 00135 Acc_MMA8452 acc(I2C_DATA, I2C_CLK, MMA8452_ADDRESS); 00136 00137 #endif 00138 BLE &ble = BLE::Instance(); 00139 ACKService<4> *ackServicePtr; 00140 00141 #if DEBUG || DEBUG_MAC || DEBUG_CONNECTION 00142 NRF52_DigitalOut advLED(RED_LED); // Red 00143 NRF52_DigitalOut scanLED(BLUE_LED); // Blue 00144 NRF52_DigitalOut connectedLED(GREEN_LED); // Green 00145 #endif 00146 00147 #if DEBUG_ACC 00148 NRF52_DigitalOut int_led(RED_LED); 00149 NRF52_DigitalOut act_led(RED_LED); 00150 #endif 00151 00152 #if ACN_FREIGHT 00153 NRF52_DigitalOut signal_led(RED_LED); 00154 #endif 00155 00156 #if ACN_FREIGHT 00157 void ledToggle(){ 00158 signal_led.toggle(); 00159 } 00160 #endif 00161 00162 void buzzerToggle(){ 00163 static uint8_t initState = 1; 00164 if(initState){ 00165 // initial state is off 00166 buzzer.enable(BUZZER_FREQUENCY_Hz); 00167 buzzer.enableChannel(0, BUZZER); 00168 buzzer.setDuty(0,0.5f); 00169 initState = 0; 00170 toggleBuzzer.detach(); 00171 toggleBuzzer.attach(buzzerToggle, BUZZER_OFF_TIME_S); 00172 } 00173 else{ 00174 buzzer.enable(0); 00175 buzzer.setDuty(0, 0); 00176 buzzer.disable(); 00177 initState = 1; 00178 toggleBuzzer.detach(); 00179 toggleBuzzer.attach(buzzerToggle, BUZZER_ON_TIME_S); 00180 } 00181 } 00182 00183 void buzzerStart(){ 00184 buzzer.enable(BUZZER_FREQUENCY_Hz); 00185 buzzer.enableChannel(0, BUZZER); 00186 buzzer.setDuty(0,0.5f); 00187 } 00188 void buzzerStop(){ 00189 buzzer.enable(0); 00190 buzzer.setDuty(0, 0); 00191 buzzer.disable(); 00192 } 00193 00194 void onConnectionCallback(const Gap::ConnectionCallbackParams_t *params){ 00195 #if DEBUG_CONNECTION 00196 scanLED = !scanLED; // Blue 00197 wait_ms(100); 00198 scanLED = !scanLED; // Blue 00199 wait_ms(100); 00200 scanLED = !scanLED; // Blue 00201 wait_ms(100); 00202 scanLED = !scanLED; // Blue 00203 wait_ms(100); 00204 scanLED = !scanLED; // Blue 00205 wait_ms(100); 00206 scanLED = !scanLED; // Blue 00207 wait_ms(100); 00208 scanLED = 1; // Blue 00209 #endif 00210 WakeSleepT.detach(); 00211 sleepFlag = false; 00212 } 00213 00214 00215 /* Restart Advertising on disconnection*/ 00216 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params){ 00217 buzzerStop(); 00218 #if DEBUG_CONNECTION 00219 advLED = !advLED; // RED 00220 wait_ms(100); 00221 advLED = !advLED; 00222 wait_ms(100); 00223 advLED = !advLED; 00224 wait_ms(100); 00225 advLED = !advLED; 00226 wait_ms(100); 00227 advLED = 1; 00228 wait_ms(100); 00229 advLED = 1; 00230 #endif 00231 WakeSleepT.attach(WakeMeUp, FREE_TIME_S); 00232 sleepFlag = true; 00233 00234 } 00235 00236 void onDataWrittenCallback(const GattWriteCallbackParams *params) { 00237 if(params->handle == ackServicePtr->getACKCharacteristicHandle()){ 00238 // Something is written into AckCharacteristic 00239 if(params->data[0] == startBuzz[0]){ 00240 if(params->data[1] == startBuzz[1]){ 00241 #if DEBUG_CONNECTION 00242 connectedLED = !connectedLED; // BLUE 00243 wait_ms(100); 00244 connectedLED = !connectedLED; 00245 wait_ms(100); 00246 connectedLED = !connectedLED; 00247 wait_ms(100); 00248 connectedLED = !connectedLED; 00249 wait_ms(100); 00250 connectedLED = !connectedLED; 00251 wait_ms(100); 00252 connectedLED = 1; 00253 wait_ms(100); 00254 #endif 00255 //buzzerStart(); 00256 toggleBuzzer.attach(buzzerToggle, BUZZER_ON_TIME_S); 00257 #if ACN_FREIGHT 00258 toggleLed.attach(ledToggle, LED_BLINK_HALF_T); 00259 #endif 00260 return; 00261 } 00262 } 00263 else if(params->data[0] == stopBuzz[0]){ 00264 if(params->data[1] == stopBuzz[1]){ 00265 toggleBuzzer.detach(); 00266 buzzerStop(); 00267 #if ACN_FREIGHT 00268 toggleLed.detach(); 00269 signal_led = 1; 00270 #endif 00271 WakeSleepT.detach(); 00272 WakeSleepT.attach(WakeMeUp, FREE_TIME_S); 00273 ble.disconnect(Gap::LOCAL_HOST_TERMINATED_CONNECTION); 00274 } 00275 } 00276 } 00277 else{ 00278 // Execute this for wrong data written into characteristic 00279 return; 00280 } 00281 } 00282 00283 /** 00284 * This function is called when the ble initialization process has failed 00285 */ 00286 void onBleInitError(BLE &ble, ble_error_t error){ 00287 /* Avoid compiler warnings */ 00288 (void) ble; 00289 (void) error; 00290 /* Initialization error handling should go here */ 00291 } 00292 00293 /** 00294 * Callback triggered when the ble initialization process has finished 00295 */ 00296 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params){ 00297 BLE& ble = params->ble; 00298 ble_error_t error = params->error; 00299 00300 if (error != BLE_ERROR_NONE) { 00301 /* In case of error, forward the error handling to onBleInitError */ 00302 onBleInitError(ble, error); 00303 return; 00304 } 00305 00306 /* Ensure that it is the default instance of BLE */ 00307 if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { 00308 return; 00309 } 00310 00311 uint8_t init_values[4] = {0,0,0,0}; 00312 /* Get my MAC address */ 00313 BLEProtocol::AddressType_t temp_address_type; 00314 ble.gap().getAddress(&temp_address_type, myMacAddress); 00315 ackServicePtr = new ACKService<4>(ble, init_values); 00316 ackServicePtr->updateMacAddress(myMacAddress); // Update MAC address 00317 00318 ble.gap().onDisconnection(disconnectionCallback); 00319 ble.gap().onConnection(onConnectionCallback); 00320 ble.gattServer().onDataWritten(onDataWrittenCallback); 00321 00322 #if ACN_FREIGHT 00323 AdvertisingFormat msd; 00324 00325 msd.manufacturerID = MANUFACTURER_ID; 00326 msd.aconnoID = ACONNO_ID; 00327 msd.productID = PRODUCT_ID; 00328 msd.version = VERSION; 00329 00330 ble.gap().accumulateAdvertisingPayload( 00331 GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, 00332 (uint8_t*)&msd, sizeof(msd)); 00333 #endif 00334 00335 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::INCOMPLETE_LIST_128BIT_SERVICE_IDS, (uint8_t*)UUID, sizeof(UUID)); 00336 ble.gap().setAdvertisingInterval(ADV_INTERVAL); // --> Has to be at least 100ms! 00337 } 00338 00339 00340 00341 void startAdvertising(){ 00342 ble.gap().startAdvertising(); 00343 #if DEBUG 00344 advLED = 0; 00345 scanLED = 1; 00346 #endif 00347 WakeSleepT.detach(); 00348 WakeSleepT.attach(WakeMeUp, ADV_TIMER_TIME_S); // Call the wakeMeUp function 00349 } 00350 00351 void WakeMeUp(){ 00352 sleepFlag = false; 00353 switch(radioState){ 00354 case OFF:{ 00355 radioState = ADVERTISING; 00356 startAdvertising(); 00357 break; 00358 } 00359 case ADVERTISING:{ 00360 radioState = OFF; 00361 WakeSleepT.detach(); 00362 WakeSleepT.attach(GoToSleep, FREE_TIME_S); 00363 break; 00364 } 00365 default: return; 00366 } 00367 } 00368 00369 void GoToSleep(){ 00370 WakeSleepT.detach(); 00371 WakeSleepT.attach(WakeMeUp, SLEEP_TIME_S); 00372 ble.gap().stopAdvertising(); 00373 sleepFlag = true; 00374 #if DEBUG 00375 advLED = 1; 00376 scanLED = 1; 00377 #endif 00378 } 00379 00380 #if USE_ACC 00381 void pulse_handler(){ 00382 #if DEBUG_WAKEUP_BUZZER 00383 buzzerStart(); 00384 wait_ms(50); 00385 buzzerStop(); 00386 #endif 00387 #if DEBUG_ACC 00388 int_led = !int_led; 00389 #endif 00390 } 00391 #endif 00392 00393 int main(){ 00394 #if DEBUG || DEBUG_MAC 00395 advLED = 1; 00396 scanLED = 1; 00397 connectedLED = 1; 00398 #endif 00399 00400 #if USE_ACC 00401 accPower = 1; 00402 i2cPower = 1; 00403 #endif 00404 00405 #if ACN_FREIGHT 00406 signal_led = 1; 00407 #endif 00408 00409 ble.init(bleInitComplete); 00410 /* SpinWait for initialization to complete. This is necessary because the BLE object is used in the main loop below. */ 00411 while (ble.hasInitialized() == false){ /* spin loop */ } 00412 __enable_irq(); 00413 00414 buzzerStart(); 00415 wait_ms(500); 00416 buzzerStop(); 00417 00418 WakeSleepT.attach(GoToSleep, AWAKE_TIME_S); 00419 00420 while(true){ 00421 ble.waitForEvent(); 00422 } 00423 }
Generated on Sun Jul 24 2022 15:28:24 by
1.7.2

