#include mess… [Solved]

I’m not a complete beginner, but I rarely work with C++, so now I decided to experiment with it a bit and try to learn about classes.

I’m working on a bigger project, but I’ve just started, so currently I’m just playing with a 16×2 LCD display. It works perfectly with the default LCD library, so no problems with that.

Right now, though, I am stuck with a problem that I don’t understand.
I have six files:
DisplayTest.ino
DisplayTest.h
SpeedLimit.cpp
SpeedLimit.h
TimeSymbol.cpp
TimeSymbol.h

All files are located in the same directory and I have them all opened in the same Arduino IDE window in six different tabs.

All code is provided further down, but first the compile error message:

In file included from sketch/TimeSymbol.h:5:0,
                 from sketch/TimeSymbol.cpp:1:
DisplayTest.h:52: error: 'TimeSymbol' does not name a type
 TimeSymbol TimeSymbol;
 ^
exit status 1
'TimeSymbol' does not name a type

So here’s the code. It’s, like I said, not by far finished, but at least it should compile. I tend to compile often, so I don’t end up with thousands of error messages…

DisplayTest.ino:

#include "DisplayTest.h"

void setup() {
    // Setup buttons
    pinMode(DecButton,INPUT);
    pinMode(IncButton,INPUT);

    // Setup display
    lcd.createChar(IndexDegC,ByteDegC);
    lcd.begin(Columns, Rows);

    // For now, just throw some text to the display to see if it actually works
    lcd.clear();
    lcd.setCursor(ColDegC,RowData);
    lcd.write(byte(IndexDegC));
    lcd.setCursor(Colkmph,RowData);
    lcd.print("km/h");
    lcd.setCursor(ColDegCVal,RowData);
    lcd.print(20);
    lcd.setCursor(ColDirection,RowData);
    lcd.print("VNV");
    lcd.setCursor(ColkmphVal,RowData);
    lcd.print(SpeedLimit.GetLimit());
    lcd.setCursor(ColDateTime,RowDateTime);
    lcd.print("2017-07-27 22:55");
}

void loop() {
    TimeSymbol.Toggle(500);
}

DisplayTest.h:

#ifndef DisplayTest_h
#define DisplayTest_h

#include <LiquidCrystal.h>

#include "SpeedLimit.h"
#include "TimeSymbol.h"

// Buttons
const int DecButton     =    2;
const int IncButton     =    4;

// Display
const int RS            =    7;
const int Enable        =    8;
const int D4            =    9;
const int D5            =   10;
const int D6            =   11;
const int D7            =   12;
LiquidCrystal lcd(RS, Enable, D4, D5, D6, D7);

const int Rows          =    2;
const int Columns       =   16;

// Display – Rows and columns
const int RowData       =    0;
const int RowDateTime   =    1;
const int ColDegC       =    2;
const int ColDegCVal    =    0;
const int Colkmph       =   12;
const int ColkmphVal    =    9;
const int ColDirection  =    4;
const int ColDateTime   =    0;
const int ColTimeSymbol =   13;

// Special characters
const int IndexDegC     =    0;

byte ByteDegC[8] = {
                    B01000,
                    B10100,
                    B01011,
                    B00100,
                    B00100,
                    B00100,
                    B00011,
                    B00000
                    };

// Create some objects
SpeedLimit SpeedLimit;
TimeSymbol TimeSymbol; // COMPILE ERROR!

#endif

SpeedLimit.cpp:

#include "SpeedLimit.h"

SpeedLimit::SpeedLimit() {
    Index=DefaultIndex;
    Limit=AvailableLimits[Index];
}

int SpeedLimit::GetLimit() {
    return Limit;
}

int SpeedLimit::IncLimit() {
    if(Index<EndIndex) {
        Index++;
        Limit=AvailableLimits[Index];
    }
    else
        Index=StartIndex;
    return Limit;
}

int SpeedLimit::DecLimit() {
    if(Index>StartIndex) {
        Index--;
        Limit=AvailableLimits[Index];
    }
    else
        Index=EndIndex;
    return Limit;
}

void SpeedLimit::PrintLimit() {
    
}

SpeedLimit.h:

#ifndef SpeedLimit_h
#define SpeedLimit_h

#include "Arduino.h"

class SpeedLimit {
    public:
        SpeedLimit();
        int GetLimit();
        int IncLimit();
        int DecLimit();
        void PrintLimit();
    private:
        int Limit;
        int Index;
        static const int StartIndex=0;
        static const int DefaultIndex=4;
        static const int EndIndex=5;
        static constexpr int AvailableLimits[]={5,25,30,40,45,60};
};

