Error message "undefined reference"

I've read a few posts on this topic, but I'm getting nowhere:

I want to make my code more readable using object oriented structures. However, I haven't gotten far and am failing at the basics. I now have three tabs, the main program, a header tab and a CPP tab. The three are neatly stored as separate files.

Here is my "stripped down" code:

IO Tab RD40

#include "my_RD40.h"

my_RD40 RD40;          // generate RD40 object

void setup()
{  
  // Serial port for debugging purposes
  Serial.begin(115200);

  RD40.setTime();
  RD40.getTime();
  Serial.printf("Zeit: %d:%d:%d\n", RD40.Hour(), RD40.Min(), RD40.Sec());
}

void loop() 
{
    RD40.getTime();
}

my_RD40.h


#ifndef my_RD40_H
#define my_RD40_H

#include <Arduino.h>

class my_RD40 {
  private:
    int _Sec;   // Sekunden (0-59)
    int _Min;   // Minuten (0-59)
    int _Hour;  // Stunden (0-23)
    int _Mday;  // Tag des Monats (1-31)
    int _Mon;   // Monat (0-11)
    int _Year;  // Jahr - 1900
    int _Wday;  // Tag der Woche (0-6, Sonntag = 0)

  public:
    my_RD40();  // Constructor

    void setTime();
    void getTime();
    int Sec();   
    int Min();   
    int Hour();  
    int Mday();  
    int Mon();   
    int Year();  
    int Wday();  
};

#endif

my_RD40.cpp

#include "my_RD40.h"
#include <Wire.h>
#include <TimeLib.h>


#define SDA 2
#define SCL 0
#define LOCATION TZ_Europe_Berlin                   // replace with your location
#define NTP "pool.ntp.org"

my_RD40::my_RD40() {
  // Setup I2C
  Wire.begin(SDA,SCL);                              // SDA=GPIO2 /  SCL=GPIO0 ==> registers the controller as I2C Master
  Wire.setClock(200000L);
}

void my_RD40::setTime() {  
  configTime(LOCATION, NTP);
  while (!time(nullptr)) {                                      // Wait until time is initialized
    delay(1000);
  }
  setTime(hour(), minute(), second(), day(), month(), year());  // Set internal clock
}

void my_RD40::getTime() {
  time_t now = time(nullptr);                                   // recall time from internal clock
  _Hour = hour(now);
  _Min = minute(now);
  _Sec = second(now);
  _Mday = day(now);
  _Mon = month(now);
  _Year = year(now);
  _Wday = weekday(now);
}

int my_RD40::Sec() {
  return _Sec;
}

int my_RD40::Min() {
  return _Min;
}

int my_RD40::Hour() {
  return _Hour;
}

int my_RD40::Mday() {
  return _Mday;
}

int my_RD40::Mon() {
  return _Mon;
}

int my_RD40::Year() {
  return _Year;
}

int my_RD40::Wday() {
  return _Wday;
}

I get several "undefined reference" errors when compiling. It looks like they are pointing to the main tab.

Any help would be appreciated.

Would you be interested in helping me help you?

Post the error messages.

fair enough. I have deleted some path information though:

c:/users/...../appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.4-gcc10.3-1757bed/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld.exe: sketch\RD40.ino.cpp.o:(.text.setup+0xc): undefined reference to `_ZN7my_RD407setTimeEv'
c:/users/...../appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.4-gcc10.3-1757bed/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld.exe: sketch\RD40.ino.cpp.o:(.text.setup+0x10): undefined reference to `_ZN7my_RD407getTimeEv'
c:/users/...../appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.4-gcc10.3-1757bed/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld.exe: sketch\RD40.ino.cpp.o:(.text.setup+0x14): undefined reference to `_ZN7my_RD404HourEv'
c:/users/...../appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.4-gcc10.3-1757bed/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld.exe: sketch\RD40.ino.cpp.o:(.text.setup+0x18): undefined reference to `_ZN7my_RD403MinEv'
c:/users/...../appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.4-gcc10.3-1757bed/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld.exe: sketch\RD40.ino.cpp.o:(.text.setup+0x1c): undefined reference to `_ZN7my_RD403SecEv'
c:/users/...../appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.4-gcc10.3-1757bed/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld.exe: sketch\RD40.ino.cpp.o: in function `setup':
C:\Users\.....\RD40/RD40.ino:23: undefined reference to `_ZN7my_RD407setTimeEv'
c:/users/...../appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.4-gcc10.3-1757bed/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld.exe: C:\Users\.....\RD40/RD40.ino:28: undefined reference to `_ZN7my_RD407getTimeEv'
c:/users/...../appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.4-gcc10.3-1757bed/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld.exe: C:\Users\.....\RD40/RD40.ino:28: undefined reference to `_ZN7my_RD404HourEv'
c:/users/...../appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.4-gcc10.3-1757bed/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld.exe: C:\Users\.....\RD40/RD40.ino:29: undefined reference to `_ZN7my_RD403MinEv'
c:/users/...../appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.4-gcc10.3-1757bed/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld.exe: C:\Users\.....\RD40/RD40.ino:30: undefined reference to `_ZN7my_RD403SecEv'
c:/users/...../appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.4-gcc10.3-1757bed/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld.exe: sketch\RD40.ino.cpp.o: in function `loop':
C:\Users\.....\RD40/RD40.ino:31: undefined reference to `_ZN7my_RD407getTimeEv'
c:/users/...../appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.4-gcc10.3-1757bed/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld.exe: C:\Users\.....\RD40/RD40.ino:40: undefined reference to `_ZN7my_RD40C1Ev'
c:/users/...../appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.4-gcc10.3-1757bed/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld.exe: sketch\RD40.ino.cpp.o: in function `_GLOBAL__sub_I_RD40':
C:\Users\.....\RD40/RD40.ino:40: undefined reference to `_ZN7my_RD40C1Ev'
collect2.exe: error: ld returned 1 exit status
Mehrere Bibliotheken wurden für "SD.h" gefunden
 Benutzt: C:\Users\.....\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\libraries\SD
 Nicht benutzt: C:\Program Files (x86)\Arduino\libraries\SD
