Using requestTemperaturesByAddress with a byte array

Hi everyone,

When using DS18B20 sensors in the loop, I have seen that it is recommended (quicker) to use the device address:

float temp1 = sensors1.requestTemperaturesByAddress(&sensor1Add);

than to use

float temp1 = sensors1.getTempCByIndex(0);

In Setup I have stored the sensor addresses to a byte array using:

//<Global>
uint8_t sensor1Add[8];

//<Setup>
  while (sensors1.getAddress(sensor1Add, x)) {
    Serial.print(F("Temp sensor bus 1 "));
    Serial.print(x + 1);
    Serial.print(" : ");
    sensors1.getAddress(sensor1Add, x);
    for (int i = 0; i < 8; i++) {
      Serial.print(sensor1Add[i], HEX);
      Serial.print(" ");
    }
    Serial.println();

    x = x + 1;
  }

But I am not sure how to use that array with the requestTemperaturesByAddress command. All the examples I can find seem to use a hard-coded address which I'm trying to avoid. Do I have to loop through all of the elements of the byte array, or is it simpler than that?

I tried:
temp4 = sensors1.requestTemperaturesByAddress(sensor1Add);

But that doesn't work.

thanks,
Danny

Does your program work properly if you use a hard coded address as a test?
Move the address from your array to a variable and use the variable as if you were using a hrd coded address.
If failure, use serial.Print() the address to see what you actually are using for an address.

Good plan, but I'm not sure what you mean by use serial.Print(). Can you just use "Serial.print(sensor1Add)" for a DeviceAddress/byte array? I'm getting compiler errors:

no matching function for call to 'print(uint8_t [8])' Serial.print(sensor1Add);

Or do you mean loop through it to show each element of the address array?

My code for showing the hex address, and then creating a CRC16 from it is:

  int x = 0;

  // Sensor 1
  while (sensors1.getAddress(sensor1Add, x)) {
    Serial.print(F("Temp sensor bus 1 "));
    Serial.print(x + 1);
    Serial.print(" : ");
    sensors1.getAddress(sensor1Add, x);
    for (int i = 0; i < 8; i++) {
      Serial.print(sensor1Add[i], HEX);
      Serial.print(" ");
    }
    Serial.println();

    x = x + 1;
  }

  Serial.print(F("CRC 1 DEC:HEX = "));
  //  for (int i = 0; i < 3; i++) {
  crcValue1 = calculateCRC16(sensor1Add, 8);
  Serial.print(crcValue1, DEC);
  Serial.print(" : ");
  Serial.println(crcValue1, HEX);
  Serial.println();

Which outputs:

Temp sensor bus 1 1 : 28 B8 BF 96 F0 1 3C 24 
CRC 1 DEC:HEX = 46938 : B75A

Why?

So I can plug sensors in and it'll work rather than having to work out which sensors are where. If I need to swap a sensor out, I don't want to have to recompile.

Sure you get errors. you have to identify WHICH one of the array you want to print. Try printing the array entry you will be using to test your temperature sensor.

I'm not sure what you mean? The array "sensor1Add" contains one address as 8-byte array, so presumably I want to print all 8-bytes?

An array is made up of individual entries. In your case 8. They are numbered 0 thru 7. serial.Print(array(0)); will get you the first address. Do the same for the rest of your array. PLEASE spend some time working on arrays in C.

I'm aware of that - I posted the full array at the bottom of post #3. Your reply #6 confused me though. And I am spending time working on arrays in C - hence these questions!

Here's a multi DS18B20 pgm I wrote years ago to monitor my water heater elements via HC-12 radios. I use only the OneWire library but maybe some parts might help.

#include <OneWire.h>
OneWire  ds(7);  // on pin 7 (a 4.7K resistor is necessary)
#include <SoftwareSerial.h>
SoftwareSerial HC12(10,11); // RX, TX
#define debug // comment this line to disable data print to serial
unsigned long start;   // update timer
const int end = 15000; // update period in milliSeconds

byte data[12];
char txBuf[4];
const byte upper[8] = {0x28,0x14,0xCE,0x4D,0x05,0x00,0x00,0x51},
           lower[8] = {0x28,0xFF,0x4A,0x00,0x22,0x04,0x00,0xFC};
const char header[] = {"\nupper  lower"};

void setup()
{
  #ifdef debug
  Serial.begin(9600);
  Serial.println("\n" __FILE__"\n");
  Serial.println(header); // scroll break text
  #endif
  HC12.begin(9600);
}
void loop()
{
  if(millis() - start > end) // time to update
  {
    start += end;            // reset update timer
    int upperVal, lowerVal;
    static byte cntr = 0;    // scroll break counter
    for(byte url = 0;url < 2;url++) // url = upper or lower
    {
      ds.reset();
      if(url == 0)
        ds.select(upper); // which sensor to read
      else 
        ds.select(lower);     
      ds.write(0xBE);         // Read Scratchpad
      for ( byte i = 0; i < 9; i++)   // we need 9 bytes
        data[i] = ds.read();
      if(url == 0)
        upperVal = data[1] << 8 | data[0];
      else
        lowerVal = data[1] << 8 | data[0] + 12;
    }     
    ds.reset();
    ds.skip(); // skip address read
    ds.write(0x44); // start conversion for all sensors
    //val = antiDither(newVal);
    #ifdef debug
    if(++cntr >= 12) // scroll break lines
    {
      cntr = 0;
      Serial.println(header);
    }
    Serial.print(upperVal >> 4); // whole degrees
    Serial.print("_");
    Serial.print(upperVal >>1 & 0x0007,HEX); // 1/8 degree
    Serial.print("    ");
    Serial.print(lowerVal >> 4);
    Serial.print("_");
    Serial.println(lowerVal >>1 & 0x0007,HEX);
    #endif
    txBuf[0] = highByte(upperVal);
    txBuf[1] = lowByte(upperVal);
    txBuf[2] = highByte(lowerVal);
    txBuf[3] = lowByte(lowerVal);
    HC12.write(&txBuf[0],4);      // transmit data

  }

// do other programming here
//...
//......
//.........
}
/*
int antiDither(int newVal) // prevents +1 <-> -1 dither
{                       
  static int val = 0, oldVal = 0;
  if(newVal != val && newVal != oldVal)
  {
    oldVal = val;
    val = newVal;
  }
  return val;
}
*/

The address is 8 bytes long. In the DallasTemperature library it is defined as type DeviceAddress . You will need an array of device address - one for each sensor. You will then need to scan the devices to get the addresses. This will not tell you which device has which address since they are all on the same bus. The device addresses come back in scan order (usually in low to high order as a for loop is the usual scan method). See the Multiple example in the Dallas Temperature examples for some ideas.

I scan the sensors one at a time and put an external label them. Then I can know which sensor is at which location. You don't need the whole address on the external label - usually just the last few byte will be enough for uniqueness.

Thanks for this - I'll check it out :+1:

Thanks oldcurmudgeon. I've got each sensor on a different bus which I understand is a bit strange for a one-wire device, but the DS18B20 is cheap and readily available in a waterproof package whereas NTCs are a bit harder to come by. I think NTCs will be a better solution for me in the long run, but I want to learn how to get this working in the mean-time.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.