Library 13- Reading temperature with Dallas DS18B20 on STM32F4

DS18B20In the last post, I show OneWire library. Today, I will use that library to show how to read temperature with Dallas’s temperature sensor DS18B20.

DS18B20 Features

  • 9 to 12 bits resolution
  • -55°C to 125°C Celsius
  • 64bit unique ROM number
  • Alarm temperatures enable or disable
  • Search devices with alarm flag set
  • Can be parasite-powered

Library

Features

  • Search sensors
  • Read temperature
  • Set resolution for each device
  • Start temperature conversion on all devices simultaneously
  • Set alarm low and high temperatures
  • Disable alarm temperatures
  • Search devices with alarm flag set
  • Data pin depends on Onewire library pin
  • Version 2.0 – January 04, 2015

Dependencies

  • CMSIS
    • STM32F4xx
    • STM32F4xx RCC
    • STM32F4xx GPIO
  • TM
    • TM ONEWIRE
    • TM DELAY
    • defines.h
Conversion time and least significant bit value for DS18B20
Resolution0 9bits 10bits 11bits 12bits
Conversion time 93.75ms 187.5ms 375ms 750ms
LSB 0.5°C 0.25°C 0.125°C 0.0625°C

Before we can start a temperature conversion, we have to know ROM code of DS18B20. If you don’t know it, then use search, that will do this for you. In example on the bottom, search for devices is included.

Start temperature conversion

You can start temperature conversion for specific sensor, or for all sensors simultaneously. Do this with

Reading temperature

Because DS18B20 needs some time (table on top) we can not immediately read temperature, if you try, you will not get correct value. If we know resolution od DS18B20 device, we can just put some delay after temperature conversions has started, or if you want to exactly know when it finished with conversion, you can use

When all devices finish with conversion, you are able to read data from them. To read temperature you have to know ROM address number. Read temperature with

Set/Get resolution

Every DS18B20 has it’s own resolution number from 9 to 12 bits. Higher resolution is, more time sensor needs to convert temperature. If you want to set resolution to DS18B20, you can do this with

You are also able to read resolution. Function will return 9 – 12 bits or 0 if device is not DS18B20.

Alarm high/low temperature

Every DS18B20 can trigger an alarm flag if temperature is greater than high temp, or lower than low temp. High and low temperatures are stored in DS18B20’s internal EEPROM. You can set temperatures with

Remember: You can only select integer numbers between -55 to 125°C. Also know, that these values are stored in EEPROM and are not deleted after power is down.

Disable alarm

If you don’t want to use alarm on specific device, you can disable it. To this with

Check alarm flag

If there are sensors with active alarm, we have somehow recognize devices that has set it. DS18B20 has specific command for search devices which have set alarm flag. You can search for ROM’s that have alarm set with

Functions and enumerations

Example

In example below I used two DS18B20 sensors connected to PD0 pin, with 4k7 pull up resistor.

Project available on Github, download library below.

Icon
TM STM32F4 DS18B20 Library

DS18B20 Temperature sensor library

tilz0R

Owner of this site. Also electronic enthusiasts, web developer, 3D printer fan, handball player and more. Big fan of STM32F4 devices. In anticipation of the new Discovery board for STM32F7 lines.

You may also like...

Read before commenting!

Before you make a new comment, make sure you agree with things listed below:

  • - Read post to make sure if it is already posted what you are asking for,
  • - Make sure you have the latest version of libraries used in your project,
  • - Make a clean and grammatically correct written message,
  • - Report as many details as possible, including what have you done so far,
  • - Do NOT post any code here. Use Pastebin,
  • - Do NOT post any error codes here. Use Pastebin,
  • - Specify STM32Fxxx family and used Discovery/EVAL/Nucleo or custom made board,
  • - Make sure your clock is set correct for PLL,
  • - If you are using my HAL drivers, please check this post how to start.
