2012-05-06 19 views
5

Sto testando la velocità di trasmissione seriale di Arduino UNO. Per le mie esigenze devo trasferire 3KB/s dal PC host all'Arduino. Ho scritto un programma molto semplice che replica il risultato di Serial.available() e poi lo ha testato nel monitor seriale dell'IDE di Arduino. Ho iniziato a inviare caratteri fino a raggiungere il massimo che è di 63 byte. Ne sono rimasto piuttosto sorpreso perché ho letto da qualche parte che l'Arduino ha un buffer Serial 128byte.Trasmissione seriale Slow Arduino

In ogni caso, ho creato un protocollo molto semplice che trasmette i dati in pacchetti da 48 byte (in realtà 49 byte a causa del carattere dell'intestazione). L'host invia un carattere d quindi 48 byte di dati. Per testare la validità della trasmissione sto inviando una semplice sequenza di byte da 0 a 47 che viene convalidata sul lato Arduino. Se la convalida fallisce, l'UNO inizia a lampeggiare il LED integrato sul PIN13. Una volta inviati i byte, l'host attende una conferma che è un semplice carattere . L'Arduino lo invia una volta che ha finito di elaborare il pacchetto vero e proprio.

Il programma host misura il numero di pacchetti trasmessi e lo visualizza dopo 1 secondo. Con una velocità di trasmissione di 9600 il PC trasmette con successo ~ 16 pacchetti/secondo (~ 800 byte/sec) che è abbastanza ok. Ho cercato di migliorare questo aumentando il baud rate su entrambi i lati a 57600; tuttavia, il numero di pacchetti inviati aumenta solo di poco. Non so quale sia il problema. Forse ho raggiunto qualche limite del convertitore seriale USB?


Ecco il mio codice.

PC (Java, sto usando jSSC per la comunicazione seriale)

package hu.inagy.tapduino.server; 

    import jssc.SerialPort; 
    import jssc.SerialPortException; 

    /** 
    * Test Arduino communication. 
    */ 
    public class App 
    { 

    private static void testComm(SerialPort port) throws SerialPortException { 
     long runningSeconds = 0; 
     long time = System.currentTimeMillis(); 
     long numberOfPackets = 0; 
     boolean packetSent = false; 
     while (runningSeconds < 10) { 
     long currentTime = System.currentTimeMillis(); 
     if (currentTime - time > 1000) { 
      runningSeconds++; 
      time = currentTime; 
      System.out.println(numberOfPackets + " packets/s"); 
      numberOfPackets = 0; 
     } 

     if (!packetSent) { 
      packetSent = true; 
      port.writeByte((byte) 'd'); 
      for (int i = 0; i < 48; i++) { 
      port.writeByte((byte) i); 
      } 
     } else { 
      byte[] received = port.readBytes(); 
      if (received != null) { 
      if (received.length > 1) { 
       throw new IllegalStateException("One byte expected, instead got: " + received.length); 
      } 

      char cmd = (char) received[0]; 
      if ('k' != cmd) { 
       throw new IllegalStateException("Expected response 'k', instead got: " + cmd); 
      } 
      packetSent = false; 
      numberOfPackets++; 
      } 
     } 

     } 
    } 

    public static void main(String[] args) 
    { 
     SerialPort port = new SerialPort("COM7"); 

     try { 
     if (!port.openPort()) { 
      throw new IllegalStateException("Failed to open port."); 
     } 
     port.setParams(57600, 8, 1, 0); 
     } catch (SerialPortException e) { 
     throw new IllegalStateException("Exception while setting up port.", e); 
     } 

     try { 
     // Wait 1.5sec for Arduino to boot successfully. 
     Thread.sleep(1500); 
     } catch (InterruptedException e) { 
     throw new IllegalStateException("Interrupt while waiting?", e); 
     } 

     try { 
     testComm(port); 
     } catch (SerialPortException exc) { 
     throw new IllegalStateException("Failure while testing communication.", exc); 
     } finally { 
     try { 
      if (!port.closePort()) { 
      throw new IllegalStateException("Failed to close port."); 
      } 
     } catch (SerialPortException e) { 
      throw new IllegalStateException("Exception while closing port.", e); 
     } 
     } 
    } 
    } 

Arduino

void setup() { 
    pinMode(13, OUTPUT); 
    Serial.begin(57600); 
} 

boolean error = false; 

void loop() { 
    if (error) { 
     digitalWrite(13, HIGH); 
     delay(1000); 
     digitalWrite(13, LOW); 
     delay(1000); 
    } else { 
    while (Serial.available()<49); 
    char cmd = Serial.read(); 
    if ('d'!=cmd) { 
     error=true; 
     return; 
    } 

    for (int i=0; i<48; i++) { 
     int r = Serial.read(); 
     if (r!=i) { 
     error=true; 
     return; 
     } 
    } 

    Serial.write('k'); 
    } 

} 
+0

Ho chiesto la stessa domanda sui forum di Arduino come http://arduino.cc/forum/index.php/topic,104699.0.html – NagyI

risposta

5

NagyI, metodo jSSC writeByte (byte b) è lo stesso writeBytes (nuovo byte [] {b}). Ad esempio:

serialPort.writeByte((byte)0xFF); 
serialPort.writeBytes(new byte[]{(byte)0xFF}); 

Queste stringhe sono equivalenti. metodo writeByte() crea un nuovo array di byte per ogni byte che si desidera inviare. La creazione di un oggetto è un'operazione costosa in Java, ecco perché, se hai bisogno del trasferimento dati ad alta velocità, utilizza array di byte preparati come nella tua risposta. Saluti, Alexey.

3

ho trovato la soluzione. La funzione writeByte di jSSC è altamente inefficiente in questo caso. Se premo il buffer da 49 byte in Java, poi lo passo subito a jSSC ottengo un grande incremento di velocità.

byte[] sendBuffer = new byte[49]; 
    sendBuffer[0] = 'd'; 

    for (byte i = 0; i < 48; i++) { 
     sendBuffer[i + 1] = i; 
    } 
    port.writeBytes(sendBuffer); 

Su Arduino forum di un membro mi ha suggerito la velocità di trasmissione 345600 che mi dà ora ~ 240 pacchetti/sec (~ 12KB/sec).

+0

+1 Hai provato la velocità di trasmissione: 9600? –

+0

L'ho fatto. ~ 18 pacchetti/sec è il risultato ora. (~ 900byte/sec) Questo è vicino al massimo teorico 960bytes/sec a quella velocità di trasmissione. E non ho contato il costo del comando ack in quello. – NagyI

0

Recentemente, ho usato questo tutorial per connettere il dispositivo Arduino UNO al PC via cavo: Arduino and Java.

+0

Ho cercato di evitare la libreria RXTX perché ha una latenza cablata di 20 ms. http://neophob.com/2011/04/serial-latency-teensy-vs-arduino/ In realtà non ho ancora misurato jSSC, quindi spero solo che sia meglio. :) – NagyI

2

Hai provato aggiungendo questa linea al vostro setup Arduino function() ?:

Serial.setTimeout(100); //this will make the Arduino wait a max of only 100ms per incoming set of serial data, before moving on 

Leggi qui: http://arduino.cc/en/Serial/SetTimeout

Arduino di default ha un timeout di 1 secondo che deve intercorrere se è sufficiente utilizzare seriale .read() per leggere i nuovi dati.Vedere la mia risposta qui per maggiori informazioni e un modo più pulito per gestire questo: Matlab serial interface with Arduino is very slow

Problemi correlati