Writing / reading serial ports on Linux

I need to implement communication between two devices via serial ports on a Raspberry Pi (with the latest Raspbian on board). Both use the CP2102 controller and are connected to the Pi.

Data stream

Terminal:

pi@pi ~ $ ls -l /dev/serial/by-id total 0 Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 -> ../../ttyUSB2 pi@pi ~ $ ls -l /dev/serial/by-path total 0 platform-bcm2708_usb-usb-0:1.2.1:1.0-port0 -> ../../ttyUSB1 platform-bcm2708_usb-usb-0:1.2.4:1.0-port0 -> ../../ttyUSB2 platform-bcm2708_usb-usb-0:1.3:1.0-port0 -> ../../ttyUSB0 

Usually, when I send a SERIAL A command, device A answers through SERIAL A and sends data through SERIAL B. After that I need to retransmit this data to device B (SERIAL C) and get a response from SERIAL C.

The problem is that SERIAL A appears on SERIAL B and SERIAL A appears SERIAL A.

I tried different languages ​​and sequential libraries, but the result is the same. So the questions are: why does this happen when using raspberries? How can I implement this feature on Raspberry Pi?

PS Both devices are working correctly. My C # code works fine. I used the System.IO.Ports.SerialPort class for this implementation, and it looks like Pi4J and RXTX solutions.

PPS Some code that I tried to use on RPi:

Serial , C ++: (very bad piece of code)

 Serial port("/dev/ttyUSB2", 115200U); Serial port1("/dev/ttyUSB1", 115200U); port1.setTimeout(Timeout::max(), 250, 0, 250, 0); port.setTimeout(Timeout::max(), 250, 0, 250, 0); cout << "Is the serial port open?"; if (port1.isOpen()) { cout << " Yes." << endl; uint8_t data[2] = { 0xAA, 0x00 }; port1.write(data, 2); data[1] = 0xFF; sleep(1); port1.write(data, 2); while (port.available() < 7); int av = port.available(); string ss; port.read(ss, av); for (int i = 0; i < av; i++){ cout << (uint)ss.at(i) << " "; } cout << "av: " + (uint)av << endl; } 

RXTX, Java:

  public class Bridge_rxtx { public static final int baudrate = 115200; protected SerialPort spDevB_Data; SerialReader devB_DataListener; protected SerialPort spDevA_Data; SerialReader DevA_DataListener; protected SerialPort spDevA_Control; SerialPortEventListener DevA_ControlListener; public Bridge_rxtx(String comDevB_Data, String comDevA_Data, String comDevA_Control) { try { spDevB_Data = setupPort(comDevB_Data); spDevA_Data = setupPort(comDevA_Data); spDevA_Control = setupPort(comDevA_Control); } catch (Exception ignored){ ignored.printStackTrace(); } try { devB_DataListener = new SerialReader(spDevB_Data.getInputStream(), spDevA_Data.getOutputStream(), "BA"); DevA_DataListener = new SerialReader(spDevA_Data.getInputStream(), spDevB_Data.getOutputStream(), "AB"); DevA_ControlListener = new SerialPortEventListener() { @Override public void serialEvent(SerialPortEvent spe) { throw new UnsupportedOperationException("Not supported yet."); } }; spDevB_Data.notifyOnDataAvailable(true); spDevA_Data.notifyOnDataAvailable(true); spDevA_Control.notifyOnDataAvailable(true); } catch (IOException ex) { Logger.getLogger(Bridge_rxtx.class.getName()).log(Level.SEVERE, null, ex); } } public void launchBridge(){ System.out.println("Starting..."); try { spDevA_Control.getOutputStream().write(new byte[] {(byte)0xAA, (byte) 0x00}, 0, 2); } catch (IOException ex) { Logger.getLogger(Bridge_rxtx.class.getName()).log(Level.SEVERE, null, ex); } try { Thread.sleep(200); } catch (InterruptedException ex) { Logger.getLogger(Bridge_rxtx.class.getName()).log(Level.SEVERE, null, ex); } try { spDevA_Control.getOutputStream().write(new byte[] {(byte)0xAA, (byte) 0xFF}, 0, 2); } catch (IOException ex) { Logger.getLogger(Bridge_rxtx.class.getName()).log(Level.SEVERE, null, ex); } System.out.println("Started"); } SerialPort setupPort(String portName) throws Exception { SerialPort serialPort = null; CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName); if (portIdentifier.isCurrentlyOwned()) { System.out.println("Error: Port is currently in use"); } else { CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000); if (commPort instanceof SerialPort) { serialPort = (SerialPort) commPort; serialPort.setSerialPortParams(baudrate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); } else { System.out.println("Error: Only serial ports are handled by this code."); } } return serialPort; } public static void main(String[] args) { Bridge_rxtx bridge = new Bridge_rxtx("/dev/ttyUSB0", "/dev/ttyUSB2", "/dev/ttyUSB1"); bridge.launchBridge(); } } 