#endif

TimeSymbol.cpp:

#include "TimeSymbol.h"

TimeSymbol::TimeSymbol() {
    CurrentSymbol=DefaultSymbol;
    CurrentTime=millis();
}

void TimeSymbol::Toggle(int TimeDiff) {
    CurrentTime=millis();
    if(LastTime-millis()>=TimeDiff) {
        LastTime=CurrentTime;
        SwapSymbol();
        lcd.setCursor(ColTimeSymbol,RowDateTime);
        lcd.write(CurrentSymbol);
    }
}

void TimeSymbol::SwapSymbol() {
    if(CurrentSymbol==DefaultSymbol)
        CurrentSymbol=AltSymbol;
    else
        CurrentSymbol=DefaultSymbol;
}

TimeSymbol.h:

#ifndef TimeSymbol_h
#define TimeSymbol_h

#include "Arduino.h"
#include "DisplayTest.h"

class TimeSymbol {
    public:
        TimeSymbol();
        void Toggle(int);
        void SwapSymbol();
    private:
        int LastTime;
        int CurrentTime;
        char CurrentSymbol;
        static const char DefaultSymbol=';';
        static const char AltSymbol=' ';
};

#endif

The main reason that I am confused by the compile error is that the line above it doesn’t give an error, and it’s done in exactly the same way… that line should cause an error too (not?), but it doesn’t.

What am I missing here? Make me feel stupid! ;D

Your mistake is including DisplayTest.h in TimeSymbol.h. That copy of DisplayTest.h tries to use a declaration in TimeSymbol.h that has not been reached yet. Remove that #include from TimeSymbol.h because TimeSymbol.h does not need any types declared in DisplayTest.h.

johnwasser: Your mistake is including DisplayTest.h in TimeSymbol.h. That copy of DisplayTest.h tries to use a declaration in TimeSymbol.h that has not been reached yet. Remove that #include from TimeSymbol.h because TimeSymbol.h does not need any types declared in DisplayTest.h.

But it's needed in TimeSymbol.cpp! That's why I have ``` #include "TimeSymbol.h" ``` in TimeSymbol.cpp and ``` #include "DisplayTest.h" ``` in TimeSymbol.h.

But I agree the whole construction is a little weird… I'll se if I can rearrange it a bit… It looks like some kind of unwanted feedback loop…

I solved the #include mess, so it compiles now, and it works perfectly as well, the little functionality there is…

I solved the problem by moving some lines in DisplayTest.h to a new file, Cursor.h. Then I had to mess a bit with #include statements.

Here are the files, as they look at the moment, compiling with no other kinds of messages than the good ones:

Sketch uses 3 048 bytes (9%) of program storage space. Maximum is 32 256 bytes.
Global variables use 84 bytes (4%) of dynamic memory, leaving 1 964 bytes for local variables. Maximum is 2 048 bytes.

DisplayTest.ino:

#include "DisplayTest.h"

void setup() {
    // Setup buttons
    pinMode(DecButton,INPUT);
    pinMode(IncButton,INPUT);

    // Setup display
    lcd.createChar(IndexDegC,ByteDegC);
    lcd.begin(Columns, Rows);

    // For now, just throw some text to the display to see if it actually works
    lcd.clear();
    lcd.setCursor(ColDegC,RowData);
    lcd.write(byte(IndexDegC));
    lcd.setCursor(Colkmph,RowData);
    lcd.print("km/h");
    lcd.setCursor(ColDegCVal,RowData);
    lcd.print(20);
    lcd.setCursor(ColDirection,RowData);
    lcd.print("VNV");
    lcd.setCursor(ColkmphVal,RowData);
    lcd.print(SpeedLimit.GetLimit());
    lcd.setCursor(ColDateTime,RowDateTime);
    lcd.print("2017-07-27 22:55");
}

void loop() {
    TimeSymbol.Toggle(lcd,500);
}

DisplayTest.h:

#ifndef DisplayTest_h
#define DisplayTest_h

#include <LiquidCrystal.h>
#include "Cursor.h"
#include "SpeedLimit.h"
#include "TimeSymbol.h"

// Display
const int RS            =    7;
const int Enable        =    8;
const int D4            =    9;
const int D5            =   10;
const int D6            =   11;
const int D7            =   12;
LiquidCrystal lcd(RS, Enable, D4, D5, D6, D7);

