Problem with TimeAlarm calling methods

Hi,

I got a pb calling function from a dedicated class.

This is my main program:

/*
   CoreSystem

   Manage Main Loop to control some electrical feature
   */

#include <inttypes.h>

#include <Time.h>
#include <TimeAlarms.h>

#include <Utils.h>
#include <Traces.h>
#include <PushButton.h>
#include <PinManager.h>
#include <FunctionalProcess.h>

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

extern Traces Tracer ;

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);
      Tracer.Print("ecran initialise");


      // 
      // GESTION DES ALLUMAGES/EXTINCTION DES LIGNES
      //
      Tracer.setLcd(&lcd);
      Alarm.timerRepeat(4, FunctionalProcess::AfficheDate);
} 

//
//  LOOP
//
void loop()  {

      Alarm.delay(0); // wait one second between clock display
}

This is the Traces class :

/*
  Traces.cpp for traces output.

*/

#include "WProgram.h"
#include "Traces.h"
#include "Time.h"
#include <Wire.h>
#include <Utils.h>
#include <DS1307.h>
#include <LiquidCrystal.h>

//=============================================================================
/* Constructor & Destructor {{{1 */
Traces::Traces()
{

      b_clearEntireLine=true; 
      l_lastIndexPositionWritten=0;
      l_selectedLine=0;
}

Traces::~Traces()
{
}

Traces::Traces( const Traces &cpy )
{
}
/* }}}1 */
//=============================================================================
/* Accessors {{{1 */
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");
      }
}
/* }}}1 */
//=============================================================================
/* Serial Print Feature {{{1 */
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);
}
/* }}}1 */
//=============================================================================
/* LCD Print Methods {{{1 */
//=============================================================================
// Print methods on LCD Top Line {{{2
void Traces::LcdPrintTopLine(String pstr) {
      l_selectedLine=0;
      _lcdPtr->home();
      _lcdPtr->print(strutils::CompleteString(pstr));
}

void Traces::LcdPrintTopLineFromLeft(String pstr) {
      l_selectedLine=0;
      Traces::LcdPrintFromLeft(pstr);
}

void Traces::LcdPrintTopLineFromRight(String pstr) {
      l_selectedLine=0;
      Traces::LcdPrintFromRight(pstr);
}
// }}}2
//=============================================================================
// Print methods on LCD Bottom Line {{{2
void Traces::LcdPrintBottomLine(String pstr) {
      l_selectedLine=1;
      _lcdPtr->home();
      _lcdPtr->print(strutils::CompleteString(pstr));
}

void Traces::LcdPrintBottomLineFromLeft(String pstr) {
      l_selectedLine=1;
      Traces::LcdPrintFromLeft(pstr);
}

void Traces::LcdPrintBottomLineFromRight(String pstr) {
      l_selectedLine=1;
      Traces::LcdPrintFromRight(pstr);
}
// }}}2
//=============================================================================
// Print methods to write from left or right direction {{{2
void Traces::LcdPrintFromLeft(String pstr) {

      // _lcdPtr->home();
      _lcdPtr->setCursor(0,0);
      // write message
      for (int i=0; i<pstr.length(); ++i)
      {
            _lcdPtr->setCursor(i,0);
            _lcdPtr->print(pstr.charAt(i));
            // delay(150);
      }
}

void Traces::LcdPrintFromRight(String pstr) {

      //
      _lcdPtr->setCursor(16,l_selectedLine);
      // write message
      int pos = 16;
      for (int i=pstr.length(); i>=0; --i)
      {
            _lcdPtr->setCursor(pos,l_selectedLine);
            _lcdPtr->print(pstr.charAt(i));
            pos--;
            // delay(150);
      }
}
// }}}2
// }}}1
//=============================================================================
// LCD Clear Methods {{{1
void Traces::LcdClearLine(int noLine) {

      _lcdPtr->home();
      for (int i=0; i<16; ++i)
      {
            _lcdPtr->setCursor(i,noLine);
            _lcdPtr->print(" ");
            delay(10);
      }
}
void Traces::LcdClearTopLine() { 
      Traces::LcdClearLine(0);
}
void Traces::LcdClearBottomLine() { 
      Traces::LcdClearLine(1);
}
void Traces::LcdClearScreen() { 
      Traces::LcdClearTopLine();
      Traces::LcdClearBottomLine();
}
// }}}1
//=============================================================================
/* Utils Private Methods {{{1 */
String Traces::Date(){

  String str ;
  str+=convert::ToTwoDigits(RTC.get(DS1307_HR, true))+":"+convert::ToTwoDigits(RTC.get(DS1307_MIN, false))+":"+convert::ToTwoDigits(RTC.get(DS1307_SEC , false))+"_";
  return str;
}
/* }}}1 */
//=============================================================================