Pi4J, Java:

 public class Bridge { public static Bridge instance; public static final int baudrate = 115200; protected Serial spDevB_Data; SerialDataListener devB_DataListener; protected Serial spDevA_Data; SerialDataListener devA_DataListener; protected Serial spDevA_Control; SerialDataListener devA_ControlListener; private Bridge() { } public Bridge(String comDevB_Data, String comDevA_Data, String comDevA_Control) { instance = this; devA_ControlListener = new SerialDataListener() { //SerialDataEvent in Pi4J doesn't support binary //data by default. I implemented this myself. public void dataReceived(SerialDataEvent event) { System.out.println(bytesToHex(toPrimitives(event.getBinaryData()))); } }; devB_DataListener = new SerialDataListener() { public void dataReceived(SerialDataEvent event) { byte[] data = toPrimitives(event.getBinaryData()); instance.spDevA_Data.write(data); System.out.println("B -> A: " + bytesToHex(data)); } }; devA_DataListener = new SerialDataListener() { public void dataReceived(SerialDataEvent event) { byte[] data = toPrimitives(event.getBinaryData()); instance.spDevB_Data.write(data); try { Thread.sleep(15); } catch (InterruptedException ex) { Logger.getLogger(Bridge.class.getName()).log(Level.SEVERE, null, ex); } System.out.println("B <- A: " + bytesToHex(data)); } }; spDevB_Data = SerialFactory.createInstance(); spDevB_Data.addListener(devB_DataListener); spDevA_Data = SerialFactory.createInstance(); spDevA_Data.addListener(devA_ControlListener); spDevA_Control = SerialFactory.createInstance(); spDevA_Control.addListener(devA_DataListener); spDevB_Data.setMonitorInterval(40); spDevA_Data.setMonitorInterval(80); spDevA_Control.setMonitorInterval(25); spDevB_Data.open(comDevB_Data, baudrate); spDevA_Data.open(comDevA_Data, baudrate); spDevA_Control.open(comDevA_Control, baudrate); } public void SetupBridge() { spDevA_Control.write(new byte[]{(byte) 0xAA, (byte) 0x00}); try { Thread.sleep(20); } catch (InterruptedException ex) { Logger.getLogger(Bridge.class.getName()).log(Level.SEVERE, null, ex); } spDevA_Control.write(new byte[]{(byte) 0xAA, (byte) 0xFF}); } } 
+7
java c ++ linux serial-port raspbian
source share
1 answer

Not enough reputation for comment: My educated guess was that it had something to do with how Linux lists hardware. I think it is possible that your USB devices will have a different serial path depending on the distribution used and the order in which they are connected.

Are you sure you use the same USB port every time? And what is the correct USB port displayed in / dev / tty?

You can force the HID to always have the same name, making sure you have the udev rule. Some info here

+1
source share

All Articles