I am communicating via UART between an RPi 3 running Android Things and an Arduino.
Upon pressing a button on the RPi app a command is sent to the Arduino. There is no problem there. Every 2 seconds the Arduino sends a packet of information.
This works perfectly until I press a button that sends data to the Arduino. The Arduino receives the button command but the Android app crashes. I can even hit the button twice before the app crashes and the Arduino successfully receives both presses. The problem seems to be when the Arduino sends the next packet after the button press.
If I disconnect RPi UART RX the button does not cause a crash. In other words, as long as there is no incoming data the app works fine and vice versa. I can't make sense of the error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: za.co.leafbox.boxcontrol, PID: 8817
java.lang.NumberFormatException: For input string: "pump"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043)
at sun.misc.FloatingDecimal.parseFloat(FloatingDecimal.java:122)
at java.lang.Float.parseFloat(Float.java:452)
at za.co.leafbox.boxcontrol.MainActivity$2.readUartBuffer(MainActivity.java:284)
at za.co.leafbox.boxcontrol.MainActivity$2.onUartDeviceDataAvailable(MainActivity.java:234)
at com.google.android.things.pio.UartDeviceImpl$UartDeviceCallbackDispatch.dispatchInterruptEvent(UartDeviceImpl.java:250)
at com.google.android.things.pio.CallbackDispatch.onFileDescriptorEvents(CallbackDispatch.java:149)
at android.os.MessageQueue.dispatchEvents(MessageQueue.java:284)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:325)
at android.os.Looper.loop(Looper.java:142)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Example of the data received:
I/MainActivity: [45, 49, 46, 48, 48, 32, 49, 56, 46, 53, 48, 32, 54, 53, 46, 49, 48, 32, 45, 48, 46, 48, 56, 32, 48, 46, 48, 48, 32, 49, 54, 46, 51, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
OnClick
function:
public void pumpToggle(View view){
try{
if (((ToggleButton) view).isChecked()) {
byte[] buffer = {'g', 'g', '\n'};
writeUartData(aNano, buffer);
}
else{
byte[] buffer = {'g', 's', '\n'};
writeUartData(aNano, buffer);
}
} catch (IOException e) {
Log.e(TAG, "Data not Sent", e);
}
}
UART callback:
private UartDeviceCallback mUartCallback = new UartDeviceCallback() {
@Override
public boolean onUartDeviceDataAvailable(UartDevice uart) {
// Read available data from the UART device
Log.i(TAG, "onUartDeviceDataAvailable");
try {
readUartBuffer(uart);
} catch (IOException e) {
Log.w(TAG, "Unable to access UART device", e);
}
// Continue listening for more interrupts
return true;
}
private void readUartBuffer(UartDevice uart) throws IOException {
// Maximum amount of data to read at one time
Log.i(TAG, "readUartBuffer");
final int maxCount = 64;
byte[] buffer = new byte[maxCount];
byte[] convertBuf = new byte[20];
boolean dataCompleteFlag = false;
uart.read(buffer, maxCount);
if (!dataCompleteFlag) {
for (int i = 0; i < maxCount; i++) {
if (buffer[i] == 36) {
dataCompleteFlag = true;
measureCount++;
dataCount = 0;
}
else if(dataCount > maxCount) {
dataCount = 0;
}
else if(buffer[i] != 0) {
finalDataBuffer[dataCount] = buffer[i];
dataCount++;
}
}
}
if (dataCompleteFlag) {
Log.i(TAG, Arrays.toString(finalDataBuffer));
int index = 0;
int offSet;
while (index < maxCount && finalDataBuffer[index] != 32) {
convertBuf[index] = finalDataBuffer[index];
index++;
}
index++;
offSet = index;
tankLevelString = new String(convertBuf);
Float tankFloat = parseFloat(tankLevelString);
tankLevelString += "cm";
while (index < maxCount && finalDataBuffer[index] != 32) {
convertBuf[index - offSet] = finalDataBuffer[index];
index++;
}
index++;
offSet = index;
airTempString = new String(convertBuf);
airTempString += "\u00b0C";
while (index < maxCount && finalDataBuffer[index] != 32) {
convertBuf[index - offSet] = finalDataBuffer[index];
index++;
}
index++;
offSet = index;
humidityString = new String(convertBuf);
humidityString += "%";
while (index < maxCount && finalDataBuffer[index] != 32) {
convertBuf[index - offSet] = finalDataBuffer[index];
index++;
}
index++;
offSet = index;
ecString = new String(convertBuf);
while (index < maxCount && finalDataBuffer[index] != 32) {
convertBuf[index - offSet] = finalDataBuffer[index];
index++;
}
index++;
offSet = index;
phString = new String(convertBuf);
while (index < maxCount && finalDataBuffer[index] != 0) {
convertBuf[index - offSet] = finalDataBuffer[index];
index++;
}
waterTempString = new String(convertBuf);
TextView airTemp = findViewById(R.id.airTemp);
airTemp.setText(airTempString);
TextView humidity = findViewById(R.id.humidity);
humidity.setText(humidityString);
TextView tankLevel1 = findViewById(R.id.tankLevel1);
tankLevel1.setText(tankLevelString);
TextView ec = findViewById(R.id.ec);
ec.setText(ecString);
TextView ph = findViewById(R.id.ph);
ph.setText(phString);
TextView wt = findViewById(R.id.waterTemp);
wt.setText(waterTempString);
}
}
@Override
public void onUartDeviceError(UartDevice uart, int error) {
Log.w(TAG, uart + ": Error event " + error);
}
};
parseFloat (tankLevelString) is the line you get the NumberFormatException on. Apparently, tankLevelString
, which is "pump", cannot be parsed into float
. I recommend to investigate what causes it.