Moved from Android forums
Im at a loss here. It want to send some serial data from arduino to android but what I send is not what is received. For example, If I put Serial.write(5), on the android side I get 48. If I put Serial.write(6) I get 1. The same problem happens when I send characters. If I send a 't', on android I get a T with 2 points on top(as if its a character from another language). ??????? What's happening?
Arduino
int count = 5;
const unsigned int BAUD_RATE = 115200;
void setup() {
Serial.begin(BAUD_RATE);
delay(10000);
}
void loop() {
//Serial.print(count, DEC);
//Serial.print(count, HEX);
Serial.print(count, OCT);
//Serial.println(count, BIN);
//Serial.write(temp);
//Serial.write("t");
Serial.write(count);
count++;
delay(2000);
}
Android
RFComm: UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
byte[] buffer = new byte[255];
Handler myHandler1 = new Handler();
Runnable receiveValues = new Runnable() {
public void run() {
try {
while (connected) {
while (in.available() > 0) {
Log.v("Note",
"For value: " + String.valueOf(in.read(buffer)));
for (int x = 0; x < buffer.length; x++)
Log.v("Note", "A " + buffer[x]);
}
Thread.sleep(50);
}
} catch (Exception e) {
connected = false;
e.printStackTrace();
}
}
};
The timing is right, every two seconds something gets sent but still I get the wrong value. As you can also see, I tried other ways to write to the serial port on the arduino but none of them work. Another thing, the end of line(when I do Serial.println()) is consistently received as a 0 on android.
Running on android 2.3.7 where min sdk = 8 (android 2.2)
Answer is really simple... Forgot about int ranges(-32768 to +32767) or in this case unsigned int(0 - 65534) and when I directly entered the baud rate, it worked well.
Serial.begin(115200);
Related
I have a Particle Photon microcontroller sending TCP packets over a hotspot WiFi network to an Android Phone. The microcontroller is acting as server, the phone as client.
The phone however is receiving some (but not all) of the packets out of order, despite the information being transmitted via tcp. It was my understanding that this would not happen - am i wrong, or is there something i can do to correct this?
Microcontroller Code:
// This #include statement was automatically added by the Particle IDE.
#include "databuffer5.h"
// This #include statement was automatically added by the Particle IDE.
#include "databuffer7.h"
const unsigned int localPort = 10000;
IPAddress remoteIP(a, b, c, d);
// An TCP instance to let us send and receive packets over wifi
TCPServer server = TCPServer(localPort);
TCPClient client;
// UDP Port used for two way communication
short msg_count = 0;
const int adcPin = A0;
int byteBuffer;
unsigned long loopTimer;
const int packetSize = 40; //number of bytes in packet - 10 ints with 4 bytes each
byte buffer[packetSize];
int j = 0;
int dataCount = 0; //dummy data that increments every loop point, to measure packet contiuity
//(creates a line with slope 1 as data)
void setup() {
// start the UDP
server.begin();
// Print your device IP Address via serial
Serial.begin(9600);
Serial.println(WiFi.localIP());
//Serial.println(System.ticksPerMicrosecond()); //returns 120, ie 120MHz
}
void loop()
{
if (client.connected())
{
loopTimer = millis(); //mark start time of loop
for (int i = 0; i < 10; i++)
{
//for testing connection
byteBuffer = i+j*10;
buffer[i*4] = ( (byteBuffer >> 24) & 0xFF); //take upper 8 bits
buffer[i*4+1] = ( (byteBuffer >> 16) & 0xFF); //take middle upper 8 bits
buffer[i*4+2] = ( (byteBuffer >> 8 ) & 0xFF); //take middle lower 8 bits
buffer[i*4+3] = ( byteBuffer & 0xFF); //take lower 8 bits
dataCount++;
if (i != 9)
{
while(millis() < (loopTimer+10*(i+1))); //ie do nothing for 10 ms (time is in ms, want to delay by exactly 10ms for each loop)
//goal here is to sample every 10ms, by delaying for the remaining time
//dont delay here for the last sample, as the udp packet will take time
//delay after instead
}
}
server.write(buffer, sizeof(buffer)); //using sizeof on a byte array so dont need to scale (ie scaling factor is 1)
j++;
if (j < 0){j = 0;}
while(millis() < (loopTimer+10*10)); //delay till 100ms after loops started
}
else
{
client = server.available();
}
}
Android (client) code:
async_udp = new AsyncTask<Void, int[], Void>() {
#Override
protected Void doInBackground(Void... params) {
byte b1[];
b1 = new byte[100];
while (serverActive) {
Socket socket = null; //previously this was DatagramSocket (UDP) - no Socket (TCP)
try {
//DatagramSocket s = new DatagramSocket(server_port, server_ip);
socket = new Socket(server_ip, server_port);
socket.setPerformancePreferences(1, 2, 2);
InputStream socketStream = socket.getInputStream();
DatagramPacket p1 = new DatagramPacket(b1, b1.length);
ByteBuffer wrapped;
int data[] = new int[10+1]; //first number for message data, second is for the message number
while (serverActive) //TODO include shutdown function
{
while (socketStream.available() < 39){}
socketStream.read(b1, 0, 40);
//packet structure is a char containing message number, and 10 shorts (2 bytes) containing data points (between 0 and 4096)
wrapped = ByteBuffer.wrap(Arrays.copyOfRange(b1, 0, 40)); // extract 40 bytes to convert to 10 ints
for (int i = 0; i < 10; i++) {
data[i] = wrapped.getInt();
}
String str = data.toString();
server_port = p1.getPort();
server_ip = p1.getAddress();
String str_msg = "RECEIVED FROM CLIENT IP =" + server_ip + " port=" + server_port + " message no = " + b1[0] +
" data=" + str; //first character is message number
statusText = str_msg;
publishProgress(data);
}
socketStream.close();
socket.close();
} catch (SocketException e) {
if (socket != null) {}
//status.append("Error creating socket");
statusText = (" Error creating socket"); //this doesn't work!
} catch (IOException e) {
//status.append("Error recieving packet");
statusText = (" Error receiving packet"); //this doesn't work!
}
try{
Thread.sleep(100, 0); //sleep for 10ms if no wifi lock is found, to stop battery being silly
} catch(Exception e){
e.printStackTrace();
}
}
return null;
}
protected void onProgressUpdate(int[]... data1)
{
super.onProgressUpdate(data1);
int data[] = data1[0];
//send data to graph
for (int i = 0; i < 9; i++)
{
series.appendData(new DataPoint(lastDataX++, data[i]), false, graphPointsMax);
//append 9 points to graph, but only redraw the grpah on the 10th
}
series.appendData(new DataPoint(lastDataX++, data[9]), true, graphPointsMax);
}
};
if (Build.VERSION.SDK_INT >= 11)
{
async_udp.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
else
{
async_udp.execute();
}
What is guaranteed by TCP, is that when you send a message - it will come in the right order, even if split by the TCP stack along the way (see TCP Segment Number, which serves as an indication which split message part belongs together with which, and in what order). So, in your case, all you are sending using:
server.write(buffer, sizeof(buffer));
no meter how big is the buffer (within the limits of TCP protocol, of course) is guaranteed to arrive in the right order and complete.
Sending several buffers one-by-one over TCP will provide you guaranteed delivery, or error notification (if any), but not the order of the messages sent. Down to the protocol level, these packets will contain different Sequence Numbers, and therefore will be treated by the TCP stack of the receiver separately, in the order the stack prefers.
I see two relatively simple things that could be done here:
try to put all you can in one buffer (not really practical approach, though)
Introduce the counter and increment each time you are sending the buffer out. Put the counter along with the buffer and check the precedence on the receiving side (phone, in your case).
I've been struggling with the problem of sending continuous data from arduino to Android.
What I want to do is get analog read convert it to 0-5V information, and send that information to Android app.
My arduino code is just simply:
//(...)defining pins and levels
SoftwareSerial BTSerial(rxPin, txPin);
void setup()
{
pinMode(getData, INPUT);
digitalWrite(keyPin, LOW);
BTSerial.begin(9600);
}
void loop()
{
contact = digitalRead(getData);
if (contact == HIGH) {
sensorValue = analogRead(sensorPin);
double voltage = sensorValue * (5.0 / 1023.0);
if (BTSerial.available()) {
Serial.write(BTSerial.read());
}
BTSerial.println(voltage, 3);
BTSerial.write("\r");
if (Serial.available()) {
BTSerial.write(Serial.read());
}
}
delay(5);
}
I need to send data informing about measurment with ~200Hz frequency.
After sending the data to application it seems that part of data is lost.
I tried higher bound rates but the problem still occurs. Is there a way to send continuous data from arduino using serial port without loosing some % of that data?
I think the problem is in the design of the receiver. I Solved BTL communication in .net Xamarin, but the principle should be the same. In Android reading from InputStream must be quick and can not use sleep. You need to use an endless cycle and there quick read data into temp buffer. Immediately a dune bytes to an auxiliary large buffer (use read / write cursor) and then, for example, in timer treat the data (I suppose you are using some packet protocol)
public override void Run()
{
WriteLogInfoToLog("ConnectedThread.Run() - before");
while (true)
{
try
{
int readBytes = 0;
lock (InternaldataReadLock)
{
readBytes = clientSocketInStream.Read(InternaldataRead, 0, InternaldataRead.Length);
Array.Copy(InternaldataRead, TempdataRead, readBytes);
}
if (readBytes > 0)
{
lock (dataReadLock)
{
dataRead = new byte[readBytes];
for (int i = 0; i < readBytes; i++)
{
dataRead[i] = TempdataRead[i];
}
}
}
}
catch (System.Exception e)
{
btlManager.btlState = BTLService.BTLState.Nothing;//Spadlo spojeni, musi spustit cele od zacatku
WriteLogInfoToLog("ConnectedThread.Run() - EXCEPTION " + e.Message + ", " + e.HResult + ", " + e.StackTrace + ", " + e.InnerException);
if (e is Java.IO.IOException)
{
}
else
{
}
break;
}
}
WriteLogInfoToLog("ConnectedThread.Run() - after");
}
I am developing Client-Server application in C++ using Qt framework, but the clients can be android phones and computers(Qt client app)
Now i'm having troubles to handle Reception of data on the server side; the server is not receiving data properly.
First, I got things working nicely between the server(Qt app) and the client(Qt app) using these methods for sending and receiving:
The size of the message is kept at the beginning of the packet to help check whether the whole message is received or not.
This is the method to send message to the clients
void Server::send(const QString &message)
{
QByteArray paquet;
QDataStream out(&paquet, QIODevice::WriteOnly);
out << (quint16) 0; // just put 0 at the head of the paquet to reserve place to put the size of the message
out << message; // adding the message
out.device()->seek(0); // coming back to the head of the paquet
out << (quint16) (paquet.size() - sizeof(quint16)); // replace the 0 value by the real size
clientSocket->write(paquet); //sending...
}
This slot is called every time a single paquet is received.
void Server::dataReceived()
{
forever
{
// 1 : a packet has arrived from any client
// getting the socket of that client (recherche du QTcpSocket du client)
QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
if (socket == 0)
return;
QDataStream in(socket);
if (dataSize == 0) // if we don't know the size of data we are suppose to receive...
{
if (socket->bytesAvailable() < (int)sizeof(quint16)) // we haven't yet receive the size of the data completly then return...
return;
in >> dataSize; // now we know the amount of data we should get
}
if (socket->bytesAvailable() < dataSize)
return;
// Here we are sure we got the whole data then we can startreadind
QString message;
in >> message;
//Processing....
dataSize = 0; // re-initialize for the coming data
}
}
This is working well when the server is talking with the Qt app Client, because the same methods are used there, and the size of quint16 will remain the same hover it doesn't work with android client, then i tried another way in which i wanted to ignore the size of the message sent, but format the message in a way such that i can know where it starts and where it ends, then with some controls i can get it however i'm stuck here, cause the data read doesn't contain anything when printed, but his size has a value(which even vary according to the amount of text the client send)!
void Server::dataReceived() // a packet is received!
{
QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
if (socket == 0)
return;
QByteArray data= socket->readAll(); //reading all data available
QString message(data)
qDebug() << data; // this prints nothing!
qDebug() << data.size();// But this prints a non null number, wich means we got something, and that number varies according to the amount of text sent!
qDebug() << message; // this also prints notghing!
}
PS: it's not working even for the Qt app Client.
Can you help me find out what's wrong, i'm a bit confused how the tcp protocol is handling the data, and if you could and also advise me a good way for doing this.
here is the android class I made for the purpose
class QTcpSocket implements Runnable {
private String ip="";
private int port;
private Socket socket;
private PrintWriter printWriter;
private DataOutputStream dataOutputStream;
private DataInputStream dataInputStream;
public QTcpSocket(String ip, int port) {
this.ip = ip;
this.port = port;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getIp() {
return this.ip;
}
public void setPort(int port) {
this.port = port;
}
public void run() {
try {
socket = new Socket(this.ip, this.port);
dataOutputStream = new DataOutputStream( socket.getOutputStream() );
dataInputStream = new DataInputStream(socket.getInputStream());
String response = dataInputStream.readUTF();
dataOutputStream.writeUTF("Hello server!");
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendMessage(String message) {
try {
dataOutputStream.writeUTF(message);
}catch (IOException e) {
e.printStackTrace();
}
}
public void disconnect() {
try {
printWriter.flush();
printWriter.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public boolean isClosed() {
return socket.isClosed();
}
}
Replace in 'data' all bytes with value 0 by value 20 and print again. I think you see nothing printed because the first byte is 0. You could also replace with 'X'. Did you already replace writeUTF() by write() ?
20 is the space character. But then you also see nothing printed so better use a X char. Strings get printed until a \0 char (which indicates the end of a string) is met. Because nothing was printed i supposed one right at the beginning. So writeUTF causes that leading 0. I could only explain that if all chars had doubled. What was the first char you sent?
But now: send size-of-message first so it equals your qt client.
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.
Thread with a similar problem:
How to do good real-time data streaming using Java Android SDK
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.
you have incorrect processing of data, if you want to get data from microcontroller board. You have to use bytesAvaliable because android bluetooth Socket is pretty slow over microcontroller boards with bluetooth. But "bytesAvaliable way" has nuance - As socket is slow receiver, bytesAvaliable can catch more then 1 packet from board in one time so you gotta devide readed data by yourself, Check my code out below! My code is getting 38 bytes packets from inertial sensor so you gotta only change count of bytes! 0xAA is the first byte of every next packet so if you find 0xAA byte and have 38 bytes you get packet and nullify iterator. But anyway I'm sure that you still can sometimes lose data because it's not high frequency data transfering way
public void run() {
byte[] bytes = new byte[38];
int iterator = 0;
while (true) {
try {
int bytesAvailable = mmInStream.available();
if (bytesAvailable > 0) {
byte[] curBuf = new byte[bytesAvailable];
mmInStream.read(curBuf);
for (byte b : curBuf) {
if (b == (byte) 0xAA && iterator == 38) {
mHandler.obtainMessage(MainActivity.DATA_READ, bytes.length, -1, bytes).sendToTarget();
iterator = 0;
bytes[iterator] = b;
} else {
bytes[iterator] = b;
}
iterator++;
}
}
} catch (IOException ex) {
Log.e(TAG, "disconnected", ex);
connectionLost();
break;
}
}
}
I have an iRobot with a RooTooth installed, which is a bluetooth to serial converter. It is said to operate just like a serial port and data should be received as such. I have been able to use a terminal program to send serial commands directly to it over a serial cable, and it works fine.
I can also use the app I have written to send commands from my phone to my computer which is monitoring incoming bluetooth commands, and it receives them exactly as intended.
However, when I send it from my phone to the rootooth, nothing happens. Is there something wrong about how I am sending the commands? Shown below is how I do it:
This is within a handler:
case SUCCESS_CONNECT:
ConnectedThread connectedThread = new ConnectedThread((BluetoothSocket)msg.obj);
String s = "128 131";
byte[] command = s.getBytes();
connectedThread.write(command);
Toast.makeText(getApplicationContext(), s, 0).show();
s = "137 0 100 128 0";
byte[] command1 = s.getBytes();
connectedThread.write(command1);
Toast.makeText(getApplicationContext(), s, 0).show();
This is my write() function
public void write(byte[] bytes) {
Log.i(tag, "In write");
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
The issue must be formatting, no? Anybody with experience here, your help would be greatly appreciated!
Recently I have attempted this:
String [] s = new String[2];
s[0] = "128";
s[1] = "131";
for(int i = 0; i < s.length; i++){
byte[] command = s[i].getBytes();
connectedThread.write(command);
Thread.yield();
}
String [] t = new String[5];
t[0] = "137";
t[1] = "0";
t[2] = "100";
t[3] = "128";
t[4] = "0";
for(int i = 0; i < t.length; i++){
byte[] command = t[i].getBytes();
connectedThread.write(command);
Thread.yield();
}
I have also tried this recent version including a "/n" string but that has not done anything either.
For anybody else that happens to run into this problem, it turns out that a .write() from an OutputStream will take ints even though it says it will only take byte[]. Creating an array of ints for each command and sending them int by int ended up working. No need to include spaces or new lines.