0
votes

I'm trying to transfer several shorts from an Arduino Pro to a Java program. The problem is, that only half of the data I tell the Arduino to send is actually sent.

Setup

Arduino Sketch

My Arduino Sketch looks like this:

// Mux control pins
#define s0 8
#define s1 9
#define s2 10
#define s3 11

// Mux in "SIG" pin
#define SIG_pin 3

byte lineEnd = 10;  // ASCII-NL

void setup() {  
/*
 * Mux und Flex
 */
// Define Digital Pin 8,9,10 and 11 as Output
// The most right Bit is the lowest! The highest 2 Bits are not accessible!
// --> B[-][-][13][12][11][10][9][8]
DDRB = B00001111;

// Write LOW to Pin 8,9,10 and 11
PORTB = B00000000;

Serial.begin(SERIAL_PORT_SPEED);

delay(500);
}

void loop()
{
printMux(0);
printMux(1);
printMux(2);
printMux(3);
printMux(4);

printMux(5);
printMux(6);
printMux(7);
printMux(8);
printMux(9);

printMux(10);
printMux(11);
printMux(12);
printMux(13);
printMux(14);

Serial.write('\n');

delay(17);
}

void printMux(byte channel){
// Write the channel to Pin 8,9,10 and 11
// I'm using direct Port Manipulation to speed the whole thing up
PORTB = channel;

unsigned char bytes[2];
int val = analogRead(SIG_pin);

bytes[0] = (unsigned int) val >> 8;
bytes[1] = val;

Serial.write(bytes[0]);
Serial.write(bytes[1]);
}

The Sketch reads the values of 15 Flex Sensors through a Multiplexer and writes those values as bytes to the Serial. Using Serial.print is not an option, because it takes quite longer to write the values as ASCII bytes and there are more bytes to send.

Java Program

On the Java side, I use the Java Simple Serial Connection to get the Serial Output of the Ardiuno and then parse the bytes back to shorts.

import java.util.ArrayDeque;

import jssc.SerialPort;
import jssc.SerialPortException;

public class SerialTest {

final static int ASCII_NL = 10;
final static int ASCII_COMMA = 42;
final static String BLUETOOTH_PORT = "COM10";
final static String USB_PORT = "COM3";
final static boolean USE_BLUETOOTH = false;

public static void main(String[] args) {
    final SerialPort sp = new SerialPort(USE_BLUETOOTH ? BLUETOOTH_PORT
            : USB_PORT);
    final ArrayDeque<Byte> byteVector = new ArrayDeque<>(48);

    try {
        sp.openPort();
        sp.setParams(SerialPort.BAUDRATE_115200, SerialPort.DATABITS_8,
                SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
        Runnable r = new Runnable() {
            @Override
            public void run() {

                while (true) {
                    try {
                        byte[] bytesRead = sp.readBytes(60);
                        if (bytesRead != null) {
                            for (byte b : bytesRead) {

                                if (b == ASCII_NL) {
                                    // We have to wait for a whole line
                                    // as a short is a 2 byte value
                                    // 15 shorts produce 30 bytes
                                    if (byteVector.size() == 30) {
                                        byte[] buffer = new byte[byteVector
                                                .size()];
                                        for (int i = 0; i < byteVector
                                                .size(); i++) {
                                            buffer[i] = byteVector.poll();
                                        }
                                        extractValues(buffer);
                                    }
                                    byteVector.clear();
                                } else {
                                    byteVector.add(b);
                                }
                            }
                        }
                    } catch (SerialPortException e) {
                        e.printStackTrace();
                    }
                    try {
                        Thread.sleep(17);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        Thread t = new Thread(r);
        t.start();
    } catch (SerialPortException e) {
        e.printStackTrace();
    }
}

static void extractValues(byte[] buffer) {
    for(byte b : buffer) {
        System.out.print(b + " ");
    }
    System.out.println();
    }
}

Problem

As for testing purposes, I only print the recieved bytes to the console. I would expect an Output like this:

1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32

Those are 30 bytes, so we received 15 shorts.

The Problem is that the Output looks like this:

1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 -32 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Only half of the bytes are transferred correctly, the rest is sent as 0.

Further testing confirmed this. When I alter the Arduino Sketch to only send 10 values and modify the Java program accordingly, it prints out 10 values followed by 10 zeros. The same goes for 4 values sent by the Arduino etc.

Why is this happening? Am I sending too much data over the Serial, so it just sends 0s when read? Is my Java program faulty? Could this be a bug in the Java Simple Serial Communication library?

Edit

The error lies somewhere in Java SimpleSerialConnection, after changing to Ardulink for communicating with the Arduino it worked nearly flawless. I'm filing a bug report for JSSC, case closed.

1

1 Answers

0
votes

Split your problem into pieces:

  1. Capture the serial communication of Arduino with a reliable terminal program.
  2. Use a different program to emulate the desired output and see if you Java code captures it properly.
  3. Throttle the output to see if the issue dissapears (would point at some buffer overflow)
  4. Replace binary by ascii communication to make analysis easier.

With other words: ensure that it runs, then tune for performance.