Problems with HardwareSerial Pointer and write

W.O.

Member
Hey guys, I am porting and adapting a LCD serial library to Teensy.

(library for LCD Display: Serial Enabled 20x4 LCD - Black on Green 5V; From: Sparkfun)
In my old LCD library, (I used it with arduino Mega Boards) there are a lot of programlines with Serial3.write().
I changed them to SerialLCD.write() and now I have this problem:

Code:
#include <Arduino.h>

// the functions below are extracted and adepted from a class only to point the PROBLEM

usb_serial_class & mySerial = Serial;
HardwareSerial & SerialLcd = Serial3;


void GoToPosLCD(const uint8_t row, const uint8_t col){ // row 0 bis 3, col 0 bis 19
  SerialLcd.write(254); // Command
  switch (row) {
  case 0:
    SerialLcd.write(128 + col); // 128 first position row 1
    break;
  case 1:
    SerialLcd.write(192 + col); // 192 first position row 2
    break;
  case 2:
    SerialLcd.write(148 + col); // 148 first position row 3
    break;
  default: 
    SerialLcd.write(212 + col); // 212 first position row 4
  }
}

void clearLCD(){
  SerialLcd.write(254);   // Command
  SerialLcd.write(0x01);  // clear LCD.
}


void setup()
{
  Serial.begin(115200);

  //extracted and adepted from a class ---------------Start
  SerialLcd.begin(9600); 
  delay(500); // wait for LCD splash screen to boot up
  SerialLcd.write(0x7C); //NOTE THE DIFFERENT COMMAND FLAG = 124 dec

  SerialLcd.write(0x10); //ctrl-P 38400 baud
  SerialLcd.flush();
  delay(10); // I am not so happy, but it's only in setup. 
  //if you switch from 9600 to 38400 baud:
  //with flush, delay(4) = to short, delay(5) = ok; without flush, delay(5) = to short, delay(6) = ok. 
  //The problem may be in the LCD? I have read this thread: http://forum.pjrc.com/threads/25487-Serial1-flush%28%29-Problems
  
  SerialLcd.begin(38400); // set up serial port for xxxx baud
  //extracted and adepted from a class ---------------End

  delay(5000); // Debug
}

void loop(){

  char tempStringPrint[]= "PrintTest ";
  char tempStringWrite[]= "WriteTest ";

  Serial.println(F("Serial without Poiner:")); // output is ok
  Serial.print(tempStringPrint); // output is ok
  Serial.write(tempStringWrite); // output is ok
  Serial.println(); // output is ok

  Serial.println(F("Serial with Poiner:")); // output is ok
  mySerial.print(tempStringPrint); // output is ok
  mySerial.write(tempStringWrite); // output is ok
  Serial.println(F("\n")); // output is ok

  clearLCD(); // output is ok

  GoToPosLCD(0, 0);                      
  SerialLcd.print(tempStringPrint); // output is ok
  SerialLcd.write(tempStringWrite); // [COLOR="#FF0000"]!!! not sended !!![/COLOR]
  GoToPosLCD(1, 0);
  Serial3.print(tempStringPrint); // output is ok
  Serial3.write(tempStringWrite); // output is ok

  GoToPosLCD(2, 0);
  SerialLcd.write("a "); // [COLOR="#FF0000"]!!! not sended !!![/COLOR]
  SerialLcd.write(0x62); // output is ok
  SerialLcd.print(" c "); // output is ok
  SerialLcd.print(0x64); // output is ok

  GoToPosLCD(3, 0);
  Serial3.write("a "); // output is ok
  Serial3.write(0x62); // output is ok
  Serial3.print(" c "); // output is ok
  Serial3.print(0x64); // output is ok

  delay(1000);
}

Output Serial Monitor: all is fine
Code:
Serial without Poiner:
PrintTest WriteTest 
Serial with Poiner:
PrintTest WriteTest 
 
Serial without Poiner:
PrintTest WriteTest 
Serial with Poiner:
PrintTest WriteTest

Output LCD:
Code:
PrintTest
PrintTest WriteTest
b c 100
a b c 100

