Передаваемые данные из другого потока, медленно последовательная связь с библиотекой Java и RxTx -- java поле с участием serial-port поле с участием raspberry-pi поле с участием uart поле с участием rxtx пол Связанный проблема

Transmitting data from another thread, slow serial link with Java and RXTX library


0
vote

проблема

русский
<Р> Хорошо, я постараюсь быть как можно более ясно с моей проблемой. Я передача последовательных данных по veeeeeeery медленного радиоканала (с помощью UART-контроллер на Raspberry Pi и самодельное радио). Это для очень конкретного проекта, в котором требование прописано <сильный> длинного диапазона и скорость имеет меньшее значение. Программа (Radio.java) работает два потока. Один потока (приемник) принимает данные телеметрии из другой программы с использованием TCP-сокета (который является очень высокой скоростью, на самом деле 100Mbit). Эта нить непрерывно сохраняет данные, которые он получает на TCP-сокете в ArrayBlockingQueue (с размером = 1), так что другой поток (передатчик) может достигать эту информацию. Скорость, при которой приемнике-нить получает данные довольно высока. Теперь я хочу, передатчик-нить для передачи данных и когда он закончил Я хочу, чтобы снова получить последние данные из приемника-нити и передать его снова через замедленную радио-связь. Таким образом, в передатчике-нить я хочу, чтобы работать следующим образом:
  1. Получить последние данные из приемника-нить

  2. <Литий> <р> данные передачи по радиоканалу (с помощью SerialPort)
  3. Не делайте НИЧЕГО, пока данные фактически не передаются.

  4. повторить.

<Р> Теперь, когда я бегу программу все относительно приемника-нить работает нормально. Но внутри передатчика-нить в строке "this.out.write (output.getBytes ());" просто ставит все внутри OutputStream в течение нескольких миллисекунд, а затем снова делает то же самое. Данные не имеют никаких шансов быть переданы! <Р> Я попробовал пример (только с помощью «SerialWriter» -thread) здесь: http://rxtx.qbang.org/wiki/index.php/Two_way_communcation_with_the_serial_port <Р> А с помощью длинного «Lirum Ipsum» -Text все работало просто отлично передающую в 50baud. Так в основном, я хочу такое же поведение в моей программе, как и при использовании System.in.read & GT; -1 ... (который я предполагаю, блокирует, причина это работает ???).

Что мне делать?

<Р> <сильный> 2015-01-01 редактировать НАЧАТЬ <Р> Я нашел эту проблему! SRobertz привести меня в правильном направлении! Проблема на самом деле не writespeed к UART-буфера. Разница между запуском «TwoWayComm» -example и моим собственным кодом, что я бегом GPS подключен к UART-RX-порту Raspberry Pi. Для того, чтобы считывать данные с GPS, это использовать «GPSD» -Software (который выводит данные в JSON-формате). В GPSD-программное обеспечение подключается к GPS с 9600 Бодом (в частности, для этого GPS-единицы), в то время как я переключаюсь на 50 бод на тот же порт (не закрывая открытое соединение, которое GPSD работает)! При попытке открыть UART с двумя различными бод-курсов является то, что Мессинг все вверх. Я переписать код так, что я:
  1. Open UART на скорости 9600 бод
  2. Данные пользователя GPS
  3. Закройте UART
  4. Откройте UART на 50 бод
  5. Передача телеметрических данных в UART
  6. Закрыть UART
  7. повторить
<Р> А теперь все работает как шарм ... <Р> <сильный> 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();         }     } }   
Английский оригинал

Alright, I'll try to be as clear as possible with my problem. I'm transmitting serial data over a veeeeeeery slow radio link (using the UART-controller on the raspberry pi and a home-built radio). It's for a very specific project where the requirement is spelled long range and speed is of less importance. The program (Radio.java) is running two threads. One thread (Receiver) receives telemetry data from another program using a TCP-socket (which is very high speed, actually 100mbit). This thread continuously saves the data it receives on the TCP-socket in an ArrayBlockingQueue (with size = 1) so that the other thread (Transmitter) can reach this data. The rate at which the Receiver-thread receives data is pretty high. Now, I want Transmitter-thread to transmit the data and when it's finished I want it to again get the latest data from Receiver-thread and transmit it again over the slow-radio-link. So in transmitter-thread I want it to work like this:

  1. Get latest data from Receiver-thread

  2. Transmit data over radio link (using the serialport)

  3. Don't do ANYTHING until the data is actually transmitted.

  4. repeat.