Traces Tracer = Traces() ;
/* set fdm=marker */

And this is the class that contains all Functional Methods:

/*
   FunctionalProcess.cpp manage some utility own tasks to provide 
   in my domotik managment

   */

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

// MANAGER
//static PinManager PinMng;
extern Traces Tracer;
//=============================================================================
/* Constructor & Destructor {{{1 */
FunctionalProcess::FunctionalProcess()
{
}
/* }}}1 */
//=============================================================================
/* {{{1 TIME MANAGMENT */
void FunctionalProcess::setRealTimeClock() {

      //setTime(22,15,00,01,18,2010);
      
      Tracer.Print("Heures du systeme embarque mise a jour.");
      // MODULE HORLOGE TEMPS REEL EMBARQUEE
      RTC.stop();
      // REGLAGE HEURE
      RTC.set(DS1307_HR   , horodatage::getHours());     // set the hours
      RTC.set(DS1307_MIN  , horodatage::getMinutes());     // set the minutes
      RTC.set(DS1307_SEC  , horodatage::getSeconds());     // set the seconds
      // REGLAGE DATE     
      RTC.set(DS1307_DATE , 12);     // set the date
      RTC.set(DS1307_MTH  , 11);     // set the month
      RTC.set(DS1307_YR   , 10);     // set the year
      RTC.set(DS1307_DOW  , 4 );     // set the day of the week
      RTC.start();
}

void FunctionalProcess::getRealTimeClock() {

    Tracer.BeginPrint(RTC.get(DS1307_HR  , true )); //read the hour and also update all the values by pushing in true
    Serial.print(":");        
    Serial.print(RTC.get(DS1307_MIN , false)); //read  minutes without update (false)
    Serial.print(":");        
    Serial.print(RTC.get(DS1307_SEC , false)); //read  seconds
    Serial.print("      ");              // some space for a more happy life
    Serial.print(RTC.get(DS1307_DATE, false)); //read  date
    Serial.print("/");        
    Serial.print(RTC.get(DS1307_MTH , false)); //read  month
    Serial.print("/");        
    Serial.print(RTC.get(DS1307_YR  , false)); //rea d year
        Serial.println();
}

void FunctionalProcess::displayRealTimeClock() {

    Tracer.BeginPrint(RTC.get(DS1307_HR  , true )); //read the hour and also update all the values by pushing in true
    Tracer.BeginPrint(":");        
    Tracer.BeginPrint(RTC.get(DS1307_MIN , false)); //read  minutes without update (false)
    Tracer.BeginPrint(":");        
    Tracer.EndPrint(RTC.get(DS1307_SEC , false)); //read  seconds
}
/* }}}1 */
//=============================================================================
/* {{{1 AFFICHAGE INFOS HORODATAGE */
//

void FunctionalProcess::AfficheInfo(const int p_Info) {
      
    Tracer.LcdPrintTopLineFromLeft(horodatage::currentTime());

      switch ( p_Info )
      {
            // time
            case 1 :
                  Tracer.LcdPrintTopLineFromLeft(horodatage::currentTime());
                  break;
            // temperature
            case 2 :
                  Tracer.LcdPrintTopLineFromRight("18.9 C");
                  break;
            // date
            case 3 :
                  Tracer.LcdPrintBottomLineFromRight(horodatage::currentDate());
                  break;
            default:
            Tracer.Print(horodatage::currentTime());
                  Tracer.LcdPrintTopLineFromLeft(horodatage::currentTime());
                  Tracer.LcdPrintTopLineFromRight("18.9 C");
                  Tracer.LcdPrintBottomLineFromRight(horodatage::currentDate());
                  break;
                  break;
      }
}

