Wednesday, May 7, 2014

Simple Fix for Arduino SoftwareSerial "setTX" Bug

There's a minor but annoying bug in Arduino's SoftwareSerial library that can trash the first few bytes sent after setup when "inverse" mode is used. It's been a known issue for some time, but is still unfixed in the current version of the library.

The problem is in the "setTX" method in the file "SoftwareSerial.cpp" located in the SoftwareSerial subdirectory of the Libraries folder. This code should set the tx pin output/HIGH for UART-polarity serial, and output/LOW for inverted serial. Unfortunately, it ignores the "inverse" case entirely:

void SoftwareSerial::setTX(uint8_t tx)
{
  pinMode(tx, OUTPUT);
  digitalWrite(tx, HIGH);


Additionally, it ought to set the pin state before turning on the output driver, as the way it's written could generate a brief glitch on the output pin. We can fix both the inverse-mode problem and the glitch by changing it to:

void SoftwareSerial::setTX(uint8_t tx)
{
  digitalWrite(tx, _inverse_logic ? LOW : HIGH );
  pinMode(tx, OUTPUT);
Now you might be reluctant to change anything in a standard library. It would be easy to forget about the fix when you download a new copy of the Arduino software. Fortunately, there's a simple and harmless workaround that you can use in your sketches: Send a dummy character (0xFF) immediately after configuring the SoftwareSerial object. In the case of our serial displays, like the GLO-216, here's code that squashes the bug without modifying the library code:

#include <softwareserial.h>  // use any pin for serial out

#define rxPin 255      // Not used, set to invalid pin #
#define txPin 3        // Hook GLO serial input to this pin.
#define inverted 1     // If GLO Spol jumper is intact (COM-polarity)
#define noninverted 0  // If GLO Spol jumper is cut (UART polarity)

// SETUP: 
void setup() { 
  SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin, inverted);
  mySerial.begin(9600); // set data rate for SoftwareSerial
  mySerial.write("\xff") ;  // write a dummy character to fix setTX bug
  delay(500);
  mySerial.write("\x0c") ;  // clear the screen 
  mySerial.print("Hello World");
}

void loop() {
}

No comments:

Post a Comment