Now, when I'm running the program everything regarding the Receiver-thread is working just fine. But inside the transmitter-thread the line "this.out.write(output.getBytes());" just puts everything inside the OutputStream in a couple of milliseconds, and then again does the same thing. The data has no chance in being transmitted!

I've tried the example (only using the "SerialWriter"-thread) here: http://rxtx.qbang.org/wiki/index.php/Two_way_communcation_with_the_serial_port

And using a long "Lirum Ipsum"-text everything worked just fine transmitting in 50baud. So basically, I want the same behaviour in my program as using System.in.read > -1... (which I guess is blocking, the reason it works???).

What should I do?

2015-01-01 edit BEGIN

I've found the problem! SRobertz lead me into the right direction! The problem is actually not the writespeed to the UART-buffer. The difference between running the "TwoWayComm"-example and my own code is that I'm running a GPS connected to UART-RX-port of the Raspberry Pi. To read data from the GPS is use the "GPSD"-software (which outputs data in a JSON-format). The GPSD-software connects to the GPS with 9600baud (specifically for this GPS-unit), while I switch to 50 baud on the same port (without closing the open connection that GPSD is running)! Trying to open UART with two different baud-rates is what is messing everything up. I've rewritten the code so that I:

  1. Open UART on 9600 baud
  2. Read GPS data
  3. Close the UART
  4. Open UART on 50 baud
  5. Transmit telemetry data to UART
  6. Close UART
  7. Repeat

And now everything works like a charm...

2015-01-01 edit END

So ... here is the code:

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

Список ответов

1
 
vote
vote
Лучший ответ
 

(небольшое предостережение: я не использовал GNU.IO на Raspberry Pi)

Во-первых, чтобы изолировать проблему, я бы поставил довольно длинный <код> sleep в потоке передатчика, после <код> this.out.write... , чтобы убедиться, что проблема не ждет последовательного порта к закончить трансмиссию.

Если это работает, то вы можете попробовать ждать <код> OUTPUT_BUFFER_EMPTY , добавив <Код> SerialPortEventListener и установка <код> 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 Для обратного использования событий (обратите внимание, что там нет монитора и нет ожидания; вместо этого работа выполняется в прослушивании / обратном вызове.)

 

