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