void FunctionalProcess::AfficheTemperature() {
      Tracer.LcdPrintTopLineFromRight("18.9 C");
}

void FunctionalProcess::AfficheDate() {
    Tracer.Print("Date");
      Tracer.LcdPrintBottomLineFromRight(horodatage::currentDate());
}
      
/* }}}1 */
FunctionalProcess FuncTask = FunctionalProcess() ;
// vim:fdm=marker:nowrap:ts=4:expandtab:

The problem is that no characters persists on my LCD screen.
When I do not use TimeAlarm class it works well.

Thank you for help

Where are the header files for the two classes?

The problem is that no characters persists on my LCD screen.

Do the characters flash on and then go away, or do they never appear?

characters flash on

/*
  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:
//=============================================================================
/* Constructor & Destructor {{{1 */
      Traces();
      ~Traces();
      Traces( const Traces &cpy );
/* }}}1 */
//=============================================================================
/* Accessors {{{1 */
      void setLcd(LiquidCrystal *lcdPtr);
/* }}}1 */
//=============================================================================
/* Serial Print Feature {{{1 */
      void Print(String pstr);
      void BeginPrint(String pstr);
      void EndPrint(String pstr);
/* }}}1 */
//=============================================================================
      /* LCD Print Methods {{{1 */
//=============================================================================
      // Print methods on LCD Top Line {{{2
      void LcdPrintTopLine             (String pstr);
      void LcdPrintTopLineFromLeft (String pstr);
      void LcdPrintTopLineFromRight(String pstr);
      // }}}2
      // Print methods on LCD Bottom Line {{{2
      void LcdPrintBottomLine                   (String pstr);
      void LcdPrintBottomLineFromLeft (String pstr);
      void LcdPrintBottomLineFromRight(String pstr);
      // }}}2
//=============================================================================
      // Print methods to write from left or right direction {{{2
      void LcdPrintFromLeft (String pstr);
      void LcdPrintFromRight(String pstr);
      // }}}2
      /* }}}1 */
//=============================================================================
// LCD Clear methods {{{1
      void LcdClearLine(int noLine) ; 
      void LcdClearTopLine()        ; 
      void LcdClearBottomLine()     ; 
      void LcdClearScreen()         ; 
// }}}1
  private:
//=============================================================================
/* Private Members {{{1 */
/* Accessors members {{{2 */
      LiquidCrystal * _lcdPtr;
/* }}}2 */
//=============================================================================
      /* LCD Print private members {{{2 */
      bool b_clearEntireLine;

      // on 16x2 LCD line, 
      //
      int l_selectedLine;
      
      // this save the position index of last character written
      // from left or from right
      int l_lastIndexPositionWritten;
      /* }}}2 */
/* }}}1 */
//=============================================================================
/* Utils Private Methods {{{1 */
      String Date();
/* }}}1 */
//=============================================================================
};
extern Traces Tracer;  // make an instance for the user
/* set fdm=marker */

#endif /* _Traces_h */
/*
  FunctionalProcess.h - PinManager functions
*/

#ifndef _FunctionalProcess_h
#define _FunctionalProcess_h

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

class FunctionalProcess;  // forward reference
typedef void (*funcPointer)();  // callback function typedef 


class FunctionalProcess
{

  private:

  public:

      static int heure;
      static int dateLiterale;
      static int temperature;

//=============================================================================
/* Constructor & Destructor {{{1 */
    FunctionalProcess();
/* }}}1 */
//=============================================================================
/* {{{1 TIME MANAGMENT */

      static void setRealTimeClock();
      static void getRealTimeClock();
      static void displayRealTimeClock();
/* }}}1 */
//=============================================================================
/* {{{1 AFFICHAGE INFOS HORODATAGE */
//
      static void AfficheInfo(const int p_Info);
      static void AfficheTemperature();
      static void AfficheDate();
/* }}}1 */
//=============================================================================
/* {{{1 GESTION DES LIGNES ELECTRIQUES */
//
//      SHUTDOWN / START POWER
//

