web-dev-qa-db-de.com

Java/Arduino - Liest Daten vom seriellen Port

Ich habe ein Programm in Java, in dem ich die Informationen lesen muss, die ein Arduino sendet ... Ich habe den Java-Code von here genommen. Nun, ich habe nicht wirklich verstanden, wie es funktioniert, aber ich habe versucht, es zu modifizieren und habe folgendes bekommen:

import Java.io.BufferedReader;
import Java.io.InputStreamReader;
import Java.io.OutputStream;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import Java.util.Enumeration;

public class Serial implements SerialPortEventListener {
    SerialPort serialPort;

    private static final String PORT_NAMES[] = {
            "/dev/tty.usbserial-A9007UX1", // Mac OS X
            "/dev/ttyUSB0", // Linux
            "COM3", // Windows
    };

    private BufferedReader input;
    private static OutputStream output;
    private static final int TIME_OUT = 2000;
    private static final int DATA_RATE = 115200;

    public void initialize() {
        CommPortIdentifier portId = null;
        Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();

        while (portEnum.hasMoreElements()) {
            CommPortIdentifier currPortId = (CommPortIdentifier) portEnum.nextElement();
            for (String portName : PORT_NAMES) {
                if (currPortId.getName().equals(portName)) {
                    portId = currPortId;
                    break;
                }
            }
        }
        if (portId == null) {
            System.out.println("Could not find COM port.");
            return;
        }

        try {
            serialPort = (SerialPort) portId.open(this.getClass().getName(),TIME_OUT);

            serialPort.setSerialPortParams(DATA_RATE, SerialPort.DATABITS_8, SerialPort.STOPBITS_1,    SerialPort.PARITY_NONE);

            input = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
            output = serialPort.getOutputStream();

            serialPort.addEventListener(this);
            serialPort.notifyOnDataAvailable(true);
        }
        catch (Exception e) {
            System.err.println(e.toString());
        }
    }

    public synchronized void serialEvent(SerialPortEvent oEvent) {
        if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
            try {
                String inputLine=input.readLine();
                System.out.println(inputLine);
            } catch (Exception e) {
                System.err.println(e.toString());
            }
        }
    }

    public synchronized void close() {
        if (serialPort != null) {
            serialPort.removeEventListener();
            serialPort.close();
        }
    }

    public Serial(String ncom){
        if(Integer.parseInt(ncom)>=3 && Integer.parseInt(ncom)<=9)
            PORT_NAMES[2] = "COM" + ncom;
        initialize();
        Thread t=new Thread() {
            public void run() {
                try {Thread.sleep(1000000);} catch (InterruptedException ie) {}
            }
        };
        t.start();
        System.out.println("Serial Comms Started");
    }

    public synchronized void send(int b){
        try{
            output.write(b);
        }
        catch (Exception e) {
            System.err.println(e.toString());
        }
    }

    public synchronized int read(){
        int b = 0;

        try{
            b = (int)input.read();
        }
        catch (Exception e) {
            System.err.println(e.toString());
        }
        return b;
    }
}

Ich erstelle das Objekt Serial mit dem COM-Port , das ich im Hauptprogramm benötige, und benutze dann Serial.read und Serial.write, wenn ich es brauche.

Serial.write funktioniert gut, Arduino erhält die Daten und zeigt sie in einem LCD -Display an. Das Problem ist Serial.read. Wenn das Programm ausgeführt wird, wird es immer von der seriellen Schnittstelle gelesen (etwa alle 40 ms). Dies bedeutet jedoch nicht, dass Arduino etwas gesendet hat. Arduino sendet nur dann ein Byte, wenn eine Taste gedrückt wird. Wenn also der Java-Code ausgeführt wird, wirft "n" eine Ausnahme, bevor etwas gelesen wird, und dies führt zu einer erheblichen Verzögerung.

Ich weiß, ich brauche etwas wie Serial.available(), ich habe input.available() versucht, aber es funktioniert nicht. Ich weiß nicht, wie ich dieses Problem lösen kann.

Wenn Sie einen Code haben, der funktioniert, wäre ich Ihnen sehr dankbar, wenn Sie mir diesen Code geben könnten. Ich brauche nur zwei Methoden, Lesen und Schreiben, es ist mir egal, wie der Code funktioniert: D

BEARBEITEN:

Ich habe die Serienklasse gewechselt, jetzt hat es wieder diese Methode, wie Apremalal sagte

public synchronized void serialEvent(SerialPortEvent oEvent) {

        if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
            try {

                String inputLine=null;
                if (input.ready()) {
                    inputLine = input.readLine();
                    panel.read(inputLine);
                }

            } catch (Exception e) {
                System.err.println(e.toString());
            }
        }       
    }

und in der anderen Klasse (Panel in diesem Fall) habe ich Folgendes:

