Android蓝牙inputstream,Android Bluetooth InputStream real time read

I am working on an Android application that receives a real time data by Bluetooth and plots it on the screen.

The data is a gyro sensor position information. I am sending it from a custom Freescale Kinetis K10 microcontroller board (designed and tested by myself). For the Bluetooth communication I am using HC-05 Bluetooth module.

The format of the data is as follows:

byte_1: position identification byte, always equals to -128

byte_2: position of axis 1

byte_3: position of axis 2

byte_4: position of axis 3

I am sending these 4 bytes continuously one after another, in that particular order. I am sending this packet of 4 bytes every 5 ms and sending the packet takes about 4.7 ms (9600 baud rate).

The data output from the microcontroller is perfect in terms of accuracy and timing (checked with a logic analyzer).

The problem is that when it is being received from the phone, some of the bytes seem to get lost. Here is the part of the code, where I am reading the InputStream:

private class ConnectedThread extends Thread {

private final BluetoothSocket mmSocket;

private final InputStream mmInStream;

private final OutputStream mmOutStream;

public ConnectedThread(BluetoothSocket socket) {

mmSocket = socket;

InputStream tmpIn = null;

OutputStream tmpOut = null;

try {

tmpIn = socket.getInputStream();

tmpOut = socket.getOutputStream();

} catch (IOException e) {

Log.e("Printer Service", "temp sockets not created", e);

}

mmInStream = tmpIn;

mmOutStream = tmpOut;

}

@Override

public void run() {

Log.i("BluetoothService", "BEGIN mConnectedThread");

byte[] buffer = new byte[4];

int bytes;

while (true) {

try {

bytes = mmInStream.read(buffer);

int position = 0;

if(buffer[0] == -128) {

if(bytes >= 2) {

sendArray.errorTilt = buffer[1];

}

if(bytes >= 3) {

sendArray.errorRoll = buffer[2];

}

if(bytes == 4) {

sendArray.errorPan = buffer[3];

}

}

else if(buffer[1] == -128) {

position = 1;

if(bytes >= 3) {

sendArray.errorTilt = buffer[2];

}

if(bytes == 4) {

sendArray.errorRoll = buffer[3];

}

if(bytes >= 2) {

sendArray.errorPan = buffer[0];

}

}

else if(buffer[2] == -128 && bytes >= 3) {

position = 2;

sendArray.errorRoll = buffer[0];

sendArray.errorPan = buffer[1];

if(bytes == 4) {

sendArray.errorTilt = buffer[3];

}

}

else if(buffer[3] == -128 && bytes == 4) {

position = 3;

sendArray.errorTilt = buffer[0];

sendArray.errorRoll = buffer[1];

sendArray.errorPan = buffer[2];

}

if(position <= bytes && bytes > 1) {

sendArray.errorUpdate = true;

}

} catch (Exception e) {

e.printStackTrace();

connectionLost();

BluetoothService.this.stop();

break;

}

}

}

public void write(int oneByte) {

try {

mmOutStream.write(oneByte);

} catch (IOException e) {

Log.e("BluetoothService", "Exception during write", e);

}

}

public void cancel() {

try {

mmSocket.close();

} catch (IOException e) {

Log.e("BluetoothService", "close() of connect socket failed", e);

}

}

}

sendArray is a singleton that keeps many different variables.

errorTilt, errorRoll and errorPan are the current values of the axis, which are being updated from the receiving buffer.

"position" keeps the position of the position identification byte. It is used for a check if any variables have been updated.

Many times just one byte is received in the input buffer and since I don't know which axis is that supposed to be, since I don't have information about it's relative position to the position byte, this particular byte is useless and gets lost.

I've tested the accuracy of receiving by the following method. I made the MCU output a triangular wave on one of the axis, instead of the axis data. On the phone the lines of the triangular wave are not straight as they are supposed to be, but randomly curved and containing artifacts.

To plot the data I am using GraphView and I am updating the graph on equal intervals from a separate thread.

I've tried using longer receiving buffer (with a modified receiving algorithm), but this doesn't help as only a few bytes are being received at a time.

I've tried implementing InputStream.available() but it was always giving 127 bytes available, which didn't seem to be true.

I've read many threads about similar problems and I spent the last 5 days working on it, but I couldn't find a good solution.

To summarize, I need to achieve accurate, real time (or close to real time) receiving of all the bytes.

Thank you.

UPDATE:

I've tried sending the information just for one of the axis, so it is simple and clear, without the need of position bytes. I was sending it again every 5 ms, but this time it was more time between the consecutive bytes, since it's just one byte in the packet.

I used InputStream.read() this time, which doesn't require a buffer. However, the incoming data was corrupted again, because random bytes couldn't be received.

I've seen different project using this method successfully, I don't know why it's not working with me. I thought it might be a problem with the HC-05 Bluetooth module I'm using, but I tried a different one - HC-06, and the situation is the same. I haven't tried a different phone, but my phone (Samsung Galaxy S3, Android 4.1.2) seems to be working OK.

UPDATE2: I've tried again testing the original code with InputStream.available() before reading from the stream.

When the condition is available()>0, there are no major changes, maybe it works slightly worse.

When the condition is available()>1, it never reads. I guess that is because of the unreliable available() method, as it says in the documentation.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值