Comment will be deleted on breaking these rules without notification!
  • JoergSH

    Hey very nice site and good documented samples!
    Thanks a lot for that!!!!

    Joerg

  • Alessandro Luciani

    Hi..thanks for the example but i have a problem… temps[0], cause i have just one sensor, seems always egual to 0.0…i verified it with add watch expression in debug…can you hel me pls??? thx a lot

    • In the beginning of the main, just after includes you have a define
      EXPECTING_SENSORS 2
      What if you set 2 to 1?

      Try and report please.
      Btw..are you sure you have DS18B20 device? If you have DS18S20 or DS1820 then it will probably not work.

      • Alessandro Luciani

        thx for answer ^^ the sensor works good, i tested it with arduino and TI STELLARIS ..and yes i put 1 expecting sensor. Now the value that gives to me is always 2.56731587e-031….?????

        • Show me your USART log please.
          From reset to some seconds.

          • Alessandro Luciani

            #include “defines.h”

            #include “stm32f4xx.h”

            #include “stm32f4xx_rcc.h”

            #include “stm32f4xx_gpio.h”

            #include “tm_stm32f4_delay.h”

            #include “tm_stm32f4_onewire.h”

            //#include “tm_stm32f4_usart.h”

            #include “tm_stm32f4_ds18b20.h”

            #include

            //How many sensors we are expecting on 1wire bus?

            #define EXPECTING_SENSORS 1

            int main(void) {

            char buf[40];

            uint8_t devices, i, j, count, alarm_count;

            uint8_t device[EXPECTING_SENSORS][8];

            uint8_t alarm_device[EXPECTING_SENSORS][8];

            float temps[EXPECTING_SENSORS];

            float val;

            //Initialize system

            SystemInit();

            //Initialize delay

            TM_DELAY_Init();

            //Initialize OneWire on pin PD0

            TM_OneWire_Init();

            //Initialize USART, TX: PA9, RX: PA10

            //TM_USART_Init(USART1, TM_USART_PinsPack_1, 115200);

            //Checks for any device on 1-wire

            devices = TM_OneWire_First();

            count = 0;

            while (devices) {

            count++;

            //Get full ROM value, 8 bytes, give location of first byte where to save

            TM_OneWire_GetFullROM(&device[count – 1][0]);

            //Get next device

            devices = TM_OneWire_Next();

            }

            //If any devices on 1wire

            if (count > 0) {

            sprintf(buf, “Devices found on 1-wire: %dnr”, count);

            //TM_USART_Puts(USART1, buf);

            //Display 64bit rom code for each device

            for (j = 0; j < count; j++) {

            for (i = 0; i < 8; i++) {

            sprintf(buf, "0x%02X ", device[j][i]);

            //TM_USART_Puts(USART1, buf);

            }

            //TM_USART_Puts(USART1, "nr");

            }

            } else {

            // TM_USART_Puts(USART1, "No devices on OneWire.nr");

            }

            //Go through all connected devices and set resolution to 12bits

            for (i = 0; i < count; i++) {

            TM_DS18B20_SetResolution(&device[i][0], TM_DS18B20_Resolution_12bits);

            }

            //Set high temperature alarm on device number 0, 25degrees celcius

            TM_DS18B20_SetAlarmHighTemperature(&device[0][0], 25);

            //Disable alarm temperatures on device number 1

            TM_DS18B20_DisableAlarmTemperature(&device[1][0]);

            while (1) {

            //Start temperature conversion on all bits

            TM_DS18B20_StartAll();

            //Wait until all are done

            while (!TM_DS18B20_AllDone());

            //Read temperature from each device separatelly

            for (i = 0; i 0) {

            //TM_USART_Puts(USART1, “THIS DEVICES HAVE ALARM!nr “);

            //Show rom of this devices

            for (j = 0; j < alarm_count; j++) {

            for (i = 0; i < 8; i++) {

            sprintf(buf, "0x%02X ", alarm_device[j][i]);

            //TM_USART_Puts(USART1, buf);

            }

            // TM_USART_Puts(USART1, "nr ");

            }

            //TM_USART_Puts(USART1, "ALARM devices recognized!nr");

            }

            //Some delay

            Delayms(1000);

            }

            }

            i eliminated the usart command cause i don't have a converter ^^

          • Ive said USART log, not code. But ok, you don’t have converter.

            So, you are watching only in debug mode?
            This will not work,because in debug mode Systick timer does not work, but onewire delay is performed with systick.

            It will be better if you make an if statement
            If temp > 28 then led on, otherwise led off
            and warm sensor with hand.

          • Alessandro Luciani

            ok thx..i’ll try then in this way or printing temps on a LCD…i’ll tell you if it’ll work

  • Slobodan Simoski

    Hello Nice Work, but i have problems and im not sure what is the problem, the sensor or im making something wrong. Here is log from terminal.

    ALARM devices recognized!
    Temp 0: 85.00000; alarm: 1
    THIS DEVICES HAVE ALARM!
    0x28 0x77 0xC3 0xA4 0x05 0x00 0x00 0xFD

    • This happen sometimes when you make a first read from sensor.
      Some sensors have some problems. Do you have Chinese sensors?

      My are all original and no-one failed.

      • WildSideMKD

        Im not 100% sure but DALLAS 18B20 is written on the sensor.

        • Jörg Boge

          Is 85° only the first result or every result is 85°?

          • WildSideMKD

            Its the same result all the time .

  • abdurrahman korkmaz

    hi, please say me that, it gives count=1 so there is a device but TM_DS18B20_Read(&OneWire1, device[0], &temps[0])) not read. why?

    • Did you start with temp conversion?

      • abdurrahman korkmaz

        /* Read temperature from ROM address and store it to temps variable */

        if (TM_DS18B20_Read(&OneWire1, device[0], &temps[0])) {

        /* Print temperature */

        sprintf(buf, “Temp %d: %3.5f; n”, i, temps[0]);

        TM_HD44780_Puts(0, 2, (uint8_t*)buf);

        } else {

        /* Reading error */

        TM_HD44780_Puts(0, 2,”reading error”);

        }

        it goes directly to “else dise ” mean “reading error

        but

        while (devices) {

        /* Increase counter */

        count=1;

        /* Get full ROM value, 8 bytes, give location of first byte where to save */

        TM_OneWire_GetFullROM(&OneWire1, device[0]);

        /* Get next device */

        devices = TM_OneWire_Next(&OneWire1);

        }

        /* If any devices on 1wire */

        if (count > 0) {

        sprintf(buf, “device count: %dn”, count);

        TM_HD44780_Puts(0, 0, (uint8_t*)buf); /* Display 64bit rom code for each device */

        sprintf(buf, “0x%02X “, device[0][0]);

        TM_HD44780_Puts(0, 1, (uint8_t*)buf);

        }

        else {

        TM_HD44780_Puts(0, 0, “no device”);

        }

        it gives cihaz count :1 and device[0][0]=0xb0

        • You have DS18B20 connected??
          0x28 is first byte of rom for DS18B20, not 0xB0.

          That’s why you get wrong data.

  • Cart_Ha

    Hi tilz0R,
    I’m currently trying to make a DS18B20 to work with the STM32F100C8 and so far I’ve been quite successful at doing so. I used your libraries and modified everything to work with above mentioned microcontroller. My code builds without errors, delay and USART work fine (i.e. I can receive data sent from the Microcontroller), only thing that seem not to work is the TM_OneWire_Reset function. I connected an externally powered DS18B20 to pin PA1 through a 4k7 Pull Up resistor to 5V as described in the sensors datasheet and modified your reset function as follows:

    uint8_t TM_OneWire_Reset(TM_OneWire_t* OneWireStruct) {
    uint8_t i;

    /* Line low, and wait 480us */
    /* ONEWIRE_LOW(OneWireStruct); Replaced by: */
    GPIO_ResetBits(OneWireStruct->GPIOx, OneWireStruct->GPIO_Pin);
    ONEWIRE_OUTPUT(OneWireStruct);
    ONEWIRE_DELAY(480);

    /* Release line and wait for 60us */
    ONEWIRE_INPUT(OneWireStruct);
    ONEWIRE_DELAY(60);

    /* Check bit value */
    i = GPIO_ReadInputDataBit(OneWireStruct->GPIOx, OneWireStruct->GPIO_Pin);

    /* Delay for 420 us */
    ONEWIRE_DELAY(420);

    /* Return value of presence pulse, 0 = OK, 1 = ERROR */
    return i;
    }

    Since the stm32f10x.h library does not contain BSRRH and BSRRL as GPIO registers I had to replace the define ONE_WIRE_LOW() with a function found in the SPL’s stm32f10x_gpio.c:

    void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
    {
    /* Check the parameters */
    assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
    assert_param(IS_GPIO_PIN(GPIO_Pin));
    GPIOx->BRR = GPIO_Pin;
    }

    Connecting an oscilloscope to the sensor’s DQ pin revealed that the bus isn’t even pulled low when calling the reset function. It simply stays in the idle high state, no matter what I do.
    I know this might be a long shot since you only work with the STM32F4 series but I can’t figure out where my mistake is and I’m hoping you might be able to help.

    Greetings,
    C.

    • You have probably wrong LOW and HIGH implementation for function.
      Other option is not seen here, sorry 🙂

      For reset F100 uses BRR register, look for GPIO registers, which one is used for set bits.

      • Cart_Ha

        Ok, I tried to replace the GPIO_ResetBits(…) with GPIO_SetBits(..) which does the following after calling:
        void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
        {
        /* Check the parameters */
        assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
        assert_param(IS_GPIO_PIN(GPIO_Pin));
        GPIOx->BSRR = GPIO_Pin;
        }

        It still does not work and there are no other GPIO registers for atomic bit manipulation.
        Maybe my problem is somewhere else and I just couldn’t find it yet.

        Thank you for your help anyway! 🙂

        • Make sure you have enabled GPIO clock! :))

          • Cart_Ha

            GPIO clock is enabled in the TM_OneWire_Init function 😉

    • Jörg Boge

      Don’t use 5 V for the Pull up, use 3k3 and 3 Volt

      • His problem is not voltage 5 or 3V, but that pin is not going LOW.
        5V throught resistor is just fine and OK.

        • Jörg Boge

          The inputs are 5V tolerant.
          However, it is not good design to apply 5 V

          • Might be true, but I wanna see this document where you read that 😉

          • Jörg Boge

            See Data sheet http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/CD00251732.pdf Page 25 , PA1 on STM32F100 IS NOT 5 V tolerant !!!!!!

          • Cart_Ha

            well, that explains a lot.

          • Cart_Ha

            Alright, I think I found a way to make it work nonetheless. I desoldered the 4k7 and thus disconnecting the 1-Wire bus and pin PA1 from the 5V supply. I then set the mode of PA1 to GPIO_Mode_IPU, pulling the line towards to the microcontrollers internal 3.3V supply. Now I simply had to customize my reset function as follows:

            uint8_t TM_OneWire_Reset(TM_OneWire_t* OneWireStruct) {
            uint8_t i = 1;

            /* Line low, and wait 480us */
            GPIO_ResetBits(OneWireStruct->GPIOx, OneWireStruct->GPIO_Pin);
            ONEWIRE_OUTPUT(OneWireStruct);
            ONEWIRE_DELAY(480);

            /* Release line and wait for 60us */
            GPIO_SetBits(OneWireStruct->GPIOx, OneWireStruct->GPIO_Pin);
            ONEWIRE_INPUT(OneWireStruct);
            ONEWIRE_DELAY(60);

            /* Check bit value */
            i = GPIO_ReadInputDataBit(OneWireStruct->GPIOx, OneWireStruct->GPIO_Pin);

            /* Delay for 420 us */
            ONEWIRE_DELAY(420);

            /* Return value of presence pulse, 0 = OK, 1 = ERROR */
            return i;
            }

            And, surprise surprise, my line is finally pulled low, when calling the function! 🙂

            Now I just have to adjust my timings, since my reset pulse is a bit off (see attached picture).

        • Cart_Ha

          Well, at this point I can’t change my 5V supply and 4k7 resistor for the DS18B20 anyway, since the pcb I use for interfacing the sensor and microcontroller was my own design I already gave into production before this problem occurred…

          • Don’t worry about 5V pullup. This is not problem.

  • Michal Szymanski

    One question. What changes are needed to run you library on STM32F053R8 ?

    • GPIO and delay related stuff. So, reading pin, initializing, setting state to pin and microseconds based delay.

  • Bartosz Kościug

    Hi,
    I have a problem with connection between the DS18B20 sensor and my nucleo stm32F401RE. Literally, I can’t read anything from data pin. I plugged onewire in vary types of pins but none of them( in e.g PA_3, PA_10, PD_2) cant detect any signal. The varable devices is always empty. What I do wrong? To make it clear I also use pull up 4.7K pullup resistor as they says in datasheet. I also checked if the sensor work on my Arduino Leonardo. Everything was good. Arudino display correctly ROM adres and temperature.
    Thanks!

    • I would say your pll settings are wrong and delay does not work. Check for pll configuration on this site.

      • Bartosz Kościug

        What Do you mean by pll setting?The pull ups? Sorry for unwise…

        • PLL settings. Check google if you don’t know what PLL is.

          You must configure it so your STM will work properly as expected.

          • Bartosz Kościug

            Yeah, so what exactly do you suggest my STM32f401 is able to work only with 84Mhz clock, while in your expample for pll you turn stm23f429 to 180Mhz. Do I need to turn mine to 84Mhz?

  • Mat

    Hey, I have problem,
    I would like to read tempreture and I use this function
    TM_DS18B20_Read(&OneWire1, device[0], &temps[0]);
    sprintf(buf, “Temp : %3.1f; “, temps[0]);
    TM_HD44780_Puts(0,0, buf);
    and everything is great ,
    but I would like to make something like that:
    float z;
    z=temps[0];
    sprintf(buf, “Temp : %3.1f; “, z);
    TM_HD44780_Puts(0,0, buf);
    and now value from sensor is completly wrong ?
    Can You help me 🙂

  • Andres Felipe Soto

    there is a minimum frequency to work this example.

    I ask this question because when low frequency below 90 MHz stops working in the stm32f429discovery.

  • Matias

    Hi!, im getting in an infinit loop when i call TM_DS18B20_Read() and I figured out it jumps to the loop when it operates with decimal or any float variable from that function. How can i solve this?

    • Definetelly problem on your side. You can show code for more info.

      • Matias

        #include “stm32f4xx.h”
        #include “stm32f4_discovery.h”

        #include “tm_stm32f4_ds18b20.h”
        #include “one_wire_lib/tm_stm32f4_onewire.h”

        #define EXPECTING_SENSORS 2

        int main(void) {

        STM_EVAL_LEDInit(LED4);
        STM_EVAL_LEDInit(LED5);

        uint8_t devices, i, j, count, alarm_count;
        uint8_t device[EXPECTING_SENSORS][8];
        float temps[EXPECTING_SENSORS];

        /* OneWire working struct */
        TM_OneWire_t OneWire1;

        /* Initialize system */
        SystemInit();

        /* Initialize delay */
        TM_DELAY_Init();

        /* Initialize OneWire on pin PD0 */
        TM_OneWire_Init(&OneWire1, GPIOD, GPIO_Pin_0);

        count = 0;
        devices = TM_OneWire_First(&OneWire1);
        while (devices) {
        /* Increase counter */
        count++;

        /* Get full ROM value, 8 bytes, give location of first byte where to save */
        TM_OneWire_GetFullROM(&OneWire1, device[count – 1]);

        /* Get next device */
        devices = TM_OneWire_Next(&OneWire1);
        }

        /* If any devices on 1wire */
        if (count > 0) {
        STM_EVAL_LEDOn(LED4);
        } else {
        STM_EVAL_LEDOn(LED5);
        }

        for (i = 0; i < count; i++) {
        /* Set resolution to 12bits */
        TM_DS18B20_SetResolution(&OneWire1, device[i],
        TM_DS18B20_Resolution_9bits);
        }

        /* Disable alarm temperatures on all devices */
        for (i = 0; i < count; i++) {
        TM_DS18B20_DisableAlarmTemperature(&OneWire1, device[i]);
        }

        while (1) {

        /* Start temperature conversion on all devices on one bus */
        TM_DS18B20_StartAll(&OneWire1);

        /* Wait until all are done on one onewire port */
        while (!TM_DS18B20_AllDone(&OneWire1))
        ;

        /* Read temperature from ROM address and store it to temps variable */
        TM_DS18B20_Read(&OneWire1, device[0], temps);

        }

        }

      • Matias

        I’ve included all dependencies you required

        • You failed. Float variable to save read value must be a pointer. Compiler made you warning or error for your fail.

          • matias

            When you put the name of an array in c, you are passing the pointer, for example:
            for array float temps[2]
            calling temps is the same that &temps[0]. (so i don’t have any warning on compiler)
            That’s not the cause of the problem. I tried also putting &temps[0]. (no difference, same error)
            What other thing can it be?

          • I never said this is a problem, you don’t need to learn me C language.
            Problem is third parameter! It requires float pointer so I can save a value in degrees into but you did not pass pointer or if you did it, your pointer is NULL.

            Clearly your problem, not problem of library.

            If you are thinking why I deleted your post with code, read before you make a comment!

          • matias

            Sorry, Majerle i didn’t understand you
            I do not question you know C language.
            And sorry for pasting the code here.

            Am I passing a not float or a NULL pointer here?
            http://pastebin.com/nqwmvD24

          • You copied other code in compare to previous. This one looks ok. In read operation, there should be no issues.

            If you get hardfault error, then you can step into and see where. Report.

          • matias

            Is a different code but with the same problem. Stepping into the Read function, it goes to this loop : http://pastebin.com/z37E7GT1

            In the switch (i’ve write a comment there) goes to the loop
            http://pastebin.com/Jy3mDD37

          • matias

            Hi majerle!
            The whole problem was a wrong configuration in my compiler floatin point configuration.
            maybe i will help if anyone has this problem too.

  • orlem

    I wanna use this library with stm32f407 with 168MHz
    Could you please give a tip about what a need to change so that works well

    thanks in advance

  • Natthapol Vanasrivilai

    I’m trying to understand what you did in your DS19B20 Library.
    On the part of WriteBit function. How do decide how long should be the pin be pulled to low in case of logic high/logic low?

    I saw 10µs, 55µs, 65µs and 5µs.

    How do you come up with this time?

    void TM_OneWire_WriteBit(TM_OneWire_t* OneWireStruct, uint8_t bit) {
    if (bit) {
    /* Set line low */
    ONEWIRE_LOW(OneWireStruct);
    ONEWIRE_OUTPUT(OneWireStruct);
    ONEWIRE_DELAY(10);

    /* Bit high */
    ONEWIRE_INPUT(OneWireStruct);

    /* Wait for 55 us and release the line */
    ONEWIRE_DELAY(55);
    ONEWIRE_INPUT(OneWireStruct);
    } else {
    /* Set line low */
    ONEWIRE_LOW(OneWireStruct);
    ONEWIRE_OUTPUT(OneWireStruct);
    ONEWIRE_DELAY(65);

    /* Bit high */
    ONEWIRE_INPUT(OneWireStruct);

    /* Wait for 5 us and release the line */
    ONEWIRE_DELAY(5);
    ONEWIRE_INPUT(OneWireStruct);
    }

    }