Output on LCD expected: the red branded are missing
Code:
PrintTest [COLOR="#FF0000"]WriteTest[/COLOR]
PrintTest WriteTest
[COLOR="#FF0000"]a[/COLOR] b c 100
a b c 100

Hardware:
LCD Display: Serial Enabled 20x4 LCD - Black on Green 5V; From: Sparkfun
Board: Teensy 3.1; Power supply: USB

Software:
Arduino IDE 1.0.5-r2
Teensyduino 1.18
compiled without compiler warnings

Workaround: I replace "write" with "print" and the library works fine

In the next update I request a FIX. Thank you

(If somebody is interrested in the small LCD library. I will post it, if it is ready.)
 
ON a tangent, and as a teaching moment for me.. what does the & operator do in this code you posted?
Code:
usb_serial_class & mySerial = Serial;
HardwareSerial & SerialLcd = Serial3;
 
ON a tangent, and as a teaching moment for me.. what does the & operator do in this code you posted?

I'm not enough of a C++ guru that I can give a teaching moment. I am only a user.
You have given me one. Thank you.

I have compiled the code with and without & operator:
1.) in both cases no compiler warnings.
2.) the output with the pointer "usb_serial_class" are the same.
3.) the output with the pointer "HardwareSerial" are different.
Without & operator: There is no output on the LCD screen.
 
A summary from above with one new facet

Code compiled without compiler warnings
Code:
// Include -----------------------------------------------------------------
#include <Arduino.h>

// Serial Monitor ----------------------------------------------------------
usb_serial_class & Serial_v1 =  Serial; // works fine, all ok (summary from above)
usb_serial_class   Serial_v2 =  Serial; // works fine, all ok (summary from above)
usb_serial_class * Serial_v3 = &Serial; // works fine, all ok (new facet)

// Serial3 -----------------------------------------------------------------
HardwareSerial & sLcd_v1 =  Serial3; // write does not work   (summary from above)
HardwareSerial   sLcd_v2 =  Serial3; // nothing works         (summary from above)
HardwareSerial * sLcd_v3 = &Serial3; // write does not work   (new facet)

// Functions -----------------------------------------------------------------
// the functions below are extracted and adepted from a class only to point the PROBLEM
void GoToPosLCD(const uint8_t row, const uint8_t col){ // row 0 to 3, col 0 to 19
  sLcd_v1.write(254); // Command
  switch (row) {
  case 0:
    sLcd_v1.write(128 + col); // 128 first position row 1
    break;
  case 1:
    sLcd_v1.write(192 + col); // 192 first position row 2
    break;
  case 2:
    sLcd_v1.write(148 + col); // 148 first position row 3
    break;
  default: 
    sLcd_v1.write(212 + col); // 212 first position row 4
  }
}

void clearLCD(){
  sLcd_v1.write(254);   // Command
  sLcd_v1.write(0x01);  // clear LCD.
}

// Setup -----------------------------------------------------------------
void setup(){
  Serial.begin(115200);

  //extracted and adepted from a class ---------------Start
  sLcd_v1.begin(9600); 
  delay(1500); // wait for LCD splash screen to boot up !!!!!!!!!!!!!!! changed to 1500 sometimes problems with the baud rate 
  sLcd_v1.write(0x7C); //NOTE THE DIFFERENT COMMAND FLAG = 124 dec

  sLcd_v1.write(0x10); //ctrl-P 38400 baud
  sLcd_v1.flush();
  delay(10);
  sLcd_v1.begin(38400); // set up serial port for xxxx baud
  //extracted and adepted from a class ---------------End
}

