Can someone help me get my data from a pointer into my Struct?

I'm auto-detecting ds18b20 1-wire sensors which are plugged into my arduino.

Everything is working as I had hoped with 2 exceptions:

  1. I cannot get the sensor address from the pointer into the struct.
  2. During this process, I need to also convert the sensor address from the typical 0x00 0x00 type hex address into its 28-xxxxx type address so I can do some other stuff with it. I can't figure out how to write a function to do that.

Here's what I'm working with...(with comments in the code).

I'm a noob with C, so detailed answers are really helpful.

typedef struct {
  DeviceAddress addr;
  char name[8];
  float temp;
  float setpoint;
  int state;
  int act;
  int id;
} Sensor;

struct Node {
  Sensor *sensor;
  Node *next;
};
Node *list = nullptr;
char *cstring;


void discoverOneWireDevices(void) {
  uint8_t i;
  char buffer[4];
  DeviceAddress addr;
  Node *nodePtr;
  Sensor *sensorPtr;

  //Looking for 1 wire devices
  ds.reset_search();
  while (ds.search(addr)) {
    //Print what we found for reference.
    Serial.println("\n\rFound \'1-Wire\' device with address:");
    for (i = 0; i < 8; i++) {
      Serial.print("0x");
      if (addr[i] < 16) {
        Serial.print('0');
      }
      Serial.print(addr[i], HEX);
      if (i < 7) {
        Serial.print(", ");
      }
    }
    if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid, skipping!");
      continue;
    }

    //build my pointer
    sensorPtr = new Sensor;
    memcpy(sensorPtr->addr, addr, sizeof(DeviceAddress));
    //I have this to prove that I can override the preset temperature (45) below and I know that I'm putting data in the Struct
    sensorPtr->temp = 22.0;

    sensorPtr->id = finder;
    nodePtr = new Node;
    nodePtr->sensor = sensorPtr;
    nodePtr->next = list;
    list = nodePtr;
    finder++;
  }

  //My default Struct that will store my 5 sensors
  Sensor sensor_list[] = {
    { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, "Zone0", 45.00, 44.44, 0, 0, 0 },
    { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, "Zone1", 45.00, 44.44, 0, 0, 1 },
    { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, "Zone2", 45.00, 44.44, 0, 0, 2 },
    { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, "Zone3", 45.00, 44.44, 0, 0, 3 },
    { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, "Zone4", 45.00, 44.44, 0, 0, 4 }
  };

  Serial.println("Finished finding");

  //Put the sensors into the struct
  for (Node *node = list; node != nullptr; node = node->next) {
    int i = node->sensor->id;
    float newTemp = sensorPtr->temp;
    //my feeble attempts to get the the addresses into my struct
    //DeviceAddress addr = {node->sensor->addr};
    // sensor_list[i].addr = {node->sensor->addr};
    sensor_list[i].act = 1;
    sensor_list[i].temp = newTemp;
    // Serial.print("Address:");
    // Serial.println(sensor_list[i].addr);

    //This shows me that the act and temp changes even though the address doesn't work
    Serial.print("Active:");
    Serial.println(sensor_list[i].act);
    Serial.print("Starting Temp:");
    Serial.println(sensor_list[i].temp);
  }


}

mudmin:
I'm auto-detecting ds18b20 1-wire sensors which are plugged into my arduino.

 nodePtr = new Node;

if you are going to dynamically allocate here, you have to free (delete) that memory before the function returns...

why not just create global objects and copy the values into those objects?

You may want to check out the Arduino-Temperature-Control-Library

Also, I wrote a Wrapper Class for that library that you may find useful.

BulldogLowell:

 nodePtr = new Node;

if you are going to dynamically allocate here, you have to free (delete) that memory before the function returns...

why not just create global objects and copy the values into those objects?

I'm a total noob, like I said. I understand that there are other ways to do it, but if I can get that info from the pointer to my struct, everything else works as expected.

I can get the other pieces of info into the struct (as demonstrated at the bottom of the code)...just not the addresses.

Yes! The linked-list! Favorite of Computer Science professors everywhere and never actually used in the real world. Although you might get asked to implement a linked list as an exercise in a job interview. Please do not worry. Your future employer will never require you to actually use that knowledge.

On an Arduino with limited memory and no operating system, it's even more dangerous. If you are going to use up to 5 sensors in a particular program then just make an array with 5 elements. It may run away and consume all the memory on the Arduino if you don't take care with it.

Your use of memcpy() looks correct. You copy the 8 bytes of the address from one memory location to another. So why not do that same thing again later on?

You could also do...

for(int j=0; j<sizeof(DeviceAddress); j++) {
  sensor_list[i].addr[j] = node->sensor->addr[j];
}

I hope that makes it more obvious how you're copying the data between two locations.

and never actually used in the real world.

