Report
4 days, 7 hours ago.

Failure to read with temperature sensor DS18B20

Hi all, I am trying to read from the DS18B20 temperature sensor using this library: https://os.mbed.com/users/hudakz/code/DS1820/ .

/media/uploads/marcozecchini/schizzo.png

The picture above shows the main function but it doesn't work. The "begin()" function always returns false and the program terminates. This happens because the "search" function doesn't ends properly.

begin()

bool DS1820::begin(void) {
    oneWire.reset_search();
    wait_ms(250);
    if(!oneWire.search(addr)) {
#if DEBUG
        serial.printf("No addresses.\r\n");
#endif
        oneWire.reset_search();
        wait_ms(250);
        return false;
    }

#if DEBUG
    serial.printf("ROM =");
    for(uint8_t i = 0; i < 8; i++) {
        serial.printf(" %x", addr[i]);
    }
    serial.printf("\r\n");
#endif

    if(OneWire::crc8(addr, 7) == addr[7]) {
        present = true;

        // the first ROM byte indicates which chip
        switch(addr[0]) {
        case 0x10:
            model_s = true;
#if DEBUG
            serial.printf("DS18S20 or old DS1820\r\n");
#endif            
            break;

        case 0x28:
            model_s = false;
#if DEBUG
            serial.printf("DS18B20\r\n");
#endif            
            break;

        case 0x22:
            model_s = false;
#if DEBUG
            serial.printf("DS1822\r\n");
#endif            
            break;

        default:
            present = false;
#if DEBUG
            serial.printf("Device doesn't belong to the DS1820 family\r\n");
#endif            
            return false;
        }
        return true;
    }
    else {
#if DEBUG    
        serial.printf("Invalid CRC!\r\n");
#endif    
        return false;
    }
}

search()

uint8_t OneWire::search(uint8_t *newAddr)
{
   uint8_t id_bit_number;
   uint8_t last_zero, rom_byte_number, search_result;
   uint8_t id_bit, cmp_id_bit;

   unsigned char rom_byte_mask, search_direction;

   // initialize for search
   id_bit_number = 1;
   last_zero = 0;
   rom_byte_number = 0;
   rom_byte_mask = 1;
   search_result = 0;

   // if the last call was not the last one
   if (!LastDeviceFlag)
   {
      // 1-Wire reset
      if (!reset())
      {
         // reset the search
         LastDiscrepancy = 0;
         LastDeviceFlag = false;
         LastFamilyDiscrepancy = 0;
         return false;
      }

      // issue the search command
      write(0xF0);

      // loop to do the search
      do
      {
         // read a bit and its complement
         id_bit = read_bit();
         cmp_id_bit = read_bit();

         // check for no devices on 1-wire
         if ((id_bit == 1) && (cmp_id_bit == 1)){
            break;
            }
         else
         {
            
            // all devices coupled have 0 or 1
            if (id_bit != cmp_id_bit)
               search_direction = id_bit;  // bit write value for search
            else
            {
               // if this discrepancy if before the Last Discrepancy
               // on a previous next then pick the same as last time
               if (id_bit_number < LastDiscrepancy)
                  search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
               else
                  // if equal to last pick 1, if not then pick 0
                  search_direction = (id_bit_number == LastDiscrepancy);

               // if 0 was picked then record its position in LastZero
               if (search_direction == 0)
               {
                  last_zero = id_bit_number;

                  // check for Last discrepancy in family
                  if (last_zero < 9)
                     LastFamilyDiscrepancy = last_zero;
               }
            }

            // set or clear the bit in the ROM byte rom_byte_number
            // with mask rom_byte_mask
            if (search_direction == 1)
              ROM_NO[rom_byte_number] |= rom_byte_mask;
            else
              ROM_NO[rom_byte_number] &= ~rom_byte_mask;

            // serial number search direction write bit
            write_bit(search_direction);

            // increment the byte counter id_bit_number
            // and shift the mask rom_byte_mask
            id_bit_number++;
            rom_byte_mask <<= 1;

            // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
            if (rom_byte_mask == 0)
            {
                rom_byte_number++;
                rom_byte_mask = 1;
            }
         }
      }
      while(rom_byte_number < 8);  // loop until through all ROM bytes 0-7

      // if the search was successful then
      if (!(id_bit_number < 65))
      {
         // search successful so set LastDiscrepancy,LastDeviceFlag,search_result
         LastDiscrepancy = last_zero;

         // check for last device
         if (LastDiscrepancy == 0)
            LastDeviceFlag = true;

         search_result = true;
      }
   }

   // if no device found then reset counters so next 'search' will be like a first
   if (!search_result || !ROM_NO[0])
   {
      LastDiscrepancy = 0;
      LastDeviceFlag = false;
      LastFamilyDiscrepancy = 0;
      search_result = false;
   }
   for (int i = 0; i < 8; i++) newAddr[i] = ROM_NO[i];
   return search_result;
  }

Does someone have any suggestion and can help me to understand why it isn't working?

Question relating to:

The B-L072Z-LRWAN1 LoRa®Discovery kit is a development tool to learn and develop solutions based on LoRa®and FSK/OOK technologies.
Comment on this question

2 Answers

4 days, 3 hours ago.

You could try this library:

https://os.mbed.com/users/Sissors/code/DS1820/

I have 8 sensors working with no problems.

Thank you for the suggestion. Are you using the " DISCO-L072CZ-LRWAN1" board?

posted by Marco Zecchini 05 Dec 2018

No but it is ST (STM32L476) so in theory and hopefully it should work with your board, some of my sensors are on over 15meters of cable and does push RFI boundaries. I will say that there are many libraries for this 1 wire device, some work better than others. I would suggest to try a basic 'hello world' to confirm functionality first then implement in your program.

This applies to all attached devices, basic 'hello world' first on each device, then implementation. This procedure saved most of my hair :)

posted by Paul Staron 06 Dec 2018
4 days ago.

Hello Marco,

  • Make sure that a 4.7k Ohm resistor is connected between the DS1820's data pin and the +3.3V pin.
  • Unfortunately it takes several microseconds in MBED to change a GPIO from output to input. In addition that's MCU specific. So my suggestion is:
    Try to tune (increase/decrease) the time that OneWire is waiting for DS1820 to pull up/down the wire

OneWire.cpp

//...
uint8_t OneWire::read_bit(void)
{
    uint8_t r;

    wire.output();
    wire = 0;
    wire.input();  // To execute this takes several us. The actual delay depends on the speed of used MCU.
    wait_us(8);    // Try to tune this. Nnormally it would be about 13us but because of the delay due to 'wire.input()' it should be reduced.
    r = wire.read();
    wait_us(54);
    return r;
}
//...

I am trying to do in this way. Decreasing the delay to 4-5 us it seems to read something but it continues not finding the ds18b20 sensor. This is what it reads (I added some debug print):

0x0

0x1

0x0

0x1

0x0

0x1

0x1

0x0

0x1

0x1

No addresses. No DS1820 sensor found!

(The prints before "No addresses" are right after the wire.read() command in read_bit() function)

Do you have any other suggestion?

posted by Marco Zecchini 06 Dec 2018

I think you are very close to make it work. printf is a very complex routine, hence it takes long time to execute. That could introduce unwanted delays. I'd suggest to tune without debug prints, just change the delay by 1us at a time. Make sure you use external 4k7 resistor. The internal pull up resistor has much greater resistance and the voltage (after changing the GPIO from output to input) might increase at a rate which is slower than the one required by the one-wire protocol.

posted by Zoltan Hudak 06 Dec 2018

To post an answer, please log in.