Smartphone talking to bluetooth works in one direction only :(

Hi there!

I try to communicate from my android to my Arduino with a bluetooth board connected. Sending messages from the board to the smartphone works fine. But sending data from the Smartphone to the board fails.

Hardware: Arduono Mega ADK, Sparkfun bluetooth Mathe Silver, 12V DC power supply, Samsung Galxy S (i9000) with Android 2.3.6. Arduino is connected to my Mac fpr the Serial Monitor

Setup:
Bluetooth GND --- Arduino GND near 5V
Bluetooth VCC --- Arduino 5V
Bluetooth TX-I --- Arduino PIN 2
Bluetooth RX-I --- Arduino PIN 3

The Arduino code:

#include <SoftwareSerial.h>

int bluetoothTx = 2; // for Device -> BT
int bluetoothRx = 3; // Connect BT-RXI to PIN: for: BT -> Device (works, also if you do not use BT-TX-O)

SoftwareSerial bluetooth(bluetoothTx, bluetoothRx);

boolean doWrite = false;
boolean doRead = true;

void setup() {
  //Setup usb serial connection to computer
  Serial.begin(9600);

  //Setup Bluetooth serial connection to android
  bluetooth.begin(115200);
  bluetooth.print("$$");
  delay(100);
  bluetooth.println("U,9600,N");
  bluetooth.begin(9600);
}

void loop() {
    // write to device: works fine
    if (doWrite) {
      bluetooth.println(cnt);
      delay(400);
    }

    // read from device: does not work :(
    if (doRead) { 
      char toSend = (char)bluetooth.read();
       Serial.println(toSend); 
      }
    }
}

to Send is always the char of (char)-1. bluetooth.available() does always return 0, also if permanently request in a loop. the same for Serial.available(); It is strange sending data from the board the the connected Android device works fine. I monitor the baud rate 9600.

Here is how I send the data via Android. It is taken from a tuorial and should work fine.

public class MainActivity extends Activity {

	TextView myLabel;
	EditText myTextbox;
	BluetoothAdapter mBluetoothAdapter;
	BluetoothSocket mmSocket;
	BluetoothDevice mmDevice;
	OutputStream mmOutputStream;
	InputStream mmInputStream;
	Thread workerThread;
	byte[] readBuffer;
	int readBufferPosition;
	int counter;
	volatile boolean stopWorker;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		Button openButton = (Button)findViewById(R.id.open);
		Button sendButton = (Button)findViewById(R.id.send);
		Button closeButton = (Button)findViewById(R.id.close);
		myLabel = (TextView)findViewById(R.id.label);
		myTextbox = (EditText)findViewById(R.id.entry);

		//Open Button
		openButton.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				try {
					findBT();
					openBT();
				}
				catch (IOException ex) { }
			}
		});

		//Send Button
		sendButton.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				try {
					sendData();
				}
				catch (IOException ex) { }
			}
		});

		//Close button
		closeButton.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				try {
					closeBT();
				}
				catch (IOException ex) { }
			}
		});
	}

	void findBT() {
		mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
		if(mBluetoothAdapter == null) {
			myLabel.setText("No bluetooth adapter available");
		}

		if(!mBluetoothAdapter.isEnabled()) {
			Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
			startActivityForResult(enableBluetooth, 0);
		}

		Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
		if(pairedDevices.size() > 0) {
			for(BluetoothDevice device : pairedDevices) {
				if(device.getAddress().equals("00:06:66:4B:44:3E"))  {
					mmDevice = device;
					break;
				}
			}
		}
		myLabel.setText("Bluetooth Device Found");
	}

	void openBT() throws IOException {
		UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); //Standard SerialPortService ID
		mmSocket = mmDevice.createRfcommSocketToServiceRecord(uuid);        
		mmSocket.connect();
		mmOutputStream = mmSocket.getOutputStream();
		mmInputStream = mmSocket.getInputStream();

		beginListenForData();

		myLabel.setText("Bluetooth Opened");
	}

	void beginListenForData() {
		final Handler handler = new Handler(); 
		final byte delimiter = 10; //This is the ASCII code for a newline character

		stopWorker = false;
		readBufferPosition = 0;
		readBuffer = new byte[1024];
		workerThread = new Thread(new Runnable() {
			public void run() {                
				while(!Thread.currentThread().isInterrupted() && !stopWorker) {
					try {
						int bytesAvailable = mmInputStream.available();                        
						if(bytesAvailable > 0) {
							byte[] packetBytes = new byte[bytesAvailable];
							mmInputStream.read(packetBytes);
							for(int i=0;i<bytesAvailable;i++) {
								byte b = packetBytes[i];
								if(b == delimiter) {
									byte[] encodedBytes = new byte[readBufferPosition];
									System.arraycopy(readBuffer, 0, encodedBytes, 0, encodedBytes.length);
									final String data = new String(encodedBytes, "US-ASCII");
									readBufferPosition = 0;

									handler.post(new Runnable() {
										public void run() {
											myLabel.setText(data);
										}
									});
								}
								else {
									readBuffer[readBufferPosition++] = b;
								}
							}
						}
					} 
					catch (IOException ex) {
						stopWorker = true;
					}
				}
			}
		});

		workerThread.start();
	}

	void sendData() throws IOException {
		final String msg = myTextbox.getText().toString();
		Log.d("BT", "send to BT: " + msg);
		if (mmOutputStream != null) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					Log.d("BT", "sendText(): Writing message to outputstream: " + msg);
					try {
						mmOutputStream.write(msg.getBytes());
						Log.d("BT", "sendText(): Writing message to outputstream completed.");
					} catch (IOException e) {
						Log.e("BT", "sendText(): Error: " + e);
					}
				}
			}).start();
		}
		myLabel.setText("Data Sent " + msg);
	}

	void closeBT() throws IOException {
		stopWorker = true;
		mmOutputStream.close();
		mmInputStream.close();
		mmSocket.close();
		myLabel.setText("Bluetooth Closed");
	}
}

