II’m working on a project using an ESP32 to connect via Bluetooth Serial. However, I’m encountering an issue where the Bluetooth connection shows that the socket is closed from the phone’s Bluetooth client
I am trying to establish a stable Bluetooth connection between my ESP32 and a phone. The ESP32 should send and receive data through this connection.
#define BLYNK_TEMPLATE_ID "TMPL6pV_GZrck"
#define BLYNK_TEMPLATE_NAME "Pow"
#define BLYNK_AUTH_TOKEN "r67qUU-4qVY8Iv1M1udj5pBTV8dTgk-m"
#include <Adafruit_Fingerprint.h>
#include <Preferences.h>
#include <BlynkSimpleEsp32.h>
#include <WiFi.h>
#include <Arduino.h>
#include <BluetoothSerial.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define speakerPin 13
#define I2C_ADDR 0x3F
#define VOLTAGE_SENSOR_PIN 36
LiquidCrystal_I2C lcd(I2C_ADDR, 20, 4);
HardwareSerial mySerial(1); // Using hardware serial port 1 for fingerprint sensor
Adafruit_Fingerprint finger(&mySerial); // Create an instance of the fingerprint sensor
Preferences preferences; // Create an instance for NVS to store data persistently
// WiFi credentials
#define WIFI_SSID "Gala"
#define WIFI_PASSWORD "12345678"
BluetoothSerial SerialBT;
bool wifiPaused = false;
unsigned long wifiPauseStartTime = 0;
uint8_t id = 0;
bool authEnabled = true; // Flag to control authentication task
int c = 1; // for buzzer module
unsigned long lastMotionTime = 0;
byte bar0[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
byte bar1[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F};
byte bar2[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F};
byte bar3[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F};
byte bar4[8] = {0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F};
byte bar5[8] = {0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F};
byte bar6[8] = {0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F};
byte bar7[8] = {0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F};
byte bar8[8] = {0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F};
// Function Prototypes
void enrollFingerprint();
bool getFingerprintEnroll();
void authenticateFingerprint();
void deleteAllFingerprints();
void blynkTask(void *pvParameters);
void authTask(void *pvParameters);
void connectToWiFi();
void displayMessage(const char *message, int row);
void displayBatteryLevel();
void drawBarGraph(int row, int col, int percentage);
void normalDisplay();
void checkWiFiConnection();
void checkBluetoothConnection();
enum DisplayMode { NORMAL, MESSAGE };
DisplayMode currentMode = NORMAL;
unsigned long lastDisplayUpdateTime = 0;
const unsigned long displayUpdateInterval = 2000; // 2 seconds
void enrollFingerprint() {
authEnabled = false; // Disable authentication during enrollment
id++; // Increment the fingerprint ID to the next available number
if (id > 127) { // Check if ID is within the allowable range for the sensor
Serial.println("Memory Full, ID is out of range!"); // Notify if memory is full
displayMessage("Memory Full", 1);
authEnabled = true; // Re-enable authentication
currentMode = NORMAL;
return;
}
Serial.print("Automatically enrolling to ID #");
Serial.println(id); // Announce which ID is being enrolled
displayMessage("Enrolling...", 1);
// Enrollment process
if (getFingerprintEnroll()) {
preferences.putUInt("lastID", id); // Save the new ID to NVS after successful enrollment
Serial.println("Fingerprint enrolled successfully.");
displayMessage("Enrolled Successfully", 1);
} else {
displayMessage("Enrollment Failed", 1);
}
authEnabled = true; // Re-enable authentication after enrollment
delay(2000);
currentMode = NORMAL;
}
bool getFingerprintEnroll() {
int p = -1;
Serial.print("Waiting for valid finger to enroll as #");
Serial.println(id);
displayMessage("Place Finger", 1);
while (p != FINGERPRINT_OK) {
p = finger.getImage(); // Try to get an image of the finger
switch (p) {
case FINGERPRINT_OK:
Serial.println("Image taken"); // Confirm image capture
break;
case FINGERPRINT_NOFINGER:
Serial.println("."); // Print dots while waiting for finger
delay(50);
break;
case FINGERPRINT_PACKETRECIEVEERR:
Serial.println("Communication error"); // Report communication error
displayMessage("Comm Error", 1);
break;
case FINGERPRINT_IMAGEFAIL:
Serial.println("Imaging error"); // Report imaging error
displayMessage("Image Error", 1);
break;
default:
Serial.println("Unknown error"); // Catch-all for other errors
displayMessage("Unknown Error", 1);
return false;
}
}
// Process the captured fingerprint image
p = finger.image2Tz(1);
if (p != FINGERPRINT_OK) {
Serial.println("Error converting image"); // Report error in image conversion
displayMessage("Image Conv. Error", 1);
return false;
}
Serial.println("Remove finger");
displayMessage("Remove Finger", 1);
delay(2000);
while (finger.getImage() != FINGERPRINT_NOFINGER); // Ensure no finger is on the sensor
Serial.println("Place same finger again");
displayMessage("Place Same Finger", 1);
while (finger.getImage() != FINGERPRINT_OK); // Wait for the same finger to be placed again
p = finger.image2Tz(2);
if (p != FINGERPRINT_OK) {
Serial.println("Error converting image"); // Report error on second image conversion
displayMessage("Image Conv. Error", 1);
return false;
}
p = finger.createModel();
if (p != FINGERPRINT_OK) {
Serial.println("Error creating model"); // Report error in creating model from images
displayMessage("Model Error", 1);
return false;
}
p = finger.storeModel(id);
if (p != FINGERPRINT_OK) {
Serial.println("Error storing model"); // Report error in storing the model in the sensor
displayMessage("Store Error", 1);
return false;
}
return true; // Return success if all steps pass
}
void authenticateFingerprint() {
if (!authEnabled) return; // Skip authentication if it's disabled
int p = finger.getImage();
if (p == FINGERPRINT_OK) {
p = finger.image2Tz();
if (p != FINGERPRINT_OK) {
return;
}
p = finger.fingerFastSearch();
if (p == FINGERPRINT_OK) {
Serial.println("Fingerprint matched!");
Serial.print("Found ID #");
Serial.println(finger.fingerID);
Serial.print("With confidence of ");
Serial.println(finger.confidence);
displayMessage("Fingerprint Matched!", 1);
digitalWrite(4, HIGH); // Turn on the LED on successful authentication
delay(5000); // Keep the LED on for 5 seconds
digitalWrite(4, LOW); // Turn off the LED automatically
currentMode = NORMAL;
} else {
if (p == FINGERPRINT_NOTFOUND) {
Serial.println("Did not find a match");
displayMessage("No Match Found", 1);
delay(2000);
currentMode = NORMAL;
}
}
}
}
void deleteAllFingerprints() {
authEnabled = false; // Disable authentication during deletion
Serial.println("Deleting all fingerprints from sensor...");
displayMessage("Deleting All...", 1);
uint8_t p = finger.emptyDatabase();
if (p == FINGERPRINT_OK) {
Serial.println("All fingerprints deleted successfully!");
id = 0; // Reset fingerprint ID counter
preferences.putUInt("lastID", id); // Save the reset ID counter in NVS
displayMessage("All Deleted", 1);
} else {
Serial.println("Failed to delete fingerprints!");
displayMessage("Delete Failed", 1);
}
authEnabled = true; // Re-enable authentication after deletion
delay(2000);
currentMode = NORMAL;
}
void authTask(void *pvParameters) {
for (;;) {
authenticateFingerprint(); // Always check for fingerprint for authentication
vTaskDelay(50 / portTICK_PERIOD_MS); // Short delay to prevent too frequent sensor checks
}
}
void blynkTask(void *pvParameters) {
for (;;) {
Blynk.run();
checkBluetoothConnection();
vTaskDelay(10 / portTICK_PERIOD_MS); // Short delay to prevent too frequent checks
}
}
void checkBluetoothConnection() {
if (SerialBT.hasClient()) {
Blynk.virtualWrite(V3, 1); // Update Blynk virtual pin V3 to indicate Bluetooth connected
} else {
Blynk.virtualWrite(V3, 0); // Update Blynk virtual pin V3 to indicate Bluetooth not connected
}
}
void bluetoothTask(void *parameter) {
for (;;) {
checkBluetoothConnection();
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
BLYNK_WRITE(V2) {
int buttonState = param.asInt();
if (buttonState == 1) {
Serial.println("WiFi paused for 5 minutes");
wifiPaused = true;
wifiPauseStartTime = millis();
WiFi.disconnect();
}
}
BLYNK_WRITE(V4) {
static bool isPlaying = false;
int BuzzState = param.asInt(); // Get the state from Blynk app
if (BuzzState == 1 && !isPlaying) {
isPlaying = true;
Serial.println("Buzzer ON");
c = 2;
} else if (BuzzState == 0 && isPlaying) {
isPlaying = false;
noTone(speakerPin);
Serial.println("Buzzer OFF");
c = 1;
}
}
BLYNK_WRITE(V5) {
int buttonState = param.asInt();
if (buttonState == 1) {
currentMode = MESSAGE;
enrollFingerprint(); // Enroll fingerprint when button V5 is pressed
}
}
BLYNK_WRITE(V6) {
int buttonState = param.asInt();
if (buttonState == 1) {
currentMode = MESSAGE;
deleteAllFingerprints(); // Delete all fingerprints when button V6 is pressed
}
}
void connectToWiFi() {
Serial.println("Connecting to WiFi...");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
int retryCount = 0;
while (WiFi.status() != WL_CONNECTED && retryCount < 20) {
delay(500);
Serial.println("Connecting...");
retryCount++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("Connected to WiFi");
} else {
Serial.println("Failed to connect to WiFi");
}
}
void checkWiFiConnection() {
if (WiFi.status() != WL_CONNECTED) {
connectToWiFi();
}
}
void buzzer() {
if (c == 2) {
playMelody();
}
}
// Buzzer melody part 1
void playMelody() {
int length = 15;
char notes[] = "ccggaagffeeddc ";
int beats[] = { 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 4 };
int tempo = 300;
for (int i = 0; i < length; i++) {
if (notes[i] == ' ') {
delay(beats[i] * tempo);
} else {
playNote(notes[i], beats[i] * tempo);
}
delay(tempo / 2);
}
}
// Buzzer melody part 2
void playNote(char note, int duration) {
char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'c' };
int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };
for (int i = 0; i < 8; i++) {
if (names[i] == note) {
playTone(tones[i], duration);
}
}
}
// Buzzer melody part 3
void playTone(int tone, int duration) {
for (long i = 0; i < duration * 1000L; i += tone * 2) {
digitalWrite(speakerPin, HIGH);
delayMicroseconds(tone);
digitalWrite(speakerPin, LOW);
delayMicroseconds(tone);
}
}
void drawBarGraph(int row, int col, int percentage) {
int segments = (percentage / 100.0) * 20;
for (int i = 0; i < 20; i++) {
if (i < segments) {
lcd.setCursor(col + i, row);
lcd.write(8);
} else {
lcd.setCursor(col + i, row);
lcd.write(0);
}
}
}
void displayBatteryLevel() {
float voltage = analogRead(VOLTAGE_SENSOR_PIN) * (3.3 / 4095.0) * (11);
lcd.setCursor(0, 2);
lcd.print("Battery Level: ");
lcd.print(voltage, 1);
lcd.print("V");
int batteryLevel = map(voltage * 100, 0, 1260, 0, 100);
lcd.setCursor(0, 3);
lcd.print("Battery: ");
drawBarGraph(3, 9, batteryLevel);
}
void displayMessage(const char *message, int row) {
lcd.clear();
lcd.setCursor(0, row);
lcd.print(message);
}
void normalDisplay() {
if (millis() - lastDisplayUpdateTime > displayUpdateInterval) {
displayBatteryLevel();
lastDisplayUpdateTime = millis();
}
}
void setup() {
Serial.begin(9600); // Initialize serial communication at 9600 baud rate
while (!Serial); // Wait until the serial port is ready, necessary for some environments
connectToWiFi(); // Connect to WiFi
mySerial.begin(57600, SERIAL_8N1, 16, 17); // Initialize the fingerprint sensor communication
Serial.println("nnAdafruit Fingerprint sensor enrollment"); // Print a startup message
if (finger.verifyPassword()) {
Serial.println("Found fingerprint sensor!"); // Print success message
} else {
Serial.println("Did not find fingerprint sensor :("); // Print failure message
while (1) { delay(1); } // Enter an infinite loop if sensor is not found
}
pinMode(4, OUTPUT); // Set digital pin 4 as an output for controlling an LED
digitalWrite(4, LOW); // Ensure the LED is off to start
preferences.begin("fingerprint", false); // Open NVS namespace 'fingerprint' for storing IDs
id = preferences.getUInt("lastID", 0); // Retrieve the last stored fingerprint ID, defaulting to 0
Serial.print("Starting from fingerprint ID #");
Serial.println(id + 1); // Print the next ID to be used for new fingerprint
// Blynk initialization
Blynk.begin(BLYNK_AUTH_TOKEN, WIFI_SSID, WIFI_PASSWORD);
// Bluetooth initialization
if (SerialBT.begin("ESP32Test")) {
Serial.println("Bluetooth initialized. Waiting for connections...");
} else {
Serial.println("Bluetooth initialization failed!");
}
lcd.begin(20, 4);
lcd.backlight();
// Custom characters for bar graph
lcd.createChar(0, bar0);
lcd.createChar(1, bar1);
lcd.createChar(2, bar2);
lcd.createChar(3, bar3);
lcd.createChar(4, bar4);
lcd.createChar(5, bar5);
lcd.createChar(6, bar6);
lcd.createChar(7, bar7);
lcd.createChar(8, bar8);
// Create tasks
xTaskCreatePinnedToCore(authTask, "AuthTask", 10000, NULL, 1, NULL, 1);
xTaskCreatePinnedToCore(blynkTask, "BlynkTask", 10000, NULL, 1, NULL, 1);
xTaskCreatePinnedToCore(bluetoothTask, "BluetoothTask", 10000, NULL, 1, NULL, 1);
}
void loop() {
if (currentMode == NORMAL) {
normalDisplay();
}
checkWiFiConnection(); // Check and maintain WiFi connection
}
I expected the Bluetooth connection to remain open and stable, allowing continuous data transmission between the ESP32 and the phone
I am using the ESP32’s built-in Bluetooth capabilities and the Arduino IDE for programming. The phone is running Android 10, and I’m using a standard Bluetooth serial terminal app to test the connection.
Can anyone help me identify why the Bluetooth connection shows the socket is closed from the phone’s Bluetooth client and how to maintain a stable connection? Any insights or suggestions would be greatly appreciated