// Loop -----------------------------------------------------------------
void loop(){

  char tempPrint[]= "P ";
  char tempWrite[]= "W ";

  // Serial Monitor --------------------
  Serial.print(F("without:   "));      // output is ok
  Serial.print(tempPrint);             // output is ok
  Serial.write(tempWrite);             // output is ok
  Serial.print("p ");                  // output is ok
  Serial.write("w ");                  // output is ok
  Serial.print(0x61);                  // output is ok
  Serial.write(0x61);                  // output is ok
  Serial.println();                    // output is ok

  Serial_v1.print(F("Serial_v1: "));   // output is ok
  Serial_v1.print(tempPrint);          // output is ok
  Serial_v1.write(tempWrite);          // output is ok
  Serial_v1.print("p ");               // output is ok
  Serial_v1.write("w ");               // output is ok
  Serial_v1.print(0x61);               // output is ok
  Serial_v1.write(0x61);               // output is ok
  Serial_v1.println();                 // output is ok

  Serial_v2.print(F("Serial_v2: "));   // output is ok
  Serial_v2.print(tempPrint);          // output is ok
  Serial_v2.write(tempWrite);          // output is ok
  Serial_v2.print("p ");               // output is ok
  Serial_v2.write("w ");               // output is ok
  Serial_v2.print(0x61);               // output is ok
  Serial_v2.write(0x61);               // output is ok
  Serial_v2.println();                 // output is ok

  Serial_v3->print(F("Serial_v3: "));  // output is ok
  Serial_v3->print(tempPrint);         // output is ok
  Serial_v3->write(tempWrite);         // output is ok
  Serial_v3->print("p ");              // output is ok
  Serial_v3->write("w ");              // output is ok
  Serial_v3->print(0x61);              // output is ok
  Serial_v3->write(0x61);              // output is ok
  Serial_v3->println();                // output is ok

  Serial.println(F("\n"));             // output is ok

  // Serial3 ----------------------
  clearLCD();                     // output is ok
  delay(300);  // LCD blink

  GoToPosLCD(0, 0);               // position is ok
  Serial3.print(F("without: "));  // output is ok
  Serial3.print(tempPrint);       // output is ok
  Serial3.write(tempWrite);       // output is ok
  Serial3.print("p ");            // output is ok
  Serial3.write("w ");            // output is ok
  Serial3.print(0x61);            // output is ok
  Serial3.write(0x61);            // output is ok

  GoToPosLCD(1, 0);               // position is ok
  sLcd_v1.print(F("sLcd_v1: "));  // output is ok
  sLcd_v1.print(tempPrint);       // output is ok
  sLcd_v1.write(tempWrite);       // !!! not sended !!!
  sLcd_v1.print("p ");            // output is ok
  sLcd_v1.write("w ");            // !!! not sended !!!
  sLcd_v1.print(0x61);            // output is ok
  sLcd_v1.write(0x61);            // output is ok

  GoToPosLCD(2, 0); 
  sLcd_v2.print(F("sLcd_v2: "));  // !!! not sended !!!
  sLcd_v2.print(tempPrint);       // !!! not sended !!!
  sLcd_v2.write(tempWrite);       // !!! not sended !!!
  sLcd_v2.print("p ");            // !!! not sended !!!
  sLcd_v2.write("w ");            // !!! not sended !!!
  sLcd_v2.print(0x61);            // !!! not sended !!!
  sLcd_v2.write(0x61);            // !!! not sended !!!

  GoToPosLCD(3, 0);               // position is ok
  sLcd_v3->print(F("sLcd_v3: ")); // output is ok
  sLcd_v3->print(tempPrint);      // output is ok
  sLcd_v3->write(tempWrite);      // !!! not sended !!!
  sLcd_v3->print("p ");           // output is ok
  sLcd_v3->write("w ");           // !!! not sended !!!
  sLcd_v3->print(0x61);           // output is ok
  sLcd_v3->write(0x61);           // output is ok

  delay(1000); // LCD blink
}

Output Serial Monitor: all is fine
Code:
without:   P W p w 97a
Serial_v1: P W p w 97a
Serial_v2: P W p w 97a
Serial_v3: P W p w 97a


without:   P W p w 97a
Serial_v1: P W p w 97a
Serial_v2: P W p w 97a
Serial_v3: P W p w 97a

Output LCD:
Code:
without: P W p w 97a
sLcd_v1: P p 97a

sLcd_v3: P p 97a
Output on LCD expected: the red branded are missing
Code:
without: P W p w 97a
sLcd_v1: P [COLOR="#FF0000"]W[/COLOR] p [COLOR="#FF0000"]w[/COLOR] 97a
[COLOR="#FF0000"]sLcd_v2: P W p w 97a[/COLOR]
sLcd_v3: P [COLOR="#FF0000"]W[/COLOR] p [COLOR="#FF0000"]w[/COLOR] 97a
On an Arduino Mega 2560 rev3 works the ported code fine. Nothing is missed.
 
