Serial write() blocks on Bluetooth ports

Hello,

I am developing a desktop app on Processing that reads data arriving on a Serial port. The app will be distributed to users running either Windows or MacOS. They will have an Arduino Uno set up to stream data to the app.

Because there is no way of knowing in advance the name of the serial port to which the user will connect their Arduino, my program iterates through every available port trying to complete a handshake. For every port, the program opens a connection, waits a few seconds for the Arduino to be ready to receive data, sends a connection message to the Arduino, and waits for the reply.

Here is a simplified version of the code:

import processing.serial.*;

Boolean HANDSHAKE_SUCCESSFUL = false;        // Keep track of success of current handshake attempt
Serial Arduino;                              // Object representing the connection to the Arduino

void setup() {
  if (TryConnectToArduino()) {
    println("Connection successful");  
  }
}

// Tries to connect to Arduino
// Tries each available port, sends connection message, and waits for a response
public Boolean TryConnectToArduino() {
  // Global variable set to true elsewhere in the program when a 
  //  response is received from the Arduino
  HANDSHAKE_SUCCESSFUL = false;

  // Connect to each available port until we find the right one
  for (String nextPort : Serial.list()) {
    try {
      // Open connection
      Arduino = new Serial(this, nextPort, 9600);
      println("Trying port " + nextPort);
   
      // Buffer data until newline and wait for connection to be set up
      Arduino.bufferUntil('\n');                                    
      delay(3000);                                
      Arduino.clear();
   
      // Send connection message
      Arduino.write("SYN\n");
   
      // Wait for reply
      delay(3000);
      
      // Check if the program received the response
      // When the response is received, serialEvent() sets HANDSHAKE_SUCCESSFUL to true
      if (HANDSHAKE_SUCCESSFUL) {
        // Success; return
        return true;    
      } else {
        // Close the current serial connection
        Arduino.clear();
        Arduino.stop();
      }
    } catch (RuntimeException e) {
      // The port is busy - it's not the right one
      println(nextPort + " was busy");
      continue;
    }
  }
  return false; 
}

// Called when data is available to be read from the Arduino
void serialEvent(Serial p) {
  // Read the data
  String response = p.readString();
    
  // Check if the data is the response we want
  if (response != null && response.equals("ACK\n")) {
    HANDSHAKE_SUCCESSFUL = true; 
  }
}

The Arduino code is a very simple script that waits for the connection message and replies:

void setup() {
  Serial.begin(9600);
  completeHandshake();
}

// Loop until we complete the three-way handshake
void completeHandshake() {
  while (true) {
    // Listen for an incoming SYN
    if (Serial.available() == 0) continue;

    // Check if we received SYN
    String syn = Serial.readString();
    if (!syn.equals("SYN\n")) continue;

    // Respond so app knows we're connected
    Serial.write("ACK\n");
    return;
  }
}

void loop() {}

In most cases, this code works fine. However, for one of my users running it on Windows, it failed. It turned out after a lot of debugging that their Bluetooth headphones were connected to their computer, and that turning off Bluetooth solved the problem.

Here is the issue: on certain Bluetooth ports, the line Arduino.write("SYN\n") blocks. The program doesn’t crash or print out an error message; the program just blocks at that function call, and never moves on. I’m not sure why this is happening, and the reference doesn’t mention any case where Serial write() would block.

This post on the Arduino forum states that, on Arduino, Serial write() blocks when the output buffer is or becomes full. I’m guessing something similar happens in Processing, but I thought that calling Arduino.clear() would prevent this.

I can think of a couple of solutions:

  1. Check if a port is associated with Bluetooth before attempting to connect. If so, ignore it.
  2. Implement a timeout to move on if a write() call is taking too long

I haven’t yet implemented these, and I would be interested in understanding a bit more clearly why this is happening first.

I would really appreciate any help, either solutions or extra information about why this is happening. Thank you!

1 Like

Hello,

Thank you for sharing!

I observed the same here when I turned Bluetooth on; there is a serial Bluetooth port on the PC from one of my devices.

I will add this issue to my serial troubleshooting checklist and serial code collection.

I worked around this as follows:

  • Connect to port to test
  • Arduino is sending a beacon (string) every few hundred milliseconds.
  • Processing checks for this Arduino string
  • Processing sends a string to Arduino to turn off beacon or otherwise; I actually changed the beacon message.

This is a handshaking initiated by the Arduino.

I am sure you can implement this with ease; my code was just something I threw together.

:)

1 Like