Hello!
I'm not sure if this question is suited for this forum or the Project Guidance one, anyway here goes.
Basically I'm making an Android app, which communicates with Arduino by using the popular HC-05 Bluetooth module. Although I'm able to send data back and forth, the quality of the data is worse than I would like, usually only ~30-60% of the data is usable.
For example, if I send "12345" with the Arduino, on the Android end the order of the characters often goes bad, and I might receive "23451" or something similar. However, the problem doesn't last too long and generally the message goes in the correct order.
On the other hand, sending "abcde" from the Android device to the Arduino is much more prone to errors. Not only it suffers from the message getting out of order, but it also prints out gibberish characters for a few message cycles before going back to normal.
I attached the code from both devices below.
Arduino code:
#include <SoftwareSerial.h>
SoftwareSerial mSerial(10, 11); // RX, TX
char bytes[6];
int index = 0;
boolean reading = false;
void setup() {
mSerial.begin(4800);
Serial.begin(9600);
Serial.println("Startup completed");
}
void loop() {
read();
mSerial.write(",12345");
delay(200);
}
void read() {
if (!reading && mSerial.read() == ',') {
reading = true;
}
if (reading) {
int i = mSerial.available();
while (i > 0 && index < 5) {
bytes[index] = mSerial.read();
i--;
index++;
}
if (index >= 4) {
for (int j = 0; j < 5; j++) {
Serial.print(bytes[j]);
}
Serial.println();
index = 0;
reading = false;
}
}
}
Android code:
/* Imports */
@TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1)
public class Main extends Activity {
private Reader ReadThread = null;
private String name = null;
private String address = null;
BluetoothAdapter adapter = null;
BluetoothSocket socket = null;
BluetoothDevice device = null;
BluetoothServerSocket ServerSocket = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_item);
System.out.println("OnCreate started");
bluetooth();
}
protected void onDestroy() {
super.onDestroy();
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void bluetooth() {
Boolean foundit = false;
adapter = BluetoothAdapter.getDefaultAdapter();
if (!adapter.isEnabled()) {
Intent turnOn = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(turnOn, 0);
}
Set<BluetoothDevice> pairedDevices = adapter.getBondedDevices();
// If there are paired devices
if (pairedDevices.size() > 0) {
// Loop through paired devices
for (BluetoothDevice deviceTmp : pairedDevices) {
if (deviceTmp.getName().toString()
.equalsIgnoreCase("ARDUINOBT")) {
name = deviceTmp.getName();
address = deviceTmp.getAddress();
device = deviceTmp;
Toast.makeText(getApplicationContext(),
"Name: " + name + ", address:" + address,
Toast.LENGTH_SHORT).show();
foundit = true;
}
break;
}
if (!foundit) {
Toast.makeText(getApplicationContext(), "BT device not found",
Toast.LENGTH_SHORT).show();
;
}
} else {
Toast.makeText(getApplicationContext(), "No paired devices",
Toast.LENGTH_SHORT).show();
}
UUID mDeviceUUID = UUID
.fromString("00001101-0000-1000-8000-00805F9B34FB");
try {
adapter.cancelDiscovery();
socket = device
.createInsecureRfcommSocketToServiceRecord(mDeviceUUID);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
socket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
socket.close();
} catch (IOException closeException) {
}
}
System.out.println("Bluetooth initialized!");
ReadThread = new Reader();
while (true) {
write(",abcde");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
socket.close();
} catch (IOException e) {
}
}
public void write(String msg) {
msg = msg;
try {
socket.getOutputStream().write(msg.getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.print("SENT: ");
System.out.println(msg);
}
private class Reader implements Runnable {
private Thread t;
public Reader() {
t = new Thread(this, "Input Thread");
t.start();
}
@Override
public void run() {
InputStream mmInStream = null;
byte[] buffer = new byte[5];
int index = 0;
boolean read = false;
try {
mmInStream = socket.getInputStream();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (true) {
// Keep listening to the InputStream until an exception occurs
try {
if ((char) mmInStream.read() == ',') {
read = true;
}
if (read) {
int i = mmInStream.available();
while (i > 0 && index < 5) {
buffer[index] = (byte) mmInStream.read();
i--;
index++;
}
if (index >= 4) {
// String strInput = new String(buffer, 0, 5);
String strInput = "";
for (int j = 0; j < buffer.length; j++) {
strInput = strInput + (char) buffer[j];
}
System.out.print("READ: ");
System.out.println(strInput);
index = 0;
read = false;
}
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
As you can see, I inserted delay() and Thread.sleep() in both Arduino and Android code to increase the stability of the connection. At first I tried 10ms, but that resulted in horrible message quality, therefore I increased it to the largest acceptable delay/sleep time (if I increase it more, the communication will be too slow for my intended purpose, rendering it useless).
Also, I add a comma to the beginning of each message as it works as a start bit - the bytes of the message are stored in the buffer array only after a comma has been received and read. This did seem to increase the quality of the communication a little bit, however, it didn't change much and the results were similar without using anything like this.
Lastly, I have set the HC-05 module to 4800 baud/s, because it seemed to be more stable at lower speeds, in fact, higher baud rates delivered gibberish bytes. Also, the module now is working without a parity or a stop bit, which can be enabled in its settings (AT mode). Should they be enabled or using commas as an improvised start/stop bit is just as good?
Hopefully someone can help out, thanks!