2013-04-14 18 views
8

Mam program w Javie, gdzie muszę przeczytać informacje wysyłane przez Arduino. Zrobiłem kod Java z here. Teraz, ja naprawdę nie rozumiem, jak to działa, ale starałem się go modyfikować i mam to:Java/Arduino - Odczytywanie danych z portu szeregowego

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; 
    } 
} 

tworzę szeregowego obiektu z COM port muszę w programie głównym, a następnie użyć Serial.read i Serial.write, gdy jest to potrzebne.

Serial.write działa świetnie, Arduino pobiera dane i wyświetla je na wyświetlaczu LCD. Problem jest następujący: Serial.read. Gdy program jest uruchomiony, odczytuje go z portu szeregowego (około 40   ms), ale to nie znaczy, że Arduino coś wysłał. Arduino wysyła bajt tylko po naciśnięciu przycisku. Tak więc, gdy kod Java jest uruchomiony, rzuca wyjątek "n", zanim coś przeczyta, a to opóźnia się tak bardzo.

Wiem, że potrzebuję czegoś takiego jak Serial.available(), próbowałem input.available(), ale to nie działa. Nie wiem, jak rozwiązać ten problem.

Jeśli masz kod, który działa, byłbym bardzo wdzięczny, gdybyś mógł mi go dać. Muszę tylko dwa sposoby, czytać i pisać, nie obchodzi mnie, jak kod działa: D

EDIT:

zmieniłem klasę seryjny, teraz znów tę metodę jako apremalal powiedział

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()); 
      } 
     }  
    } 

aw drugiej klasie (panel w tym przypadku) mam to:

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

drukować wartości poprawnie, ale data == "255" zawsze jest fałszywe, nawet jeśli naprawdę dostać 255 .... Próbowałem zrobić Integer.parseInt, ale nic się nie zmieniło. Dlaczego do diabła?

EDIT 2: Ok rozwiązany: \

public void read(String data){ 

    serialRead = Integer.parseInt(data); 

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

Teraz work..don't wiem dlaczego musiałem to zrobić ... meh cokolwiek :)

Odpowiedz

8

Nie chcesz specjalnie pisać funkcji odczytu, która już istnieje w przykładowym kodzie. Jako TheMerovingian wskazał, że możesz sprawdzić bufor wejściowy przed przeczytaniem. Oto działa kod, którego użyłem w jednym z moich projektów .

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"); 
} 
} 

EDYCJA: funkcja serialEvent odpowiada za odczyt bufora.

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. 
} 
+0

Tak ... to jest przykładowy kod java z arduino playground ... –

+0

Edytowałem metodę serialEvent, aby uniknąć problemu, o którym wspomniałeś – Anuruddha

+0

tak, ale ten kod wypisuje dane na konsoli. Potrzebuję tego, z innej klasy (jak moja Main.java), zdobądź dane i wykorzystaj je. Podobnie jak "if (Serial.read() = 255) {dosomething()}" –

0

Klasa BufferedReader ma ready() metoda, która zwraca True, jeśli "bufor nie jest pusty lub jeśli podstawowy strumień znaków jest gotowy." i inaczej: False. Możesz więc dodać sprawdzanie w metodzie read(), aby upewnić się, że przed odczytaniem są dane do odczytania.

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; 
} 

Wygląda na to kod ma try-catch w miejscu obsłużyć jeśli te rzeczy nie, co jest możliwe, co powoduje, że opóźnienie ponieważ try-catch są dość drogie. Tak więc test input.ready() powinien skutkować mniejszą liczbą wyjątków.

+0

Dodałem input.ready(), a teraz dostaję java.io.IOException: Bazowy strumień wejściowy zwrócił zero bajtów po naciśnięciu przycisku. Z seryjnego monitora Arduino widzę dane, które wysyłam, więc wiem, że to działa, ale potem w Javie, podczas gdy naciskam przycisk, program właśnie utknął, a kiedy go zwolnię, rzuca wyjątek, a następnie kontynuuje normalne działanie –

+0

Co dokładnie mówi ten wyjątek? – TheMerovingian

+0

java.io.IOException: Bazowy strumień wejściowy zwrócił zero bajtów –

Powiązane problemy