Samo Penic
2022-05-16 e0a3ca6fe6dcca8b7557063a1d99ff614d9547fa
Further development of firmware for Bluetooth data transmission.
3 files added
1 files modified
452 ■■■■■ changed files
firmware/bluetooth_acceleromer_receiver_v1/bluetooth_acceleromer_receiver_v1.ino 211 ●●●●● patch | view | raw | blame | history
firmware/bluetooth_accelerometer_v1/bluetooth_accelerometer_v1.ino 117 ●●●●● patch | view | raw | blame | history
firmware/bt_debug/bt_debug.ino 93 ●●●●● patch | view | raw | blame | history
firmware/trigger_firmware/trigger_firmware.ino 31 ●●●●● patch | view | raw | blame | history
firmware/bluetooth_acceleromer_receiver_v1/bluetooth_acceleromer_receiver_v1.ino
New file
@@ -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);
}
firmware/bluetooth_accelerometer_v1/bluetooth_accelerometer_v1.ino
New file
@@ -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() {
}
firmware/bt_debug/bt_debug.ino
New file
@@ -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);
}
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);
}