Note that Serial now resets most Arduino boards
in
Core Library Questions
•
6 months ago
After updating from Processing 1.51 to the latest version of Processing 2 I found that my serial communication with an Arduino Uno no longer functioned as expected. This problem persisted even though I was only using the 32-bit version of Processing (as recommended in a variety of forums). I have solved the problem and thought I'd share the solution in case others had similar issues.
The problem has to do with whether or not opening a Serial connection also causes the Arduino to reset. Original Arduino boards could only be reset manually via a button, but later boards are now able to be be reset in software by asserting the DTR (Data Transmission Ready) pin on the serial line. This is a great feature of the Arduino since it allows the Arduino IDE to send a reset to the Arduino which then is able to accept the upload of a new program.
HOWEVER, this is not necessarily the desired outcome when you want to simply use Processing to communicate with an Arduino. It seems that Processing 1.51 used the "latest" version of RXTX (version 2.2pre) for serial connections. This version of RXTX does not seem to assert DTR when it opens a serial connection, and thus connecting to an Arduino does not cause a reset. But in Processing 2, the RXTX library has been replaced with an earlier, and the officially stable, version of RXTC (version 2.1-7). In other words, later versions of Processing use an older (but more stable) version of RXTX for the serial library.
The older version of RXTX DOES assert DTR when a serial connection is first open, and this indeed resets newer Arduino's that have an ability to respond to this signal (older Arduino's that do not have software reset abilities are unaffected). Note that I am assuming the root of the difference is in the RXTX versions since I was not able to find any differences between the Serial.java code in the Processing 1.51 and Processing 2 libraries that would now cause DTR to be set whereas it was not before.
For some applications a reset of the Arduino is no big deal. It just means that the setup() code will be called when the serial connection if first opened (and any variables in SRAM will be lost, which might be a big deal for some applications).
In my case, the problem was much worse because my Processing code begins to communicate with the Arduino over the serial port as soon as it opens. I have it send a specific "handshake" command and wait for a specific response to ensure that there is indeed an Arduino with the right code on the other side of the serial line.
Unfortunately, sending serial data to the Arduino immediately after it is reset is how the Arduino is programmed. If upon a reset the Arduino does not see anything on the serial line for a short period of time, it starts executing the setup() code as expected. But if it does see something immediately, it will intercept and try to interpret this as a uploaded program. This causes no harm since the data being sent is highly unlikely to be of the form of Arduino-uploadable code (and is therefore ignored), but it does mean these initial characters never make it to your Arduino program.
There are two solutions. The first is to set a delay of about one second (1000 milliseconds) after you open a Serial connection to the Arduino and before you send any characters. Just remember that the Arduino is being reset and will start processing its setup() code.
The other solution is to have the Arduino begin the handshake process, rather than Processing. In other words, put something in the Arduino setup() code that immediately writes a predefined string to the serial port after it is opened. On the Processing side, listen for this string after opening the Serial connection and don't write anything to the port until this string is received. This ensure that Arduino is up and running (and not in "programming mode") before Processing tries to send anything.
Others may find this type of behavior obvious, and indeed there are a lot of discussions about Arduino resets in various forums --- what tripped me up was that my code worked perfectly with Processing 1.51 and I could not figure out what changed in Processing 2 to cause this problem. Though I'm not 100% sure the issue is caused by a revert to RXTX 2.1-7, it's the only explanation that seems consistent with the observed behavior.
A better long-term solution would be to have the ability to choose whether DTR is asserted or not asserted when Serial is called. There are methods that allows the user to query the state, isDTR(), or set the state, setDTR(), of a SerialPort after it is opened, but this does not effect the behavior when first opened (and can't even be called since the port is not yet even defined). There also seems to be a static version of setDTR that can be invoked without a specific port being open, but I have not seen this used successfully in any of the forums. Also, it seems to be a method of RXTXPort, not SerialPort, which is what Processing uses.
1