[SOLVED] Help with using Java GUI to control LED using bluetooth HC-05 module

My project is to be able to toggle an LED using a GUI written in java over bluetooth, by using a HC-05 module. I am using pin 2 to control the LED. I have wired a voltage divider between the Arduino and the HC-05 as the HC-05 cannot take the full 5V.

However, the LED doesn't go on when I click the button.

I was able to do this without the bluetooth module by just using the USB.

This is my Arduino code for the project

#include <SoftwareSerial.h> 

// Connecting Arduino Pin 10 (RX) to HC-05 TXD
// Connecting Arduino Pin 11 (TX) to HC-05 RXD 
SoftwareSerial bluetoothSerial(10, 11); // RX, TX 

const int ledPin = 2; // Digital pin for the LED

void setup() {
  Serial.begin(9600); //Arduino baud rate
  Serial.println("Listening for commands from HC-05...");

  bluetoothSerial.begin(9600); //HC-05 baud rate
  Serial.println("SoftwareSerial initialized at 9600 baud.");

  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW); //LED is off initially
  Serial.println("LED initialized on Pin 2 (OFF).");
}

void loop() {
  //Checking if 3 bytes are available from HC-05
  if (bluetoothSerial.available() >= 3) {
    byte byte1 = bluetoothSerial.read();
    byte byte2 = bluetoothSerial.read();
    byte byte3 = bluetoothSerial.read();

    //Prints bytes to the Serial Monitor via USB
    Serial.print("Received BT: 0x");
    if (byte1 < 0x10) Serial.print("0"); Serial.print(byte1, HEX);
    Serial.print(" 0x");
    if (byte2 < 0x10) Serial.print("0"); Serial.print(byte2, HEX);
    Serial.print(" 0x");
    if (byte3 < 0x10) Serial.print("0"); Serial.print(byte3, HEX);
    Serial.print(" -> ");

 
    if (byte2 == (byte)ledPin) { // Checking if the command is for the LED pin (Pin 2)
      if (byte1 == (byte)0xF4) { // Command 0xF4: Initial setup
        if (byte3 == (byte)1) { // 1 for ON
          digitalWrite(ledPin, HIGH);
          Serial.println("INIT command: LED ON");
        } else if (byte3 == (byte)0) { // 0 for OFF
          digitalWrite(ledPin, LOW);
          Serial.println("INIT command: LED OFF");
        } else {
          Serial.println("INIT command: Unknown state for LED.");
        }
      } else if (byte1 == (byte)0xF5) { // 0xF5 toggles LED
        if (byte3 == (byte)0) { // 0 for OFF
          digitalWrite(ledPin, LOW);
          Serial.println("TOGGLE command: LED OFF");
        } else if (byte3 == (byte)1) { // 1 for ON
          digitalWrite(ledPin, HIGH);
          Serial.println("TOGGLE command: LED ON");
        } else {
          Serial.println("TOGGLE command: Unknown state for LED.");
        }
      } else {
        Serial.println("Unknown command type for Pin 2.");
      }
    } else {
      Serial.println("Command not for LED pin (byte2 did not match ledPin).");
    }
  }

  delay(5);
}

This is my java code written in the IntelliJ IDE.

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import com.fazecast.jSerialComm.SerialPort;

public class GUI {
    private JFrame frame;
    public SerialPort arduino_port = null;
    private static final String TARGET_PORT_NAME = "cu.HC-05"; //This is my port name for the HC-05
    public boolean LED_IS_ON = false;
    private JButton button = new JButton(" ");
    private JLabel statusLabel; // For displaying connection status


    public static final int BAUD_RATE = 9600;

    public GUI() {

        makeFrame();
        frame.setVisible(true);
        ports();
    }

