From e0a3ca6fe6dcca8b7557063a1d99ff614d9547fa Mon Sep 17 00:00:00 2001
From: Samo Penic <samo.penic@gmail.com>
Date: Mon, 16 May 2022 23:16:20 +0000
Subject: [PATCH] Further development of firmware for Bluetooth data transmission.

---
 firmware/bt_debug/bt_debug.ino                                                   |   93 +++++++++++
 firmware/bluetooth_acceleromer_receiver_v1/bluetooth_acceleromer_receiver_v1.ino |  211 ++++++++++++++++++++++++++
 firmware/trigger_firmware/trigger_firmware.ino                                   |   31 ++-
 firmware/bluetooth_accelerometer_v1/bluetooth_accelerometer_v1.ino               |  117 ++++++++++++++
 4 files changed, 442 insertions(+), 10 deletions(-)

diff --git a/firmware/bluetooth_acceleromer_receiver_v1/bluetooth_acceleromer_receiver_v1.ino b/firmware/bluetooth_acceleromer_receiver_v1/bluetooth_acceleromer_receiver_v1.ino
new file mode 100644
index 0000000..d47610b
--- /dev/null
+++ b/firmware/bluetooth_acceleromer_receiver_v1/bluetooth_acceleromer_receiver_v1.ino
@@ -0,0 +1,211 @@
+
+/** NimBLE_Server Demo:
+ *
+ *  Demonstrates many of the available features of the NimBLE client library.
+ *
+ *  Created: on March 24 2020
+ *      Author: H2zero
+ *
+*/
+
+#include <NimBLEDevice.h>
+
+void scanEndedCB(NimBLEScanResults results);
+
+static NimBLEAdvertisedDevice* advDevice=nullptr;
+
+static bool doConnect = false;
+static uint32_t scanTime = 0; /** 0 = scan forever */
+static NimBLEClient* BTClient=nullptr;
+NimBLERemoteCharacteristic* BTChr = nullptr;
+
+/** Define a class to handle the callbacks when advertisments are received */
+class AdvertisedDeviceCallbacks: public NimBLEAdvertisedDeviceCallbacks {
+
+    void onResult(NimBLEAdvertisedDevice* advertisedDevice) {
+//        Serial.print("Advertised Device found: ");
+//        Serial.println(advertisedDevice->toString().c_str());
+        if(advertisedDevice->isAdvertisingService(NimBLEUUID("DEAD")))
+        {
+//            Serial.println("Found Our Service");
+            /** stop scan before connecting */
+            NimBLEDevice::getScan()->stop();
+            /** Save the device reference in a global for the client to use*/
+            advDevice = advertisedDevice;
+            /** Ready to connect now */
+            doConnect = true;
+        }
+    };
+};
+
+
+
+
+/** Callback to process the results of the last scan or restart it */
+void scanEndedCB(NimBLEScanResults results){
+//    Serial.println("Scan Ended");
+}
+
+
+/** Handles the provisioning of clients and connects / interfaces with the server */
+bool connectToServer() {
+    NimBLEClient* pClient = nullptr;
+
+    /** Check if we have a client we should reuse first **/
+    if(NimBLEDevice::getClientListSize()) {
+        /** Special case when we already know this device, we send false as the
+         *  second argument in connect() to prevent refreshing the service database.
+         *  This saves considerable time and power.
+         */
+        pClient = NimBLEDevice::getClientByPeerAddress(advDevice->getAddress());
+        if(pClient){
+            if(!pClient->connect(advDevice, false)) {
+  //              Serial.println("Reconnect failed");
+                return false;
+            }
+ //           Serial.println("Reconnected client");
+        }
+        /** We don't already have a client that knows this device,
+         *  we will check for a client that is disconnected that we can use.
+         */
+        else {
+            pClient = NimBLEDevice::getDisconnectedClient();
+        }
+    }
+
+    /** No client to reuse? Create a new one. */
+    if(!pClient) {
+        if(NimBLEDevice::getClientListSize() >= NIMBLE_MAX_CONNECTIONS) {
+//            Serial.println("Max clients reached - no more connections available");
+            return false;
+        }
+
+        pClient = NimBLEDevice::createClient();
+
+//        Serial.println("New client created");
+
+//        pClient->setClientCallbacks(&clientCB, false);
+        /** Set initial connection parameters: These settings are 15ms interval, 0 latency, 120ms timout.
+         *  These settings are safe for 3 clients to connect reliably, can go faster if you have less
+         *  connections. Timeout should be a multiple of the interval, minimum is 100ms.
+         *  Min interval: 12 * 1.25ms = 15, Max interval: 12 * 1.25ms = 15, 0 latency, 51 * 10ms = 510ms timeout
+         */
+        pClient->setConnectionParams(12,12,0,51);
+        /** Set how long we are willing to wait for the connection to complete (seconds), default is 30. */
+        pClient->setConnectTimeout(5);
+
+
+        if (!pClient->connect(advDevice)) {
+            /** Created a client but failed to connect, don't need to keep it as it has no data */
+            NimBLEDevice::deleteClient(pClient);
+  //          Serial.println("Failed to connect, deleted client");
+            return false;
+        }
+    }
+
+    if(!pClient->isConnected()) {
+        if (!pClient->connect(advDevice)) {
+//            Serial.println("Failed to connect");
+            return false;
+        }
+    }
+
+  //  Serial.print("Connected to: ");
+  //  Serial.println(pClient->getPeerAddress().toString().c_str());
+ //   Serial.print("RSSI: ");
+ //   Serial.println(pClient->getRssi());
+
+    /** Now we can read/write/subscribe the charateristics of the services we are interested in */
+    NimBLERemoteService* pSvc = nullptr;
+    NimBLERemoteCharacteristic* pChr = nullptr;
+    NimBLERemoteDescriptor* pDsc = nullptr;
+    BTClient = NimBLEDevice::getClientByPeerAddress(advDevice->getAddress());
+    pSvc = pClient->getService("DEAD");
+    if(pSvc) {     /** make sure it's not null */
+        pChr = pSvc->getCharacteristic("BEEF");
+        BTChr = pSvc->getCharacteristic("BEEF");
+        if(pChr) {     /** make sure it's not null */
+            if(pChr->canRead()) {
+        //        Serial.print(pChr->getUUID().toString().c_str());
+        //        Serial.print(" Value: ");
+        //        Serial.println(pChr->readValue().c_str());
+            }
+
+        }
+
+    } else {
+//        Serial.println("DEAD service not found.");
+    }
+
+
+//    Serial.println("Done with this device!");
+    return true;
+}
+
+void setup (){
+    Serial.begin(115200);
+//    Serial.println("Starting NimBLE Client");
+    /** Initialize NimBLE, no device name spcified as we are not advertising */
+    NimBLEDevice::init("");
+
+    /** Set the IO capabilities of the device, each option will trigger a different pairing method.
+     *  BLE_HS_IO_KEYBOARD_ONLY    - Passkey pairing
+     *  BLE_HS_IO_DISPLAY_YESNO   - Numeric comparison pairing
+     *  BLE_HS_IO_NO_INPUT_OUTPUT - DEFAULT setting - just works pairing
+     */
+    //NimBLEDevice::setSecurityIOCap(BLE_HS_IO_KEYBOARD_ONLY); // use passkey
+    //NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_YESNO); //use numeric comparison
+
+    /** 2 different ways to set security - both calls achieve the same result.
+     *  no bonding, no man in the middle protection, secure connections.
+     *
+     *  These are the default values, only shown here for demonstration.
+     */
+    //NimBLEDevice::setSecurityAuth(false, false, true);
+    NimBLEDevice::setSecurityAuth(/*BLE_SM_PAIR_AUTHREQ_BOND | BLE_SM_PAIR_AUTHREQ_MITM |*/ BLE_SM_PAIR_AUTHREQ_SC);
+
+    /** Optional: set the transmit power, default is 3db */
+    NimBLEDevice::setPower(ESP_PWR_LVL_P9); /** +9db */
+
+    /** Optional: set any devices you don't want to get advertisments from */
+    // NimBLEDevice::addIgnored(NimBLEAddress ("aa:bb:cc:dd:ee:ff"));
+
+    /** create new scan */
+    NimBLEScan* pScan = NimBLEDevice::getScan();
+
+    /** create a callback that gets called when advertisers are found */
+    pScan->setAdvertisedDeviceCallbacks(new AdvertisedDeviceCallbacks());
+
+    /** Set scan interval (how often) and window (how long) in milliseconds */
+    pScan->setInterval(45);
+    pScan->setWindow(15);
+
+    /** Active scan will gather scan response data from advertisers
+     *  but will use more energy from both devices
+     */
+    pScan->setActiveScan(true);
+    /** Start scanning for advertisers for the scan time specified (in seconds) 0 = forever
+     *  Optional callback for when scanning stops.
+     */
+    pScan->start(scanTime, scanEndedCB);
+
+}
+
+
+void loop (){
+    /** Loop here until we find a device we want to connect to */
+    while(!doConnect){
+      if(BTClient){
+        Serial.print(millis());
+        Serial.print(": "); 
+         Serial.println( (int)(BTChr->readValue().data()[0]));
+                  }
+             //Serial.println(millis());     
+        delay(10);
+    }
+   
+    doConnect = false;
+    connectToServer();
+    
+  //  NimBLEDevice::getScan()->start(scanTime,scanEndedCB);
+}
diff --git a/firmware/bluetooth_accelerometer_v1/bluetooth_accelerometer_v1.ino b/firmware/bluetooth_accelerometer_v1/bluetooth_accelerometer_v1.ino
new file mode 100644
index 0000000..1f117c5
--- /dev/null
+++ b/firmware/bluetooth_accelerometer_v1/bluetooth_accelerometer_v1.ino
@@ -0,0 +1,117 @@
+
+/** NimBLE_Server Demo:
+ *
+ *  Demonstrates many of the available features of the NimBLE server library.
+ *  
+ *  Created: on March 22 2020
+ *      Author: H2zero
+ * 
+*/
+
+#include <NimBLEDevice.h>
+
+static NimBLEServer* pServer;
+NimBLECharacteristic* pBeefCharacteristic;
+int counter;
+
+/** Handler class for characteristic actions */
+class CharacteristicCallbacks: public NimBLECharacteristicCallbacks {
+    void onRead(NimBLECharacteristic* pCharacteristic){
+        counter++;
+        pCharacteristic->setValue(counter);
+        Serial.print(pCharacteristic->getUUID().toString().c_str());
+        Serial.print(": onRead(), value: ");
+        Serial.println(pCharacteristic->getValue().c_str());
+        
+    };
+
+
+};
+    
+
+static CharacteristicCallbacks chrCallbacks;
+
+
+void setup() {
+    Serial.begin(115200);
+    Serial.println("Starting NimBLE Server");
+    counter = 0;
+    /** sets device name */
+    NimBLEDevice::init("Acell_Miha_1");
+
+    /** Optional: set the transmit power, default is 3db */
+    //NimBLEDevice::setPower(ESP_PWR_LVL_P9); /** +9db */
+    
+    /** Set the IO capabilities of the device, each option will trigger a different pairing method.
+     *  BLE_HS_IO_DISPLAY_ONLY    - Passkey pairing
+     *  BLE_HS_IO_DISPLAY_YESNO   - Numeric comparison pairing
+     *  BLE_HS_IO_NO_INPUT_OUTPUT - DEFAULT setting - just works pairing
+     */
+    //NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY); // use passkey
+    //NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_YESNO); //use numeric comparison
+
+    /** 2 different ways to set security - both calls achieve the same result.
+     *  no bonding, no man in the middle protection, secure connections.
+     *   
+     *  These are the default values, only shown here for demonstration.   
+     */ 
+    //NimBLEDevice::setSecurityAuth(false, false, true); 
+    NimBLEDevice::setSecurityAuth(/*BLE_SM_PAIR_AUTHREQ_BOND | BLE_SM_PAIR_AUTHREQ_MITM |*/ BLE_SM_PAIR_AUTHREQ_SC);
+
+    pServer = NimBLEDevice::createServer();
+//    pServer->setCallbacks(new ServerCallbacks());
+
+    NimBLEService* pDeadService = pServer->createService("DEAD");
+    pBeefCharacteristic = pDeadService->createCharacteristic(
+                                               "BEEF",
+                                               NIMBLE_PROPERTY::READ |
+                                               //NIMBLE_PROPERTY::WRITE |
+                               /** Require a secure connection for read and write access */
+                                               NIMBLE_PROPERTY::READ_ENC   // only allow reading if paired / encrypted
+                                               //NIMBLE_PROPERTY::WRITE_ENC   // only allow writing if paired / encrypted
+                                              );
+  
+    pBeefCharacteristic->setValue(counter);
+    pBeefCharacteristic->setCallbacks(&chrCallbacks);
+
+    /** 2904 descriptors are a special case, when createDescriptor is called with
+     *  0x2904 a NimBLE2904 class is created with the correct properties and sizes.
+     *  However we must cast the returned reference to the correct type as the method
+     *  only returns a pointer to the base NimBLEDescriptor class.
+     */
+//    NimBLE2904* pBeef2904 = (NimBLE2904*)pBeefCharacteristic->createDescriptor("2904"); 
+//    pBeef2904->setFormat(NimBLE2904::FORMAT_UTF8);
+
+   /** Note a 0x2902 descriptor MUST NOT be created as NimBLE will create one automatically
+     *  if notification or indication properties are assigned to a characteristic.
+     */
+
+    /** Custom descriptor: Arguments are UUID, Properties, max length in bytes of the value */
+  NimBLEDescriptor* pBeef2904 = pBeefCharacteristic->createDescriptor(
+                                               "C01D",
+                                               NIMBLE_PROPERTY::READ | 
+                                               NIMBLE_PROPERTY::WRITE|
+                                               NIMBLE_PROPERTY::WRITE_ENC, // only allow writing if paired / encrypted
+                                               20
+                                              );
+
+    /** Start the services when finished creating all Characteristics and Descriptors */  
+    pDeadService->start();
+
+
+    NimBLEAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
+    /** Add the services to the advertisment data **/
+    pAdvertising->addServiceUUID(pDeadService->getUUID());
+ 
+    /** If your device is battery powered you may consider setting scan response
+     *  to false as it will extend battery life at the expense of less data sent.
+     */
+    pAdvertising->setScanResponse(true);
+    pAdvertising->start();
+
+    Serial.println("Advertising Started");
+}
+
+
+void loop() {
+}
diff --git a/firmware/bt_debug/bt_debug.ino b/firmware/bt_debug/bt_debug.ino
new file mode 100644
index 0000000..afe5911
--- /dev/null
+++ b/firmware/bt_debug/bt_debug.ino
@@ -0,0 +1,93 @@
+/* Uporabi z aplikacijo za android, dostopno na:
+ *  
+ *  https://play.google.com/store/apps/details?id=appinventor.ai_samo_penic.Geiger_counter_2020
+ *  
+ *  Poletni tabor inovativnih tehnologij
+ *  
+ *  Samo Penic, 2020
+ */
+
+#include "WiFi.h" 
+#include <BLEDevice.h>
+#include <BLEServer.h>
+#include <BLEUtils.h>
+#include <BLE2902.h>
+
+#define BT_NAME "Geiger counter No. 1"
+#define LED 2
+#define GEIGER_INPUT 22
+
+BLECharacteristic *pCharacteristic;
+bool deviceConnected = false;
+
+uint8_t txString[5]={'R','E','S','P','\0'}; //20 bytes is maximum packet size for BTLE!!!
+int i;
+
+#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
+#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
+#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
+
+class MyServerCallbacks: public BLEServerCallbacks {
+    void onConnect(BLEServer* pServer) {
+      deviceConnected = true;
+    };
+
+    void onDisconnect(BLEServer* pServer) {
+      deviceConnected = false;
+    }
+};
+
+void IRAM_ATTR count_plus_one() {
+
+}
+
+void setup() {
+//  setCpuFrequencyMhz(80);
+//  adc_power_off();
+  WiFi.mode(WIFI_OFF);
+  
+  Serial.begin(115200); /* Serijski vmesnik je vedno uporaben za razhroscevanje in raziskovanje med razvojem */
+//  pinMode(GEIGER_INPUT, INPUT); /* Nastavimo vhodni signal -- napetostni impulzi, kot odraz tokovnih pulzov skozi Geiger-Mullerjevo elektronko */
+//  attachInterrupt(GEIGER_INPUT, &count_plus_one, RISING); /* Ob impulzu zazenemo prekinitveno rutino. Tako optimalno prestejemo impulze */
+
+  pinMode(LED, OUTPUT); /* Na ploscici imamo se eno modro LED. Morda jo kdaj uporabimo? */
+
+
+  // Create the BLE Device
+  BLEDevice::init(BT_NAME); /* Poimenujmo nas stevec. Ime se bo pokazalo na seznamu BT naprav na telefonu */
+
+  // Create the BLE Server
+  BLEServer *pServer = BLEDevice::createServer();
+  pServer->setCallbacks(new MyServerCallbacks());
+
+  // Create the BLE Service
+  BLEService *pService = pServer->createService(SERVICE_UUID);
+
+  // Create a BLE Characteristic
+  pCharacteristic = pService->createCharacteristic(
+                      CHARACTERISTIC_UUID_TX,
+                      BLECharacteristic::PROPERTY_NOTIFY
+                    );
+                      
+  pCharacteristic->addDescriptor(new BLE2902());
+
+  // Start the service
+  pService->start();
+
+  // Start advertising
+  pServer->getAdvertising()->start();
+  
+
+}
+
+void loop() {
+  if (deviceConnected) {
+  
+
+    pCharacteristic->setValue(txString,5);
+    
+    pCharacteristic->notify(); // Send the value to the app!
+
+  }
+  delay(99);
+}
diff --git a/firmware/trigger_firmware/trigger_firmware.ino b/firmware/trigger_firmware/trigger_firmware.ino
index 996053d..8ac69bd 100644
--- a/firmware/trigger_firmware/trigger_firmware.ino
+++ b/firmware/trigger_firmware/trigger_firmware.ino
@@ -20,10 +20,15 @@
 char dataToSend[4] = "TRG";
 
 void IRAM_ATTR isr() {
-    digitalWrite(OUT_TRIGGER, HIGH);
-    radio.write( &dataToSend, sizeof(dataToSend) );
-    delay(1);
-    digitalWrite(OUT_TRIGGER,LOW);
+//    detachInterrupt(digitalPinToInterrupt(IN_TRIGGER));
+    digitalWrite(OUT_TRIGGER, LOW);
+    long time=micros();
+    while(micros()-time<4000);
+    digitalWrite(OUT_TRIGGER,HIGH);
+//        radio.write( &dataToSend, sizeof(dataToSend) );
+
+//    attachInterrupt(digitalPinToInterrupt(IN_TRIGGER), isr, RISING);
+  
 }
 
 
@@ -38,17 +43,23 @@
   radio.begin();
   radio.openWritingPipe(address);
   radio.setPALevel(RF24_PA_MAX);
-  //radio.setDataRate( RF24_250KBPS );
+  radio.setDataRate( RF24_250KBPS );
 
-  pinMode(IN_TRIGGER, INPUT_PULLUP);
+  //pinMode(IN_TRIGGER, INPUT_PULLUP);
   pinMode(OUT_TRIGGER, OUTPUT);
-  attachInterrupt(IN_TRIGGER, isr, RISING);
-  
+  digitalWrite(OUT_TRIGGER,HIGH);
+  attachInterrupt(digitalPinToInterrupt(IN_TRIGGER), isr, FALLING);
+  Serial.begin(115200);
 
 }
 
 void loop() {
   // put your main code here, to run repeatedly:
-//radio.write( &dataToSend, sizeof(dataToSend) );
-//    delay(5000);
+Serial.print(micros());
+Serial.println(": ---> TRG");
+radio.write( &dataToSend, sizeof(dataToSend) );
+Serial.print(micros());
+Serial.println(": TRG--->");
+    delay(5000);
+
 }

--
Gitblit v1.9.3