2009-09-08 9 views
7

Używam RXTX od około roku, bez zbyt wielu problemów. Właśnie zacząłem nowy program do interakcji z nowym sprzętem, więc ponownie wykorzystałem metodę connect(), której używałem w innych moich projektach, ale mam dziwny problem, którego nigdy wcześniej nie widziałem.Problemy z odbiorem w RXTX

Problem

Urządzenie działa dobrze, bo kiedy połączyć z HyperTerminal, wysyłam rzeczy i otrzymać to, czego oczekuję, a Serial Port Monitor (SPM) to odzwierciedla.

Jednak po uruchomieniu prostego klonu HyperTerminal, który napisałem, aby zdiagnozować problem, który mam z moją główną aplikacją, bajty są wysyłane, zgodnie z SPM, ale nic nie jest odbierane, a mój SerialPortEventListener nigdy nie odpala. Nawet gdy sprawdzę dostępne dane w głównej pętli, reader.ready() zwraca false. Jeśli zignoruje to sprawdzenie, otrzymam wyjątek, szczegóły poniżej.

odpowiedniej sekcji metody connect()

// Configure and open port 
port = (SerialPort) CommPortIdentifier.getPortIdentifier(name) 
             .open(owner,1000) 
port.setSerialPortParams(baud, databits, stopbits, parity); 
port.setFlowControlMode(fc_mode); 
final BufferedReader br = new BufferedReader(
          new InputStreamReader(
           port.getInputStream(), 
           "US-ASCII")); 

// Add listener to print received characters to screen 
port.addEventListener(new SerialPortEventListener(){ 
    public void serialEvent(SerialPortEvent ev) { 
    try { 
     System.out.println("Received: "+br.readLine()); 
    } catch (IOException e) { e.printStackTrace(); } 
    } 
}); 
port.notifyOnDataAvailable(); 

Wyjątek

java.io.IOException: Underlying input stream returned zero bytes 
     at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:268) 
     at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306) 
     at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158) 
     at java.io.InputStreamReader.read(InputStreamReader.java:167) 
     at java.io.BufferedReader.fill(BufferedReader.java:136) 
     at java.io.BufferedReader.read(BufferedReader.java:157) 
     at <my code> 

Wielkie pytanie (znowu)

Chyba wyeliminować wszystkie możliwe problemy sprzętowe, więc co może być wro ng z moim kodem lub biblioteką RXTX?

Edit: coś ciekawego

Kiedy otwieram HyperTerminal po wysłaniu kilka poleceń z Java, które powinny dostał odpowiedzi, wszystkie odpowiedzi pojawiają się natychmiast, jak gdyby były one umieszczone w buforze gdzieś, ale niedostępne.

Edit 2: Próbowaliśmy czegoś nowego, same wyniki

wpadłem przykład kodu znalezione here, z tych samych wyników. Nie pojawiły się żadne dane, ale kiedy przełączyłem się na nowy program, przyszło wszystko naraz.

Edycja 3

Sprzęt jest w porządku, a nawet inny komputer ma ten sam problem. Nie używam żadnego adaptera USB.

Również zacząłem używać PortMon, i to daje mi interesujące wyniki. HyperTerminal i RXTX nie używają tych samych ustawień, a RXTX zawsze odpytuje port, w przeciwieństwie do HyperTerminal, ale wciąż nie widzę, jakie ustawienia miałyby na to wpływ. Jak tylko będę mógł odizolować konfigurację od stałego pobierania, opublikuję moje dzienniki PortMon.

Edycja 4

Czy to możliwe, że jakiś aktualizacji systemu Windows w ciągu ostatnich 3 miesięcy mogło spowodować to? Zepsuł jeden z moich programów bazujących na mex'ach MATLAB.

Edycja 5

Ja również zauważyłem kilka rzeczy, które różnią się między HyperTerminal RxTx i osobny program Okazało się, że komunikuje się z urządzeniem (ale nie robić tego, co chcę, co jest dlaczego jestem toczenia mój własny program)

  • HyperTerminal - ustawić bez kontroli przepływu, ale RTS portu szeregowego monitora i DTR wskaźniki są zielone
  • Inny program - nie wiem, jakie ustawienia myśli, że używa, ale tylko Wskaźnik RTS SPM jest zielony
  • RXTX - bez względu na ustawioną kontrolę przepływu, tylko wskaźniki CTS i DTR SPM są włączone.

Od plikach pomocy szeregowego portu monitora'S (sparafrazowanych):

the indicators display the state of the serial control lines 

    RTS - Request To Send 
    CTS - Clear To Send 
    DTR - Data Terminal Ready 

Odpowiedz

7

OK, przepraszam, tak długo zajęło mi wracać do tego pytania. Oto, jak działam.

Uwaga: Ta metoda NIE praca dla wszystkich, proszę przeczytać poniżej przed kopiowaniem/wklejania do własnego kodu

public void connect(CommPortIdentifier portId) throws Failure { 
    if (portId == null) 
     throw new Failure("No port set"); 

    try { port = (SerialPort) portId.open(getClass().getName(), 10000); } 
    catch (PortInUseException e) { 
     throw new Failure("Port in use by " + e.currentOwner,e); } 

    try { 
     port.setSerialPortParams(9600, SerialPort.DATABITS_8, 
       SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); 
     port.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN 
           | SerialPort.FLOWCONTROL_RTSCTS_OUT); 
    } catch (UnsupportedCommOperationException e) { throw new Failure(e); } 

    port.setRTS(true); 

    // More setup 
} 

