正在从另一个线程传输数据,使用Java和RXTX库的慢速串行链接

问题描述 投票:0回答:2

好吧,我会尽我所能解决问题。我正在通过veeeeeeery慢速无线电链路传输串行数据(使用树莓派上的UART控制器和自制无线电)。它是针对一个非常具体的项目,其中要求拼写为[[long range并且速度不太重要。该程序(Radio.java)正在运行两个线程。一个线程(接收器)使用TCP套接字(非常高的速度,实际上是100mbit)从另一个程序接收遥测数据。该线程将它在TCP套接字上接收到的数据连续保存在ArrayBlockingQueue(大小= 1)中,以便另一个线程(发送器)可以访问此数据。接收器线程接收数据的速率非常高。现在,我希望Transmitter-thread传输数据以及完成时,我希望它再次从Receiver-thread获取最新数据,并通过慢速无线电链路再次传输数据。因此,在发射器线程中,我希望它像这样工作:

  1. 从Receiver-thread获取最新数据
  2. 通过无线电链路传输数据(使用串行端口)
  3. 在实际发送数据之前,请勿做任何事情。
  4. 重复。

现在,当我运行程序时,与接收器线程有关的所有东西都工作正常。但是在发送器线程内部的行“ this.out.write(output.getBytes());”只需在几毫秒内将所有内容放入OutputStream中,然后再次执行相同的操作。数据没有机会传输!

我已经在这里尝试了该示例(仅使用“ SerialWriter”线程):http://rxtx.qbang.org/wiki/index.php/Two_way_communcation_with_the_serial_port

并且使用长的“ Lirum Ipsum”文本,一切正常,以50baud传输。因此,基本上,我希望程序中的行为与使用System.in.read> -1 ...相同(我想这是阻塞的,它起作用的原因???)。

我该怎么办?

2015-01-01编辑开始

我发现了问题! SRobertz带我朝正确的方向前进!问题实际上不是UART缓冲区的写入速度。运行“ TwoWayComm”示例和我自己的代码之间的区别在于,我正在运行连接到Raspberry Pi的UART-RX端口的GPS。要从GPS读取数据,请使用“ GPSD”软件(以JSON格式输出数据)。 GPSD软件以9600baud(专门用于此GPS装置)连接到GPS,而我在同一端口上切换到50波特(无需关闭GPSD正在运行的开放连接)!试图以两种不同的波特率打开UART就是搞砸了一切。我重写了代码,以便我:

    以9600波特打开UART
  1. 读取GPS数据
  2. 关闭UART
  3. 以50波特打开UART
  4. 将遥测数据发送到UART
  5. 关闭UART
  6. 重复
  • 现在,所有内容都像一个魅力...

    2015-01-01编辑END

  • 所以...这是代码:

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ArrayBlockingQueue; import gnu.io.CommPort; import gnu.io.CommPortIdentifier; import gnu.io.SerialPort; public class RADIO { ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<String>(1); void connect(String portName) throws Exception { CommPortIdentifier portIdentifier = CommPortIdentifier .getPortIdentifier(portName); if (portIdentifier.isCurrentlyOwned()) { System.out.println("Error: Port is currently in use"); } else { int timeout = 2000; CommPort commPort = portIdentifier.open(this.getClass().getName(), timeout); if (commPort instanceof SerialPort) { SerialPort serialPort = (SerialPort) commPort; serialPort.setSerialPortParams(50, SerialPort.DATABITS_7, SerialPort.STOPBITS_2, SerialPort.PARITY_NONE); // Open outputstream to write to the serial port OutputStream out = serialPort.getOutputStream(); (new Thread(new Receiver(queue))).start(); (new Thread(new Transmitter(out, queue))).start(); } else { System.err.println("Error: Not serial port."); } } } public static class Receiver implements Runnable { OutputStream out; protected ArrayBlockingQueue<String> queue = null; public Receiver(ArrayBlockingQueue<String> queue) { this.queue = queue; } public void run() { // Open TCP-connection try { ServerSocket serverSocket = new ServerSocket(1002); Socket clientSocket = serverSocket.accept(); // Wait for the client to start up BufferedReader in = new BufferedReader(new InputStreamReader( clientSocket.getInputStream())); String inputLine, outputLine; while ((inputLine = in.readLine()) != null) { queue.clear(); queue.put(inputLine); } } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static class Transmitter implements Runnable { OutputStream out; protected ArrayBlockingQueue<String> queue = null; String output = ""; public Transmitter(OutputStream out, ArrayBlockingQueue<String> queue) { this.out = out; this.queue = queue; } public void run() { try { while (true) { output = queue.take(); this.out.write(output.getBytes()); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void main(String[] args) { try { (new RADIO()).connect("/dev/ttyAMA0"); } catch (Exception e) { e.printStackTrace(); } } }

    java serial-port raspberry-pi uart rxtx
    2个回答
    1
    投票
    (一个小警告:我在树莓派上没有使用gnu.io)

    首先,要确定问题所在,在sleep之后,我将在发送器线程中放置相当长的this.out.write...,以确认问题不在等待串行端口等待。完成传输。

    如果可以,那么您可以尝试通过添加一个OUTPUT_BUFFER_EMPTYSerialPortEventListener并设置notifyOnOutputEmpty(true),使您的SerialPortEventListener沿着[>]行的监视器

    class ExampleMonitor implements SerialPortEventListener { boolean condition; public synchronized serialEvent(SerialPortEvent ev) { condition = true; notifyAll(); } public synchronized void awaitCondition() throws InterruptedException { while(!condition) wait(); condition = false; }

    然后做

    myExampleMonitor.awaitCondition(),而不是发送线程中的sleep

    请参阅http://rxtx.qbang.org/wiki/index.php/Event_based_two_way_Communication以了解事件的逆向用法(请注意,那里没有监视器,没有等待;相反,工作是在侦听器/回调中完成的。)


    0
    投票
    我正在运行一个需要通过同一串行端口发送和接收数据的Java程序,我使用Jserialcomm 2.5.3库,我正在使用侦听器侦听读写事件,但是一旦串行端口进入接收模式,我无法打开Write侦听器。
    © www.soinside.com 2019 - 2024. All rights reserved.