2012-05-06 23 views
5

Testuję prędkość transmisji seryjnej mojego Arduino UNO. Do moich wymagań muszę przenieść 3KB/s z komputera PC do Arduino. Napisałem bardzo prosty program, który odsyła wynik z Serial.available(), a następnie przetestował go w monitorze szeregowym Arduino IDE. Zacząłem wysyłać znaki, aż osiągnąłem maksimum, czyli 63 bajty. Byłem bardzo zaskoczony, ponieważ czytałem gdzieś, że Arduino ma bufor na 128 bitów Serial.Powolna transmisja szeregowa Arduino

W każdym razie, stworzyłem bardzo prosty protokół, który przesyła dane w 48 bajtowych pakietach (w rzeczywistości 49 bajtów z powodu znaku nagłówka). Host wysyła znak d, a następnie 48 bajtów danych. Do testowania poprawności transmisji wysyłam sekwencję bajtów prostych od 0 do 47, która jest sprawdzana po stronie Arduino. Jeśli walidacja nie powiedzie się, UNO zacznie migać diodę LED na urządzeniu PIN13. Po wysłaniu bajtów host oczekuje na potwierdzenie, które jest prostym znakiem k. Arduino wysyła to, gdy zakończy przetwarzanie rzeczywistego pakietu.

Program hosta mierzy liczbę przesłanych pakietów i wyświetla go po 1 sekundzie. Przy prędkości transmisji wynoszącej 9600 komputer z powodzeniem przesyła ~ 16 pakietów na sekundę (~ 800 bajtów/s), co jest całkiem w porządku. Próbowałem to poprawić, zwiększając prędkość transmisji z obu stron do 57600; jednak liczba wysłanych pakietów wzrasta tylko nieznacznie. Nie wiem, na czym polega problem. Może trafiłem na jakiś limit konwertera szeregowego USB?


Oto mój kod.

PC (Java, używam jSSC dla portu komunikacji szeregowej)

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

Zadałem to samo pytanie na forach Arduino, jak również http://arduino.cc/forum/index.php/topic,104699.0.html – NagyI

Odpowiedz

5

NagyI, metoda jSSC writeByte (bajt b) jest tym samym writeBytes (nowy bajt [] {b}). Na przykład:

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

Te struny są równoważne. Metoda writeByte() tworzy nową tablicę bajtów dla każdego bajtu, który chcesz wysłać. Tworzenie obiektu jest kosztowną operacją w Javie, dlatego jeśli potrzebujesz szybkiego transferu danych, przygotuj tablice bajtowe, tak jak w Twojej odpowiedzi. Pozdrawiam, Alexey.

3

Znalazłem rozwiązanie. Funkcja writeByte jSSC jest w tym przypadku wysoce nieefektywna. Jeśli wstępnie przygotowałem 49 bajtowy bufor w Javie, a następnie przekazałem go natychmiast do jSSC, otrzymałem bardzo duże zwiększenie prędkości.

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

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

Na forum Arduino jest członkiem zaproponował mi szybkość transmisji 345600, który daje mi teraz ~ 240 pakietów/sek (~ 12KB/s).

+0

+1 Czy próbowałeś prędkości transmisji: 9600? –

+0

Zrobiłem. ~ 18 pakietów na sekundę jest teraz wynikiem. (~ 900byte/s) To blisko teoretycznego maksimum 960b/s przy tej szybkości transmisji. I nie wliczałem w to kosztu polecenia ack. – NagyI

0

Niedawno użyłem tego samouczka do połączenia urządzenia Arduino UNO z komputerem za pomocą kabla: Arduino and Java.

+0

Próbowałem uniknąć biblioteki RXTX, ponieważ ma ona opóźnienie na poziomie 20 ms. http://neophob.com/2011/04/serial-latency-teensy-vs-arduino/ Właściwie to nie mam jeszcze pewności jSSC, więc mam tylko nadzieję, że jest lepiej. :) – NagyI

2

Have() funkcja ?: próbowałeś dodanie tego wiersza do Arduino konfiguracji

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

przeczytać tutaj: http://arduino.cc/en/Serial/SetTimeout

Arduino domyślnie ma limitu czasu 1 sek, który musi upłynąć, jeśli po prostu użyć seryjny .read() w celu odczytu w nowych danych.Zobacz moją odpowiedź tutaj, aby uzyskać więcej informacji i czystszy sposób radzenia sobie z tym: Matlab serial interface with Arduino is very slow