2015-07-24 12 views
7

Ho bisogno di implementare la comunicazione tra due dispositivi tramite porte seriali su Raspberry Pi (con l'ultimo Raspbian a bordo). Entrambi utilizzano il controller CP2102 e sono collegati al Pi.Porte seriali che scrivono/leggono in linux

Data flow

Terminal:

[email protected] ~ $ ls -l /dev/serial/by-id 
total 0 
Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 -> ../../ttyUSB2 

[email protected] ~ $ 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 

Normalmente quando trasmetto comando SERIAL A, il dispositivo A risponde attraverso SERIAL A e invia i dati attraverso SERIAL B. Dopo che devo ritradurre questi dati al dispositivo B (SERIAL C) e ricevere risposta da SERIAL C.

Il problema è che in SERIAL B appare una risposta SERIAL B e SERIAL B appare su SERIAL A.

Ho provato diverse lingue e librerie seriali ma il risultato è lo stesso. Quindi le domande sono: perché sta succedendo quando si utilizza Raspberry Pi? Come posso implementare questa funzionalità su Raspberry Pi?

P.S. Entrambi i dispositivi funzionano correttamente. Il mio codice C# funziona perfettamente. Ho usato la classe System.IO.Ports.SerialPort per quella implementazione e sembra che le soluzioni Pi4J e RXTX.

P.P.S. Alcuni codice che ho cercato di usare il RPI:

Serial, C++: (pessimo pezzo di codice)

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(), "B-A"); 
       DevA_DataListener = new SerialReader(spDevA_Data.getInputStream(), spDevB_Data.getOutputStream(), "A-B"); 
       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}); 
    } 
} 
+1

"Il problema è che una risposta SERIALE su SERIAL B e dati SERIAL B appare su SERIAL A" <- probabilmente una domanda stupida (non ho idea del layout hardware) ma ... È il cablaggio OK? – fge

+0

Un rimedio semplice potrebbe essere semplicemente il prefisso di un identificatore ai dati inviati attraverso ciascuna delle porte. Quindi arriva l'algoritmo per capire se accettare la risposta o negarla. –

+0

RPi ha due porte USB. Ogni dispositivo collegato a uno di essi. Quindi il cablaggio è OK :) –

risposta

1

Non abbastanza reputazione per commentare: La mia ipotesi istruita sarebbe che ha qualcosa a che fare con il modo in cui Linux enumera l'hardware. Penso che sia possibile che i tuoi dispositivi USB abbiano un altro percorso seriale a seconda della distro usata, e l'ordine di collegarli.

Sei sicuro di utilizzare la stessa porta USB ogni volta? E che la porta USB corretta è mappata su/dev/tty?

È possibile forzare un HID ad avere sempre lo stesso nome assicurandosi di avere una regola udev per questo. Alcune informazioni here

+0

Sono sicuro che il problema non ha nulla in comune con l'enumerazione dei dispositivi in ​​Linux.In realtà ho abbandonato l'idea di connettere entrambi i dispositivi al Pi perché non è più rilevante.Tuttavia grazie per la risposta –

+0

sei il benvenuto; è stato appena attivato da un commento che stava funzionando bene con C# su Windows. Non so quale implemazione di C# si sta eseguendo sul Raspberry. – acidjunk