PDA

View Full Version : Problems with HardwareSerial Pointer and write



W.O.
04-01-2014, 02:41 PM
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:


#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); // !!! not sended !!!
GoToPosLCD(1, 0);
Serial3.print(tempStringPrint); // output is ok
Serial3.write(tempStringWrite); // output is ok

GoToPosLCD(2, 0);
SerialLcd.write("a "); // !!! not sended !!!
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

Serial without Poiner:
PrintTest WriteTest
Serial with Poiner:
PrintTest WriteTest

Serial without Poiner:
PrintTest WriteTest
Serial with Poiner:
PrintTest WriteTest

Output LCD:

PrintTest
PrintTest WriteTest
b c 100
a b c 100

Output on LCD expected: the red branded are missing

PrintTest WriteTest
PrintTest WriteTest
a 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.)

stevech
04-01-2014, 05:36 PM
ON a tangent, and as a teaching moment for me.. what does the & operator do in this code you posted?

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

W.O.
04-01-2014, 09:28 PM
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.

W.O.
04-02-2014, 11:40 AM
ON a tangent, and ...

The problem that I have posted occur from the concept on this link: (see: "2 Answers", second part)
http://stackoverflow.com/questions/7455570/how-to-pass-serial-object-by-reference-to-my-class-in-arduino
There may be an answer to your question.

stevech
04-02-2014, 04:36 PM
OK. It's to be a reference rather than a pointer to a class instance.

W.O.
04-12-2014, 06:15 PM
Code compiled without compiler warnings

// 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

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:

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

without: P W p w 97a
sLcd_v1: P W p w 97a
sLcd_v2: P W p w 97a
sLcd_v3: P W p w 97a
On an Arduino Mega 2560 rev3 works the ported code fine. Nothing is missed.

stevech
04-12-2014, 07:23 PM
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)?

W.O.
04-12-2014, 08:26 PM
Is the baud rate ...

If I change in my Teensy 3.1 code only this:

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:

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

W.O.
04-12-2014, 09:30 PM
On this link:
www.pjrc.com/teensy/td_uart.html (http://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();


// 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();
// If you uncomment the line above: PointerTeensy31:11: error: 'HardwareSerial1' was not declared in this scope
// 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:

without: P W p w 97a

Output on Serial Monitor expected: the red branded are missing

without: P W p w 97a
Serial_v0: P W p w 97a

Output LCD:

without: P W p w 97a

Output on LCD expected: the red branded are missing

without: P W p w 97a
sLcd_v3: P W p w 97a

Code compiled without compiler warnings
It does not Work. What is the reason?

PaulStoffregen
04-12-2014, 10:11 PM
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.

PaulStoffregen
04-12-2014, 11:07 PM
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:



// 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.

PaulStoffregen
04-13-2014, 05:53 PM
Here is a HardwareSerial.h that should fix the problems with "sLcd_v1" and "sLcd_v3".

PaulStoffregen
04-13-2014, 05:57 PM
Regarding "sLcd_v2", this code can never work:



HardwareSerial sLcd_v2 = Serial3;


Instead, you must use this:



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".

W.O.
04-14-2014, 04:56 PM
Thank you very much, for the professional answer and the fast written FIX.