Tak, w moim przypadku, problemem było to, że moje dane urządzenie wymaga Kontrola przepływu RTS. Inne urządzenia mogą wymagać różnych rzeczy (CTS, XON/XOFF), więc sprawdź instrukcję urządzenia. Domyślnie RXTX wyłącza wszystkie mechanizmy kontroli przepływu (w przeciwieństwie do Hypertrm lub innych programów). Włączenie każdego z nich jest procesem dwuetapowym.

  1. Po utworzeniu obiektu SerialPort, należy wywołać metodę setFlowControlMode() i bitowe OR ('|') niezbędne SerialPort.FLOWCONTROL_ stałych
  2. Ustaw odpowiednią kontrolę przepływu true lub false (tak jak ja z port.setRTS(true))

Dla innych z podobnymi problemami, jeśli to nie pomoże, proponuję

  1. Korzystanie serial program do monitorowania portów, taki jak Serial Port Monitor i/lub PortMon (oba systemy Windows), aby zobaczyć, co się właściwie dzieje.
  2. Wysyłanie deweloperów RxTx w [email protected] (są one bardzo pomocne)
+1

Czy mógłbyś opublikować kontrolkę przepływu, której używałeś? z góry dzięki ... – Oso

+0

Mam nadzieję, że ta edycja pomoże –

+0

@drhorrible Widzę, jak ustawić flowcontrol na swoim obiekt szeregowy. To jasne. Jednak próbuję dowiedzieć się, jak można wykryć, że znak kontroli przepływu został wysłany? Używam XON XOFF vs RTS tak jak Ty. Zakładam jednak, że powinna być podobna. 0x13,0x11 to postacie, które spodziewam się zobaczyć w wydaniu serialEvent? Jak mogłeś to wykryć w kodzie? – ril3y

0

(może być zbyt proste, ale równie dobrze może zacząć gdzieś ...)

jest port w użyciu? Zamiast:

port = (SerialPort) CommPortIdentifier.getPortIdentifier(name) 
             .open(owner,1000) 

co:

CommPortIdentifier portIdentifier; 
try { 
    portIdentifier = CommPortIdentifier.getPortIdentifier(name); 
} catch (NoSuchPortException nspe) { 
    // handle? 
} 
if (portIdentifier.isCurrentlyOwned()) { 
    // handle? 
} 
port = portIdentifier.open(owner, 1000); 
if (!(port instanceof SerialPort)) { 
    // handle? 
} 

Czy połykanie żadnych wyjątków?

+0

Dzięki, ale reszta metody connect() przechwytuje wszystkie te wyjątki i drukuje ślady stosu i matryce. –

0

Próbowałem RXTX kilka miesięcy temu i wpadłem na podobne problemy. Proponuję dwie rzeczy:

  1. Stwórz wirtualny comport za pomocą com0com. Włącz rejestrowanie śledzenia. Porównaj dzienniki w przypadku korzystania z Hyperterminal w porównaniu do uruchamiania własnego programu. Różnica uwydatni to, co robisz źle.

  2. Moim skromnym zdaniem projekt RXTX jest wadliwy, a jego implementacja jest dość błędna (spójrz na jego kod źródłowy, co za bałagan!). Opublikowałem alternatywną bibliotekę pod adresem http://kenai.com/projects/jperipheral z następującymi zastrzeżeniami: Jest to tylko system Windows i nie ma żadnych gotowych plików binarnych. Oba te ulegną zmianie w najbliższej przyszłości. Jeśli jesteś zainteresowany wypróbowaniem go, wyślij mi e-mail pod numerem http://desktopbeautifier.com/Main/contactus, a wyślę Ci gotową wersję.

+1

Dostępne jest również [purejavacomm] (https://github.com/nyholku/purejavacomm). – HRJ

2

istnieje prostsze rozwiązanie tego problemu. Oto, co zrobiłem:

BufferedReader br = new BufferedReader(new InputStreamReader(in)); 
    String line; 

    while (keepRunning) { 
     try { 
      while ((br.ready()) && (line = br.readLine()) != null) { 
.... 
} 

Jeśli sprawdzisz, czy bufor "jest gotowy", zanim go przeczytasz, nie powinno być problemu.

2

Ok, robię sobie z tego wątku jest bardzo stary, ale żadne z tych rozwiązań nie pracował dla mnie. Miałem ten sam problem i próbowałem wszystkiego, aby to naprawić, bezskutecznie. Potem zrobiłem kilka badań na temat tego, co powoduje problem, a gdy nie ma do czynienia z komunikacją szeregową, dzieje się to na końcu pliku. Pomyślałem więc, że muszę dodać zakończenie do tego, co jest odbierane przez Aplikację Javy, w szczególności powrót linii (\ n). I na pewno to naprawiło problem dla mnie! Mam nadzieję, że to pomoże komuś nowemu, ponieważ nie oczekuję, że pomoże to nikomu już w tym wątku ...

0

Jeśli ktoś nadal otrzymuje java.io.IOException: Underlying input stream returned zero bytes po przeczytaniu znaków za pomocą br.readline() dla RXTX (nawet kiedy sprawdzamy najpierw sprawdzić, czy br.readline() == null), po prostu zrób to proste poprawkę z try/catch:

String line; 
while (true){ 
    try{ 
     line = br.readLine(); 
    }catch(IOException e){ 
     System.out.println("No more characters received"); 
     break; 
    } 
    //Print the line read 
    if (line.length() != 0) 
     System.out.println(line); 
} 

zrobiłem kilka poszukiwania i wydaje się, że jest to najlepszy/najprostszy sposób na obejście tego problemu.

EDIT: Biorę to z powrotem. Próbowałem tego i wciąż miałem problemy. Zalecam bezpośrednią pracę z surowym InputStream i wdrożenie własnej metody read/readLine za pomocą metody InputStream.read(). To działało dla mnie.