(a small caveat: I haven't used gnu.io on the raspberry pi)

First, to isolate the problem, I would put a fairly long sleep in the transmitter thread, after this.out.write... to verify that the problem is not waiting for the serial port to finish the transmission.

If that works, then you can try waiting for OUTPUT_BUFFER_EMPTY, by adding a SerialPortEventListener and setting notifyOnOutputEmpty(true), making your SerialPortEventListener a monitor along the lines of

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

and then do

myExampleMonitor.awaitCondition() instead of the sleep in the transmit thread.

See http://rxtx.qbang.org/wiki/index.php/Event_based_two_way_Communication for the inverse use of events (note that there, there is no monitor and no waiting; instead, the work is done in the listener/callback.)

</div
 
 
 
 

Связанный проблема

1  Я хочу, чтобы мой NPC посмотреть в направлении, на котором я стою. Как бы я сделал это наиболее эффективно?  ( I want my npc to look in the direction i am standing at how would i do this mos ) 
В настоящее время я строю 2D игру с Slick2D, и сейчас я реализую свой первый NPC. У меня уже есть спрайты, я смог нарисовать его, были столкновения, и так д...

1  Libgdx setscreen () сбивает игру, когда сделано несколько раз  ( Libgdx setscreen crashes game when done multiple times ) 
У меня есть <код> GameScreen и после окончания уровня, я устанавливаю экран обратно в <код> GameScreen как перезапустить , когда пользовательская кнопка пе...

0  Не могу найти какие-либо рабочие примеры использования официального Google Translate Java API (Rev41)  ( Cant find any working examples of using the official google translate java api ) 
У меня потребовалось около 5 минут, чтобы использовать API Google Translate REST от JavaScript, Nodejs, wget и Java через библиотеку Sun's Jersey, но я не мог...

26  Как добавить кнопку в ряд jtable в качелях java  ( How to add button in a row of jtable in swing java ) 
Я сделал один важный графический интерфейс, который имел jtable с некоторыми строками и столбцами. Как я должен добавить кнопку для строки в JTable? ...

-1  Как установить Jlint-3.0 на Ubuntu 14.04.2? [Дубликат]  ( How to install jlint 3 0 on ubuntu 14 04 2 ) 
<в сторону CLASS = "S-NEWACTS S-WELTIVE__info JS-Post-New Imide MB16« Роль = «Статус»> Этот вопрос уже есть ответы здесь : ...

427  Что означает «не может найти символ» или «не может разрешить символ» ошибка?  ( What does a cannot find symbol or cannot resolve symbol error mean ) 
Пожалуйста, объясните следующее о «не можете найти символ», - не может разрешить ошибки символа «или« символ не найден »: . Что они имеют в виду? Что може...

3  Добавление музыки / звука в программы Java  ( Adding music sound to java programs ) 
Я делаю несколько мини Java Games, и мне было интересно, как я могу добавить звук / музыку в свои программы. Я смотрел видео на YouTube и последовал за предос...

1  Неправильное количество прошедших args, но я передаю правильную сумму  ( Wrong number of args passed but i pass the correct amount ) 
Я использую quil с cljure и получаю странную ошибку. Я получаю ошибку <код> Exception in :draw function: #error { :cause Wrong number of args (1) pass...

2  Мой бар jmenu не показывает  ( My jmenu bar is not showing up ) 
Мой jmenubar не показывает, когда я запускаю свое приложение. Как я могу это исправить ?? Поэтому, когда я бегу свой Jframe, мне нужно увидеть мой jmenubar ...

-3  Как прекратить воспроизведение сервиса в Android  ( How to stop playing service in android ) 
У меня есть вопрос о сервисе и трансляции в Android.I Создайте страницу будильника, которые используя класс тревоги Reciver (он расширяет класс трансляции) дл...

0  Прокрутите вверх относительной макета при прокрутке вверх по просмотру  ( Scroll up relative layout when scrolling up listview ) 
Я создаю приложение. и пользовательская информация отображается в относительной макете. При относительной макете - это список с элементами, создаваемыми польз...

0  Можем ли мы проверить, что текст в поле «Пароль» отображается в маске? [закрыто]  ( Can we check that text in password field is displayed masked ) 
<в сторону CLASS = "S-NEWACTS S-WELTIVE__info JS-Post-New Imide MB16« Роль = «Статус»> закрыт . Этот вопрос нуждается в Детали или ясность . В настоящее...

4  Ссылка метода против лямбда экспрессия  ( Method reference vs lambda expression ) 
Я хочу заменить лямбда выражение по ссылке метода в примере ниже: <код> public class Example { public static void main(String[] args) { ...

3  Итализация через хесмап: «Для» петля с использованием произвольного доступа или итератора?  ( Iterating over a hashmap for loop using random access or iterator ) 
Мне нужно повторить через хешмап, чтобы извлекать значения, хранящиеся в нем. Как бонус, у меня также есть список клавиш. Поэтому у меня есть возможность по...

0  Java Applet Рисование формы на входе пользователя  ( Java applet drawing shapes by user input ) 
Вот то, что я хотел сделать. Есть текстовое поле, и пользователь входит в то, что он хочет. Например, «прямоугольник» или «прямоугольник», «круг» или «круг». ...

Связанный проблема

1  Я хочу, чтобы мой NPC посмотреть в направлении, на котором я стою. Как бы я сделал это наиболее эффективно? 
1  Libgdx setscreen () сбивает игру, когда сделано несколько раз 
0  Не могу найти какие-либо рабочие примеры использования официального Google Translate Java API (Rev41) 
26  Как добавить кнопку в ряд jtable в качелях java 
-1  Как установить Jlint-3.0 на Ubuntu 14.04.2? [Дубликат] 
427  Что означает «не может найти символ» или «не может разрешить символ» ошибка? 
3  Добавление музыки / звука в программы Java 
1  Неправильное количество прошедших args, но я передаю правильную сумму 
2  Мой бар jmenu не показывает 
-3  Как прекратить воспроизведение сервиса в Android 
0  Прокрутите вверх относительной макета при прокрутке вверх по просмотру 
0  Можем ли мы проверить, что текст в поле «Пароль» отображается в маске? [закрыто] 
4  Ссылка метода против лямбда экспрессия 
3  Итализация через хесмап: «Для» петля с использованием произвольного доступа или итератора? 
0  Java Applet Рисование формы на входе пользователя