On an Arduino Mega 2560 rev3 works the ported code fine.
Is the baud rate higher on the Teensy than on the Mega 2560 (LCD limitations as to display processing delays) ?
Both using same number of stop bits (8N1 vs. 8N1.5 vs 8N2)?
 
Last edited:
Is the baud rate ...

If I change in my Teensy 3.1 code only this:
Code:
  GoToPosLCD(1, 0);               // position is ok
  sLcd_v1.print(F("sLcd_v1: "));  // output is ok
  sLcd_v1.print(tempPrint);       // output is ok
  sLcd_v1.write(tempWrite);       // !!! not sended !!!
  sLcd_v1.print("p ");            // output is ok
  sLcd_v1.write("w ");            // !!! not sended !!!
  sLcd_v1.print(0x61);            // output is ok
  sLcd_v1.write(0x61);            // output is ok

  GoToPosLCD(2, 0); 
  sLcd_v2.print(F("sLcd_v2: "));  // !!! not sended !!!
  sLcd_v2.print(tempPrint);       // !!! not sended !!!
  sLcd_v2.write(tempWrite);       // !!! not sended !!!
  sLcd_v2.print("p ");            // !!! not sended !!!
  sLcd_v2.write("w ");            // !!! not sended !!!
  sLcd_v2.print(0x61);            // !!! not sended !!!
  sLcd_v2.write(0x61);            // !!! not sended !!!

  GoToPosLCD(3, 0);               // position is ok
  sLcd_v3->print(F("sLcd_v3: ")); // output is ok
  sLcd_v3->print(tempPrint);      // output is ok
  sLcd_v3->write(tempWrite);      // !!! not sended !!!
  sLcd_v3->print("p ");           // output is ok
  sLcd_v3->write("w ");           // !!! not sended !!!
  sLcd_v3->print(0x61);           // output is ok
  sLcd_v3->write(0x61);           // output is ok
to:
Code:
  GoToPosLCD(1, 0);               // position is ok
  Serial3.print(F("sLcd_v1: "));  // output is ok
  Serial3.print(tempPrint);       // output is ok
  Serial3.write(tempWrite);       // output is ok
  Serial3.print("p ");            // output is ok
  Serial3.write("w ");            // output is ok
  Serial3.print(0x61);            // output is ok
  Serial3.write(0x61);            // output is ok

  GoToPosLCD(2, 0);               // position is ok
  Serial3.print(F("sLcd_v2: "));  // output is ok
  Serial3.print(tempPrint);       // output is ok
  Serial3.write(tempWrite);       // output is ok
  Serial3.print("p ");            // output is ok
  Serial3.write("w ");            // output is ok
  Serial3.print(0x61);            // output is ok
  Serial3.write(0x61);            // output is ok

  GoToPosLCD(3, 0);              // position is ok
  Serial3.print(F("sLcd_v3: ")); // output is ok
  Serial3.print(tempPrint);      // output is ok
  Serial3.write(tempWrite);      // output is ok
  Serial3.print("p ");           // output is ok
  Serial3.write("w ");           // output is ok
  Serial3.print(0x61);           // output is ok
  Serial3.write(0x61);           // output is ok

Then the Teensy 3.1 makes a great work with the LCD Display. ALL IS FINE
 
Problems with HardwareSerial() Function

On this link:
www.pjrc.com/teensy/td_uart.html see: “Uart Object Names”

You offer:

If you wish to use a different name, you copy this line …

// This line defines a "Uart" object to access the serial port
HardwareSerial Uart = HardwareSerial();

Code:
// Include -----------------------------------------------------------------
#include <Arduino.h>

// Serial Monitor ----------------------------------------------------------
HardwareSerial Serial_v0 = HardwareSerial(); // nothing works!!! 
// I hope on Teensy 3.1 "HardwareSerial()" is Serial?

// Serial1 -----------------------------------------------------------------
//HardwareSerial Serial_v1 = HardwareSerial1(); 
// [COLOR="#FF0000"]If you uncomment the line above: PointerTeensy31:11: error: 'HardwareSerial1' was not declared in this scope[/COLOR]
// I hope on Teensy 3.1 "HardwareSerial1()" is Serial1?

