have you ever looked at code for so long, an obvious bug evades you?

KrisKasprzak

Well-known member
I'm writing a small library for Thermistors. You pass in the measured resistance and it spits out a temp. The arduino compiler claims my definition of an array to hold constants is defined multiple times--I don't see it in my .h .cpp, .ino files.

Anything look wrong?


Code looks fine to me but I get a C:\Users\ADMINI~1\AppData\Local\Temp\arduino_build_860596\libraries\Thermistor\Thermistor.cpp.o:(.data.tc+0x0): multiple definition of `tc'
C:\Users\ADMINI~1\AppData\Local\Temp\arduino_build_860596\sketch\sketch_feb20a.ino.cpp.o:(.data.tc+0x0): first defined here
c:/program files (x86)/arduino/hardware/tools/arm/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/bin/ld.exe: Disabling relaxation: it will not work with multiple definitions
collect2.exe: error: ld returned 1 exit status
Error compiling for board Teensy 4.0.


.h file
Code:
/*


*/


#ifndef THERMISTOR_h
#define THERMISTOR_h

#if ARDUINO >= 100
	#include "Arduino.h"
#else
	#include "WProgram.h"
#endif


double tc[14][11] {
{1,2880,3,-9.094,2251.74,229098,-27448200,0.003354016,0.000349502,0.000002095959,0.0000004260615},
{2,2990,3,-10.2296,2887.62,132336,-25025100,0.003354016,0.000341556,0.000004955455,0.0000004364236},
{3,3041,3,-11.1334,3658.73,-102895,516652,0.003354016,0.000334929,0.000003683843,0.0000007050455},
{4,3136,3,-12.4493,4702.74,-402687,31968300,0.003354016,0.000324388,0.000002658012,-0.000000270156},
{5,3390,3,-12.6814,4391.97,-232807,15096430,0.003354016,0.000299341,0.000002135133,-0.000000005672},
{6,3528,0.5,-12.0596,3687.667,-7617.13,-5914730,0.003354016,0.000290967,0.000001632136,0.000000071922},
{6,3528,0.5,-21.0704,11903.95,-2504699,247033800,0.003354016,0.0002933908,0.000003494314,-0.000000771269},
{7,3560,1.5,-13.0723,4190.574,-47158.4,-11992560,0.003354016,0.0002884193,0.000004118032,0.000000178679},
{8,3740,2,-13.8973,4557.725,-98275,-7522357,0.003354016,0.0002744032,0.000003666944,0.0000001375492},
{9,3977,0.75,-14.6337,4791.842,-115334,-3730535,0.003354016,0.000256985,0.000002620131,0.00000006383091},
{10,4090,1.5,-15.5322,5229.973,-160451,-5414091,0.003354016,0.0002519107,0.000003510939,0.0000001105179},
{11,4190,1.5,-16.0349,5459.339,-191141,-3328322,0.003354016,0.0002460382,0.000003405377,0.000000103424},
{12,4370,2.5,-16.8717,5759.15,-194267,-6869149,0.003354016,0.000236772,0.00000358514,0.0000001255349},
{13,4570,1.5,-17.6439,6022.726,-203157,-7183526,0.003354016,0.0002264097,0.000003278184,0.0000001097628}
};



class Thermistor {

	public:

		Thermistor(double B25=3977);

		double getTempF(float Resistance);
		double getTempC(float Resistance);
		double getTempK(float Resistance);
		double getTempR(float Resistance);

		void setConstants(double ConstA1, double ConstB1, double ConstC1, double ConstD1);
		void setNominalResistance(double R1);
		void getConstants(double &ConstA1, double &ConstB1, double &ConstC1, double &ConstD1);

		private:
		void ComputeTemps(double Resistance);
		double consta1, constb1, constc1, constd1, tempk, tempc, tempf, tempr, r1;
		bool found;

};

#endif
. cpp file
Code:
/*

*/

#include "Thermistor.h"


Thermistor::Thermistor(double B25) {
	int i = 0;
	r1 = 10000.0;

	found = false;

	for (i = 0; i < 13; i++) {

		if (tc[i][1] == B25) {
			consta1 = tc[i][7];
			constb1 = tc[i][8];
			constc1 = tc[i][9];
			constd1 = tc[i][10];
			found = true;
		}

	}

}



double Thermistor::getTempF(float Resistance){

	ComputeTemps(Resistance);
	return tempf;

}
double Thermistor::getTempC(float Resistance){
	ComputeTemps(Resistance);
	return tempc;
}
double Thermistor::getTempK(float Resistance){
	ComputeTemps(Resistance);
	return tempk;
}
double Thermistor::getTempR(float Resistance){
	ComputeTemps(Resistance);
	return tempk;
}

void Thermistor::ComputeTemps(double Resistance){

	if (found) {
		tempk = 1.0 / (consta1 + (constb1 * (log(Resistance / r1))) + (constc1 * pow(log(Resistance / r1), 2)) + (constd1 * pow(log(Resistance / r1), 3)));
		tempc = tempk - 273.15;
		tempf = (tempc * 1.8f) + 32.0f;
		tempr = tempk;
	}
	else {
		// constants found report some error loooking temperature
		tempk = -999999.99;
		tempc = -999999.99;
		tempf = -999999.99;
		tempr = -999999.99;
	}

}
void  Thermistor::setConstants(double ConstA1, double ConstB1, double ConstC1, double ConstD1){
	consta1 = ConstA1;
	constb1 = ConstB1;
	constc1 = ConstC1;
	constd1 = ConstD1;
}

void  Thermistor::setNominalResistance(double R1){
	r1 = R1;
}


void  Thermistor::getConstants(double &ConstA1, double &ConstB1, double &ConstC1, double &ConstD1){
	ConstA1 = consta1;
	ConstB1 = constb1;
	ConstC1 = constc1;
	ConstD1 = constd1;
}


. ino file
Code:
#include "Thermistor.h"

int b = 0;
float volts = 0.0;
float rest = 0.0;
unsigned long t = 0;
unsigned long count;

Thermistor RoomTemp(3977);

void setup() {
  Serial.begin(115200);
  analogReadResolution(12);
}

void loop() {
  b = b + analogRead(A0);
  count ++;
  if ((millis() - t) > 500) {
    b = b / count;
    volts = (float) b / 4096.0;
    rest = ( volts * 10000) / (3.3f - volts);
    Serial.print("Room Temp ");
    //Serial.println(RoomTemp.getTempF(rest), 4);
    count = 0;
    b = 0;
    t = millis();
  }

}
 
You've declared an initialized (non-const) variable in a .h file, which gets used twice in the compilation, once for .cpp and once for .ino,
creating two copies of the thing.
The #ifndef guard can't stop this, you have to declare the thing extern in the .h and actually define it in the .cpp. Then
the linker will resolve the reference at link-time as only one compilation unit defines the variable in its object file.

I reckon .h file that's going to be shared shouldn't generate any code (other than inline functions or macros) or any data (other than const),
so its not creating anything that can be inconsistent or wrongly duplicate between separate compilation units that use it as an interface.
 
I move the array to the .cpp file and all works. I was sure I did it the original way in other libraries.

Thanks to all
 
you could also put that array in the class itself, rather than global scope, under private, since only your library accesses it
 
Back
Top