      //      SHUTDOWN / START POWE
      //      LAMPADAIRE
      static void CouperLampadaire();
      static void AlimenterLampadaire();
      //      PROJECTEUR_ALLEE
      static void CouperProjoAllee();
      static void AlimenterProjoAllee();
      //      APPENTI
      static void CouperAppenti();
      static void AlimenterAppenti();
      //      PUIT
      static void CouperPuit();
      static void AlimenterPuit();
/* }}}1 */
//=============================================================================
/* {{{1 STATIC FUNC POINTER */
      static funcPointer fp_afficheDate;
/* }}}1 */
};
extern FunctionalProcess FuncTask;  // make an instance for the user

#endif /* _FunctionalProcess_h */

I'm at a loss to understand why FunctionalProcess is a class. It contains nothing but static methods.

What is horodatage? I don't see any mention of it in the header files.

a) FunctionalProcess intends to have only Functional methods. Maybe it's bad to use only static methods. You should replace it by what ?

b) horodatage is a namespace

/*
  Utils.h - Utils functions
*/

#ifndef _Utils_h
#define _Utils_h

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


namespace strutils
{
      String CompleteString  ( String &str );
}

namespace convert
{
      String ToString    ( float num );
      String ToTwoDigits ( int digits);
}

namespace horodatage
{
      String       currentTime        ( );
      String       currentDate        ( );
      int       getHours               ( );
      int       getMinutes             ( );
      int       getSeconds             ( );
      int       getYear              ( );
      int       getMonth             ( );
      int       getDay               ( );
      String       getDayOfWeek         ( );
      String       getMonthOfYear      ( );

}
//extern Utils Tracer;  // make an instance for the user

#endif /* _Utils_h */

The cpp

/*
   Utils.cpp for Utils output.

   */

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

namespace strutils
{
      String CompleteString( String &str )
      {
            String tmpStr="";
            tmpStr+=str;
            int completionLg = 16 - tmpStr.length();

            // erase the row
            for (int i = 0; i < completionLg; ++i)
            {
                  tmpStr+=" ";
            }
            return tmpStr;
      }
}

namespace convert
{
      String ToString(float num)
      {
            String str="";
            char ascii[32];

            int temp1 = (num - (int)num) * 100;
            sprintf(ascii,"%0d.%d", (int)num, temp1);

            Tracer.Print(ascii);

            str+=ascii;

            return str;
      }
      //
      String ToTwoDigits(int digits)
      {
            String str="";
            if(digits < 10)
            {
                  str="0";
            }
            str+=digits;

            return str;
      }
}

namespace horodatage
{
      String currentTime()
      {
            String str="";
              str+=convert::ToTwoDigits(RTC.get(DS1307_HR, true))+":"+convert::ToTwoDigits(RTC.get(DS1307_MIN, false))+":"+convert::ToTwoDigits(RTC.get(DS1307_SEC , false));
            return str;
      }

      // TIME
      int getHours( )
      {
            return RTC.get(DS1307_HR, true);      
      }
      int getMinutes( )
      {
            return RTC.get(DS1307_MIN, false);
      }
      int getSeconds( )
      {
            return RTC.get(DS1307_SEC , false);
      }
      
      // DATE
      String currentDate()
      {
            String str="";
              str+=horodatage::getDayOfWeek( )+" "+horodatage::getDay()+" "+horodatage::getMonthOfYear();
            return str;
      }

      int getYear( )
      {
            return RTC.get(DS1307_YR, false);      
      }
      int getMonth( )
      {
            return RTC.get(DS1307_MTH, false);
      }
      int getDay( )
      {
            return RTC.get(DS1307_DATE , false);
      }
       
      String       getDayOfWeek( )
      {
            String days[7]={ "Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi","Dimanche" };

            return days[RTC.get(DS1307_DOW, false)];
      }
      String       getMonthOfYear( )
      {
            String months[12]={ "Jan","Fev","Mar","Avr","Mai","Jui","Jui","Aou","Sep","Oct","Nov","Dec"};
            return months[horodatage::getMonth()-1];
      }
}

