Creating Libraries that uses other libraries

Hello Arduino community!

Im currently in a study group thats in the process of designing an exercise device, and im the one in charge of finding out how to code the arduino controlling everything. We've gotten ahold of one of those SparkFun electronics LCD displays, and i've been looking through the code on this side, and got it to work pretty easily. however, I've started to encounter some problems now. Making a small GUI for a 20x4 LCD Display takes quite a bit of coding, and even though it isnt something i cannot figure out how to do, we decided that it would be much nicer if we could make classes or libraries for the different thing, so only the thing the main sketch has to do is to include these classes/libs and then read inputs from the user and call the different functions(or whatever it is called) from the other classes, showing the right things in the GUI at the right time.

This is the serialLCDFunctions.cpp

#include "SoftwareSerial.h"
#include "Arduino.h"
#include "serialLCDFunctions.h"

//SerialLCD Functions
void::serialLCDFunctions selectLineOne(){  //puts the cursor at line 0 char 0.
   Serial.write(0xFE);   //command flag
   Serial.write(128);    //position
}
void::serialLCDFunctions selectLineTwo(){  //puts the cursor at line 2 char 0.
   Serial.write(0xFE);   //command flag
   Serial.write(192);    //position
}
void::serialLCDFunctions selectLineThree(){  //puts the cursor at line 3 char 0.
   Serial.write(0xFE);   //command flag
   Serial.write(148);    //position
}
void::serialLCDFunctions selectLineFour(){  //puts the cursor at line 4 char 0.
   Serial.write(0xFE);   //command flag
   Serial.write(212);    //position
}
void::serialLCDFunctions goTo(int position) { //position = line 1: 0-19, line 2: 20-39, etc, 79+ defaults back to 0
if (position<20){ Serial.write(0xFE);   //command flag
              Serial.write((position+128));    //position
}else if (position<40){Serial.write(0xFE);   //command flag
              Serial.write((position+128+64-20));    //position 
}else if (position<60){Serial.write(0xFE);   //command flag
              Serial.write((position+128+20-40));    //position
}else if (position<80){Serial.write(0xFE);   //command flag
              Serial.write((position+128+84-60));    //position              
} else { goTo(0); }
}
void::serialLCDFunctions clearLCD(){
   Serial.write(0xFE);   //command flag
   Serial.write(0x01);   //clear command.
}
void::serialLCDFunctions backlightOn(){  //turns on the backlight
    Serial.write(0x7C);   //command flag for backlight stuff
    Serial.write(157);    //light level.
}
void::serialLCDFunctions backlightOff(){  //turns off the backlight
    Serial.write(0x7C);   //command flag for backlight stuff
    Serial.write(128);     //light level for off.
}
void::serialLCDFunctions backlight50(){  //sets the backlight at 50% brightness
    Serial.write(0x7C);   //command flag for backlight stuff
    Serial.write(143);     //light level for off.
}
void::serialLCDFunctions serCommand(){   //a general function to call the command flag for issuing all other commands   
  Serial.write(0xFE);
}

And this is the serialLCDFunction.h

#ifndef serialLCDFunctions_h
#define serialLCDFunctions_h

#include "Arduino.h"

class serialLCDFunctions
{
public:

	void selectLineOne();
	void selectLineTwo();
	void selectLineThree();
	void selectLineFour();

	void goTo(int position);

	void clearLCD();

	void backlightOn();
	void backlightOff();
	void backlight50();

	void serCommand();
	
private:

};

#endif

please note that this piece of code (above) is actually dependant on the softwareSerial.h lib.

the prototypeGUI.cpp (this will in time "create" all different screens in the GUI)

#include "Arduino.h"
#include "prototypeGUI.h"
#include "serialLCDFunctions.h"

void prototypeGUI::startScreen(){ 
//Definition af startskærm
selectLineOne();
Serial.print("  Welcome to C17's");
delay(10);
selectLineTwo();
Serial.print(" Exercise prototype");
delay(10);
selectLineFour();
Serial.print("        >OK<");
delay(10);
}

and the prototypeGUI.h

#ifndef prototypeGUI_h
#define prototypeGUI_h

#include "Arduino.h"


class prototypeGUI
{
public:
	void startScreen();


private:

};

#endif

problem is that this doesn't work it tells me that:

/home/rasmus/arduino/arduino-1.0/libraries/prototypeGUI/serialLCDFunctions.cpp:7:26: error: expected initializer before ‘selectLineOne’
/home/rasmus/arduino/arduino-1.0/libraries/prototypeGUI/serialLCDFunctions.cpp:11:26: error: expected initializer before ‘selectLineTwo’
/home/rasmus/arduino/arduino-1.0/libraries/prototypeGUI/serialLCDFunctions.cpp:15:26: error: expected initializer before ‘selectLineThree’
/home/rasmus/arduino/arduino-1.0/libraries/prototypeGUI/serialLCDFunctions.cpp:19:26: error: expected initializer before ‘selectLineFour’
/home/rasmus/arduino/arduino-1.0/libraries/prototypeGUI/serialLCDFunctions.cpp:23:26: error: expected initializer before ‘goTo’

