Pages: [1]   Go Down
Author Topic: Serial communication is slow  (Read 1633 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've tried to search my problem but haven't found anything related yet so hopefully i won't get beaten for opening a new topic. smiley-slim
I've asked this question on StackOverflow also: http://stackoverflow.com/questions/10472514/slow-arduino-serial-transmission

I'm testing my Arduino UNO's serial transmission speed. For my requirements i have to transfer eta. 3kB/s from the host PC to the Arduino. I've written a very simple program which replies back the result of Serial.available() then tested it in the Arduino IDE's Serial monitor. I've started sending characters till i reached the maximum which is 63 bytes. I was quiet surprised of that because i've read somewhere that the Arduino has a 128byte Serial buffer.

Anyway i've made up a very simple protocol which transmits data in 48 byte packets (actually 49 bytes because of the header character). The host sends a d character then 48 bytes of data. For testing the validity of the transmission i'm sending a simple byte sequence from 0 to 47 which gets validated on the Arduino side. If the validation fails the UNO starts to blink the onboard LED on PIN13. Once the bytes are sent the host waits for an acknowledgement which is a simple k character. The Arduino sends this once it finishes processing the actual packet.

The host program meassures the number of transmitted packets and display it after 1 second. With a baud rate of 9600 the PC successfully transmits ~16 packets/second (~800 bytes/sec) which is quiet ok. I've tried to improve this by increasing the baud rate on both sides to 57600 however the number of sent packets increase only a little. I don't know what's the problem. Maybe i've hit some kind of limit of the USB serial converter?

Here is my code.

PC (Java, i'm using jSSC http://code.google.com/p/java-simple-serial-connector/ for serial port communication)

Code:
      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

Code:
    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');
      }
     
    }
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 211
Posts: 13477
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


If you want serial throughput just use

Serial.begin(345600); iso 57600   will be 6x as fast  See also  - http://arduino.cc/forum/index.php/topic,61381.msg444421.html#msg444421-
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you robtillaart!

I've made the baud rate change as you suggested on both ends. But i still get only 19 packets/second as the maximum.
Maybe my code does something non optimally. smiley-red
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've found the solution. The writeByte function of jSSC is highly inefficient in this case. If i premade the 49 byte buffer in Java then pass it at once to jSSC i get a very big speed boost.

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

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

With baud rate 345600 it gives me now ~240 packets/sec (~12KB/sec). smiley
« Last Edit: May 06, 2012, 02:21:35 pm by inagy » Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 211
Posts: 13477
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


345600 is in theory max 28-29KB/sec so 12KB is quite nice in practice.


You might even try baudrate 500000 as it is a divider of the clockspeed it is quite a stable although not common speed. should get you to 300 packets a second I expect.

What throughput do you need?
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I need eta 3kB/sec. So i've already achieved what i need. smiley I guess there is still room for improvement though.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I've started sending characters till i reached the maximum which is 63 bytes. I was quiet surprised of that because i've read somewhere that the Arduino has a 128byte Serial buffer.
Prior to 1.0, the Arduino did have a 128 byte buffer. With 1.0, outgoing serial data is now buffered, too, so the buffer size was cut in half, so that the two buffers take up no more space than the one buffer did.
Logged

Pages: [1]   Go Up
Jump to: