/********* Pleasedontcode.com ********** Pleasedontcode thanks you for automatic code generation! Enjoy your code! - Terms and Conditions: You have a non-exclusive, revocable, worldwide, royalty-free license for personal and commercial use. Attribution is optional; modifications are allowed, but you're responsible for code maintenance. We're not liable for any loss or damage. For full terms, please visit pleasedontcode.com/termsandconditions. - Project: "BLE Client" - Source Code NOT compiled for: ESP32 DevKit V1 - Source Code created on: 2025-02-11 18:03:14 ********* Pleasedontcode.com **********/ /****** SYSTEM REQUIREMENTS *****/ /****** SYSTEM REQUIREMENT 1 *****/ /* **ESP32 BLE Client (Stable & Crash-Free)** - */ /* Scans for `PERIPH`, connects when found, auto- */ /* reconnects if lost. - Separate tasks for BLE */ /* connection & Modbus RTU handling. - FreeRTOS, */ /* mutexes, watchdogs, and memory tracking to prevent */ /* crased */ /****** END SYSTEM REQUIREMENTS *****/ /* START CODE */ /****** DEFINITION OF LIBRARIES *****/ #include //https://github.com/arduino-libraries/ArduinoBLE #include //https://github.com/adafruit/DHT-sensor-library #include // Added for BLE functionality /****** FUNCTION PROTOTYPES *****/ void setup(void); void loop(void); /***** DEFINITION OF DIGITAL INPUT PINS *****/ const uint8_t myDHT22_DHT22_DOUT_PIN_D4 = 4; // Define UUIDs for BLE service and characteristics static BLEUUID serviceUUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E"); static BLEUUID charUUID("6e400003-b5a3-f393-e0a9-E50E24DCCA9E"); static BLEUUID rxUUID("6e400002-b5a3-f393-e0A9-E50E24DCCA9E"); // Global variables static bool connected = false; static BLEClient* pClient = nullptr; static BLERemoteService* pRemoteService = nullptr; static BLERemoteCharacteristic* pRemoteCharacteristic = nullptr; static BLERemoteCharacteristic* pRemoteRxCharacteristic = nullptr; static BLEAdvertisedDevice* myDevice = nullptr; static BLEScan* pBLEScan = nullptr; // BLE Client callback class MyClientCallback : public BLEClientCallbacks { void onConnect(BLEClient* pclient) { Serial.println("Connected to peripheral."); } void onDisconnect(BLEClient* pclient) { connected = false; Serial.println("Disconnected from peripheral."); } }; // Task: Scan for BLE devices and connect void scanAndConnectTask(void* pvParameters) { esp_task_wdt_add(NULL); // Enable watchdog for this task while (1) { Serial.println("Scanning for BLE devices..."); pBLEScan->start(5, false); vTaskDelay(1000 / portTICK_PERIOD_MS); BLEScanResults foundDevices = *pBLEScan->getResults(); // FIXED POINTER ERROR for (int i = 0; i < foundDevices.getCount(); i++) { BLEAdvertisedDevice advertisedDevice = foundDevices.getDevice(i); Serial.println("Found Device: " + advertisedDevice.toString()); if (advertisedDevice.haveName() && advertisedDevice.getName() == "PERIPH") { pBLEScan->stop(); myDevice = new BLEAdvertisedDevice(advertisedDevice); Serial.println("Target device found. Connecting..."); if (connectToServer()) { Serial.println("Connected successfully."); } else { Serial.println("Connection failed. Retrying..."); } myDevice = nullptr; } } printMemoryUsage("scanAndConnectTask"); vTaskDelay(5000 / portTICK_PERIOD_MS); esp_task_wdt_reset(); // Reset watchdog to prevent task hang } } // Function: Connect to BLE server bool connectToServer() { if (pClient != nullptr && pClient->isConnected()) { return true; } pClient = BLEDevice::createClient(); pClient->setClientCallbacks(new MyClientCallback()); if (!pClient->connect(myDevice)) { Serial.println("Failed to connect to peripheral."); delete pClient; pClient = nullptr; return false; } pRemoteService = pClient->getService(serviceUUID); if (pRemoteService == nullptr) { Serial.println("Failed to find service UUID."); pClient->disconnect(); return false; } pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID); pRemoteRxCharacteristic = pRemoteService->getCharacteristic(rxUUID); if (pRemoteCharacteristic == nullptr || pRemoteRxCharacteristic == nullptr) { Serial.println("Failed to find characteristics."); pClient->disconnect(); return false; } connected = true; return true; } // Task: Send and receive data void sendReceiveTask(void* pvParameters) { esp_task_wdt_add(NULL); // Enable watchdog for this task while (1) { if (connected) { sendReadRequestToSlave(0x43, 5); readDataFromPeripheral(); } printMemoryUsage("sendReceiveTask"); vTaskDelay(5000 / portTICK_PERIOD_MS); esp_task_wdt_reset(); // Reset watchdog to prevent task hang } } // Function: Send read request to slave device void sendReadRequestToSlave(uint16_t startingAddress, uint16_t length) { Serial.println("Sending read request..."); if (!connected || pRemoteRxCharacteristic == nullptr) { Serial.println("Not connected or RX characteristic unavailable."); return; } uint8_t requestData[8] = { 0x20, 0x03, (startingAddress >> 8) & 0xFF, startingAddress & 0xFF, (length >> 8) & 0xFF, length & 0xFF, 0x72, 0xAC }; pRemoteRxCharacteristic->writeValue(requestData, sizeof(requestData)); } // Function: Read data from peripheral void readDataFromPeripheral() { if (!connected || pRemoteCharacteristic == nullptr) { Serial.println("Not connected or TX characteristic unavailable."); return; } String value = pRemoteCharacteristic->readValue(); Serial.print("Received Data: "); Serial.println(value); Serial.print("Data (HEX): "); for (size_t i = 0; i < value.length(); i++) { Serial.print((uint8_t)value[i], HEX); Serial.print(" "); } Serial.println(); } // Function: Print memory usage void printMemoryUsage(const char* taskName) { Serial.print("[MEMORY] Task: "); Serial.print(taskName); Serial.print(" | Free Heap: "); Serial.print(esp_get_free_heap_size()); Serial.print(" bytes | Min Heap: "); Serial.print(esp_get_minimum_free_heap_size()); Serial.println(" bytes"); } void setup(void) { Serial.begin(57600); // Initialize Serial for debugging Serial.println("Starting BLE Client..."); BLEDevice::init("CENTRAL"); // Set TX power esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT, ESP_PWR_LVL_P9); // This line may not be compatible with ArduinoBLE library // Initialize BLE scan pBLEScan = BLEDevice::getScan(); pBLEScan->setInterval(2000); pBLEScan->setWindow(1000); pBLEScan->setActiveScan(true); // Create tasks on specific cores xTaskCreatePinnedToCore(scanAndConnectTask, "Scan Task", 10240, NULL, 1, NULL, 0); xTaskCreatePinnedToCore(sendReceiveTask, "Data Task", 10240, NULL, 2, NULL, 1); pinMode(myDHT22_DHT22_DOUT_PIN_D4, INPUT_PULLUP); // Initialize DHT sensor pin } void loop(void) { // put your main code here, to run repeatedly: delay(500); // Delay to prevent overwhelming the loop } /* END CODE */