2012-05-06 24 views
5

Estoy probando la velocidad de transmisión en serie de mi Arduino UNO. Para mis requisitos, tengo que transferir 3KB/s desde la PC host al Arduino. Escribí un programa muy simple que contesta el resultado de Serial.available() y luego lo probé en el monitor serial Arduino IDE. Empecé a enviar caracteres hasta que alcancé el máximo, que es de 63 bytes. Estaba bastante sorprendido de eso porque leí en alguna parte que el Arduino tiene un búfer en serie de 128 bytes.Transmisión en serie lenta Arduino

De todos modos, he creado un protocolo muy simple que transmite datos en paquetes de 48 bytes (en realidad 49 bytes debido al carácter del encabezado). El host envía un carácter d y luego 48 bytes de datos. Para probar la validez de la transmisión, estoy enviando una secuencia de bytes simple de 0 a 47 que se valida en el lado de Arduino. Si la validación falla, UNO comienza a parpadear el LED integrado en PIN13. Una vez que se envían los bytes, el host espera un acuse de recibo que es un simple k carácter. El Arduino lo envía una vez que termina de procesar el paquete real.

El programa de host mide el número de paquetes transmitidos y lo muestra después de 1 segundo. Con una velocidad en baudios de 9600, la PC transmite con éxito ~ 16 paquetes/segundo (~ 800 bytes/seg), lo que está bastante bien. Intenté mejorar esto aumentando la velocidad en baudios en ambos lados a 57600; sin embargo, la cantidad de paquetes enviados aumenta solo un poco. No sé cuál es el problema. Tal vez he alcanzado algún tipo de límite del convertidor serial USB?


Aquí está mi código.

PC (Java, estoy usando jSSC de comunicación del puerto serial)

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

He hecho la misma pregunta en los foros de Arduino también http://arduino.cc/forum/index.php/topic,104699.0.html – NagyI

Respuesta

5

NagyI, método jSSC writeByte (byte b) es el mismo writeBytes (new byte [] {b}). Por ejemplo:

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

Estas cadenas son equivalentes. El método writeByte() crea una nueva matriz de bytes para cada byte que desea enviar. Crear un objeto es una operación costosa en Java, por eso, si necesita una transferencia de datos de alta velocidad, use matrices de bytes preparadas como en su respuesta. Saludos, Alexey.

3

que he encontrado la solución. La función writeByte de jSSC es altamente ineficiente en este caso. Si hice previamente el búfer de 49 bytes en Java y luego lo paso de inmediato a jSSC, recibo un aumento de velocidad muy grande.

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

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

en el foro de Arduino es un miembro me sugirió la velocidad de transmisión 345600 que me da ahora ~ 240 paquetes/seg (~ 12 KB/seg).

+0

+1 ¿Has probado la velocidad en baudios: 9600? –

+0

Lo hice. ~ 18 paquetes/seg es el resultado ahora. (~ 900byte/sec) Eso está cerca del máximo teórico de 960bytes/seg a esa velocidad en baudios. Y no he contado el costo del comando ack en eso. – NagyI

0

Recientemente, utilicé este tutorial para conectar el dispositivo Arduino UNO a la PC a través del cable: Arduino and Java.

+0

He intentado evitar la lib de RXTX porque tiene una latencia cableada de 20 ms. http://neophob.com/2011/04/serial-latency-teensy-vs-arduino/ En realidad, todavía no he medido la SSCS, así que solo espero que sea mejor. :) – NagyI

2

Ha intentado añadir esta línea a su configuración Arduino función() ?:

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

Lea aquí: http://arduino.cc/en/Serial/SetTimeout

Arduino por defecto tiene un tiempo de espera de 1 segundo que debe transcurrir si simplemente utiliza de serie .read() para leer en nuevos datos.Vea mi respuesta aquí para más información y una manera más clara de manejar esto: Matlab serial interface with Arduino is very slow