Passing LCD ref to UtilTrace Class

Hi,

I have done init of LCD into setup of my main program.

a) Now I would like to delegate lcd.print to my util class Traces.cpp
I have done this by pointer but I would like to do it by reference

b) Furthermore, I have a problem cause the line below
Tracer.LCDPRINT("info");

display fugitive info before disappearing.

Thank you

Main.pde sketch

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);




//
//  SETUP
//

void setup()  { 

      // SERIAL
      Serial.begin(9600); 

      // LCD
        lcd.begin(16, 2);
        lcd.setCursor(0, 0);
        lcd.clear();
        delay(2000);
}

void loop()  { 


      Tracer.PRINT("info ");
      Tracer.LCDPRINT("info");

      delay(1000);     //waiting a second
}

Then the util Trace class

/*
  traces.h - low level traces functions
*/

#ifndef _Traces_h
#define _Traces_h

#include "WProgram.h"
#include <inttypes.h>
#include <LiquidCrystal.h>
#include "Time.h"

class Traces
{
  public:
    Traces();
   
      void PRINT(String pstr);
      void BEGINPRINT(String pstr);
      void ENDPRINT(String pstr);
      // LCD
      void setLCD(LiquidCrystal & plcd);
      void LCDPRINT(String pstr);

  private:
      // 
      String sepDate ;
      String sepHour ;
      String sepMilli;
      String sepTxt  ;
      //
      String DATE();
      LiquidCrystal *_lcd;
};

extern Traces Tracer;  // make an instance for the user

#endif /* _Traces_h */


___________________________

/*
  Traces.cpp for traces output.
*/

#include "WProgram.h"
#include "Traces.h"
#include "Time.h"
#include <Wire.h>
#include <Utils.h>
#include <DS1307.h> // written by  mattt on the Arduino forum and modified by D. Sjunnesson
#include <LiquidCrystal.h>

Traces::Traces()
{
      sepDate = "_" ;
      sepHour = ":" ;
      sepMilli= "." ;
      sepTxt  = ": ";
      //
}

void Traces::PRINT(String pstr) {
   Serial.println(DATE()+pstr);
}

void Traces::BEGINPRINT(String pstr) {
   Serial.print(DATE()+pstr);
}

void Traces::ENDPRINT(String pstr) {
   Serial.println(pstr);
}

//LCD PRINT
void Traces::LCDPRINT(String pstr) {


   _lcd->setCursor(0, 0);
   _lcd->print(DATE()+pstr);
}

void Traces::setLCD(LiquidCrystal & plcd){


   _lcd = &plcd;
}


String Traces::DATE(){

  String str ;
  str+=convert::ToTwoDigits(RTC.get(DS1307_HR, true))+sepHour+convert::ToTwoDigits(RTC.get(DS1307_MIN, false))+sepHour+convert::ToTwoDigits(RTC.get(DS1307_SEC , false))+sepTxt;
  return str;
}

Traces Tracer = Traces() ;

Now I would like to delegate lcd.print to my util class Traces.cpp
I have done this by pointer but I would like to do it by reference

Are you asking permission, or do you have a problem?

Furthermore, I have a problem cause the line below
Tracer.LCDPRINT("info");

display fugitive info before disappearing.

The line in the code disappears? The data on the lcd disappears? Why? Did you call the cops?

A couple of comments on the code. By convention, all capital letter names are reserved for #define statements. Function names use Pascal case or camel case (First letter of each word capitalized, with the first word being capitalized or not).

Creating an instance of the class for the user isn't recommended. Leave that as a task for the user to perform.

Can you give me example please of a util class used by main loop arduino sketch ?

Can you give me example please of a util class used by main loop arduino sketch ?

You mean like Serial.print()?

Not at all.

A Utility Class as Serial.print but mine should encapsulate LCDCrystal lib, Serial lib that's why I asked you to tell me how passing LCDCrystal obj to my util class.

Thank you for examples.

And I'm wondering, if the LCD functionality is to be wrapped in your class, why your class doesn't create the LCD instance.

But, if the LCD instance is to be available to your library AND the sketch, then the sketch should create it.

LiquidCrystal LCD(<Some pin numbers>);

Then, your class is instantiated:

MyClass myInst();

Then, your class has a method and a field:

void SetLCD(LiquidCrystal &refLCD);

LiquidCrystal &theLCD;

And an implementation:

MyClass::SetLCD(LiquidCrystal &refLCD)
{
   theLCD = refLCD;
}

And a usage:

theLCD.print("Hey!");

I think this will work, but I don't have a library, or Arduino, of LCD handy to test.

Hum, I have coded as you learn to me but I wonder if my Traces.cpp class has to inheritate or has to have a ref member of LCDCrystal.

In fact, I find logical to initialize in Setup the LCD.
This is done:

void setup()  { 

      // SERIAL
      Serial.begin(9600); 

      // LCD
        lcd.begin(16, 2);
        lcd.setCursor(0, 0);

Then I don't want to pass reference of LCD each time I have to write on it even if it works well:
Tracer.LcdPrint(lcd, horodatage::currentTime()); this
code has to change for me

I would like a call line code like that :

Tracer.LcdPrint(horodatage::currentTime());

without LCD.

So I have written a setLcd on my Traces class:
and declare ref member

void setLcd(const LiquidCrystal &lcdObj);
const LiquidCrystal _lcdRef;

in the Traces.cpp

void Traces::setLcd(const LiquidCrystal &lcdObj) {
      _lcdRef = lcdObj;
}

it fails at compiling
[quote]
C:\arduino\arduino-0021\libraries\Traces\Traces.cpp: In constructor 'Traces::Traces()':
C:\arduino\arduino-0021\libraries\Traces\Traces.cpp:17: error: no matching function for call to 'LiquidCrystal::LiquidCrystal()'
C:\arduino\arduino-0021\libraries\LiquidCrystal/LiquidCrystal.h:56: note: candidates are: LiquidCrystal::LiquidCrystal(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)
C:\arduino\arduino-0021\libraries\LiquidCrystal/LiquidCrystal.h:54: note:                 LiquidCrystal::LiquidCrystal(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)
C:\arduino\arduino-0021\libraries\LiquidCrystal/LiquidCrystal.h:52: note:                 LiquidCrystal::LiquidCrystal(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)
C:\arduino\arduino-0021\libraries\LiquidCrystal/LiquidCrystal.h:49: note:                 LiquidCrystal::LiquidCrystal(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)
C:\arduino\arduino-0021\libraries\LiquidCrystal/LiquidCrystal.h:45: note:                 LiquidCrystal::LiquidCrystal(const LiquidCrystal&)
C:\arduino\arduino-0021\libraries\Traces\Traces.cpp: In copy constructor 'Traces::Traces(const Traces&)':
C:\arduino\arduino-0021\libraries\Traces\Traces.cpp:30: error: no matching function for call to 'LiquidCrystal::LiquidCrystal()'
C:\arduino\arduino-0021\libraries\LiquidCrystal/LiquidCrystal.h:56: note: candidates are: LiquidCrystal::LiquidCrystal(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)
C:\arduino\arduino-0021\libraries\LiquidCrystal/LiquidCrystal.h:54: note:                 LiquidCrystal::LiquidCrystal(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)
C:\arduino\arduino-0021\libraries\LiquidCrystal/LiquidCrystal.h:52: note:                 LiquidCrystal::LiquidCrystal(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)
C:\arduino\arduino-0021\libraries\LiquidCrystal/LiquidCrystal.h:49: note:                 LiquidCrystal::LiquidCrystal(uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t)
C:\arduino\arduino-0021\libraries\LiquidCrystal/LiquidCrystal.h:45: note:                 LiquidCrystal::LiquidCrystal(const LiquidCrystal&)
C:\arduino\arduino-0021\libraries\Traces\Traces.cpp: In member function 'void Traces::setLcd(const LiquidCrystal&)':
C:\arduino\arduino-0021\libraries\Traces\Traces.cpp:53: error: passing 'const LiquidCrystal' as 'this' argument of 'LiquidCrystal& LiquidCrystal::operator=(const LiquidCrystal&)' discards qualifiers
[/quote]

It looks like you will need to use pointers, since the member _lcdRef is causing the LiquidCrystal constructor to be invoked.

It's unfortunate that LiquidCrystal didn't provide a default, no argument constructor and a begin method, like other classes do.

Ok I understand.

1/ I modify LCDCrystal Lib to have default constr
2/ I use pointer...uh

I use pointer...uh

What is the aversion to pointers? When you understand them, they become indispensable.

Ok it is done and work passing by pointer.

But I have a last question:

My setup do this :

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void setup()  { 

      // SERIAL
      Serial.begin(9600); 

      // LCD
        lcd.begin(16, 2);
        lcd.setCursor(0, 0);
        lcd.clear();
        delay(2000);
      Tracer.Print("ecran initialise");


        // PIN MANAGMENT ASSIGNATION
        // DURATION 1 second
      Tracer.setLcd(&lcd);
} 

void loop()  { 
      Tracer.LcdPrint(horodatage::currentDate());

      delay(2100);     //waiting a second


}

My tracer class:

class Traces
{
  public:
      Traces();
      ~Traces();
      Traces( const Traces &cpy );
   
      void Print(String pstr);
      void BeginPrint(String pstr);
      void EndPrint(String pstr);
      void setLcd(LiquidCrystal *lcdPtr);
      //
      void LcdPrint(String pstr) ;


void Traces::setLcd(LiquidCrystal *lcdPtr) {

      if (  lcdPtr != NULL )
      {
            _lcdPtr = lcdPtr;
            Traces::Print("Le module de trace contient un pointeur vers le LCD OK!");
            delay(500);
      }
      else
      {
            Traces::Print("Erreur pointeur nul sur le module de trace");
      }
}

Now in the setup I have done a remark.

I f I put the line Tracer.setLcd(&lcd); just after init of LCD it fails.
Certainly because of 2 seconds needed for lcd init.

Thank you Paul

I f I put the line Tracer.setLcd(&lcd); just after init of LCD it fails.
Certainly because of 2 seconds needed for lcd init.

You don't show where in the sketch you tried to put the call to setLcd, nor how it fails, or what evidence you have of a lack of success. But, it is certainly not failing because the hardware initialization takes time.

The call line was in the loop delayed by 5100 seconds.

Its works like that so I am trying to make evolutions of displaying text.
Like in rail station

The call line was in the loop delayed by 5100 seconds.

The call to setLcd should take place in setup(), not loop. You only need to do it once.

Yes that's I have done.