I'm trying to have an Arduino UNO send values to a IOIO board (https://github.com/ytai/ioio/wiki/UART) over UART. As someone turns a rotary encoder, I want it to send a 0 for CW, 1 for CCW, and 2 for a press. Everything checks out in the Serial Monitor from the Arduino, but I don't know how to read the values and parse them on the Java-end correctly. It all comes through as seemingly random numbers, sometimes occasionally the correct number is there.
I've tried both of these methods on the Arduino side:
Serial.write(1);
byte data[] = {1};
Serial.write(data, 1);
Also Serial.write automatically writes to pin 1, so theres no need to create a SoftwareSerial object.
When reading this on the Java side, I just get mostly 255, occasionally the correct number, and occasionally a random number in between 0 and 255:
#Override
public void connect() throws ConnectionLostException {
try{
// rx pin = 6
mUart = ioio_.openUart(RX_PIN, IOIO.INVALID_PIN, 9600, Parity.NONE, StopBits.ONE);
mInput = mUart.getInputStream();
}
catch(ConnectionLostException e){
Log.e(TAG, "connection lost:" + e.getMessage());
ioio_.disconnect();
throw e;
}
}
#Override
public void loop(int loopCount) throws ConnectionLostException {
try{
byte[] response = new byte[1];
int read = mInput.read();
}catch(IOException e){
Log.d(TAG, "error: " + e.getMessage());
}
}
I've also tried using BufferedReaders, while passing Strings through Serial.println, but a lot of crazy characters were getting output from the Java side (tried encoding in both UTF-8 and ASCII).
Baud rates are matched up at 9600, and I'm on a 5v RX pin on the IOIO, and that pin is connected to the TX pin (pin 1) on the Arduino Uno.
Does anyone point to a simple way of transmitting & receiving an integer?
Related
String Serial_Input must contain a serial number card RFID (MIFARE) like this A45F45A7 (8 byte). sometimes when I approach the card to the RFID reader of arduino the string is like this A45F45 (truncated) , miss any char. there is a solution better that while loop ? (more elegant and efficient) Using Arduino IDE Serial Monitor the card's serial number is correct.
public static void connectionToCom(SerialPort serialPort, ComboBox<String> cbxComPort, TextArea txaMessages) throws SerialPortException
{
int baudrate = 9600; int databits = 8; int stopbits = 1; int parity = 0;
serialPort.openPort() ;
serialPort.setParams(baudrate, databits, stopbits, parity) ;
String Serial_Input = null;
try {
while (true)
{
if (serialPort.readString() != null)
{
Serial_Input = serialPort.readString(8);
System.out.println("Card Serial: " + Serial_Input + "\n");
//serialPort.closePort();
}
}
}
catch (SerialPortException ex){
txaMessages.appendText(ex.toString());
}
}
Here the result image
You could use the method addEventListener(SerialPortEventListener listener, int mask). It call a callback method whenever you receive a byte via serialPort.
The problem with the incomplete string could be 2 problems
The code is executing before the whole string is received. To solve this, you must add a code to verify the length of string you are receiving.
You are using readString twice. You may lost some bytes of the string in first usage.
I have a simple class that handles socket connections:
public class SimpleConnection {
// Socket, input and output streams
protected Socket mSocket;
protected DataInputStream mIn;
protected DataOutputStream mOut;
public boolean createConnection(String ip, int port) {
SocketAddress socketAddress = new InetSocketAddress(ip, port);
mSocket = new Socket();
try {
mSocket.connect(socketAddress, 3000);
mIn = new DataInputStream(mSocket.getInputStream());
mOut = new DataOutputStream(mSocket.getOutputStream());
} catch (IOException e) {
return false;
}
return true;
}
public boolean sendData(byte[] data) {
try {
mOut.writeInt(data.length);
mOut.write(data);
mOut.flush();
} catch (Exception e) {
e.printStackTrace();
closeSocket();
return false;
}
return true;
}
}
This has worked until Android N. With Android N, mOut.writeInt(data.length) just sends four zeros instead of the length of data.length. This causes the server to misinterpreted the message and for the whole program to not work.
I was able to "fix" the problem by converting the integer to a byte[4]:
byte[] len = Utilities.intToByteArray(data.length);
mOut.write(len);
intToByteArray is shown here.
My question is: Why isn't writeInt not working anymore on Android N? On other Android versions this code runs just fine.
I use the latest Android Studio with Java 8, gradle 2.1.3 and Android buildtools 24.0.2.
Edit:
The receiving part looks like this in Qt:
void readData(QTcpSocket* client_) {
while (client_->bytesAvailable()) {
int expected_length_;
QDataStream s(client_);
s >> expected_length_;
qLog(Debug) << expected_length_;
// Read data with expected_length_
QBuffer buffer_;
buffer_.write(client_->read(expected_length_));
}
}
expected_length_ is 0 where with the fix it is 15. Interestingly, client_->bytesAvailable() is 1 with the writeInt variant on Android N.
I did another test using nc -p 1234 -l 0.0.0.0 | xxd:
▶ nc -p 1234 -l 0.0.0.0 | xxd
00000000: 0000 000f 0815 1001 aa01 0808 8edb 0110 ................
00000010: 0118 00 ...
This is the output for both variants... so it seems writeInt() works as expected, but why does it work for Android <= 6 and not for Android 7?!??
Edit2:
After analyzing the traffic I found out that the integer is split in multiple TCP frames. I changed the server code to check if client_->bytesAvailable() >= 4 and only then to read the integer from the socket. This fixed the problem and the writeInt() variant works now too.
But why did the behaviour suddenly change?
After analyzing the traffic I found out that writeInt() flushes the data
It did exactly what you told it to do. DataOutputStream is not buffered, and there is no BufferedOutputStream under it, so writeInt() wrote four bytes to the network.
prematurely.
There is no such thing as 'prematurely' in TCP. TCP makes no guarantees about packetization or segmentation. If you want to control this so-called 'premature flush', use mOut = new DataOutputStream(new BufferedOutputStream(Socket.getOutputStream())); and flush it yourself after writing the data.
So some frames have only one or two bytes, that's why bytesAvailable is only 1.
This was your main problem. You are misusing available(). It isn't an end of message indicator. See the Javadoc.
You also didn't check to see that you had actually read the four bytes of the length word.
As far as I can see you aren't checking to see that you've received all the bytes of data either.
In general you have to loop until you get everything that is expected.
The server code QDataStream reads the int with only one or two byte. After adding if (client_->bytesAvailable() < 4) break; and waiting for more data it works. But I still don't understand why the behaviour changed.
It can change any time. Your code broke because it relied on several invalid assumptions.
I have managed to set up the connection between my arduino and the App with the help of Instructables blog.
The connection is set but i need the sensor output value of the ardunio to be displayed on a TextView. This is the Arduino code.
How do i program my Android studio program to read the output value of the serial monitor in the Arduino?
Okay, in the tutorial shows how send data from the app to arduino, but not how receive data from the arduino to your app for do this, you will need:
Send data from arduino by HC-06.
Receive and decode your data in the app.
show decoded data in the TextView.
a litle example for do this.
In Arduino:
can be the example of the arduino page you must only make sure that HC-06 is properly connected in Serial port.
In the app code you can use this code to receive data, only change the name of SocketBT instance, for the instance that you need.
private class TareaLeer extends Thread
{
#Override
public void run()
{
while(SocketBT.isConnected())
{
InputStream inputStream;
try {
inputStream = SocketBT.getInputStream();
byte[] buffer = new byte[256];
if (inputStream.available() > 0) {
inputStream.read(buffer);
int i = 0;
for (i = 0; i < buffer.length && buffer[i] != 0; i++) {
}
String strInput = new String(buffer, 0, i);
String Recepcion = strInput;
Log.d("Recibi",Recepcion);
//Here you can pass the value of recepcion to any globlal variable and show in TextView
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Parar();
}
}
for show it on TextView you can do this.
MyTextView.setText(Recepcion);
this is a very general explanation, for do it , you need know how android code works basically, but is a good example for start Android and Arduino Programming.
I'm new to StackOverflow lol, but I've been relying on this website for awhile. I have a question regarding a Java socket server that I created. Upon connection (client and server), my application creates a thread for that client. This is an MMORPG game server... at least trying to be. With one player, it doesn't lag that bad. With two, however, it began to show some lags...
If I was to spam left-right-left-right on one of the client, and move around normally with the other, the other would feel glitchy. I'm hoping to get some assistant since I've spent over a week and a half tangled up =) It's about time I ask for help.
The code is simple:
public static void main(String[] args) throws IOException{
serverRooms.put(roomNumber, new Room());
try {
System.out.println("Starting Server...");
serverSocket = new ServerSocket(9595, 20);
System.out.println("Server Started");
while(run){
Socket socket = serverSocket.accept(); // Check if we have a connection, otherwise wait
Player player = new Player(playerCount++, socket, roomNumber);
new Thread(player).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
That's how it is all started! On the Player object, it looks like :
public void run() {
while(playerIsConnected) {
try {
int msgid = input.readUnsignedByte();
messageHandler(this, msgid);
} catch (IOException e) {
System.err.println("Player have signed off");
playerIsConnected = false;
}
}
// If Player leaves, close socket, and end thread
try {
socket.close();
} catch (IOException e) {
System.out.println("We got an error while closing a socket on player " + pid + ".");
}
}
messageHandler happens to be a static method from a Final Static class. It is a global method that can be called by every thread (Can this be the cause of the lag??)
public final class MessageControl {
public static void messageHandler(Player player, int msgid) throws IOException{
DataInputStream input = player.getInputStream();
switch (msgid) {
case 10:
byte hspd = (byte) Math.signum(input.readByte());
byte vspd = (byte) Math.signum(input.readByte());
byte dir = input.readByte();
updatePlayerPosition(player);
byte spd = (byte) (hspd != 0 && vspd != 0 ? player.spd-1 : player.spd);
// Prepare packet and send to clients
ByteBuffer buffer = ByteBuffer.allocate(11);
buffer.put((byte) 10);
buffer.put(shortToByte_U16(player.pid));
buffer.put(shortToByte_U16(player.x));
buffer.put(shortToByte_U16(player.y));
buffer.put((byte)(hspd*spd));
buffer.put((byte)(vspd*spd));
buffer.put((byte)(dir));
sendPacketToAllClients(player, buffer, true);
// Update Player info
player.hspd = (byte) hspd;
player.vspd = (byte) vspd;
player.dir = dir;
player.lastUpdate = System.currentTimeMillis();
break;
}
private static void sendPacketToAllClients(Player player, ByteBuffer buffer, boolean includeMe){
for (Player otherPlayer : player.room.getPlayersInRoom()){
if (otherPlayer.pid != player.pid || includeMe){
sendPacketToClient(otherPlayer, buffer);
}
}
}
}
Regarding the shortToByte_U16(), I just created a simple method that conerts shorts to bytes (sending buffer packets via bytes to client). Example, I have about 5 of these conversions, which would include conversion for unsigned u16
public static byte[] shortToByte_16(int x){
short s = (short) x;
byte[] ret = new byte[2];
ret[0] = (byte)(s & 0xff);
ret[1] = (byte)((s >> 8) & 0xff);
return ret;
}
Looking at the following structure, any ideas why I be lagging?
EDIT : I think I improved it a lot by setting the setTcpNoDelay to true. The lag seems to still be there when I spam left/right on my end... the other player on my screen seems glitchy.
Socket socket = serverSocket.accept(); // Check if we have a connection, otherwise wait
socket.setTcpNoDelay(true); // This helped a lot!!!
Player player = new Player(playerCount++, socket, roomNumber);
new Thread(player).start();
From what I am seeing... my "spamming left/right" end seems to be missing the packet sent by the server.
Problem solved. =) setTcpNoDelay true did the trick. Regarding the part when I said I was missing packets, I actually didn't. The two messages merged and came in as one message. My program only read the first few bytes and ignored the rest. Had to put a byte in front to indicate the size of message. Once that was in place, I set a while loop to read through it til it can't read anymore. =) thanks everyone for helping me. My first post and it was a grand experience.
I have implmented JSSC API so I can communicate with the Com Port.
I send a command like "N\r\n"
and what i receive in a normal hyperterminal should look like this:
0100071CA79215021803164442180000
0100071C9F5415021803164514520000
0100071CDF5115022106142956600000
NOK
But when i do the same with the JSSC API i receive this (only the first code)
010
0071CA79
2150218
0316444
218
The Problem is that i randomly receive bit parts and at the end of the code i lose some parts. But thats not important i only need the first 12 digits of every code.
The Question is now how do i get the function to only receive the full line and not bitparts?
This is the receiving part of the class
class PortReader2 implements SerialPortEventListener {
#Override
public void serialEvent(SerialPortEvent event) {
if(event.isRXCHAR()&& event.getEventValue() > 2) {
try {
// получение ответа от порта
String receivedData = serialPort.readString();
System.out.println(receivedData.length() + ":" + receivedData);
}
catch (SerialPortException ex) {
System.out.println("Error in receiving response from port: " + ex);
}
}
}
}
This is the sending part
public void sendCodeCommand(SerialPort serialPort) {
// writing string to port
try {
Thread.sleep(3000);
serialPort.writeBytes("N\r\n".getBytes());
} catch (SerialPortException | InterruptedException ex) {
Logger.getLogger(ComPortSendReceive.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("String wrote to port, waiting for response..");
}
To fix the stated problem you need to concatenate the strings you receive into another string that accumulates the string fragments you receive from the readString() function, which is in the serialEvent handler. Because it is it's owm thread it gets a certain amount of cpu time to get serial data so it effectively gets partial sequential reads of the serial port input data. So this example puts the partial inputs together to create the "whole" input.
String serialString;
So within the serialEvent handler:
try {
serialStringFragment = serialPort.readString();
serialString.concat(serialStringFragment);
}
Either the string you get from readString() or the accumulation string can be scanned for tokens like eol condition. For Example:
String [] dlLines = serialString.split("\r\n");
will break each line out to an element in the dlLines string array.
However I have found that if I have fixed length output from my target device this works better:
serialPort.readString(int bytecount);
inline with the write serial string, eliminating the serialEvent handler.
This is a bit contrived but In other words:
String expectedStringLength "0100071CA79215021803164442180000";
int serialstrlen = expectedStringLength.length();
So the serialstrlen should obviously become constants for each expected line.
serialPort.writeString("N\r\n");
serialPort.readString(serialstrlen+2); // assuming cr lf
should get you the first line.
Put the readString() in a loop, change serialstrelen argument value according to the expected strings. Check the strings for alternate content for error handling. This has worked for me.