PlatformIO Community

<artificial>:...: undefined reference to `...'

Hello,

I am a inexperienced programmer and I am facing a problem on PIO.

What can I do to solve the following error:
:(.text.startup+0x2fe): undefined reference to `timerState’

Like I said, I am a beginner, tell me what you need to help me.

So I will be happy to receive as much advice as possible.

Appreciate your help,
Cyril

The compiler says the definition of that variable or function was not found.

For anything more we’d need to see the code + platformio.ini.

Thank you for your answer.

First the platformio.ini:

Then the error:

Processing Arduino mega 2560 (board: megaatmega2560; platform: atmelavr; framework: arduino)
----------------------------------------------------------------------------------------Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelavr/megaatmega2560.html
PLATFORM: Atmel AVR (3.4.0) > Arduino Mega or Mega 2560 ATmega2560 (Mega 2560)
HARDWARE: ATMEGA2560 16MHz, 8KB RAM, 248KB Flash
DEBUG: Current (avr-stub) On-board (avr-stub, simavr)
PACKAGES:
 - framework-arduino-avr 5.1.0
 - toolchain-atmelavr 1.70300.191015 (7.3.0)
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 12 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <LiquidCrystal> 1.0.7
|-- <Adafruit BusIO> 1.8.2
|   |-- <Wire> 1.0
|   |-- <SPI> 1.0
|-- <Adafruit MCP9600 Library> 1.1.2
|   |-- <Adafruit BusIO> 1.8.2
|   |   |-- <Wire> 1.0
|   |   |-- <SPI> 1.0
|   |-- <Wire> 1.0
|   |-- <SPI> 1.0
|-- <Button>
|-- <PressureControl>
|-- <TemperatureControl>
|-- <LaminatorTimer>
|-- <Wire> 1.0
Building in release mode
Compiling .pio\build\Arduino mega 2560\src\buttonsState.cpp.o
Compiling .pio\build\Arduino mega 2560\src\laminationProcess.cpp.o

[...]