exit status 1
Fehler beim Kompilieren für das Board Generic ESP8285 Module.

I trust this helps

I mention this because the error message posted points in this direction. Thanks for posting the error message.

I see that GPIO_NUM_2 of the ESP32 developer module is being used for the SDA line to transmit I2C data.

Most ESP32 developer boards have the onboard LED at GPIO_2. I have found that the circuit required to run the LED may cause issues when transmitting data via GPIO_NUM_2.

The natural I2C pins for the ESP32 under the Arduino IDE should be used for I2C; see your developers board pinout.

The error message also points to an issue in loop() and setup(), I'd comment all the code in loop(). Comment out all

void setup()
{  
  // Serial port for debugging purposes
  Serial.begin(115200);

  RD40.setTime();
  //RD40.getTime();
  //Serial.printf("Zeit: %d:%d:%d\n", RD40.Hour(), RD40.Min(), RD40.Sec());
}

and see if the error is reproduced.

Also, for setting/getting the ESP32's time I prefer to use the ESP32Time library. GitHub - fbiego/ESP32Time: An Arduino library for setting and retrieving internal RTC time on ESP32 boards, which seems to 'understand' the ESP32's way a bit better than other time libraries.

Thank you for the reply.

I should have mentioned, that I am using an ESP8266-01s. As you know, this tiny board only has two IO pins available.

  1. I2C
    I do have running (and very comprehensive) C code for the controller, which I just would like to restructure. I found that it actually is possible to use the two I/O lines on the ESP-01s as I2C pins.

  2. ESP32Time
    Thank you for the hint. However, as I run the code on an ESP8266, this might not work. I have been struggling with the various time libraries (time.h, tineLib.h, etc.) for long. I just do not understand why such a base function is so cumbersome to deal with.

The thought behind the my_RD40 class is to create a class that manages the hardware layer (i2C, Wifi, and time). However, I failed with the class structure already.

Unfortunately, I am traveling now and can only continue to work on the code next weekend. I will let you know, what I find out.

just in case someone is interested:

the error was in the method my_RD40::setTime(). Inside this method I had used the function setTime(hour(), minute(), second(), day(), month(), year()). This is a function of TimeLib.h. However, I had used the same name (namely setTime()) also for my own method. Thus there was the name twice - that was then too much of a good thing.

Just for the eternal files of the forum the corrected and working code:

RD40

#include "my_RD40.h"

my_RD40 RD40;                                                       // generate RD40 object

void setup(){
  
  // Serial port for debugging purposes
  Serial.begin(115200);

  RD40.setMyTime();
  RD40.getMyTime();
  Serial.printf("Zeit: %d:%d:%d\n", RD40.Hour(), RD40.Min(), RD40.Sec());
}

void loop() {
    RD40.getMyTime();
}

my_RD40.h

#ifndef my_RD40_H
#define my_RD40_H

#include <Arduino.h>

class my_RD40 {
  private:
    int _Sec;   // Sekunden (0-59)
    int _Min;   // Minuten (0-59)
    int _Hour;  // Stunden (0-23)
    int _Mday;  // Tag des Monats (1-31)
    int _Mon;   // Monat (0-11)
    int _Year;  // Jahr - 1900
    int _Wday;  // Tag der Woche (0-6, Sonntag = 0)

    
  public:
    my_RD40();  // Constructor

    void setMyTime();
    void getMyTime();
    int Sec();   
    int Min();   
    int Hour();  
    int Mday();  
    int Mon();   
    int Year();  
    int Wday();  
};

#endif

my_RD40.cpp

#include "my_RD40.h"
#include <TimeLib.h>
#include <TZ.h>
#include <Wire.h>

#define _SDA 2
#define _SCL 0
#define LOCATION TZ_Europe_Berlin                   // replace with your location
#define NTP "pool.ntp.org"

my_RD40::my_RD40() {
  // Setup I2C
  Wire.begin(_SDA,_SCL);                              // SDA=GPIO2 /  SCL=GPIO0 ==> registers the controller as I2C Master
  Wire.setClock(200000L);
}

void my_RD40::setMyTime() {  
  configTime(LOCATION, NTP);
  while (!time(nullptr)) {                                      // Wait until time is initialized
    delay(1000);
  }
  setTime(hour(), minute(), second(), day(), month(), year());  // Set internal clock
}

void my_RD40::getMyTime() {
  time_t now = time(nullptr);                                   // recall time from internal clock
  _Hour = hour(now);
  _Min = minute(now);
  _Sec = second(now);
  _Mday = day(now);
  _Mon = month(now);
  _Year = year(now);
  _Wday = weekday(now);
}

int my_RD40::Sec() {
  return _Sec;
}

int my_RD40::Min() {
  return _Min;
}

int my_RD40::Hour() {
  return _Hour;
}

int my_RD40::Mday() {
  return _Mday;
}

int my_RD40::Mon() {
  return _Mon;
}

int my_RD40::Year() {
  return _Year;
}

int my_RD40::Wday() {
  return _Wday;
}

You are on an ESP8266?

Don't use an external NTP library. NTP + DST is part of the ESP core since years. You don't need an external library for that.

https://werner.rothschopf.net/202011_arduino_esp8266_ntp_en.htm

p.s.: there is a very active German forum in the international section for your next question.

Thank you for the comment. Very helpful link. I have adapted my code.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.