    private void makeFrame() {
        frame = new JFrame("BLUETOOTH LED CONTROL");
        frame.setLayout(new BorderLayout());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


        statusLabel = new JLabel("Status: Initializing...");
        frame.add(statusLabel, BorderLayout.NORTH);

        JLabel instructionLabel = new JLabel("Click the button to switch the LED on/off");

        button.setEnabled(false);
        button.setText("OFF");
        button.setBackground(Color.RED);
        button.setOpaque(true);
        button.setBorderPainted(true);
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (arduino_port != null && arduino_port.isOpen()) {
                    System.out.println("Button clicked. Current internal LED state: " + (LED_IS_ON ? "ON" : "OFF"));
                    LED_IS_ON = !LED_IS_ON; // Toggles the LED's state

                    byte[] command = new byte[3];
                    command[0] = (byte) 0xF5; // 0xF5 (Toggles LED on Arduino)
                    command[1] = (byte) 0x02; // Pin 2 (Arduino's ledPin)

                    if (LED_IS_ON) {
                        command[2] = (byte) 0x01; //LED on
                        button.setText("OFF");
                        button.setBackground(Color.GREEN);
                        System.out.println("Sending command: 0xF5 0x02 0x01 (Turn LED ON)");
                    } else {
                        command[2] = (byte) 0x00; // LED off
                        button.setText("ON");
                        button.setBackground(Color.RED);
                        System.out.println("Sending command: 0xF5 0x02 0x00 (Turn LED OFF)");
                    }

                    arduino_port.writeBytes(command, command.length);
                } else {
                    statusLabel.setText("Status: Not connected!");
                    System.err.println("Button clicked but port is not open.");
                }
            }
        });

        JPanel controlPanel = new JPanel(new FlowLayout());
        controlPanel.add(instructionLabel);
        controlPanel.add(button);

        frame.add(controlPanel, BorderLayout.CENTER);

        frame.pack();
        frame.setLocationRelativeTo(null);
    }

    private void ports() {
        statusLabel.setText("Status: Attempting to connect to " + TARGET_PORT_NAME + "...");
        button.setEnabled(false); // Disables button when truing to connect

        if (arduino_port != null && arduino_port.isOpen()) {
            arduino_port.closePort();
            System.out.println("Closed the previously open port.");
        }

        //This lists all the available ports
        SerialPort[] ports = SerialPort.getCommPorts();
        System.out.println("Available Serial Ports: ");
        boolean targetPortFound = false;

        for (SerialPort port : ports) {
            String currentPortName = port.getSystemPortName();
            System.out.println(currentPortName); // Print all ports found

            if (currentPortName.equals(TARGET_PORT_NAME)) {
                arduino_port = port;
                targetPortFound = true;
                System.out.println("Target port '" + TARGET_PORT_NAME + "' found.");

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    System.err.println("Thread interrupted before port open: " + e.getMessage());
                    Thread.currentThread().interrupt();
                    statusLabel.setText("Status: Connection interrupted.");
                    return;
                }

                if (arduino_port.openPort()) {
                    System.out.println("Port " + TARGET_PORT_NAME + " opened successfully.");
                    statusLabel.setText("Status: Connected to " + TARGET_PORT_NAME);
                    button.setEnabled(true);
                    arduino_port.setBaudRate(BAUD_RATE);
                    arduino_port.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING, 0, 0);

                    try {
                        Thread.sleep(100);
                        byte[] initialCommand = new byte[3];
                        initialCommand[0] = (byte) 0xF4; // Command 0xF4 (Init LED on Arduino)
                        initialCommand[1] = (byte) 0x02; // Pin 2 (Arduino's ledPin)
                        initialCommand[2] = (byte) 0x01; // Send 1 (LED ON)

                        arduino_port.writeBytes(initialCommand, initialCommand.length);
                        System.out.println("Initial command sent: " + String.format("0x%02X 0x%02X 0x%02X", initialCommand[0], initialCommand[1], initialCommand[2]));
                        LED_IS_ON = true; // Sync GUI state with initial command (LED should be ON)
                        button.setText("OFF"); // Button says "OFF" for next click (to turn it OFF)
                        button.setBackground(Color.GREEN); // LED is ON, so button implies next action is OFF
                    } catch (InterruptedException e) {
                        System.err.println("Thread interrupted during initial command send: " + e.getMessage());
                        Thread.currentThread().interrupt();
                        statusLabel.setText("Status: Initial command interrupted.");
                        arduino_port.closePort();
                    } catch (Exception e) {
                        System.err.println("Error sending initial command: " + e.getMessage());
                        statusLabel.setText("Status: Initial command failed.");
                        arduino_port.closePort();
                    }
                    break;
                } else {
                    System.err.println("Failed to open port: " + TARGET_PORT_NAME + ". It might be in use or permissions issue.");
                    statusLabel.setText("Status: Failed to open " + TARGET_PORT_NAME);
                    button.setEnabled(false);
                }
            }
        }
        System.out.println("End of Port Scan");
        if (!targetPortFound || !arduino_port.isOpen()) {
            System.err.println("Error: Target port '" + TARGET_PORT_NAME + "' not found or could not be opened. " +
                    "Please verify the name, Bluetooth pairing, and ensure it's not already in use.");
            statusLabel.setText("Status: " + TARGET_PORT_NAME + " not found or accessible.");
            button.setEnabled(false);
        }
    }

This is my wiring. I am not too sure but I suspect the problem lies here.

I am hoping someone could alert me to where I have gone wrong.

What about Serial.prints you have on your code?
Your LED needs current limiting resistor.
You have 3 resistors that make voltage divider. What values?

The current limiting resistor for the LED is 220 ohms, the 3 resistors in the voltage divider are each 1 kilo ohm because I don't have a 2k

It's not present on your image. There is only resistor on transistor base.

I thought the resistor next to the transistor was the current limiting resistor but now I am not sure. Should I add a resistor between the anode and 5V?

Also the serial monitor doesn't print out any bytes from this bit of code.

 Serial.print("Received BT: 0x");
    if (byte1 < 0x10) Serial.print("0"); Serial.print(byte1, HEX);
    Serial.print(" 0x");
    if (byte2 < 0x10) Serial.print("0"); Serial.print(byte2, HEX);
    Serial.print(" 0x");
    if (byte3 < 0x10) Serial.print("0"); Serial.print(byte3, HEX);
    Serial.print(" -> ");

I am also a bit curious, but is there a reason why it would work for just the USB if it isn't a current limiting resistor?

Yes.
But your image presents that you don't use 5V.
Which is the reason you didn't burn the LED.

Anyway, if you don't get Serial.prints, your problem is not dead LED.
Try the code from this tutorial to see if it works.

1 Like

How have you proven the wifi works?

I'm sorry but I am not sure what you mean. Could you please clarify?

What are you seeing that indicates the connection (sorry... wifi? bluetooth?) is paired and passing data?

The HC-05 is paired because it blinks twice then switches off on repeat. However, it seems like the data is not being transmitted to the Arduino as nothing shows up on the serial monitor. The Arduino and the HC-05 are both set to 9600 baud.

Do you have an LED and current limit resistor on the Arduino's BT tx/rx pins to monitor activity? (similar effect to the RX/TX LED on the Arduino)

A good way to trouble shoot these HC-05/Arduino problems is as follows.

  1. Confirm that the program works with input from the ide serial monitor.
  2. Add the HC-05 and get it working with a standard phone app like Kai Morich's Serial Bluetooth Terminal
  3. Use your custom app.

I've got it working now.

The problem was that my Mac was creating the wrong type of serial port for the HC-05. I tried it with a Windows instead and it was fine.

Thank you for all these suggestions.

Would you show what the Mac was creating so others might use this to identify their (future) issues? Tnx.

It displayed the service for the HC-05 as Braille ACL, when it should be SerialPort since it functions as a Serial Port Profile.