Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API mbed nRF51822
Fork of MCS_LRF by
main.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "mbed.h" 00018 #include "Serial.h" 00019 #include "BLE.h" 00020 #include "DeviceInformationService.h" 00021 #include "UARTService.h" 00022 #include "bleHelper.h" 00023 #include "laser.h" 00024 #include "ACA.h" 00025 00026 00027 00028 00029 /* Set this if you need debug messages on the console; 00030 * it will have an impact on code-size and power consumption. */ 00031 #define NEED_CONSOLE_OUTPUT 0 00032 00033 // only used for parsing tag data- will not work if parse function is called from within serial interrupt 00034 #define NEED_PARSE_TRACE 0 00035 00036 Serial pc(USBTX, USBRX); 00037 #if NEED_CONSOLE_OUTPUT 00038 #define DEBUG(...) { pc.printf(__VA_ARGS__); } 00039 #else 00040 #define DEBUG(...) /* nothing */ 00041 #endif /* #if NEED_CONSOLE_OUTPUT */ 00042 00043 #if NEED_PARSE_TRACE 00044 #define TRACE(...) { pc.printf(__VA_ARGS__); } 00045 #else 00046 #define TRACE(...) 00047 #endif /* #if NEED_TRACE */ 00048 00049 #define SET_PARAM_CMD_MASK 0x8000 // commands with MSB set to 0 are to get the parameter and MSB of 1 to set the parameter 00050 #define READER_BAUD_RATE 115200 00051 #define PB_DEBUNCE_TIME 100 00052 #define PB_HOLD_TIME 1000 // ms- Holding the push button longer than this will turn the laser dot off if it is on 00053 00054 #define BATT_VALUE_THRESHOLD 0.5360f // values by experiment 3.6V 00055 //#define BATT_VALUE_HYSTERYSIS 0.0200f // about 0.05 volt 00056 00057 #define ACTIVITY_TIMEOUT_SEC 60 // default value- turn laser off if no measurement for more than this many seconds 00058 00059 #undef NORDIC // is board nordic DK? 00060 00061 #ifdef NORDIC 00062 DigitalOut connectionLed(p21); 00063 DigitalOut triggerLed(p22); 00064 Serial serial(p13, p17); // tx, rx === NOTE tx port pin needs to be wired and verified (for nordic DK) 00065 Laser laser(serial); 00066 InterruptIn triggerButton(p18); // Button 2 00067 #else 00068 DigitalOut connectionLed(p23); 00069 //PwmOut connectionLed(p23); // good idea using PwmOut but it seems that period can't be set to longer than about 1s 00070 DigitalOut redLed(p24); 00071 InterruptIn triggerButton(p22); 00072 DigitalOut disableLRF(p28); 00073 DigitalOut enableBattVoltSense (p29); 00074 AnalogIn battVoltage (p1); 00075 DigitalOut nReset(p30); 00076 DigitalIn LRF_BOOT(p25, PullNone); 00077 DigitalIn LRF_CAL(p0, PullNone); 00078 // IO For ACA 00079 DigitalOut disableVBUS(p8); 00080 DigitalOut ID_SW1(p7); 00081 DigitalOut ID_SW(p6); 00082 DigitalIn VBUS_IN(p5, PullNone); 00083 #endif 00084 00085 Serial* serialPtr; 00086 Laser* laserPtr; 00087 BLEDevice ble; 00088 UARTService *uartServicePtr; 00089 BLEHelper* bleHelper; 00090 static uint8_t isConnected = 0; 00091 Timer timer; 00092 Ticker batteryChecker; 00093 Ticker activityChecker; 00094 Ticker connectionLedBlinker; 00095 Ticker ACACharger; 00096 uint16_t activityTimeout = ACTIVITY_TIMEOUT_SEC; 00097 00098 // settings for blinking the connection LED- Blink to save power 00099 uint16_t connectionLedOffCount = 0; 00100 #define CONNECTION_LED_OFF_TIME_MS 2000 00101 #define CONNECTION_LED_ON_TIME_MS 20 00102 #define CONNECTION_LED_OFF_COUNT (CONNECTION_LED_OFF_TIME_MS / CONNECTION_LED_ON_TIME_MS) 00103 // 00104 00105 const static char DEVICE_NAME[] = "MCS_EEP_01"; 00106 const static char MANUFACTURER[] = "MCS"; 00107 const static char MODEL[] = "Model 2"; 00108 const static char SERIAL_NO[] = "SN 1234"; 00109 const static char HARDWARE_REV[] = "hw-rev 1.1"; 00110 const static char FIRMWARE_REV[] = "fw-rev 1.5"; 00111 const static char SOFTWARE_REV[] = "soft-rev 1.5"; 00112 00113 // these values must macth definitions in the XML file accompanying this device 00114 const static uint16_t distanceCmd = 0x0001; 00115 const static uint16_t triggerCmd = 0x0002; 00116 const static uint16_t redDotCmd = 0x0003; 00117 const static uint16_t resetCmd = 0x0004; 00118 const static uint16_t nSamplesCmd = 0x0005; 00119 const static uint16_t activityTimeoutCmd = 0x0006; 00120 00121 00122 void activityCheckerTask(); 00123 void resetActivityCheckerTask(); 00124 void turnLaserPowerOff(); 00125 00126 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) 00127 { 00128 DEBUG("Disconnected!\n\r"); 00129 DEBUG("Restarting the advertising process\n\r"); 00130 ble.startAdvertising(); 00131 isConnected = 0; 00132 // connectionLed = isConnected; 00133 00134 // turn off blinking LED 00135 // connectionLed.pulsewidth_ms(0); 00136 } 00137 00138 void connectionCallback(const Gap::ConnectionCallbackParams_t *params) 00139 { 00140 DEBUG("Connected!\n\r"); 00141 isConnected = 1; 00142 //connectionLed = isConnected; 00143 // connectionLed.pulsewidth_ms(25); 00144 } 00145 00146 void passkeyDisplayCallback(Gap::Handle_t handle, const SecurityManager::Passkey_t passkey) 00147 { 00148 printf("Input passKey: "); 00149 for (unsigned i = 0; i < Gap::ADDR_LEN; i++) { 00150 printf("%c ", passkey[i]); 00151 } 00152 printf("\r\n"); 00153 } 00154 00155 void securitySetupCompletedCallback(Gap::Handle_t handle, SecurityManager::SecurityCompletionStatus_t status) 00156 { 00157 if (status == SecurityManager::SEC_STATUS_SUCCESS) { 00158 printf("Security success\r\n"); 00159 } else { 00160 printf("Security failed\r\n"); 00161 } 00162 } 00163 00164 static void processData(const GattWriteCallbackParams *params) 00165 { 00166 if(params->len >= 2) { 00167 uint16_t command = params->data[0] + (params->data[1] << 8); 00168 bool isSetCmd = (command & SET_PARAM_CMD_MASK) == SET_PARAM_CMD_MASK; 00169 DEBUG("command: %d \r\n", command); 00170 00171 switch(command & ~SET_PARAM_CMD_MASK) { 00172 case distanceCmd: 00173 if(!isSetCmd && params->len == 2) { 00174 // form the reply to send 00175 DEBUG("CMD is GET distance\n\r"); 00176 laserPtr->triggerDistanceMeasurement(); 00177 } 00178 break; 00179 00180 // TODO not needed really- can just use the distance command 00181 case triggerCmd: 00182 if(isSetCmd && params->len == 3) { 00183 // form the reply to send 00184 DEBUG("CMD is SET trigger\n\r"); 00185 laserPtr->triggerDistanceMeasurement(); 00186 } 00187 break; 00188 00189 case redDotCmd: 00190 if(isSetCmd && params->len == 3) { 00191 DEBUG("CMD is SET redDot\n\r"); 00192 laserPtr->setRedDot(params->data[2]); 00193 } 00194 break; 00195 00196 case resetCmd: 00197 if(isSetCmd && params->len == 3) { 00198 DEBUG("CMD is reset\n\r"); 00199 nReset = 0; 00200 wait_ms(100); 00201 nReset = 1; 00202 wait_ms(1000); 00203 laserPtr->enableMeasurement(true); 00204 } 00205 break; 00206 00207 case nSamplesCmd: 00208 if(isSetCmd && params->len == 4) { 00209 DEBUG("CMD is nSample\n\r"); 00210 int16_t nSamples = params->data[2] + (params->data[3] << 8); 00211 laserPtr->setNumberOfSamples(nSamples); 00212 } 00213 break; 00214 00215 case activityTimeoutCmd: 00216 if(isSetCmd && params->len == 4) { 00217 DEBUG("CMD is nSample\n\r"); 00218 activityTimeout = params->data[2] + (params->data[3] << 8); 00219 } 00220 break; 00221 00222 default: 00223 break; 00224 } 00225 } 00226 } 00227 00228 00229 // Serial driver seems to be buggy and allocate p8 and p10 for flow control 00230 // by default- Need to manually disable flow control since the function for 00231 // disabling Serail.set_flow_control(Serial::Disabled) is not recognised by 00232 // the compiler either! Could be something to do with the target processor?? 00233 static void disableFlowControl() 00234 { 00235 uint32_t base = 0x40002000; 00236 uint32_t ctsOffset = 0x510; 00237 uint32_t rtsOffset = 0x508; 00238 00239 uint32_t cts = base + ctsOffset; 00240 uint32_t rts = base + rtsOffset; 00241 00242 uint32_t* pcts = (uint32_t*)cts; 00243 uint32_t* prts = (uint32_t*)rts; 00244 00245 // no pin allocated for CTS and RTS 00246 *pcts = 0xffffffff; 00247 *prts = 0xffffffff; 00248 } 00249 00250 void resetActivityCheckerTask() 00251 { 00252 activityChecker.detach(); 00253 activityChecker.attach(activityCheckerTask, activityTimeout); 00254 } 00255 00256 void onDataWritten(const GattWriteCallbackParams *params) 00257 { 00258 if ((uartServicePtr != NULL) && (params->handle == uartServicePtr->getTXCharacteristicHandle())) { 00259 uint16_t bytesRead = params->len; 00260 DEBUG("received %u bytes\n\r", bytesRead); 00261 for(int i = 0; i < bytesRead; i++) { 00262 DEBUG("0x%X ", params->data[i]); 00263 } 00264 DEBUG("\n\r", bytesRead); 00265 00266 // echo? 00267 // ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), params->data, bytesRead); 00268 00269 // make sure the laser is not powered off due to inactivity 00270 resetActivityCheckerTask(); 00271 laserPtr->turnLaserPowerOn(); 00272 00273 processData(params); 00274 } 00275 } 00276 00277 // this is an ISR, so do not spend too much time here and be careful with printing debug info 00278 void readerCallback() 00279 { 00280 //if(serial.readable()) { 00281 // laserPtr->processRxData(serial.getc()); 00282 // } 00283 } 00284 00285 /* This method is called when a distance measurement is ready to be sent to the client. 00286 send distance measurement to the connected BLE client */ 00287 void distanceCallcack(float distance, float elapsedTime) 00288 { 00289 uint8_t buf[10]; 00290 uint16_t arrayLen = 2; 00291 memcpy(&buf[0], &arrayLen, sizeof(uint16_t)); 00292 memcpy(&buf[2], &distance, sizeof(float)); 00293 memcpy(&buf[6], &elapsedTime, sizeof(float)); 00294 bleHelper->sendPacketOverBLE(distanceCmd, buf, sizeof(buf)); 00295 } 00296 00297 void notifyActivityTimeout(){ 00298 uint8_t buf[1]; 00299 bleHelper->sendPacketOverBLE(activityTimeoutCmd, buf, 0); 00300 } 00301 00302 void connectionLedBlinkerTask() 00303 { 00304 if(isConnected) { 00305 if(connectionLed) { 00306 connectionLed = 0; 00307 connectionLedOffCount = 0; 00308 } else if(++connectionLedOffCount > CONNECTION_LED_OFF_COUNT) { 00309 connectionLed = 1; 00310 } 00311 } else { 00312 connectionLed = 0; 00313 } 00314 } 00315 00316 00317 void batteryCheckerTask(void) 00318 { 00319 enableBattVoltSense = 1; 00320 wait_ms(20); // wait for the circuit to settle 00321 float batt = battVoltage.read(); 00322 enableBattVoltSense = 0; 00323 00324 if(redLed == 0 && batt < BATT_VALUE_THRESHOLD) { 00325 redLed = 1; 00326 } 00327 } 00328 00329 00330 /* processor for the hardware trigger button */ 00331 void triggerFall() 00332 { 00333 resetActivityCheckerTask(); 00334 laserPtr->turnLaserPowerOn(); 00335 00336 laserPtr->triggerDistanceMeasurement(); 00337 00338 timer.reset(); 00339 timer.start(); 00340 } 00341 00342 void turnLaserPowerOff() 00343 { 00344 laserPtr->turnLaserPowerOff(); 00345 notifyActivityTimeout(); 00346 } 00347 00348 /* interrupt processor for when the button is released. If it has been pushed and held, turn the red dot off on release, 00349 otherwise debunce and make a measurement */ 00350 void triggerRise() 00351 { 00352 int elapsed = timer.read_ms(); 00353 timer.stop(); 00354 if(elapsed > PB_HOLD_TIME) { 00355 turnLaserPowerOff(); 00356 } 00357 //else if(elapsed > PB_DEBUNCE_TIME) { 00358 // laserPtr->triggerDistanceMeasurement(); 00359 // } 00360 } 00361 00362 void activityCheckerTask() 00363 { 00364 // too long with no activity- turn pwer off from laser to preserve power 00365 turnLaserPowerOff(); 00366 } 00367 00368 int main(void) 00369 { 00370 connectionLed = 0; 00371 00372 // turn laser on and reset and wait for it to settle 00373 disableLRF = 0; 00374 nReset = 1; 00375 wait_ms(1000); 00376 00377 DEBUG("Initialising the nRF51822\n\r"); 00378 ble.init(); 00379 00380 /* Initialize BLE security */ 00381 bool enableBonding = true; 00382 bool requireMITM = false; 00383 ble.securityManager().init(enableBonding, requireMITM, SecurityManager::IO_CAPS_NONE); 00384 00385 ble.onDisconnection(disconnectionCallback); 00386 ble.onConnection(connectionCallback); 00387 ble.onDataWritten(onDataWritten); 00388 ble.securityManager().onPasskeyDisplay(passkeyDisplayCallback); 00389 ble.securityManager().onSecuritySetupCompleted(securitySetupCompletedCallback); 00390 00391 /* setup advertising */ 00392 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); 00393 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); 00394 ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, (const uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME) - 1); 00395 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,(const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed)); 00396 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, 00397 (uint8_t *)GattService::UUID_DEVICE_INFORMATION_SERVICE, sizeof(GattService::UUID_DEVICE_INFORMATION_SERVICE)); 00398 ble.setAdvertisingInterval(GapAdvertisingParams::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(1000)); 00399 ble.startAdvertising(); 00400 00401 // check battery level now and every minute afterwards 00402 batteryCheckerTask(); 00403 batteryChecker.attach(batteryCheckerTask, 60); 00404 00405 // check acticity once every 3 minutes 00406 activityChecker.attach(activityCheckerTask, activityTimeout); 00407 00408 /* Setup uart service */ 00409 UARTService uartService(ble); 00410 uartServicePtr = &uartService; 00411 00412 /* Setup auxiliary service. */ 00413 DeviceInformationService deviceInfo(ble, MANUFACTURER, MODEL, SERIAL_NO,HARDWARE_REV, FIRMWARE_REV, SOFTWARE_REV); 00414 00415 /* Setup bleHelper */ 00416 BLEHelper helper(&ble, uartServicePtr); 00417 bleHelper = &helper; 00418 00419 // setup serial port to LRF 00420 serialPtr = new Serial(p27, p26); 00421 disableFlowControl(); 00422 serialPtr->baud(READER_BAUD_RATE); 00423 // serial.attach(&readerCallback); 00424 00425 // processors for the trigger button 00426 triggerButton.fall(&triggerFall); 00427 triggerButton.rise(&triggerRise); 00428 00429 // setup laser 00430 laserPtr = new Laser(*serialPtr); 00431 laserPtr->enableMeasurement(true); 00432 laserPtr->setDistaceCallback(&distanceCallcack); 00433 laserPtr->turnLaserPowerOn(); 00434 laserPtr->setRedDot(false); // turn off dot initially 00435 00436 // setup blinking connectionLed 00437 // connectionLed.period(2.0f); 00438 connectionLedBlinker.attach(connectionLedBlinkerTask, CONNECTION_LED_ON_TIME_MS / 1000.0f); 00439 00440 // Setup task to implement ACA Charger mode on phone. 00441 ACACharger.attach(ACAChargerTask, ACA_CHARGER_TASK_TIME_MS / 1000.0f); 00442 00443 while (true) { 00444 ble.waitForEvent(); 00445 } 00446 }
Generated on Sat Jul 16 2022 03:52:21 by
1.7.2
