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 BLE_HID mbed nRF51822
Fork of BLENano_HID by
main.cpp
00001 /** 00002 * Handheld BLE finger input device based on Seeed Studio Tiny BLE (TinyBLE). 00003 * By Shervin Emami (http://shervinemami.info/), 25th Aug 2018. 00004 * If the analog voltage on a "finger" pin is below a threshold voltage, 00005 * then it sends a mouse command using Bluetooth BLE, so that any computer or 00006 * smartphone can be configured to perform a desired function due to this input event. 00007 * 00008 * 00009 * This program implements a complete HID-over-Gatt Profile: 00010 * - HID is provided by KeyboardService 00011 * - Battery Service 00012 * - Device Information Service 00013 * 00014 * Complete strings can be sent over BLE using printf. Please note, however, than a 12char string 00015 * will take about 500ms to transmit, principally because of the limited notification rate in BLE. 00016 * KeyboardService uses a circular buffer to store the strings to send, and calls to putc will fail 00017 * once this buffer is full. This will result in partial strings being sent to the client. 00018 00019 * Tested with mbed libraries for April 2nd, 2018. If you use a newer version of mbed or other 00020 * libs and you have problems, try rolling back to April 2nd, 2018. 00021 */ 00022 00023 // Configure the settings of my board. 00024 #include "tiny_ble.h" // Seeed Studio Tiny BLE 00025 00026 00027 // Define LOG_MESSAGES if you want various debug messages to be sent to the PC via a UART cable. 00028 #define LOG_MESSAGES 00029 00030 00031 const float FINGER1_PRESS = 0.42f; // Set how much the person needs to press their finger in to trigger a keypress. 00032 const float FINGER2_PRESS = 0.41f; // Note that each finger is slightly different strength, due to the mechanical design. 00033 const float FINGER3_PRESS = 0.38f; // 00034 const float FINGER4_PRESS = 0.37f; // 00035 00036 const float FINGER1_RELEASE = 0.35f; // Set how much the person needs to release their finger to finish a keypress. 00037 const float FINGER2_RELEASE = 0.35f; // Note that each finger is slightly different strength, due to the mechanical design. 00038 const float FINGER3_RELEASE = 0.34f; // 00039 const float FINGER4_RELEASE = 0.34f; // 00040 00041 const float BATTERY_NEEDS_CHARGE = 0.198f; // 0.20 means >= 3.4V, 0.19 means >= 2.4V. 00042 00043 00044 /* mbed Microcontroller Library 00045 * Copyright (c) 2015 ARM Limited 00046 * 00047 * Licensed under the Apache License, Version 2.0 (the "License"); 00048 * you may not use this file except in compliance with the License. 00049 * You may obtain a copy of the License at 00050 * 00051 * http://www.apache.org/licenses/LICENSE-2.0 00052 * 00053 * Unless required by applicable law or agreed to in writing, software 00054 * distributed under the License is distributed on an "AS IS" BASIS, 00055 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00056 * See the License for the specific language governing permissions and 00057 * limitations under the License. 00058 */ 00059 00060 #include "mbed.h" 00061 00062 #include "ble/BLE.h" 00063 //#include "KeyboardService.h" 00064 #include "MouseService.h" 00065 00066 00067 #include "examples_common.h" 00068 00069 00070 00071 #undef HID_DEBUG 00072 #undef LOG 00073 #ifdef LOG_MESSAGES 00074 #define LOG(...) { pc.printf(__VA_ARGS__); } 00075 Serial pc(UART_TX, UART_RX); 00076 #else 00077 #define LOG(...) 00078 #endif 00079 #define HID_DEBUG LOG 00080 00081 00082 AnalogIn battery(BATTERY_PIN); // For measuring the battery level 00083 AnalogIn finger1(FINGER1_PIN); // For measuring a finger level 00084 AnalogIn finger2(FINGER2_PIN); // 00085 AnalogIn finger3(FINGER3_PIN); // 00086 AnalogIn finger4(FINGER4_PIN); // 00087 DigitalOut waiting_led(LED_RED); // For showing BLE is trying to connect 00088 DigitalOut connected_led(LED_GREEN); // For showing BLE is connected 00089 DigitalOut status_led(LED_BLUE); // For showing BLE is busy 00090 DigitalOut enable_out3v3(OUT3V3_PIN); // For using OUT_3V3 pin of TinyBLE 00091 00092 #define LED_ON 0 // LEDs on Tiny BLE need 0V to light up. 00093 #define LED_OFF 1 // 00094 00095 00096 bool haveAskedForRecharge = false; // Only ask for a recharge once per poweron. Requires user to turn device off once per day! 00097 00098 00099 InterruptIn button1(BUTTON_PIN); // For sending a BLE command 00100 00101 BLE ble; 00102 //KeyboardService *kbdServicePtr; 00103 MouseService *mouseServicePtr; 00104 00105 static const char DEVICE_NAME[] = "ShervMouse"; 00106 static const char SHORT_DEVICE_NAME[] = "ShMouse"; 00107 00108 00109 // Status flags that are updated in ISR callback functions. 00110 volatile bool check_fingers = false; 00111 volatile bool press_keyup[5] = {false}; 00112 00113 00114 00115 static void onDisconnect(const Gap::DisconnectionCallbackParams_t *params) 00116 { 00117 HID_DEBUG("discon\n\r"); 00118 waiting_led = LED_ON; 00119 connected_led = LED_OFF; 00120 00121 ble.gap().startAdvertising(); // restart advertising 00122 } 00123 00124 static void onConnect(const Gap::ConnectionCallbackParams_t *params) 00125 { 00126 HID_DEBUG("conn\n\r"); 00127 waiting_led = LED_OFF; 00128 connected_led = LED_ON; 00129 } 00130 00131 00132 00133 00134 00135 // ISR callback function that is automatically called every 0.1 seconds or so. 00136 // Make sure there isn't anything slow like printf in this ISR! 00137 static void heartbeat_ISR() { 00138 if (!mouseServicePtr->isConnected()) 00139 waiting_led = !waiting_led; 00140 else { 00141 //connected_led = !connected_led; 00142 //waiting_led = 0; 00143 } 00144 00145 // Signal that we should check the finger sensors soon. 00146 check_fingers = true; 00147 } 00148 00149 00150 int main() 00151 { 00152 #ifdef LOG_MESSAGES 00153 pc.baud(115200); // Use fast UART for log messages instead of default 9600 bps. 00154 #endif 00155 00156 waiting_led = LED_OFF; // Set LEDs to blue, until ready. 00157 connected_led = LED_OFF; 00158 status_led = LED_ON; 00159 00160 wait(1); 00161 LOG("---- Shervin's Mouse Input device, using TinyBLE + BLE HID mouse service ----\n\r"); 00162 00163 // Call the button1_ISR function whenever the pushbutton is pressed. 00164 //button1.rise(button1_ISR); 00165 00166 HID_DEBUG("initialising ticker\n\r"); 00167 00168 // Call the heartbeat_ISR function every 0.1 seconds 00169 Ticker heartbeat; 00170 heartbeat.attach(heartbeat_ISR, 0.1f); 00171 00172 HID_DEBUG("enabling finger sensors\n\r"); 00173 enable_out3v3 = 1; 00174 00175 HID_DEBUG("initialising ble\n\r"); 00176 ble.init(); 00177 00178 ble.gap().onDisconnection(onDisconnect); 00179 ble.gap().onConnection(onConnect); 00180 00181 initializeSecurity(ble); 00182 00183 HID_DEBUG("adding hid mouse service\n\r"); 00184 MouseService mouseService(ble); 00185 mouseServicePtr = &mouseService; 00186 00187 HID_DEBUG("adding device info and battery service\n\r"); 00188 initializeHOGP(ble); 00189 00190 HID_DEBUG("setting up gap\n\r"); 00191 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::MOUSE); 00192 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, 00193 (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); 00194 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, 00195 (uint8_t *)SHORT_DEVICE_NAME, sizeof(SHORT_DEVICE_NAME)); 00196 00197 HID_DEBUG("advertising\n\r"); 00198 ble.gap().startAdvertising(); 00199 00200 // Turn LEDs to green connected. 00201 connected_led = LED_ON; 00202 waiting_led = LED_OFF; 00203 status_led = LED_OFF; 00204 00205 // Run forever ... 00206 LOG("Ready to run forever ...\n\r"); 00207 int counter1 = 0; 00208 int counter2 = 0; 00209 while (true) { 00210 ble.waitForEvent(); 00211 00212 // Signal that we should check the finger sensors soon. 00213 if (check_fingers) { 00214 check_fingers = false; 00215 00216 // Measure all the finger sensors and battery level. 00217 float fing1 = finger1.read(); 00218 float fing2 = finger2.read(); 00219 float fing3 = finger3.read(); 00220 float fing4 = finger4.read(); 00221 float batt = battery.read(); 00222 00223 // If a finger was pressed and now has been released, possibly send another event. 00224 if (press_keyup[1] && fing1 < FINGER1_RELEASE) { 00225 press_keyup[1] = false; // Clear the flag 00226 LOG("key up for 1.\n\r"); 00227 00228 // Nothing needs to be done for releasing a mouse click. 00229 } 00230 if (press_keyup[2] && fing2 < FINGER2_RELEASE) { 00231 press_keyup[2] = false; // Clear the flag 00232 LOG("key up for 2.\n\r"); 00233 00234 // Nothing needs to be done for releasing a mouse click. 00235 } 00236 if (press_keyup[3] && fing3 < FINGER3_RELEASE) { 00237 press_keyup[3] = false; // Clear the flag 00238 LOG("key up for 3.\n\r"); 00239 00240 // Stop the scrolling. 00241 mouseServicePtr->setSpeed(0, 0, 0); 00242 } 00243 if (press_keyup[4] && fing4 < FINGER4_RELEASE) { 00244 press_keyup[4] = false; // Clear the flag 00245 LOG("key up for 4.\n\r"); 00246 00247 // Stop the scrolling. 00248 mouseServicePtr->setSpeed(0, 0, 0); 00249 } 00250 00251 00252 // Very occasionally, show the connected LED 00253 counter1++; 00254 if (counter1 == 1) { 00255 if (mouseServicePtr->isConnected()) { 00256 connected_led = LED_ON; 00257 waiting_led = LED_OFF; 00258 } 00259 } 00260 if (counter1 == 2) { 00261 //counter2 = 0; 00262 connected_led = LED_OFF; 00263 waiting_led = LED_OFF; 00264 } 00265 00266 00267 // Occasionally show some debug info 00268 if (counter1 > 15) { 00269 //counter2++; 00270 LOG("%.2f%. F1=%.2f, F2=%.2f, F3=%.2f, F4=%.2f\n\r", batt, fing1, fing2, fing3, fing4); 00271 00272 // Check for low battery 00273 if (batt < BATTERY_NEEDS_CHARGE) { 00274 // Toggle blue LED 00275 waiting_led = LED_OFF; 00276 connected_led = LED_OFF; 00277 status_led = !status_led; 00278 if (!haveAskedForRecharge) { 00279 //send_string("RECHARGE BATTERY!"); 00280 haveAskedForRecharge = true; 00281 } 00282 LOG("RECHARGE BATTERY!\n\r"); 00283 } 00284 //else { 00285 //} 00286 counter1 = 0; 00287 } 00288 00289 // Check if a finger was pressed 00290 if (fing1 > FINGER1_PRESS && !press_keyup[1]) { 00291 LOG("finger 1.\n\r"); 00292 press_keyup[1] = true; // Don't trigger this event again until the finger has been released. 00293 00294 mouseServicePtr->setButton(MOUSE_BUTTON_LEFT, BUTTON_DOWN); 00295 wait(0.05); // Add a slight delay 00296 ble.waitForEvent(); // Add a slight delay 00297 mouseServicePtr->setButton(MOUSE_BUTTON_LEFT, BUTTON_UP); 00298 } 00299 if (fing2 > FINGER2_PRESS && !press_keyup[2]) { 00300 LOG("finger 2.\n\r"); 00301 press_keyup[2] = true; // Don't trigger this event again until the finger has been released. 00302 00303 mouseServicePtr->setButton(MOUSE_BUTTON_RIGHT, BUTTON_DOWN); 00304 wait(0.05); // Add a slight delay 00305 ble.waitForEvent(); // Add a slight delay 00306 mouseServicePtr->setButton(MOUSE_BUTTON_RIGHT, BUTTON_UP); 00307 } 00308 if (fing3 > FINGER3_PRESS && !press_keyup[3]) { 00309 LOG("finger 3.\n\r"); 00310 press_keyup[3] = true; // Don't trigger this event again until the finger has been released. 00311 00312 // Start scrolling down, until the user releases this finger. 00313 mouseServicePtr->setSpeed(0, 0, 1); 00314 } 00315 if (fing4 > FINGER4_PRESS && !press_keyup[4]) { 00316 LOG("finger 4.\n\r"); 00317 press_keyup[4] = true; // Don't trigger this event again until the finger has been released. 00318 00319 // Start scrolling up, until the user releases this finger. 00320 mouseServicePtr->setSpeed(0, 0, -1); 00321 } 00322 } 00323 } 00324 }
Generated on Mon Jul 25 2022 12:29:34 by
