1

I am creating a project using PlatformIO and a Nodemcuv2 micro-controller.

I have written a class for serial communication SerialCommunicationHandler. This class ICommunicationHandler implements a Interface. See the code below.

ICommunicationHandler.h

class ICommunicationHandler {
public:
    virtual void sendTemperature(float temp) = 0;
    virtual void receiveData() = 0;
    virtual void update() = 0;

protected:
    virtual void parseData() = 0;
    virtual void showParsedData() = 0;
};

SerialCommunicationHandler

headerfile

#include "ICommunicationHandler.h"
class SerialCommunicationHandler : public ICommunicationHandler {
private:
//atributes needed for storing and modifying incoming data.

    static char incomingData[6]; //char array to temporarily store incoming data.
    static char receivedData[6]; //char array to copy incoming data to.
    static unsigned int messagePosition; //index of the incomingData array.

    bool receiving;
    bool newData;
    void parseData() override;
    void receiveData() override;
    void showParsedData() override;

public:
    explicit SerialCommunicationHandler();
    void sendTemperature(float temp) override;
    void update() override;
};

.cpp

#include <Arduino.h>
#include "SerialCommunicationHandler.h"

SerialCommunicationHandler::SerialCommunicationHandler() {
    messagePosition = 0;
    receiving = false;
    newData = false;
}

void SerialCommunicationHandler::receiveData() {
    //check if there are bytes in the serial buffer.
    while (Serial.available() > 0){
        char inByte = Serial.read();
        //check if the byte is a starting or ending character;
        switch (inByte) {
            case '<':
                //start receiving characters
                receiving = true;
                break;
            case '>':
                //stop receiving and parse the incoming data.
                receiving = false;
                newData = true;
                strcpy(receivedData, incomingData); //copy incoming data into receivedData for further parsing.
                memset(incomingData, 0, sizeof(incomingData)); //resetting incomingData.
                messagePosition = 0;
                break;
            default:
                if (receiving) {
                    incomingData[messagePosition] = inByte; //add incoming byte to array.
                    messagePosition++;
                }
                break;
        }
    }
}

void SerialCommunicationHandler::parseData() {
    if (newData) {
        showParsedData();
    }
    newData = false;
}

void SerialCommunicationHandler::showParsedData() {
    Serial.println(receivedData);
}

void SerialCommunicationHandler::sendTemperature(float temp) {
    Serial.println(temp);
}

void SerialCommunicationHandler::update() {
    receiveData();
    parseData();
}

When building I get multiple undefined refernce errors:

*/ld.exe: .pio\build\nodemcuv2\src\SerialCommunicationHandler.cpp.o:(.text._ZN26SerialCommunicationHandler14s
howParsedDataEv+0x0): undefined reference to `_ZN26SerialCommunicationHandler12receivedDataE`
*/ld.exe: .pio\build\nodemcuv2\src\SerialCommunicationHandler.cpp.o:(.text._ZN26SerialCommunicationHandlerC2E
v+0x4): undefined reference to `_ZN26SerialCommunicationHandler15messagePositionE'
*/ld.exe: .pio\build\nodemcuv2\src\SerialCommunicationHandler.cpp.o:(.text._ZN26SerialCommunicationHandler11r
eceiveDataEv+0x0): undefined reference to `_ZN26SerialCommunicationHandler12incomingDataE'

collect2.exe: error: ld returned 1 exit status
*** [.pio\build\nodemcuv2\firmware.elf] Error 1

I have checked my code multiple times for syntax errors or misspelling but have found nothing. My IDE doesnt bring up any errors as well. Any information on what might be causing the undefined reference error is welcome.

TortleTurtle
  • 23
  • 1
  • 9

1 Answers1

1

headerfile

#include "ICommunicationHandler.h"

class SerialCommunicationHandler : public ICommunicationHandler {
private:
//atributes needed for storing and modifying incoming data.
static char incomingData[6]; //char array to temporarily store incoming data.
static char receivedData[6]; //char array to copy incoming data to.
static unsigned int messagePosition; //index of the incomingData array.
   // ... etc

These are only declarations of the static member variables. You also have to define them in the cpp file, just like you do with the member functions:

.cpp file:

void SerialCommunicationHandler::showParsedData() {
    Serial.println(receivedData);
}

// static data members
char SerialCommunicationHandler::incomingData[6] = {};
char SerialCommunicationHandler::receivedData[6] = {};
unsigned int SerialCommunicationHandler::messagePosition = 0;
BoP
  • 2,310
  • 1
  • 15
  • 24
  • `messagePosition` is being declared in the constructor of `SerialCommunicationHandler`. The two char arrays are being initialised in the 'recieveData()`. All three variables are not being used before being initialised. I tried declaring everything in the constructor but this doesn't help. In case I misunderstood can you provide an example? – TortleTurtle Feb 14 '22 at 13:17
  • Static members exist even before creating the first class object, so initializing them in the constructor is not what is intended. They have to be defined separately in the .cpp file. I added an example of that to my answer. Alse see [Definition or declaration](https://stackoverflow.com/questions/1410563/what-is-the-difference-between-a-definition-and-a-declaration/1410632#1410632) – BoP Feb 14 '22 at 14:39