// Serial2 -----------------------------------------------------------------
HardwareSerial Serial_v2 = HardwareSerial2();   // I have not tested 
// I hope on Teensy 3.1 "HardwareSerial2()" is Serial2?

// Serial3 -----------------------------------------------------------------
HardwareSerial   sLcd_v3 =  HardwareSerial3(); // nothing works!!!
// I hope on Teensy 3.1 "HardwareSerial3()" is Serial3?

// Functions -----------------------------------------------------------------
// the functions below are extracted and adepted from a class only to point the PROBLEM
void GoToPosLCD(const uint8_t row, const uint8_t col){ // row 0 to 3, col 0 to 19
  Serial3.write(254); // Command
  switch (row) {
  case 0:
    Serial3.write(128 + col); // 128 first position row 1
    break;
  case 1:
    Serial3.write(192 + col); // 192 first position row 2
    break;
  case 2:
    Serial3.write(148 + col); // 148 first position row 3
    break;
  default: 
    Serial3.write(212 + col); // 212 first position row 4
  }
}

void clearLCD(){
  Serial3.write(254);   // Command
  Serial3.write(0x01);  // clear LCD.
}

// Setup -----------------------------------------------------------------
void setup(){
  Serial.begin(115200);

  //extracted and adepted from a class ---------------Start
  Serial3.begin(9600); 
  delay(1500); // wait for LCD splash screen to boot up 
  Serial3.write(0x7C); //NOTE THE DIFFERENT COMMAND FLAG = 124 dec

  Serial3.write(0x10); //ctrl-P 38400 baud
  Serial3.flush();
  delay(10);

  Serial3.begin(38400); // set up serial port for xxxx baud
  //extracted and adepted from a class ---------------End
}

// Loop -----------------------------------------------------------------
void loop(){

  char tempPrint[]= "P ";
  char tempWrite[]= "W ";

  // Serial Monitor ----------------------------------------------------------
  Serial.print(F("without:   "));      // output is ok
  Serial.print(tempPrint);             // output is ok
  Serial.write(tempWrite);             // output is ok
  Serial.print("p ");                  // output is ok
  Serial.write("w ");                  // output is ok
  Serial.print(0x61);                  // output is ok
  Serial.write(0x61);                  // output is ok
  Serial.println();                    // output is ok

  Serial_v0.print(F("Serial_v0: "));   // !!! not sended !!!
  Serial_v0.print(tempPrint);          // !!! not sended !!!
  Serial_v0.write(tempWrite);          // !!! not sended !!!
  Serial_v0.print("p ");               // !!! not sended !!!
  Serial_v0.write("w ");               // !!! not sended !!!
  Serial_v0.print(0x61);               // !!! not sended !!!
  Serial_v0.write(0x61);               // !!! not sended !!!
  Serial_v0.println();                 // !!! not sended !!!
  
  Serial.println();                    // output is ok

  // Serial3 -----------------------------------------------------------------
  clearLCD();                     // output is ok
  delay(300);  // LCD blink

  GoToPosLCD(0, 0);               // position is ok
  Serial3.print(F("without: "));  // output is ok
  Serial3.print(tempPrint);       // output is ok
  Serial3.write(tempWrite);       // output is ok
  Serial3.print("p ");            // output is ok
  Serial3.write("w ");            // output is ok
  Serial3.print(0x61);            // output is ok
  Serial3.write(0x61);            // output is ok

  GoToPosLCD(1, 0);               // !!! not sended !!!
  sLcd_v3.print(F("sLcd_v3: "));  // !!! not sended !!!
  sLcd_v3.print(tempPrint);       // !!! not sended !!!
  sLcd_v3.write(tempWrite);       // !!! not sended !!!
  sLcd_v3.print("p ");            // !!! not sended !!!
  sLcd_v3.write("w ");            // !!! not sended !!!
  sLcd_v3.print(0x61);            // !!! not sended !!!
  sLcd_v3.write(0x61);            // !!! not sended !!!

  delay(1000); // LCD blink
}

Output Serial Monitor:
Code:
without:   P W p w 97a

