5 years, 4 months 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.

5 Answers

5 years ago.

Hi,

Did you resolve your issue? Because I have the same problem with STM32L072CZ board

5 years, 3 months ago.

Hi, I have the same problem. Did you solved the problem?

Thank you

I have found some issues since I did a recent MBED OS2 update, I could no longer read more than one sensor. Revert back to a 2016 version and works fine. Looks like there are some timing issues, RTC also has a problem now.

posted by Paul Staron 18 Jan 2019

Thank you Paul. I'm sorry, when you say MBED OS2, you mean MBED OS 5.2 ? https://github.com/ARMmbed/mbed-os/releases/tag/mbed-os-5.2.0

Thanks

posted by Enrico Verz 18 Jan 2019

No, the classic OS2 libraries here:

https://os.mbed.com/users/mbed_official/code/mbed-dev/

posted by Paul Staron 18 Jan 2019

I have had a bit of a result, try this MBED-DEV version:

https://os.mbed.com/users/maxxir/code/mbed-dev/

I have my sensors back and RTC working.

posted by Paul Staron 18 Jan 2019

OK, Thank you again Paul. I'm sorry but i'm having trouble to use this version of MBED-dev. The online version of MBED get stuck when i try to import this library to a new empty project.

Then i tryed using mbed-cli on my linux machine: mbed new empty3 mbedlib force-mbed2-tools mbed add http://os.mbed.com/users/mbed_official/code/mbed-dev/ mbed add http://os.mbed.com/users/Sissors/code/DS1820/

Then I add a simple main.cpp file

mbed compile -t GCC_ARM -m DISCO_L072CZ_LRWAN1

The copilation get stuck on a python error : "in find_build_profile if MBED_SDK_REV_MAP.has_key(build): AttributeError: 'dict' object has no attribute 'has_key' "

Could you suggest me the right way to do that?

Thank you for your time

posted by Enrico Verz 19 Jan 2019

I should have found the correct way to apply the mbed-dev: $mbed import http://os.mbed.com/users/hudakz/code/DS1820_Hello/ $mbed remove mbed $mbed add http://os.mbed.com/users/maxxir/code/mbed-dev/ $mbed compile -t GCC_ARM -m DISCO_L072CZ_LRWAN1 flash

But unfortunately the board still do not found the DS1820 sensor.. Any suggestion?

posted by Enrico Verz 19 Jan 2019
4 years, 10 months ago.

Hello,

have you resolved this problem for DISCO-L072CZ-LRWAN1? Because I have same situation with the latest DS1820 library and latest mbed-os release (5.12.4). I'm trying same code on DISCO-STM32F769I and it works. Any suggestions?

5 years, 4 months 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
5 years, 4 months 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

I have modified the OneWire library to make it less dependent on the speed of used MCU. The right moment for bit sampling is now calculated based on the time needed to change the GPIO from output to input:

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

    wire.output();
    wire = 0;
    timer.start();
    wire.input();   // the time this takes depends on the used MCU
    wait_us(12 - timer.read_us());  // wait the time remaining to 12us
    r = wire.read();
    timer.stop();
    timer.reset();
    wait_us(54);
    return r;
}
posted by Zoltan Hudak 20 Jan 2019

I have tried your suggestion but it is still not working...it keep returning "No sensor found". Have you tried on a board like mine? It is from L0 STM series. I have tried with another one of the same series and the problem still remains.

posted by Marco Zecchini 07 Mar 2019