public void read(String data){
    System.out.println(data);
    System.out.println(data == "255");
    if(data == "255")
        //code here 
}

Die Werte werden korrekt ausgegeben, aber data == "255" ist immer falsch, auch wenn ich wirklich eine 255 bekomme .... Ich habe versucht, Integer.parseInt zu tun, aber es hat sich nichts geändert. Warum zur Hölle?

EDIT 2: Ok gelöst: \

public void read(String data){

    serialRead = Integer.parseInt(data);

    if(serialRead == 255)
        //code here 
}

Nun, es ist Arbeit ... weiß nicht, warum ich das tun musste ... meh was auch immer :)

9

Sie möchten nicht speziell eine Lesefunktion schreiben, die bereits im Beispielcode enthalten ist. Wie The Merovingian darauf hinweist, können Sie den Eingangspuffer vor dem Lesen überprüfen.

import Java.io.BufferedReader;
import Java.io.InputStreamReader;
import Java.io.OutputStream;
import gnu.io.CommPortIdentifier; 
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent; 
import gnu.io.SerialPortEventListener; 
import Java.util.Enumeration;


public class SerialTest implements SerialPortEventListener {
SerialPort serialPort;
    /** The port we're normally going to use. */
private static final String PORT_NAMES[] = {                  "/dev/tty.usbserial-A9007UX1", // Mac OS X
        "/dev/ttyUSB0", // Linux
        "COM35", // Windows
};
private BufferedReader input;
private OutputStream output;
private static final int TIME_OUT = 2000;
private static final int DATA_RATE = 9600;

public void initialize() {
    CommPortIdentifier portId = null;
    Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();

    //First, Find an instance of serial port as set in PORT_NAMES.
    while (portEnum.hasMoreElements()) {
        CommPortIdentifier currPortId = (CommPortIdentifier) portEnum.nextElement();
        for (String portName : PORT_NAMES) {
            if (currPortId.getName().equals(portName)) {
                portId = currPortId;
                break;
            }
        }
    }
    if (portId == null) {
        System.out.println("Could not find COM port.");
        return;
    }

    try {
        serialPort = (SerialPort) portId.open(this.getClass().getName(),
                TIME_OUT);
        serialPort.setSerialPortParams(DATA_RATE,
                SerialPort.DATABITS_8,
                SerialPort.STOPBITS_1,
                SerialPort.PARITY_NONE);

        // open the streams
        input = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
        output = serialPort.getOutputStream();

        serialPort.addEventListener(this);
        serialPort.notifyOnDataAvailable(true);
    } catch (Exception e) {
        System.err.println(e.toString());
    }
}


public synchronized void close() {
    if (serialPort != null) {
        serialPort.removeEventListener();
        serialPort.close();
    }
}

public synchronized void serialEvent(SerialPortEvent oEvent) {
    if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
        try {
            String inputLine=null;
            if (input.ready()) {
                inputLine = input.readLine();
                            System.out.println(inputLine);
            }

        } catch (Exception e) {
            System.err.println(e.toString());
        }
    }
    // Ignore all the other eventTypes, but you should consider the other ones.
}

public static void main(String[] args) throws Exception {
    SerialTest main = new SerialTest();
    main.initialize();
    Thread t=new Thread() {
        public void run() {
            //the following line will keep this app alive for 1000    seconds,
            //waiting for events to occur and responding to them    (printing incoming messages to console).
            try {Thread.sleep(1000000);} catch (InterruptedException    ie) {}
        }
    };
    t.start();
    System.out.println("Started");
}
}

EDIT: Für das Lesen des Puffers ist die Funktion serialEvent zuständig.

public synchronized void serialEvent(SerialPortEvent oEvent) {
 if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
    try {
        String inputLine=null;
        if (input.ready()) {
            inputLine = input.readLine();
            System.out.println(inputLine);
        }

    } catch (Exception e) {
        System.err.println(e.toString());
    }
 }
// Ignore all the other eventTypes, but you should consider the other ones.
}
10
Anuruddha

Die BufferedReader-Klasse verfügt über eine ready() -Methode, die True zurückgibt, wenn "der Puffer nicht leer ist oder der zugrunde liegende Zeichenstrom bereit ist." und False ansonsten. Sie können also eine Prüfung in der read()-Methode hinzufügen, um sicherzustellen, dass Daten gelesen werden, bevor Sie versuchen, zu lesen.

public synchronized int read(){

    int b = 0;  

    try{
        if (input.ready()) {
            b = (int)input.read();
        }
    }catch (Exception e) {
        System.err.println(e.toString());
    }
    return b;
}

Es sieht so aus, als hätte der Code einen try-catch im Griff, wenn diese Dinge fehlschlagen, was möglicherweise zu einer Verzögerung führt, da try-catch ziemlich teuer ist. Die input.ready()-Prüfung sollte also zu weniger Ausnahmen führen.

0
TheMerovingian