I know this is Messy business. I could easily put all different functions in the main sketch, but its messy and i dont want that. The reason im being quite persistent about this is because i really want to learn how to make all my functions in the libs and then just tell the program how to use those in the main sketch. (or however to say it) i want to learn.

can you also post the *.ino files?

Sounds like I missed something, 'cus i don't know that file extension, and i have created no .ino files.

you're on the right track, here is a small example of classes and files.

A.h file

class A{

  public:
    
  void MethodA( void );
  bool FunctionB( void );
  bool FunctionC( int i_A );
};

A.cpp

  #include "A.h"


  void A::MethodA( void )
    {
      return;
    }

  bool A::FunctionB( void )
    {
      return true;
    }

  bool A::FunctionC( int i_A )
    {
      return i_A > 0;
    }

Note the placement of '::'

Also any libraries that your custom library uses, must be also included in the sketch file.

Note the placement of '::'

Awesome, however, that changed the error codes to:

/home/rasmus/arduino/arduino-1.0/libraries/prototypeGUI/prototypeGUI.cpp: In member function ‘void prototypeGUI::startScreen()’:
/home/rasmus/arduino/arduino-1.0/libraries/prototypeGUI/prototypeGUI.cpp:10:15: error: ‘selectLineOne’ was not declared in this scope
/home/rasmus/arduino/arduino-1.0/libraries/prototypeGUI/prototypeGUI.cpp:13:15: error: ‘selectLineTwo’ was not declared in this scope
/home/rasmus/arduino/arduino-1.0/libraries/prototypeGUI/prototypeGUI.cpp:16:16: error: ‘selectLineFour’ was not declared in this scope

I presume this is somehow because, the "prototypeGUI" class doesn't recognise the functions from the "serialLCDFunctions" class
is that because i have to put them in the prototypeGUI.h document like I put the "void startScreen();" in it?

oh, and just another question, however unrelated: is this the way classes are normally built in C++? in 2 documents I mean.

If you want to use those functions like that ( calling selectLineOne statically )
You will need to modify like so ( using my previous example ).

class A{

  public:
    
  static void MethodA( void );
  static bool FunctionB( void );
  static bool FunctionC( int i_A );
};

the cpp stays the same ( should be fine ).

and you use the functions like

A::MethodA();
bool b_A = A::FunctionB();
bool b_B = A::FunctionC( 4 );

I don't think I follow 100% This is what I did:

#ifndef prototypeGUI_h
#define prototypeGUI_h

#include "Arduino.h"
#include "serialLCDFunctions.h"

class prototypeGUI
{
public:
	static void startScreen();


private:

};

#endif

and

#include "Arduino.h"
#include "prototypeGUI.h"
#include "serialLCDFunctions.h"

void prototypeGUI::startScreen(){ 
//Definition af startskærm
serialLCDFunctions::selectLineOne();
Serial.print("  Welcome to C17's");
delay(10);
serialLCDFunctions::selectLineTwo();
Serial.print(" Exercise prototype");
delay(10);
serialLCDFunctions::selectLineFour();
Serial.print("        >OK<");
delay(10);
}

was this what you meant? and should the same thing be done with the other lib?

or did i get it all wrong?

I would only make the serialLCDFunctions class have the static members.
So remove the static from.

static void startScreen();

And you will have to use the prototypeGUI class.

prototypeGUI p_Prototype;

//used like.
p_Prototype.startScreen();

And you will have to use the prototypeGUI class.

in the sketch you mean?

yes, the two options are, using the class statically or instantiating an object and use its methods.

In file included from sketch_apr26a.cpp:2:0:
/home/rasmus/arduino/arduino-1.0/libraries/prototypeGUI/prototypeGUI.h:9:20: error: aggregate ‘prototypeGUI p_Prototype’ has incomplete type and cannot be defined
/home/rasmus/arduino/arduino-1.0/libraries/prototypeGUI/prototypeGUI.h:10:1: error: expected unqualified-id before ‘{’ token

after I changed the prototypeGUI.h file to

#ifndef prototypeGUI_h
#define prototypeGUI_h

#include "Arduino.h"
#include "serialLCDFunctions.h"

class prototypeGUI p_Prototype;
{
public:
	void startScreen();


private:

};

#endif

yes, the two options are, using the class statically or instantiating an object and use its methods.

Sorry, but didn't exactly understand this.

i am so confused :astonished:

class prototypeGUI p_Prototype;

Wrong!

Have you noticed that HardwareSerial, LiquidCrystal, EthernetServer, EthernetClient, and other class follow a pattern with the names? There's a reason for that.

So, what should your class name? You can't create an instance of the class by doing anything in the header file. Instances are created in source files.

Instances are created in source files.

how? do you mean the .cpp file?

how? do you mean the .cpp file?

Yes. You can also create instances in the sketch (.ino/.pde).

Yes. You can also create instances in the sketch (.ino/.pde).

I'm just going to try. think i recognise this from Java actually, and completely misunderstood what you said first >.<

For some reason it had to be done in the sketch, but its okay.

Now it works, and i would like to thank you all for your help :slight_smile: do you know that weird feeling when you realise that the problem was something obvious? that pretty much what i feel like right now :stuck_out_tongue: