class member array duplicating between instances

I have a class which is passed an array (the address of Dallas temperature devices). The data from that array is then placed into a member array. In this example, I instantiate two instances of the class with two different arrays. I then find that when accessing or using the member arrays from both instances they are identical even though I have initialed the instances with different data. I can do a simple form of this in a single file and it works fine. But, since this is part of a very large measurement system I am building, I break things up into many files... and then I get the behavior I described above.

I have removed all unnecessary code and striped out all extra variables and methods to illustrate this while trying to provide a complete enough picture of the structure of the code.

Why are both of the m_OneWireAddress becoming the same data?
THANK YOU.

mysensors.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class iAllSensors
{
};

class AllSensors : public iAllSensors
{
protected:
    uint8_t     m_SensorPort;
];

template <size_t arraysize>
class AnalogSensor : public AllSensors
{
  protected:
   uint32_t m_DataArray[arraysize];

  public:
    // constructor
    AnalogSensor(uint8_t SensorPort)
    {
        this->m_SensorPort = SensorPort;
    }
};

template <size_t arraysize>
class OneWireSensor : public AnalogSensor<arraysize>
{
  public:
    DeviceAddress m_OneWireAddress;  
    //DeviceAddress is defined as: typedef uint8_t DeviceAddress[8];
    
    // constructor
    OneWireSensor (uint8_t SensorPort, uint8_t OneWireAddress[]) :
                AnalogSensor<arraysize>(SensorPort)
    {
        for(int i=0; i<8;i++)
        {
            m_OneWireAddress[i] = OneWireAddress[i];
        }
    }
};


mysensors.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "mysensors.h"

// forward declarations (initialized in create_sensors.cpp)

uint8_t ONBOARD_ADDRESS[8] =
        {
           0x28, 0x4C, 0x0B, 0x0E, 0x0E, 0x00, 0x00, 0x87
        };
OneWireSensor<ONBOARD_TEMPERATURE_SENSOR_ARRAYSIZE>
OneWireOnboardSensor(PIN_IN_ONE_WIRE, ONBOARD_ADDRESS);



uint8_t CHANNEL_2_ADDRESS[8] =
        {
           0x28, 0x95, 0x28, 0x49, 0xF6, 0xCD, 0x3C, 0x8D 
        };
OneWireSensor<CHANNEL_2_ARRAYSIZE> 
OneWireChannel2(PIN_IN_ONE_WIRE, CHANNEL_2_ADDRESS);


create_sensors.h
1
2
3
#include "mysensors.h"

void CreateSensors(void);


create_sensors.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "mysensors.h"
#include "create_sensors.h"

void CreateSensors(void)
{

    extern uint8_t ONBOARD_ADDRESS[8];
    OneWireSensor<ONBOARD_SENSOR_ARRAYSIZE> 
    OneWireOnboardSensor(PIN_IN_ONE_WIRE,ONBOARD_ADDRESS);


    extern uint8_t CHANNEL_2_ADDRESS[8];
    OneWireSensor<CHANNEL_2_ARRAYSIZE>
    OneWireChannel2(PIN_IN_ONE_WIRE, CHANNEL_2_ADDRESS);
}


initalize.h
 
void initialize (void);


initialize.cpp
1
2
3
4
5
6
7
8
9
10
11
#include "initialize.h"
#include "mysensors.h"
#include "create_sensors.h"

OneWire oneWire(PIN_IN_ONE_WIRE);
DallasTemperature OneWireBus(&oneWire);
OneWireBus.begin();

CreateSensors();



main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include "initialize.h"
#include "mysensors.h"

extern DallasTemperature OneWireBus;

extern DeviceAddress CHANNEL_2_ADDRESS, ONBOARD_ADDRESS;

void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    Serial.print("0x");
    if (deviceAddress[i] < 0x10)
      Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
    if (i < 7)
      Serial.print(", ");
  }
  Serial.println("");
}

void setup()
{
 initialize();
}


