Personal Library "collect2: error: ld returned 1 exit status"

Hi all!

I am trying to create my own library. I followed this perfectly, and yet when I try to use a pin definition in a different function in my library, compile fails and says that the pin wasn't declared in this scope. I already added the pin as a private variable in the .h file. Do I have to define the pin at the beginning of the .cpp file also?

Thanks in advance!

Without seeing your library files and a test sketch it will be impossible to provide constructive help

Yeah, I probably should have added them to begin with. Sorry.

Gate.h:

/*
  Gate.h - Library for controlling gates.
  Created by K Gray, December 26, 2021.
  Released into the public domain.
*/

#ifndef Gate_h
#define Gate_h

#include "Arduino.h"

#include <math.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <ESP8266WiFi.h>

class Gate
{
  public:
    Gate(int pin1, int pin2, int pin3, int pin4);
    void Magnet(int magnetPin);
    void LEDStrip(int r, int g, int b);
    
    void OTAStart(const char OTAPassword[]);
    void WiFiStart(char WiFiNetwork[], char WiFiPassword[]);
    void start(char WiFiNetwork[], char WiFiPassword[], const char OTAPassword[]);
    
    void gate(int Direction);
    void stop();
    void magnet(int magnetValue);
    void ledStrip(int red, int green, int blue);
    void calcDist(float CurrentLatitude, float CurrentLongitude, float SavedLatitude, float SavedLongitude);
    void waitForGate(int travelDist, int travelSpeed, int percentOfTravel);
    void delayForGate(int DFGTime);

    void WFGFunction();
    
    int direction;

    float distance;
    boolean emergencyStop = false;
  private:
    int _pin1;
    int _pin2;
    int _pin3;
    int _pin4;
    int _magPin;
    int _r;
    int _g;
    int _b;
    char _OTAPassword;
    String _WiFiSSID;
    String _WiFiPASS;
    int _Direction;
    int _magnetValue;
    int _red;
    int _green;
    int _blue;
    float _CurrentLatitude;
    float _CurrentLongitude;
    float _SavedLatitude;
    float _SavedLongitude;
    int _travelDist;
    int _travelSpeed;
    int _percentOfTravel;
    int _DFGTime;
    
    int _wfg;
    int _totalDelay;
};

#endif

Gate.cpp:

/*
  Gate.cpp - Library for controlling gates.
  Created by K Gray, December 26, 2021.
  Released into the public domain.
*/

#include "Arduino.h"
#include "Gate.h"

Gate::Gate(int pin1, int pin2, int pin3, int pin4){
  pinMode(pin1, OUTPUT);
  pinMode(pin2, OUTPUT);
  pinMode(pin3, OUTPUT);
  pinMode(pin4, OUTPUT);
  _pin1 = pin1;
  _pin2 = pin2;
  _pin3 = pin3;
  _pin4 = pin4;
}

void Gate::Magnet(int magnetPin){
  pinMode(magnetPin, OUTPUT);
  _magPin = magnetPin;
}

void Gate::LEDStrip(int r, int g, int b){
  pinMode(r, OUTPUT);
  pinMode(g, OUTPUT);
  pinMode(b, OUTPUT);
  _r = r;
  _g = g;
  _b = b;
}