Output on Serial Monitor expected: the red branded are missing
Code:
 without:   P W p w 97a
 [COLOR="#FF0000"]Serial_v0: P W p w 97a[/COLOR]

Output LCD:
Code:
 without: P W p w 97a

Output on LCD expected: the red branded are missing
Code:
 without: P W p w 97a
 [COLOR="#FF0000"]sLcd_v3: P W p w 97a[/COLOR]

Code compiled without compiler warnings
It does not Work. What is the reason?
 
Last edited:
I'm setting up to test this....

I don't have this Sparkfun LCD, so I'm going to try to use a laptop with a FTDI USB-serial cable and CoolTerm to view the data.
 
I have reproduced the problem. I'll work on a fix soon.

There are a LOT of code fragments above. Here's what I'm using for testing:

Code:
// Serial3 pointer issue
// forum.pjrc.com/threads/25494-Problems-with-HardwareSerial-Pointer-and-write
// 
HardwareSerial & sLcd_v1 =  Serial3; // write does not work   (summary from above)
HardwareSerial   sLcd_v2 =  Serial3; // nothing works         (summary from above)
HardwareSerial * sLcd_v3 = &Serial3; // write does not work   (new facet)

void setup() {
  Serial3.begin(9600);
}
  
void loop() {
  char tempPrint[]= "P ";
  char tempWrite[]= "W ";
  
  Serial3.print(F("Serial3: "));  // output is ok
  Serial3.print(tempPrint);       // output is ok
  Serial3.write(tempWrite);       // !!! not sended !!!
  Serial3.print("p ");            // output is ok
  Serial3.write("w ");            // !!! not sended !!!
  Serial3.print(0x61);            // output is ok
  Serial3.write(0x61);            // output is ok
  delay(1000);
  
  sLcd_v1.print(F("sLcd_v1: "));  // output is ok
  sLcd_v1.print(tempPrint);       // output is ok
  sLcd_v1.write(tempWrite);       // !!! not sended !!!
  sLcd_v1.print("p ");            // output is ok
  sLcd_v1.write("w ");            // !!! not sended !!!
  sLcd_v1.print(0x61);            // output is ok
  sLcd_v1.write(0x61);            // output is ok
  delay(1000);

  sLcd_v2.print(F("sLcd_v2: "));  // !!! not sended !!!
  sLcd_v2.print(tempPrint);       // !!! not sended !!!
  sLcd_v2.write(tempWrite);       // !!! not sended !!!
  sLcd_v2.print("p ");            // !!! not sended !!!
  sLcd_v2.write("w ");            // !!! not sended !!!
  sLcd_v2.print(0x61);            // !!! not sended !!!
  sLcd_v2.write(0x61);            // !!! not sended !!!
  delay(1000);

  sLcd_v3->print(F("sLcd_v3: ")); // output is ok
  sLcd_v3->print(tempPrint);      // output is ok
  sLcd_v3->write(tempWrite);      // !!! not sended !!!
  sLcd_v3->print("p ");           // output is ok
  sLcd_v3->write("w ");           // !!! not sended !!!
  sLcd_v3->print(0x61);           // output is ok
  sLcd_v3->write(0x61);           // output is ok
  
  delay(50000);
}

I'm sending from a Teensy 3.1 on my Linux desktop to a FTDI USB-serial cable connected to a Mac laptop running CoolTerm. I do not have the Sparkfun LCD.

I'll post a followup here when I have more info or a fix. It's Saturday afternoon. Robin & I have plans this evening, so probably won't get any time on this until Sunday or early next week.
 
Here is a HardwareSerial.h that should fix the problems with "sLcd_v1" and "sLcd_v3".
 

Attachments

  • HardwareSerial.h
    8.2 KB · Views: 384
Regarding "sLcd_v2", this code can never work:

Code:
HardwareSerial  sLcd_v2 = Serial3;

Instead, you must use this:

Code:
HardwareSerial3  sLcd_v2 = Serial3;

The other two create pointers to the Serial3 object, but for "sLcd_v2", you're actually creating the object itself. If you use "HardwareSerial" as the object name, you'll get Serial1. The "= Serial3" portion does nothing. The only way to create the object actually as Serial3 is with "HardwareSerial3".
 
Back
Top