The Android log tells me the data is really sent:

D/BT(24456): send to BT: testdata
D/BT(24456): sendText(): Writing message to outputstream: testdata
D/BLZ20_ASOCKWRP(24456): asocket_write
I/BLZ20_WRAPPER(24456): blz20_wrp_poll: nfds 2, timeout -1 ms
D/BLZ20_WRAPPER(24456): blz20_wrp_poll: transp poll : (fd 53) returned r_ev [POLLOUT ] (0x4)
D/BLZ20_WRAPPER(24456): blz20_wrp_poll: return 1
I//system/bin/btld(22030): btlif_bts_api_data_cb: btlif_bts_api_data_cb : hdl 32, len 8
I//system/bin/btld(22030): jw_if_rfcomm_cl_cback: jw_if_rfcomm_cl_cback event=BTA_JV_RFCOMM_WRITE_EVT
I//system/bin/btld(22030): bts_alloc_buf: hdr:0x40425a00, max 1712, offset 18, len 0 
I//system/bin/btld(22030): bts_alloc_buf: peer mtu 127
I//system/bin/btld(22030): rfc_setup_rx_buf: pushed in queue p_buf #0: 0x40425a00, len:0, offset:18
D/BLZ20_WRAPPER(24456): blz20_wrp_write: wrote 8 bytes out of 8 on fd 53
D/BT(24456): sendText(): Writing message to outputstream completed.

Thank you for your ideas.
Best regards

I am having similar issues using Leonardo, Sparkfun BlueSmirf, Galaxy Note 2 (4.2.1) or Droid 2 (2.3.6).

I've confirmed that the RN-42 (bluetooth transmitter) is functional by shorting the RX and TX on the Bluesmirf board. When I use S2 Bluetooth Terminal on my phone to send a command, the RN-42 immediately echoes what I transmit. Thus, the antenna, RX, and TX work.

The arduino will transmit perfectly to the android, but the android does not seem to transmit to the arduino.

I've tried removing the hardware serial to see if that blocks receiving, but that didn't work.

I've spent a little more time on this.

I've tried changing the baud rate on the bluetooth from 9600-115200 (with corresponding changes in the arduino code) and haven't had any success. I've also tried plugging the bluetooth TX into both the softwareserial RX and the hardware serial RX. I've tried matching the bluetooth baud rate to the serial monitor baud rate. No luck.

I've one through the RN-42 manual to see if there are settings on the bluetooth that could affect this. I tried slave and master. I tried changing the profile from SPP to gateway or master. I tried turning on role switching. None of these worked (in fact, made bluetooth connections stop working so I had to reset to factory several times).

I am connecting to bluetooth using BlueTerm on my android phone. I am able to see input from the arduino. I try to send characters by typing in the terminal.

This is the code I'm using to verify the connection. It seems like the BT is sending the characters to the arduino, but the arduino simply isn't recognizing it or storing it in the serial buffer.

#include <SoftwareSerial.h>