That is NOT true. I've written lots of code that actually uses linked lists. Doubly linked, usually, so they can be traversed in either direction.

MorganS:
Your use of memcpy() looks correct. You copy the 8 bytes of the address from one memory location to another. So why not do that same thing again later on?

You could also do...

for(int j=0; j<sizeof(DeviceAddress); j++) {

sensor_list[i].addr[j] = node->sensor->addr[j];
}




I hope that makes it more obvious how you're copying the data between two locations.

Thanks for providing actual code. I will give that a shot as soon as I get home to my arduino!

To explain what I'm doing and why I'm doing it that way.

  1. I'm great having a hard cap of 15 ds18b20 probes per arduino because arduinos are cheap and this allows my 16 bank of relays to control 15 zones and have 1 relay for my auto-reset feature that resets the arduino if it can't establish an MQTT connection for x number of minutes.

  2. I clearly don't know what I'm talking about but the pointers can be destroyed/unset whatever you call it after the Struct is populated to save memory. They're only used at boot.

  3. The pointer->struct thing is working great at the moment to give me an easily accessible set of data per sensor that I can loop through...address, setpoints, etc.

  4. Now as to why I'm really doing this...sensor data is pretty useless if you don't know where the sensor is located. Unfortunately for arduino, that means (usually) hard coding the address on the arduino for every single sensor...which means that if a sensor is added/replaced...you're updating the arduino itself wherever it's located.

  5. I'm wanting to convert the 0x00 address to the 28- address to take advantage of the fact that all of these sensors already have unique serial numbers. This means that if I bind the serial number in with the message that contains the temp data (I can list the sensor's location server side) which means I can swap sensors out at will in the field.

  6. Each arduino has a unique serial number that I'm giving it, so server side I can verify that the sensor id and arduino id are a matching pair and throw up red flags if something seems fishy.

  7. When a new sensor attempts to send data to the server, it gets sort of sandboxed in a queue where I can confirm the sensor's location etc and "approve" it.

Sooooooo....Am I thinking about this wrong?

The way I see it, the Struct gives me a nice, manageable list for storing data, but I literally don't care about the order because I have the serial number of the sensor.

gfvalvo:
You may want to check out the Arduino-Temperature-Control-Library

Also, I wrote a Wrapper Class for that library that you may find useful.

Thanks so much for this. I'll give it a whirl!

gfvalvo:
Also, I wrote a Wrapper Class for that library that you may find useful.

That wrapper is pretty impressive. I have an arduino with 5 probes on it that is ready to test. I'll give it a whirl when I get home. Thanks again!

mudmin:
I have an arduino with 5 probes on it that is ready to test. I'll give it a whirl when I get home. Thanks again!

Let me know how it goes. You didn’t say which Arduino you’re using, but I just confirmed that the included example compiles error-free for an Uno. So, try the example first. You just need to change the line:

const uint8_t ONE_WIRE_BUS = 2;

to whatever pin your sensors are using.

Of course, you need to install both the wrapper library and the Arduino-Temperature-Control-Library that I linked in Reply #2.

MorganS:
Yes! The linked-list! Favorite of Computer Science professors everywhere and never actually used in the real world. Although you might get asked to implement a linked list as an exercise in a job interview. Please do not worry. Your future employer will never require you to actually use that knowledge.

On an Arduino with limited memory and no operating system, it's even more dangerous. If you are going to use up to 5 sensors in a particular program then just make an array with 5 elements. It may run away and consume all the memory on the Arduino if you don't take care with it.

Your use of memcpy() looks correct. You copy the 8 bytes of the address from one memory location to another. So why not do that same thing again later on?

You could also do...

for(int j=0; j<sizeof(DeviceAddress); j++) {

sensor_list[i].addr[j] = node->sensor->addr[j];
}




I hope that makes it more obvious how you're copying the data between two locations.

Actually, I did use it quite successfully on a Burroughts Medium system main frame. The banking programs ran at night, 5 nights a week. The system spooled all the print lines to a sequential disk file. There were dozens of programs in many applications. I changed all the programs to send the print lines to a queue in memory. I wrote a program to take the lines from the queue and put them in a linked list file. Much more to the logic than I can quickly recall. Each report had an id and each print line had a sequential number.

When a report was complete programs could print, or create microfiche files or remote sites could see the report page on their terminal and print the screen on an attached printer.

All worked perfectly, except the ability to reuse space when a report was started over. Disk space was cheap, so just started over and left the bogus records.

This was back in the 1970's.

Paul

MorganS:
I hope that makes it more obvious how you're copying the data between two locations.

Morgan, thanks so much for your help. This is definitely getting me close. I'm doing this whole thing for a camp I'm working at and I'm wondering if there's any way that you'd be interested in doing a skype/google hangout to help me walk through a few of these things. I think someone who knows what they're talking about could talk me through a few of these concepts pretty quickly. I'd make a donation to you for your time.