void Gate::OTAStart(const char OTAPassword[]){
  // Port defaults to 8266
  ArduinoOTA.setPort(8266);
  // Hostname defaults to esp8266-[ChipID]
  ArduinoOTA.setHostname("GateESP");
  // No authentication by default
  ArduinoOTA.setPassword(OTAPassword);//(const char 

  ArduinoOTA.onStart([]() {
    Serial.println("Start");
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  ArduinoOTA.begin();
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void Gate::WiFiStart(char WiFiNetwork[], char WiFiPassword[]){
  WiFi.mode(WIFI_STA);
  WiFi.begin(WiFiNetwork, WiFiPassword);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }
}

void Gate::start(char WiFiNetwork[], char WiFiPassword[], const char OTAPassword[]){
  WiFi.mode(WIFI_STA);
  WiFi.begin(WiFiNetwork, WiFiPassword);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }

  // Port defaults to 8266
  ArduinoOTA.setPort(8266);
  // Hostname defaults to esp8266-[ChipID]
  ArduinoOTA.setHostname("GateESP");
  // No authentication by default
  ArduinoOTA.setPassword(OTAPassword);//(const char 

  ArduinoOTA.onStart([]() {
    Serial.println("Start");
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  ArduinoOTA.begin();
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void Gate::gate(int Direction){
  if (direction == 1){
    if (Direction == 1){
      digitalWrite(_pin1, HIGH);
      digitalWrite(_pin2, LOW);
      digitalWrite(_pin3, HIGH);
      digitalWrite(_pin4, LOW);
    }
    if (Direction == 2){
      digitalWrite(_pin1, LOW);
      digitalWrite(_pin2, HIGH);
      digitalWrite(_pin3, LOW);
      digitalWrite(_pin4, HIGH);
    }
  }
  else if (direction == 2){
    if (Direction == 1){
      digitalWrite(_pin1, LOW);
      digitalWrite(_pin2, HIGH);
      digitalWrite(_pin3, LOW);
      digitalWrite(_pin4, HIGH);
    }
    if (Direction == 2){
      digitalWrite(_pin1, HIGH);
      digitalWrite(_pin2, LOW);
      digitalWrite(_pin3, HIGH);
      digitalWrite(_pin4, LOW);
    }
  }
}

void Gate::stop(){
  digitalWrite(_pin1, LOW);
  digitalWrite(_pin2, LOW);
  digitalWrite(_pin3, LOW);
  digitalWrite(_pin4, LOW);
}

void Gate::magnet(int magnetValue){
  digitalWrite(_magPin, magnetValue);
}

void Gate::ledStrip(int red, int green, int blue){
  analogWrite(red, _r);
  analogWrite(green, _g);
  analogWrite(blue, _b);
}

void Gate::calcDist(float CurrentLatitude, float CurrentLongitude, float SavedLatitude, float SavedLongitude){
  // HaverSine version
  const float Deg2Rad = 0.01745329252;               // (PI/180)  0.017453293, 0.0174532925
  //const double EarthRadius = 6372.795;              //6372.7976 In Kilo meters, will scale to other values
  const float EarthRadius = 20908120.1;              // In feet  20908128.6
  float DeltaLatitude, DeltaLongitude, a, Distance;

  // degrees to radians
  CurrentLatitude = (CurrentLatitude + 180) * Deg2Rad;     // Remove negative offset (0-360), convert to RADS
  CurrentLongitude = (CurrentLongitude + 180) * Deg2Rad;
  SavedLatitude = (SavedLatitude + 180) * Deg2Rad;
  SavedLongitude = (SavedLongitude + 180) * Deg2Rad;

  DeltaLatitude = SavedLatitude - CurrentLatitude;
  DeltaLongitude = SavedLongitude - CurrentLongitude;

  a =(sin(DeltaLatitude/2) * sin(DeltaLatitude/2)) + cos(CurrentLatitude) * cos(SavedLatitude) * (sin(DeltaLongitude/2) * sin(DeltaLongitude/2));
  Distance = EarthRadius * (2 * atan2(sqrt(a),sqrt(1-a)));
  distance = Distance;
}



void waitForGate(int travelDist, int travelSpeed, int percentOfTravel){
  int _totalDelay = ((((travelDist*percentOfTravel)/travelSpeed)*1000)-500)/2;
  int _wfg;
  Begin:
  _wfg++;
  while(_wfg <= _totalDelay){
    void WFGFunction();
    goto Begin;
  }
  _wfg = 0;
}

void Gate::delayForGate(int DFGTime){
  delay(DFGTime);
}

void WFGFunction(){}

Example1_Gate.ino:

#include <Gate.h>

Gate gate1(D3,D4,D7,D8);

#define direction = 1;

void setup(){
  gate1.WiFiStart("MYSSID", "MYPASS");
  gate1.Magnet(D5);
  gate1.LEDStrip(D1, D2, D6);
}

void loop(){
  gate1.gate(1);
  gate1.waitForGate(12,0.4,0.8);
  gate1.stop();
  gate1.delayForGate(5000);
  gate1.gate(2);
  gate1.waitForGate(12,0.4,0.8);
  gate1.stop();
  gate1.delayForGate(5000);
}

Verbose output on compiling the example:

Arduino: 1.8.19 (Mac OS X), Board: "LOLIN(WEMOS) D1 R2 & mini, 80 MHz, Flash, Disabled (new aborts on oom), Disabled, All SSL ciphers (most compatible), 32KB cache + 32KB IRAM (balanced), Use pgm_read macros for IRAM/PROGMEM, 4MB (FS:2MB OTA:~1019KB), v2 Lower Memory, Disabled, None, Only Sketch, 921600"











/Users/user/Desktop/Arduino/libraries/Gate/Gate.cpp: In function 'void WFGFunction()':
/Users/user/Desktop/Arduino/libraries/Gate/Gate.cpp:205:7: error: 'emergencyStop' was not declared in this scope
  205 |   if (emergencyStop == true){
      |       ^~~~~~~~~~~~~
/Users/user/Desktop/Arduino/libraries/Gate/Gate.cpp:206:18: error: '_pin1' was not declared in this scope
  206 |     digitalWrite(_pin1, LOW);
      |                  ^~~~~
/Users/user/Desktop/Arduino/libraries/Gate/Gate.cpp:207:18: error: '_pin2' was not declared in this scope
  207 |     digitalWrite(_pin2, LOW);
      |                  ^~~~~
/Users/user/Desktop/Arduino/libraries/Gate/Gate.cpp:208:18: error: '_pin3' was not declared in this scope
  208 |     digitalWrite(_pin3, LOW);
      |                  ^~~~~
/Users/user/Desktop/Arduino/libraries/Gate/Gate.cpp:209:18: error: '_pin4' was not declared in this scope
  209 |     digitalWrite(_pin4, LOW);
      |                  ^~~~~
Multiple libraries were found for "WiFiUdp.h"
 Used: /Users/user/Library/Arduino15/packages/esp8266/hardware/esp8266/3.0.2/libraries/ESP8266WiFi
 Not used: /Applications/Electronics/Arduino.app/Contents/Java/libraries/WiFi
 Not used: /Users/user/Desktop/Arduino/libraries/WiFi101
exit status 1
Error compiling for board LOLIN(WEMOS) D1 R2 & mini.

FYI, I do realize I am biting off more than I can chew.

No, declare once in the .h file

Ensure your .cpp has a #include for the <filename.h>
& ensure your .ino sketch has a #include <filename.h>

IF YOU put the .h & .cpp in the sketch older, use:

#include "filename.h"

Normally your .cpp file would #include your .h file, like in the tutorial you said you followed perfectly.

:white_check_mark:

:white_check_mark:

:white_check_mark:

My .cpp file does include my .h file.

It is risky to use Arduino functions in an object constructor. If you make a global object it will be "constructed" before the Arduino core is initialized. That is why many libraries have a 'begin' method that you call from setup() after the core is initialized. That gives the library a safe place to call Arduino functions.

If you manually moved files into /Arduino/libraries, you must restart the ArduinoIDE.

I already do that every time I change the library.

Oh. I didn't realize that. I'll move the pin setups to my .start function.

I have had a couple of times when the auto-protyping of functions just did not work! 'tis been a long time but I had to do the C thing and declare them myself:


// Function prototypes:
static void reset_display(void);
void StartUp_OLED();
void displayOn(void);
void displayOff(void);
static void clear_display(void);
static void SendChar(unsigned char data);
static void sendCharXY(unsigned char data, int X, int Y);
static void sendcommand(unsigned char com);
static void setXY(unsigned char row,unsigned char col);
static void sendStr(unsigned char *string);
static void sendStrXY( char *string, int X, int Y);
static void init_OLED(void);
void Draw_WIFI();
void Draw_WAVES();
void Scan_Wifi_Networks();
void Do_Connect();


I just changed the pin definitions to be in a begin function, and now there is an error.

Exampe1_Gate:7:6: error: 'void Gate::setup()' cannot be overloaded with 'void Gate::setup()'
    7 | void setup(){
      |      ^~~~~

Compilation output says that same thing 2 times for setup and 2 times for loop.

/Users/user/Desktop/Arduino/libraries/Gate/examples/Exampe1_Gate/Exampe1_Gate.ino: In member function 'void Gate::setup()':
Exampe1_Gate:8:3: error: invalid use of member function 'Gate Gate::myGate()' (did you forget the '()' ?)
    8 |   myGate.WiFiStart("MYSSID", "MYPASS");
      |   ^~~~~~
      |         ()

Compilation says that about fifty times for multiple places.

What could be causing that suddenly?

How do I declare my self? Do I add "static" before each function in the .h file?

Post your complete updated code every time you make even the smallest change to the smallest part of it. That way we don't have to hunt through previous post to piece together what you have now.

Not sure exactly your question:
https://www.geeksforgeeks.org/can-a-c-class-have-an-object-of-self-type/

OK. It is just a lot to copy and paste over and over.

Gate.h:

/*
  Gate.h - Library for controlling gates.
  Created by K Gray, December 26, 2021.
  Released into the public domain.
*/

#ifndef Gate_h
#define Gate_h

#include "Arduino.h"

#include <math.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <ESP8266WiFi.h>

class Gate {
  public:
    void Magnet(int magnetPin);
    void LEDStrip(int r, int g, int b);
    
    void OTAStart(const char OTAPassword[]);
    void WiFiStart(char WiFiNetwork[], char WiFiPassword[]);
    void begin(int pin1, int pin2, int pin3, int pin4){
    
    void gate(int Direction);
    void stop();
    void magnet(int magnetValue);
    void ledStrip(int red, int green, int blue);
    float calcDist(float CurrentLatitude, float CurrentLongitude, float SavedLatitude, float SavedLongitude);
    void waitForGate(int travelDist, int travelSpeed, int percentOfTravel);
    void delayForGate(int DFGTime);

    void WFGFunction();
    
    int direction;
    boolean emergencyStop = false;
  private:
    int _pin1;
    int _pin2;
    int _pin3;
    int _pin4;
    int _magPin;
    int _r;
    int _g;
    int _b;
    char _OTAPassword;
    String _WiFiSSID;
    String _WiFiPASS;
    int _Direction;
    int _magnetValue;
    int _red;
    int _green;
    int _blue;
    float _CurrentLatitude;
    float _CurrentLongitude;
    float _SavedLatitude;
    float _SavedLongitude;
    int _travelDist;
    int _travelSpeed;
    int _percentOfTravel;
    int _DFGTime;
    
    int _wfg;
    int _totalDelay;
};

#endif

Gate.cpp:

/*
  Gate.cpp - Library for controlling gates.
  Created by K Gray, December 26, 2021.
  Released into the public domain.
*/

#include "Arduino.h"
#include "Gate.h"

Gate::Gate();

void Gate::Magnet(int magnetPin){
  pinMode(magnetPin, OUTPUT);
  _magPin = magnetPin;
}

void Gate::LEDStrip(int r, int g, int b){
  pinMode(r, OUTPUT);
  pinMode(g, OUTPUT);
  pinMode(b, OUTPUT);
  _r = r;
  _g = g;
  _b = b;
}

void Gate::OTAStart(const char OTAPassword[]){
  // Port defaults to 8266
  ArduinoOTA.setPort(8266);
  // Hostname defaults to esp8266-[ChipID]
  ArduinoOTA.setHostname("GateESP");
  // No authentication by default
  ArduinoOTA.setPassword(OTAPassword);//(const char 

  ArduinoOTA.onStart([]() {
    Serial.println("Start");
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  ArduinoOTA.begin();
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void Gate::WiFiStart(char WiFiNetwork[], char WiFiPassword[]){
  WiFi.mode(WIFI_STA);
  WiFi.begin(WiFiNetwork, WiFiPassword);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }
}

void Gate::begin(int pin1, int pin2, int pin3, int pin4){
  pinMode(pin1, OUTPUT);
  pinMode(pin2, OUTPUT);
  pinMode(pin3, OUTPUT);
  pinMode(pin4, OUTPUT);
  _pin1 = pin1;
  _pin2 = pin2;
  _pin3 = pin3;
  _pin4 = pin4;
}

void Gate::gate(int Direction){
  if (direction == 1){
    if (Direction == 1){
      digitalWrite(_pin1, HIGH);
      digitalWrite(_pin2, LOW);
      digitalWrite(_pin3, HIGH);
      digitalWrite(_pin4, LOW);
    }
    if (Direction == 2){
      digitalWrite(_pin1, LOW);
      digitalWrite(_pin2, HIGH);
      digitalWrite(_pin3, LOW);
      digitalWrite(_pin4, HIGH);
    }
  }
  else if (direction == 2){
    if (Direction == 1){
      digitalWrite(_pin1, LOW);
      digitalWrite(_pin2, HIGH);
      digitalWrite(_pin3, LOW);
      digitalWrite(_pin4, HIGH);
    }
    if (Direction == 2){
      digitalWrite(_pin1, HIGH);
      digitalWrite(_pin2, LOW);
      digitalWrite(_pin3, HIGH);
      digitalWrite(_pin4, LOW);
    }
  }
}

void Gate::stop(){
  digitalWrite(_pin1, LOW);
  digitalWrite(_pin2, LOW);
  digitalWrite(_pin3, LOW);
  digitalWrite(_pin4, LOW);
}

void Gate::magnet(int magnetValue){
  digitalWrite(_magPin, magnetValue);
}

void Gate::ledStrip(int red, int green, int blue){
  analogWrite(red, _r);
  analogWrite(green, _g);
  analogWrite(blue, _b);
}

float Gate::calcDist(float CurrentLatitude, float CurrentLongitude, float SavedLatitude, float SavedLongitude){
  // HaverSine version
  const float Deg2Rad = 0.01745329252;               // (PI/180)  0.017453293, 0.0174532925
  //const double EarthRadius = 6372.795;              //6372.7976 In Kilo meters, will scale to other values
  const float EarthRadius = 20908120.1;              // In feet  20908128.6
  float DeltaLatitude, DeltaLongitude, a, Distance;

  // degrees to radians
  CurrentLatitude = (CurrentLatitude + 180) * Deg2Rad;     // Remove negative offset (0-360), convert to RADS
  CurrentLongitude = (CurrentLongitude + 180) * Deg2Rad;
  SavedLatitude = (SavedLatitude + 180) * Deg2Rad;
  SavedLongitude = (SavedLongitude + 180) * Deg2Rad;

  DeltaLatitude = SavedLatitude - CurrentLatitude;
  DeltaLongitude = SavedLongitude - CurrentLongitude;

  a =(sin(DeltaLatitude/2) * sin(DeltaLatitude/2)) + cos(CurrentLatitude) * cos(SavedLatitude) * (sin(DeltaLongitude/2) * sin(DeltaLongitude/2));
  Distance = EarthRadius * (2 * atan2(sqrt(a),sqrt(1-a)));
  return(Distance);
}



void waitForGate(int travelDist, int travelSpeed, int percentOfTravel){
  int _totalDelay = ((((travelDist*percentOfTravel)/travelSpeed)*1000)-500)/2;
  int _wfg;
  Begin:
  _wfg++;
  while(_wfg <= _totalDelay){
    void WFGFunction();
    goto Begin;
  }
  _wfg = 0;
}

void Gate::delayForGate(int DFGTime){
  delay(DFGTime);
}

void WFGFunction(){}

Example1_Gate.ino:

#include <Gate.h>

Gate myGate();

#define direction = 1;

void setup(){
  myGate.WiFiStart("MYSSID", "MYPASS");
  myGate.begin(D3,D4,D7,D8);
  myGate.Magnet(D5);
  myGate.LEDStrip(D1, D2, D6);
}

void loop(){
  myGate.gate(1);
  myGate.waitForGate(12,0.4,0.8);
  myGate.stop();
  myGate.delayForGate(5000);
  myGate.gate(2);
  myGate.waitForGate(12,0.4,0.8);
  myGate.stop();
  myGate.delayForGate(5000);
}

Yea, but you're the one asking for free help. So, you should make it easy for those that might provide that help.

I do lots of multi-tab projects and I am attaching an ESP32 that is somewhat busy. Maybe you will see something in how it is setup.

ESP32_HSPI_ILI9341.zip (324.7 KB)