void loop()
{

printAddress(OneWireOnboardSensor.m_OneWireAddress);

printAddress(OneWireChannel2.m_OneWireAddress);

// BOTH OF THE ABOVE LINES PRINT THE ONBOARD_ADDRESS[8] data:
//           0x28, 0x4C, 0x0B, 0x0E, 0x0E, 0x00, 0x00, 0x87



Last edited on
And for clarity... the following, in one file, works just fine.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <Arduino.h>

#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 7
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature OneWireBus(&oneWire);


uint8_t ONBOARD_ADDRESS[] =
    {
        0x28, 0x4C, 0x0B, 0x0E, 0x0E, 0x00, 0x00, 0x87 
    };

uint8_t CHANNEL_2_ADDRESS[8] =
    {
        0x28, 0x95, 0x28, 0x49, 0xF6, 0xCD, 0x3C, 0x8D  
    };

class OneWireSensor
{
protected:
  DeviceAddress m_OneWireAddress;

public:
  OneWireSensor(uint8_t OneWireAddress[])
  {
    for (int i = 0; i < 8; i++)
    {
      m_OneWireAddress[i] = OneWireAddress[i];
    }
  }

  float GetTemp()
  {
    return (OneWireBus.getTempC(m_OneWireAddress));
  }
};

// create the instances
OneWireSensor OnboardSensor(ONBOARD_ADDRESS);

OneWireSensor Channel2Sensor(CHANNEL_2_ADDRESS);

void setup()
{
  OneWireBus.begin(); // start the one wire sensor library
  Serial.begin(115200);
}

void loop()
{
  OneWireBus.requestTemperatures();

  Serial.print("Onboard Temperature GetTemp: ");
  Serial.println(OnboardSensor.GetTemp());

  Serial.print("Channel2 Temperature GetTemp: ");
  Serial.println(Channel2Sensor.GetTemp());
  Serial.println();


// WITH THE SENSORS IN TWO VERY DIFFERENT TEMPERATURES, 
// THE ABOVE TWO PRINTS SHOW THE CORRECT, and different, DATA
  delay(500);
}



CreateSensors() does nothing. It create two local variables and dismiss them. The global variables with the same name are not affected.

The global variables will also be created and initialized. So it's hard to tell why they contain the same data.

the following, in one file, works just fine.
It's complete different. Why do you introduce template?
Coder777,
Thanks for your comments. To answer your question, the template is here as part of a much bigger program that involves lots of different sensors which require different methods to support their usage. As noted, I tried to get rid of as much code as possible while still illustrating the structure of the program.

I have the interface class so that I can step through all of the instances of the sensors using standard iterators such as for and while. Many of the sensor types are in an analog category and so they become daughters of the AnalogSensor category.

There are a LOT more variables passed to each constructor in reality than what I have shown in the examples above.

It seems you are saying I need to move the address array declarations out of the createSensors() routine and into a global space. I understand. I completely eliminated create_sensors.cpp and CreateSensors() (which was called by initialize and I failed to show that in the code above, but have since fixed that.). NOW I STILL HAVE THE SAME RESULTS WHERE THE PRINT OF THE ADDRESSES FOR BOTH INSTANCES SHOWS THE SAME ADDRESS. Any idea why?
Last edited on
It seems you are saying I need to move the address array declarations out of the createSensors() routine and into a global space. I understand.
Actually you did that already.
In mysensors.cpp: Line 9/10 and 13/14 are identically to those in create_sensors.cpp. Again: createSensors() has no effect.
Can you tell the difference between local and global variables?

I would recommend to reduce the amount of global variables.
We're still not getting to the answer to the question of why do both instances of the sensor show the same data in m_OneWireAddress?
It's difficult to help without a real program to debug. If you could create a "minimal reproducible example" then it's more likely that someone will be able to help (you're also likely to find the problem yourself in the process).

https://en.wikipedia.org/wiki/Minimal_reproducible_example

The Arduino library limits the number of people who can actually run your code so if you manage to remove it from your "minimal reproducible example" then that would increase your chances of getting help (assuming it's not essential for reproducing the bug).
Last edited on
Line 7/9 in initialize.cpp. What is the purpose of this lines? They are not executed and shouldn't even compile.
Coder777: You are correct. This is a cut/paste error on my part. Those two lines were actually in the function initialize().

Peter87: Yes, indeed, a minimal reproducible example was my goal. I did strip the code down from several thousand lines (eliminating a lot of other stuff that worked as part of the larger project) and did a bit of restructuring and found it worked... Then I took that structure and re-factored (for lack of a better term) the original code. The test code still returned the same address for both instances of the one-wire sensors. After a lot of work, I finally cut the few lines of test code from my minimal example and pasted them into the refactored large code set. Low and behold, the correct data was printed. I cannot see any difference in the test code lines so I still have no idea what really "fixed" things which is a disappointing result after all this work as I was really hoping to understand the root cause. It is as if these lines of code were cached weirdly in the IDE as crazy as that sounds despite having cleaned the build many times, restarted the IDE, etc. Very frustrating, but the working code on the other hand is very pleasing as the extensibility and flexibility of the resulting code was well worth the time invested.

Thanks for your thoughts on this.
If I were to take a wild guess I'd say you ran afoul of the ODR.
https://en.cppreference.com/w/cpp/language/definition
https://eel.is/c++draft/basic.def.odr

It's just a hunch based on the symptom you described, plus the involvement of templates & the preprocessor in this and your prior thread.
Last edited on
Registered users can post here. Sign in or register to post.