The main pb is that my screen is re initialized every 4 seconds:

This is the serial output

18:30:02_ecran initialise
18:30:02_--------------------------------
Ê18:30:06_ecran initialise
18:30:06_--------------------------------
Ê18:30:09_ecran initialise
18:30:09_--------------------------------
Ê18:30:13_ecran initialise
18:30:13_--------------------------------
Ê

The trace comes from this code :

/*
   CoreSystem

   Manage Main Loop to control some electrical feature
   */

#include <inttypes.h>

#include <Time.h>
#include <TimeAlarms.h>

// niva add features
#include <Utils.h>
#include <Traces.h>
#include <PushButton.h>
#include <PinManager.h>
#include <FunctionalProcess.h>

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

extern Traces Tracer ;
extern FunctionalProcess FuncTask ;


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);
      Tracer.Print("[b]ecran initialise[/b]");

      Tracer.setLcd(&lcd);
      Alarm.timerRepeat(4, FuncTask.AfficheDate);
} 

//
//  LOOP
//
void loop()  {


      Alarm.delay(0); // wait one second between clock display


}

FunctionalProcess intends to have only Functional methods. Maybe it's bad to use only static methods. You should replace it by what ?

The functions can be put in a .cpp file, with the declarations in the .h file, with no mention of a class anywhere.

If you feel that you need something, use a namespace like you do in Utils.h.

Since the system resets every 4 seconds, and the AfficheDate method of the FuncTask object is called every 4 seconds, I'd suspect either a problem with the AfficheDate function or that FuncTask was a NULL pointer.

Personally, I never like extern stuff. Either the Tracer class should create the instance of the FunctionalProcess class (which really should go away) or the main sketch should.

The main sketch should create the Tracer class, not declare a pointer to an external instance.

The reason I say this is this. Suppose I get two LCD's. Suppose I want to have an instance of the Tracer class for each LCD. They way you have it architected, I can't do that.

Since your class creates a single instance, one instance is all I can have.

Tracer is here only to Trace some text on Serial or LCD screen.

So FunctionalProcess class should use Tracer. It is a unique object that all others classes should access.

I have began to write an accessor
setTracer on FunctionalProcess class.

Have you got a better way in order to make all classes to know the Tracer? (Out of using Singleton)

Got a pb on link :
My util namespaces need Tracer object too.

namespace convert
{
      String ToString(float num)
      {
            String str="";
            char ascii[32];

            int temp1 = (num - (int)num) * 100;
            sprintf(ascii,"%0d.%d", (int)num, temp1);

            Tracer.Print(ascii);

            str+=ascii;

            return str;
      }
      //
      String ToTwoDigits(int digits)
      {
            String str="";
            if(digits < 10)
            {
                  str="0";
            }
            str+=digits;

            return str;
      }
}

I have deleted all extern Traces Tracer declarations and write the main pde like that :

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

Traces Tracer = Traces();
FunctionalProcess FuncTask = FunctionalProcess() ;



//
//  SETUP
//

void setup()  {

My util namespaces need Tracer object too.

A pointer to the Tracer object can be passed to the methods that need it. Theoretically, those namespaces are not to be made public, so those methods should only be called by the Tracer class methods.

A pointer to the Tracer object can be passed to the methods that need it

I don't find useful to pointer each time that a function need to Trace something.
I should use inheritance in order to simplify?

FunctionalProcess : public Tracer ?

For namespace I must pass pointer ?

Can you tell me how you would design the use of a Traces class out of passing pointer methods to it ?

I don't find useful to pointer each time that a function need to Trace something.

In the spirit of object oriented programming, encapsulation says that you SHOULD find it useful.

The Tracer class' methods is the only one that needs to pass pointers to itself to the utility methods.

FunctionalProcess : public Tracer ?

The FunctionalProcess class shouldn't exist at all, so it shouldn't derive from Tracer.

For namespace I must pass pointer ?

No. A namespace is just that. It's a way of prefixing functions to ensure that your function is the one that is actually called when a function of a specific name is invoked. You can't have pointers to namespaces.