// Buttons
const int DecButton     =    2;
const int IncButton     =    4;

const int Rows          =    2;
const int Columns       =   16;

// Special characters
const int IndexDegC     =    0;

byte ByteDegC[8] = {
                    B01000,
                    B10100,
                    B01011,
                    B00100,
                    B00100,
                    B00100,
                    B00011,
                    B00000
                    };

// Create some objects
SpeedLimit SpeedLimit;
TimeSymbol TimeSymbol;

#endif

Cursor.h:

#ifndef Cursor_h
#define Cursor_h

// Display – Rows and columns
const int RowData       =    0;
const int RowDateTime   =    1;
const int ColDegC       =    2;
const int ColDegCVal    =    0;
const int Colkmph       =   12;
const int ColkmphVal    =    9;
const int ColDirection  =    4;
const int ColDateTime   =    0;
const int ColTimeSymbol =   13;

#endif

SpeedLimit.cpp:

#include "SpeedLimit.h"

SpeedLimit::SpeedLimit() {
    Index=DefaultIndex;
    Limit=AvailableLimits[Index];
}

int SpeedLimit::GetLimit() {
    return Limit;
}

int SpeedLimit::IncLimit() {
    if(Index<EndIndex) {
        Index++;
        Limit=AvailableLimits[Index];
    }
    else
        Index=StartIndex;
    return Limit;
}

int SpeedLimit::DecLimit() {
    if(Index>StartIndex) {
        Index--;
        Limit=AvailableLimits[Index];
    }
    else
        Index=EndIndex;
    return Limit;
}

void SpeedLimit::PrintLimit() {
    
}

SpeedLimit.h:

#ifndef SpeedLimit_h
#define SpeedLimit_h

#include "Arduino.h"

class SpeedLimit {
    public:
        SpeedLimit();
        int GetLimit();
        int IncLimit();
        int DecLimit();
        void PrintLimit();
    private:
        int Limit;
        int Index;
        static const int StartIndex=0;
        static const int DefaultIndex=4;
        static const int EndIndex=5;
        static constexpr int AvailableLimits[]={5,25,30,40,45,60};
};

#endif

TimeSymbol.cpp:

#include "TimeSymbol.h"

TimeSymbol::TimeSymbol() {
    CurrentSymbol=DefaultSymbol;
    CurrentTime=millis();
}

void TimeSymbol::Toggle(LiquidCrystal Display,int TimeDiff) {
    CurrentTime=millis();
    if(CurrentTime-LastTime>=TimeDiff) {
        LastTime=CurrentTime;
        SwapSymbol();
        Display.setCursor(ColTimeSymbol,RowDateTime);
        Display.write(CurrentSymbol);
    }
}

void TimeSymbol::SwapSymbol() {
    if(CurrentSymbol==DefaultSymbol)
        CurrentSymbol=AltSymbol;
    else
        CurrentSymbol=DefaultSymbol;
}

TimeSymbol.h:

#ifndef TimeSymbol_h
#define TimeSymbol_h

#include "Arduino.h"
#include "Cursor.h"
#include <LiquidCrystal.h>

class TimeSymbol {
    public:
        TimeSymbol();
        void Toggle(LiquidCrystal,int);
        void SwapSymbol();
    private:
        int LastTime;
        int CurrentTime;
        char CurrentSymbol;
        static const char DefaultSymbol=';';
        static const char AltSymbol=' ';
};

#endif

guraknugen:
But it’s needed in TimeSymbol.cpp! That’s why I have
** **#include "TimeSymbol.h"** **
in TimeSymbol.cpp and
** **#include "DisplayTest.h"** **
in TimeSymbol.h.

But I agree the whole construction is a little weird… I’ll se if I can rearrange it a bit… It looks like some kind of unwanted feedback loop…

Then put it where it is needed. If it’s needed in TimeSymbol.cpp, #include it in TimeSymbol.cpp. If it’s not needed in TimeSymbol.h, don’t #include it there.

There is no rule that says the .cpp file can only have .h included in it.

And this is not your only problem with these headers.

Do not declare variables in a header, even const ones. Copy those variables to a cpp file, and declare them extern in the header. Once you fix the compiler errors, you'll have linker errors all over the place, and linker error messages are much more cryptic to decipher than mere compiler errors.

DisplayTest.h does not need the Cursor header included.