serial bug

edited September 2015 in Library Questions

This code produces a good throughput as you can see:

// Example by Tom Igoe
import processing.serial.*;
// The serial port:
Serial myPort;       
// List all the available serial ports:
println(Serial.list());
// Open the port you are using at the rate you want:
myPort = new Serial(this, Serial.list()[1], 115200);
// Send "ciao" out the serial port:
myPort.write("ciao ciao ciao ciao");

ciao

while this one takes 18ms to send the same number of byte:

import processing.serial.*;
// The serial port:
Serial myPort;       
// List all the available serial ports:
println(Serial.list());
// Open the port you are using at the rate you want:
myPort = new Serial(this, Serial.list()[1], 115200);
// Send "ciao" out the serial port:
for(int i=0;i<20;i++)
{  myPort.write(i & 0xFF);
}  

num

so why?

Answers

  • edited September 2015 Answer ✓

    Dunno. Maybe append() everything as 1 StringBuilder?
    Then send them all at once w/ 1 write() only? :-??

    // forum.processing.org/two/discussion/12399/serial-bug
    // 2015-Sep-04
    
    import processing.serial.Serial;
    Serial s;
    
    final char QTY = 20, CHARS = 2;
    final StringBuilder sb = new StringBuilder(QTY*CHARS);
    
    s = new Serial(this, Serial.list()[1], 115200);
    //s.bufferUntil(ENTER);
    
    for (char i = 0; i != QTY; sb.append(i++).append(ENTER));
    //println(sb.length(), sb.capacity(), QTY*CHARS);
    
    s.write(sb.toString());
    sb.setLength(0);
    
    exit();
    
  • edited September 2015 Answer ✓

    A variant replacing StringBuilder w/ a byte[] array: :D

    // forum.processing.org/two/discussion/12399/serial-bug
    // 2015-Sep-04
    
    import processing.serial.Serial;
    Serial s;
    
    final byte QTY = 20, BYTES = 2;
    final byte[] bytes = new byte[QTY*BYTES];
    
    s = new Serial(this, Serial.list()[1], 115200);
    //s.bufferUntil(ENTER);
    
    for (byte i = 0; i < QTY; bytes[i] = i, bytes[i+1] = ENTER, i += BYTES);
    s.write(bytes);
    
    exit();
    
  • There's a problem. I tried them both and this is last: wrong Not all the values can send as characters. The first ones are escape sequences

  • edited September 2015

    Never mind. Now it seems to work with these adjustments:

    import processing.serial.Serial;
    Serial s;
    final byte[] bytes = new byte[32];
    s = new Serial(this, Serial.list()[1], 115200);
    //s.bufferUntil(ENTER);
    for (int i = 0; i < 32; bytes[i] =byte(i),  i ++);
    s.write(bytes);
    exit();
    

    right

  • edited September 2015 Answer ✓

    Both of my 2 examples are based on your 2nd example,
    which sends out a sequence of 20 values within 0 to 19 range, followed by an ENTER for each 1.
    Therefore, they send values, not ASCII/Unicode characters!
    If you don't want that ENTER, either remove it or append it as the last value! :-B

  • edited September 2015
    // forum.processing.org/two/discussion/12399/serial-bug
    // 2015-Sep-04
    
    import processing.serial.Serial;
    Serial s;
    
    final byte QTY = 040, BYTES = 1;
    final byte[] bytes = new byte[QTY*BYTES + 1];
    
    s = new Serial(this, Serial.list()[1], 115200);
    //s.bufferUntil(ENTER);
    
    for (byte i = 0; i < QTY; bytes[i] = i, i += BYTES);
    bytes[bytes.length - 1] = ENTER;
    s.write(bytes);
    
    exit();
    
  • Already done. Now I try on a sequence of 8kwords (to break in bytes) that is what I need. Thanks

  • edited September 2015

    By "8kwords" you mean 8192 bytes * 2 bytes (16 bits)? :-/

  • I have 8k * 16bits so I'll create an array of 16k * 8bits to send

  • edited September 2015

    No need for a byte[16*1024] array. Datatype String internally stores a char[] array.
    That is, each element is 16 bits. Thus char[8*1024] is just the size you're gonna need. O:-)

  • No. The size I need is 16kbytes because I need to send 8192 values of 16 bit. To overcome the problem of the slow transmission, I have to transform 8kwords into a pseudo string can be sent in a reasonable time

  • edited September 2015

    The size I need is 16kbytes because I need to send 8192 values of 16 bit.

    Primitive char datatype is 16 bits! So char[8*1024] has the same # of bytes as byte[16*1024]. ~O)

  • ok! Maiby I'm confused because i know C and not java. But I notice that any single write on serial send just one byte so that every data in excess of 8 bits is truncated to the lowest significant byte. Now it isn't very important understand how it work but I verified that the last code works fine for me

  • edited September 2015

    But I notice that any single write on serial send just one byte so that every data in excess of 8 bits is truncated to the lowest significant byte.

    Indeed only 1 8-bit byte is sent each time. But when we pass a String[] to write(), it invokes getBytes(): http://docs.oracle.com/javase/8/docs/api/java/lang/String.html#getBytes--

    So each char is sent as 2 byte AFAIK. 8-X

  • edited September 2015

    I am increasingly confused. Maybe strings doesn't matter but I verified that this code:

    import processing.serial.Serial; 
    Serial s; 
    final byte[] bytes = new byte[8]; 
    s = new Serial(this, Serial.list()[1], 115200); 
    //s.bufferUntil(ENTER); 
    for (int i = 0; i < 8; bytes[i] =byte(i), i ++); 
    s.write(bytes); exit();
    

    produced this output that's exactly what I need awesome

    and I've verified that it works on long sequence too

  • edited September 2015
    • If your charset is restricted to ASCII, UTF-8 or Western (Windows-1252 / ISO 8859-15),
      byte[] is the best approach.
    • However, if it comes from Java's char datatype, which is UTF-16, char[] & String[] are easier.
  • edited September 2015

    Seems like I was wrong that getBytes() would get us 2 bytes for each character.
    At least in its default charset when using Windows, getBytes() seems to convert characters as 1 byte. Possibly Western (Windows-1252) charset. #-o

    String s = "How many bytes are sent here?";
    println(s.length(), s.getBytes().length);
    
    s = "Arrête de te la péter!";
    println(s.length(), s.getBytes().length);
    println(new String(s.getBytes()));
    
    exit();
    
  • I don't need deepen any more. Not now. I am going to realize an AWG (arbitrary waveform generator) and I'm using Processing as user interface and a microcontrller circuit (like arduino) as executor so, when I've designed the waveform, I have to transmit the samples to the microcontroller. Before now it took too long (about 20s) and now it take reasonable time (less than 1s).

  • edited September 2015

    If it's just plain values, of course you don't have to worry about character encodings! :>

  • No, at all, at least for this project. I just have to overcome the problem with the pause between sending a multitude of numerical data that I believe to be a bug

Sign In or Register to comment.