int stimPin = 13;
int state = 0;
int reading;
int previous = LOW;
char pcSignal = '0'; // 0 means default
long time = 0;
long debounce = 200;

int bluetoothTx = 2;
int bluetoothRx = 3;

SoftwareSerial bluetooth(bluetoothTx, bluetoothRx);

void setup()
{
 Serial.begin(9600);
 bluetooth.begin(57600); // I configured the RN-42 to operate at 57.6k
 bluetooth.println("blue tooth initiated!");
 pinMode(stimPin, OUTPUT);
  
}// setup 

void loop()
{
  
  //Serial.println(bluetooth.read());
 // bluetooth.println(pcSignal);
 
  if (bluetooth.available()) // see if there are at least 1 characters available
  {
    pcSignal = bluetooth.read();
    Serial.print("BT SERIAL CHANGED PC SIGNAL TO: ");
    Serial.println(pcSignal); 
  }// if Serial.available()


  if (Serial.available() > 0)
  {
    pcSignal = Serial.read();
    Serial.print("SERIAL MONITOR CHANGED PC SIGNAL CHANGED TO: ");
    Serial.println(pcSignal);
  }//
 

  
  switch(pcSignal)
  {
    case '0':
      break;
    case '1':
      wink();
      break;
    case '2':
      wink();
      wink();
      break;
    case '3':
      break;
    case '4':
      break;
    case '5':
      break;
    case '6':
      break;
    default:
      errorSignal();
      break;
  }// switch pcSignal  
    
  //Serial.println(bluetooth.read());
  //Serial.println(pcSignal);
  delay(1000);
  bluetooth.println(pcSignal);
  Serial.println(pcSignal);
  
}// loop()

void wink(){
  
 digitalWrite(stimPin, HIGH);
 delay(1200);
 digitalWrite(stimPin, LOW);
 delay(350);
  
}//blink for debuggin




void errorSignal(){
  //wink();
  //wink();
  //wink();
  digitalWrite(stimPin, HIGH);
  delay(100);
  digitalWrite(stimPin, LOW);
  delay(150);
  digitalWrite(stimPin, HIGH);
  delay(100);
  digitalWrite(stimPin, LOW);
  delay(150);
  digitalWrite(stimPin, HIGH);
  delay(100);
  digitalWrite(stimPin, LOW);
  delay(150);
  digitalWrite(stimPin, HIGH);
  delay(100);
  digitalWrite(stimPin, LOW);
  delay(150);
  digitalWrite(stimPin, HIGH);
  delay(100);
  digitalWrite(stimPin, LOW);
  delay(150);
  delay(333);
}// errorSignal

This problem seems to pop up in March. Previous thread: http://arduino.cc/forum/index.php?topic=96518.0

The conclusion of that thread is that the particular RN-42 chip was bad and, once replaced, functioned as expected.

Not a satisfying answer since, as far as all the testing showed, my chip works fine. Perhaps this is a common issue with the sparkfun boards?

Edit:

A quick look at the sparkfun forums turned up this post: BlueSMIRF - no transmission, receive OK. - SparkFun Electronics Forum

This person looked at the TX pin using an oscilloscope and found no activity at the pin. They replaced their board and it functioned as expected. Interestingly, they also shorted their TX and RX pins ("hardware echo") and found no transmission on their terminal.

So, one way transmission is a known problem. A bad TX pin can be the issue and can be detected by doing either a hardware echo OR monitoring it with an oscilloscope.

We seem to have a second cause of one way transmission that is different from a bad TX pin.

Final edit:
I was able to resolve my issue by switching from Leonardo to Uno. It's a simple fix to make the Leonardo work. Simply modify the pin connections and code so that you use pins 8 and 9 instead of 2 and 3. The issue is related to softwareserial:

"Not all pins on the Leonardo support change interrupts, so only the following can be used for RX: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI)."

And for the original poster, this info may solve your problem:

"Not all pins on the Mega and Mega 2560 support change interrupts, so only the following can be used for RX: 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69"

Apparently the interrupts are necessary for receiving but not transmitting. Who knew?

Thank you very much for your research!!! :slight_smile: :slight_smile: :slight_smile:
I will try to use your hint on Mega and UNO.

Best regards
filyra

I was able to successfully use an RN42 with a Nano. Thing was that i had to reduce the baud rate from 115200 to 9600. This allowed the Arduino to catch up. You can view the results and sample program here: http://arduino.cc/forum/index.php/topic,141397.msg1151052.html#msg1151052