Compiling .pio\build\Arduino mega 2560\FrameworkArduino\wiring_shift.c.o
Archiving .pio\build\Arduino mega 2560\libFrameworkArduino.a
Linking .pio\build\Arduino mega 2560\firmware.elf
C:\Users\bothr\AppData\Local\Temp\cca5HHcC.ltrans0.ltrans.o: In function `main':
<artificial>:(.text.startup+0x2d0): undefined reference to `processState'
<artificial>:(.text.startup+0x2d4): undefined reference to `processState'
<artificial>:(.text.startup+0x2d8): undefined reference to `timerState'
<artificial>:(.text.startup+0x35a): undefined reference to `processStates()'
<artificial>:(.text.startup+0x360): undefined reference to `processState'
<artificial>:(.text.startup+0x364): undefined reference to `processState'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\Arduino mega 2560\firmware.elf] Error 1
============================== [FAILED] Took 7.66 seconds ==============================

And the code. My code is made of the main and several sub-function:

The main.ccp:

// Sub-functions

#include <headers.hpp>

#include <laminationProcess.hpp>

#include <processStates.hpp>


void setup() {

  // set up the LCD's number of columns and rows:

  lcd.begin(20, 4);

  buttonsInit();

  processInit();

  bottomChamberTemperature.init();

  topChamberPressure.init();

  bottomChamberPressure.init();

}

void loop() {

  // check the buttons status

  buttonsRun();

  // Process statement 

  processStates();

 

  // Process definition

  laminationProcess ();

  bottomChamberTemperature.run();

  topChamberPressure.run();

  bottomChamberPressure.run();

}

processStates.hpp:

#ifndef _H_PROCESS

#define _H_PROCESS

// #include <librairies.hpp>

#include <Arduino.h>

//int state;

extern String statusName;

extern int remaningTime;

extern int nextStepTime;

void processInit();

void processStates();

#endif

processStates.cpp:

#include <processStates.hpp>

#include <processParameters.hpp>

#include <laminationProcess.hpp>

#include <headers.hpp>

#include <laminatorLCD.hpp>

void processInit() {

  processState = 1;

  timerState = 0;

}

void procesStates() {

  if (processState == 1) {

    statusName = "preheating";

    

    if (bottomChamberTemperature.readTemperature() >= processTemp) {

      lcdPrint(6);

    }    

    else {

      lcdPrint(4);

    }

    if (startButton.state == HIGH) {

      if(bottomChamberPressure.test() == 1) {

        processState = 2;

      }

      else if (bottomChamberPressure.test() == 0) {

        lcdPrint(8);

      }

    }

  }

  

  if (processState == 2) {

    statusName = "gluing";

    lcdPrint(5);

    if (bottomChamberPressure.readPressure() <= gluingPressure) {

      processState = 3;

    }

  }

  if (processState == 3) {

    statusName = "post gluing";

    if (bottomChamberPressure.readPressure() >= 0) {

      processState = 4;

    }

  }

  if (processState == 4) {

    statusName = "air vacuuming";

    lcdPrint(1);

    if (bottomChamberPressure.readPressure() <= vacuumPressure && timerState == 0) {

      time0 = millis();

      timerState = 1;

    }

    

    if (millis() >= time0 + vacuumDelay * 1000 * 60) {

      processState = 5;

      topChamberPressure.setInitialTime((millis() - time0) * 1000);

      timerState = 0;

    }

    nextStepTime = vacuumDelay - (millis() - time0) * 1000 * 60;

  }

  if (processState == 5) {

    statusName = "lamination 1/3";

    lcdPrint(1);

    if (timerState == 0) {

      time1 = millis();

      timerState = 1;

    }

    if (millis() >= time1 + push1Delay * 1000 * 60) {

      processState = 6;

      topChamberPressure.setInitialTime((millis() - time0) * 1000);

      timerState = 0;

    }

    nextStepTime = push1Delay - (millis() - time1) * 1000 * 60;

  }

  if (processState == 6) {

    statusName = "lamination 2/3";

    lcdPrint(1);

    if (timerState == 0) {

      time2 = millis();

      timerState = 1;

    }

    if (millis() >= time2 + push2Delay * 1000 * 60) {

      processState = 7;

      topChamberPressure.setInitialTime((millis() - time0) * 1000);

      timerState = 0;

    }

    nextStepTime = push2Delay - (millis()-time2) * 1000 * 60;

  }

  if (processState == 7) {

    statusName = "lamination 3/3";

    lcdPrint(1);

    if (timerState == 0) {

      time3 = millis();

      timerState = 1;

    }

    if (millis() >= time3 + push3Delay * 1000 * 60) {

      processState = 8;

      topChamberPressure.setInitialTime((millis() - time0) * 1000);

      timerState = 0;

    }

    nextStepTime = push3Delay - (millis() - time3) * 1000 * 60;

  }

  if (processState == 8) {

    statusName = "back to atmo. pressure";

    if (bottomChamberPressure.readPressure() >= 0) {

      processState = 1;

    }

  }

  remaningTime = vacuumDelay + push1Delay + push2Delay + push3Delay - (millis() - time0) * 1000 * 60;

}

headers.hpp:

#ifndef _H_HEADERS

#define _H_HEADERS

#include <arduinoPins.hpp>

#include <TemperatureControl.hpp>

#include <PressureControl.hpp>

#include <Button.hpp>

#include <Arduino.h>

#include <LiquidCrystal.h>

#include <buttonsState.hpp>

#include <laminatorLCD.hpp>

// Define I2C address

const int i2c_temp_mat = 0x67;

extern unsigned long time0;  // value of millis() when the vacuum is reach for the first time

extern unsigned long time1;  // value of millis() when the firt push start

extern unsigned long time2;  // value of millis() when the second push start

extern unsigned long time3;  // value of millis() when the third push start

extern bool timerState;

extern int processState;

// initialize the library by associating any needed LCD interface pin

// with the Arduino pin number it is connected to

const int rs = 11, en = 12, d4 = 2, d5 = 3, d6 = 4, d7 = 5; // ATTENTION !!! CES VALEURS LA CORESPONDENT A L'ARDUINO UNO

static LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

static TemperatureControl bottomChamberTemperature(HEATER_PIN, TEMPERATURE_PIN);

static PressureControl topChamberPressure(VACUUM_TOP_PIN, ATMOSPHERIC_TOP_PIN, PRESSURE_TOP_PIN);

static PressureControl bottomChamberPressure(VACUUM_BOTTOM_PIN, ATMOSPHERIC_BOTTOM_PIN, PRESSURE_BOTTOM_PIN);

static Button startButton(START_BUTTON_PIN, START_LED_PIN);

static Button stopButton(STOP_BUTTON_PIN, STOP_LED_PIN);

static Button parametersButton(PARAMETERS_BUTTON_PIN);

#endif

Tell me if anything is missing.

Declaring static variables in a header is not good. Every .c/.cpp file that includes this header will have its own variable instantiated like this, and they won’t be the same accross files, since static means “limit scope to this compilation unit”. It should said extern LiquidCrystal lcd; here in the header with LiquidCrystal lcd(rs, en, d4, d5, d6, d7); being placed in a .cpp file.

So if we look at that variable

It’s declared in the header file, but in no .c/.cpp file there is

int processState;

or

int processState = <some initial value>;

So the variable is just declared to exist with an extern declaration, but is not actually defined. Hence “undefined referenced”.

They way you create and share global variables in the code is wrong, as said above. Make sure the headers only have an extern declaration (and not static), and make sure one .cpp file defines that variable (must not have an extern declaration when defining).

See e.g. related topic Tutorial for creating multi cpp file arduino project - #19 by peekpt

Ok, I will add [quote]int processState;[/quote] and [quote]bool timerState;[/quote] in processStates.cpp:

But I have 2 questions:

1)Will I keep the processState and timerState values or will they be reset each time the program executes processStates ()?

2)Why I don’t have the same error with tim0, time1, time2 and time3?

They’re global variables, their values only change when explicitly modified with an assignment statement. Until then they stay the same. There’s no “auto-reset to 0” after a function is executed or something.

Either the compiler is early-exiting after seeing the errors or you do have unsigned long time0; in some header file that you’ve not shown.

are all files not shown.

Thank you for the information.

I double checked, those variables are only in the files I shared.
Anyway, I know how to solve this problem if it happen again.

Last thing now, about the <artificial>:(.text.startup+0x35a): undefined reference to `processStates().
Why this void is undefined?

Because you called the implementation procesStates() instead of processStates().

This is also probably why the time0 errors etc didn’t show up. Since you’re not calling into procesStates() it doesn’t access those variables and thus the linker doesn’t need them and doesn’t throw an error.

If you call the function implementation by the correct name, the errors should start appearing.

Shame on me…

Thank your Max, you are the best!