DS18B20 Address as string -> convert to hex so usable as address

Hi

This has probably been asked many times, but I have had no luck finding as answer to my problem in all the discussions I have read (which I’ve been doing most of today…).

My scenario is:
Ethernet enabled arduino that is sent a message containing a list of addresses (delimited by !) from an initiating database program. Arduino then needs to parse the string is receives, read the temperature from the DS18B20 that corresponds to the address parsed, then build up a string of temps and addresses to return to the database program so it can review and store them. The string may be 1 address, or up to 10.

I have the comms part working, although some will probably ask why the received message is going to a string not a char array. The simplest and most honest answer to that is my experience in C amounts to not too much more than the code below… I can’t seem to get it to work doing that way. I had sucess with the string route.

Be that as it may (happy for pointers on that…) my problem is I have the address as a string, but when I get to the “DeviceAddress device ={ addy }” line, of course it won’t compile as addy is a string. I can’t seem to find any way to convert this to, what I’m guessing is an unsigned long hex integer, and then have that work as an address.

My code (in full) is

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

// Data wire is plugged into pin 3 on the Arduino
#define ONE_WIRE_BUS 3

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
DeviceAddress device;

// Enter a MAC address and IP address for your controller below.

byte mac = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(10,81,134, 35);

int q = 0;
String readString;
String addy = “”;
unsigned long addr;
float tempC = 150;
unsigned long w;

EthernetServer server(7001);
boolean alreadyConnected = false; // whether or not the client was connected previously

void setup() {
// initialize the ethernet device
Ethernet.begin(mac, ip);
// start listening for clients
server.begin();
// Open serial communications and wait for port to open:
Serial.begin(9600);
sensors.begin();
Serial.print("Server up - ");
Serial.println(Ethernet.localIP());
}

void loop() {
// wait for a new client:

EthernetClient client = server.available();

// OK Have one
if (client) {
while (client.available() > 0 ) {
char inChar = client.read();
readString += inChar;
}

client.flush();

client.println(“MessageReceived”);

Serial.println(“Reply sent”);

}

readAddy();

if(addy.length() > 0) {
client.println(addy);
Serial.println(addy);
addy = “”;
}
}

void readAddy(){
if (readString.length() > 0 ) {
addy = “”;
Serial.print("Hi: ");
Serial.println(readString);
q = q + 1;

for(int x = 1; x < readString.length(); x++){
if (readString.charAt(x) == ‘!’) { // ! signifies start of DS18B20 address in string received
for(int y = x + 1; y < x + 47; y++){ // so the next 46 chars are the address
addr += readString.charAt(y);
addy += readString.charAt(y);
}
const char* newAddy = addy.c_str();
DeviceAddress device = { strtoul(newAddy, 0 ,16) };
//addy should be 0x28, 0x2D, 0xF4, 0x21, 0x05, 0x00, 0x00, 0x91, but not seen as string…
sensors.setResolution(device, 12);
char addr[50];
sensors.requestTemperaturesByAddress(device);
float tempC = sensors.getTempC(device);
delay(1000);
Serial.print(tempC);
Serial.print(" from ");
Serial.println(newAddy);
x = x + 45;
}
}
Serial.println("Address: ");
Serial.println(tempC);
readString = “”;
}
}

Apologies for the long post, but this has been frustrating me mightily and I can’t seem to find the answer. It may be that I have found the answer, but not understood what I was seeing, given my, shall we say, not overwhelming experience in C.

Thanks in advnce

Moderator edit: Tags corrected. Please don’t use “Copy for forum” format.

Yes, you're heading the right route with

            DeviceAddress device =  { strtoul(newAddy, 0 ,16) };

However, there's a couple of things wrong.

  1. You already have device defined:
DeviceAddress device;

so you are creating and assigning a new device variable that only has scope within the

          if (readString.charAt(x) == '!') {  // ! signifies start of DS18B20 address in string received

block.

I don't know the format of the DeviceAddress struct, but surely you should just assign the results of the strtoul to the right member variable of the existing device?

Also, I would suggest lots of debugging. Inspect what you are passing to strtoul, and what it is returning.

Yes, you're heading the right route with

No, OP isn't.

The strtoul() function returns one long. The address is composed of 8 bytes.

majenko: I don't know the format of the DeviceAddress struct, but surely you should just assign the results of the strtoul to the right member variable of the existing device?

Ok, so you do it 8 times then. Use something like strtok() to break the string up, depending on its format?

I’d use sscanf().

uint8_t i;
int addrv[8];

        sscanf(newAddy, "%x,%x,%x,%x,%x,%x,%x,%x",
                &addrv[0], &addrv[1], &addrv[2], &addrv[3],
                &addrv[4], &addrv[5], &addrv[6], &addrv[7]);  // parse the 8 ascii hex bytes in 8 ints

        for(i = 0; i< 8; i++)
        {
                device[i] = (__typeof__(device[0])) addrv[i]; //fill in device address bytes using a cast
        }

Just make sure your newAddy string is null terminated after the 8th hex byte.

— bill

Thanks Bill.

Legend. Works like a bought one.

Hopefully I can scrape over the rest of the hurdles myself.

Now I just have to put the missing hair back in... ;-)

Thank you for trying to be helpful, but you need to use code tags.