peterschwarz / clj-serial

Simple Serial Access for Clojure
Eclipse Public License 1.0
41 stars 11 forks source link

Reopening a COM port after writing to it fails the first time its attempted #4

Closed WickedShell closed 9 years ago

WickedShell commented 9 years ago

I open a COM port, attach a listener (that is immediately being feed with streamed data), write out a couple of bytes (10 in my current test), then close the port. The next time I try to open the port at any baud rate it fails to open, but the time after that succeeds. The error thrown on the first reconnect is:

Exception in thread "async-dispatch-1" java.lang.Error: java.la ng.Exception: Sorry, couldn't connect to the port with path COM8 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor. java:1148) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor .java:617) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.Exception: Sorry, couldn't connect to the port with path CO M8 at serial.core$open.doInvoke(core.clj:74) at clojure.lang.RestFn.invoke(RestFn.java:439) at radioDemo.radio$disconnect$fn77$state_machine9229auto__78$fn 80.invoke(radio.clj:53) at radioDemo.radio$disconnect$fn__77$state_machine9229auto__78.invo ke(radio.clj:53) at clojure.core.async.impl.ioc_macros$run_state_machine.invoke(ioc_macro s.clj:940) at clojure.core.async.impl.ioc_macros$run_state_machine_wrapped.invoke(i oc_macros.clj:944) at radioDemo.radio$disconnect$fn__77.invoke(radio.clj:53) at clojure.lang.AFn.run(AFn.java:22) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor. java:1142) ... 2 more

Running on Windows 7 x64, Java 8, and using [clj-serial "2.0.3-SNAPSHOT"]

peterschwarz commented 9 years ago

I've tried to reproduce this using the following arduino code for serial echoing:

/* Simple Serial ECHO script : Written by ScottC 03/07/2012 */

/* Use a variable called byteRead to temporarily store
   the data coming from the computer */
byte byteRead;

void setup() {                
// Turn the Serial Protocol ON
  Serial.begin(9600);
}

void loop() {
   /*  check if data has been sent from the computer: */
  if (Serial.available()) {
    /* read the most recent byte */
    byteRead = Serial.read();
    /*ECHO the value that was read, back to the serial port. */
    Serial.write(byteRead);
  }
}

(I don't know what device you're using but I wanted to have something to connect to). Following that setup I did the following:

  1. I setup a Win7 x86 VM (I only have Win 8.1 hardware), with Java 8.
  2. I created a basic lein project and added the [clj-serial "2.0.3-SNAPSHOT"] dependency.
  3. Ran lein repl
  4. Executed the following:

    => (require '[serial.core :as s])
    => (def port (s/open "COM3" :baud-rate 9600))
    => (s/listen port #(println (char (.read %))))
    => (defn bstr [s] (.getBytes s "ASCII")) ; a util for string->bytes
    => (s/write port (bstr "Hello"))
    ; You should see this echoed back
    => (s/close port)
    => (def port (s/open "COM3" :baud-rate 9600))
    ; and repeat

This worked fine with no issues.

Are you sure that you're closing the port correctly? Does your device have some disconnect time or connect time that you're not accounting for?

WickedShell commented 9 years ago

Hmm... You are correct actually, something about the device I'm using causes Windows to get very unhappy about it. (And causes a different windows machine to burn 33% of all processing time in ClearCommError inside purejavacomm when reading one byte at a time until it is perpetually 12k behind on parsing the data stream). It looks like it's a weird quirk of the windows driver that is causing it here. I'll reopen if I can find a test case outside of just this particular device. (I don't have any Arduino's but I have some TI Stellaris/Tiva boards sitting around, as well as a FTDI cable I can test against).