Connecting ds18b20 to nrf9160dk

Hi, 

I am looking to connect the ds18b20 sensor to the nrf9160dk. I followed this post, but when I tried running it, I was getting a "create_nordic_project.py failed (1)" saying "error: cmake failed". 

I am a complete beginner when using the development kit so please bear with my questions. 

I have added "CONFIG_GPIO" in the prj.conf file, is there anything else I should be adding. 

Additionally, should I be making changes to the cmake file? The link above only mentioned the .c and .h file so I wasn't sure what else should be changed. 

If anyone could help me with this or could point me to resources that will help me solve this, I would really appreciate it. 

Update : The code is now running without any build errors but not printing any values. I had been using the hello_world sample to run it before which was giving the error, but then I tried switching to the blinky sample and running on that and it's building and running without any errors. (Would anybody know why this is).

My issue now is that it is not printing any values or anything to the Debug terminal on SES or the LTE Link Monitor. Does anyone know why this may be?

  • Hi 

    I attempted to use the above function, but it is still not reading the values correctly, and the way it calculated the temperature is wrong. I managed to probe the data line with a logic analyzer and may have found the issue but I don't know how to fix it. So it looks like there is a delay when setting the pin to low/high from the state it was in before.

    I tried only running the SetResolution function and this screenshot is the reset function that is called in the beginning of setResolution function. It should only be low for 480 us but is low for 558 us.

    This delay is seen everywhere else, like this screenshot shows the first couple bits that are sent from the "sendbyte(SKIPROM)" command in SetResolution(). It is sending LSB first and should be sending 0,0,1,1,0,0,1,1. when sending 0's, it should only be low for 65us but it is low for 157 us (1st screenshot). And when sending high, it should be low for only 10 us but it is low for 80 us (2nd screenshot). This causes an issue because in order to Write 1 to the DS18B20 sensor, it needs to switch to the high state within 15 us after being low (setting it low is what initializes the timeslot). 

    So now I know why it was sending me wrong values but I have no idea how to fix it. Can anyone please provide some guidance on what I can do to make the delays in my code execute more accurately without so much delay in switching between setting the pin High/Low?

    Is the issue that the clock is too slow? Or is there something else I should be doing?

    And here is my main.c, I changed the delays a little bit. Every other file is exactly the same. ( I apologize in advance for the large amounts of commented code.)

    #include <drivers/gpio.h>
    #include <stdio.h>
    #include <zephyr.h>
    #include <device.h>
    #include <devicetree.h>
    
    #include "ds18b20.h"
    
    #define GPIO0_LABEL DT_PROP(DT_NODELABEL(gpio0), label)
    #define GPIO0_STATUS DT_PROP(DT_NODELABEL(gpio0), status)
    #define DS_PIN 21
    
    // Commands
    #define STARTCONVO 0x44
    #define READSCRATCH 0xBE
    #define WRITESCRATCH 0x4E
    #define SKIPROM 0xCC
    
    // Scratchpad locations
    #define TEMP_LSB        0
    #define TEMP_MSB        1
    
    // Device resolution
    #define TEMP_9_BIT  0x1F //  9 bit
    #define TEMP_10_BIT 0x3F // 10 bit
    #define TEMP_11_BIT 0x5F // 11 bit
    #define TEMP_12_BIT 0x7F // 12 bit
    
    typedef uint8_t ScratchPad[9];
    
    //Datasheet: https://datasheets.maximintegrated.com/en/ds/DS18B20.pdf
    
    static float temp = 0;
    static const struct device *gpio_dev;
    
    
    /**@brief Function for sending one bit to bus.
     */
    void ds18b20_send(uint8_t bit)
    {
        //nrf_gpio_cfg_output(DS_PIN);
        //nrf_gpio_pin_clear(DS_PIN);
        //nrf_delay_us(5);
        gpio_pin_set(gpio_dev, DS_PIN, 0);
        gpio_pin_configure(gpio_dev, DS_PIN, GPIO_OUTPUT);
        
        //k_usleep(10);
    
        if(bit==1)
        {   
            k_usleep(10);
            //nrf_gpio_pin_set(DS_PIN);
            gpio_pin_set(gpio_dev, DS_PIN, 1);
            k_usleep(55);
    
        }
        else
        {
            k_usleep(65);
            gpio_pin_set(gpio_dev, DS_PIN, 1);
            k_usleep(5);
    
        }
        //nrf_delay_us(80);
        //nrf_gpio_pin_set(DS_PIN);
    
        //k_usleep(60);
        //gpio_pin_set(gpio_dev, DS_PIN, 1);
        //k_usleep(2);
        
    }
    
    
    /**@brief Function for reading one bit from bus.
     */
    unsigned char ds18b20_read(void)
    {
        printf("In ds18b20_read function");
        unsigned char presence=0;
        
        //nrf_gpio_cfg_output(DS_PIN);
        //nrf_gpio_pin_clear(DS_PIN);
        //nrf_delay_us(2);
    
        //nrf_gpio_pin_set(DS_PIN);;
        //nrf_delay_us(15);
    
        //nrf_gpio_cfg_input(DS_PIN,NRF_GPIO_PIN_NOPULL);
    
        gpio_pin_configure(gpio_dev, DS_PIN, GPIO_OUTPUT_LOW);
        gpio_pin_set(gpio_dev, DS_PIN, 0);
        k_usleep(2);
    
        gpio_pin_set(gpio_dev, DS_PIN, 1);
        k_usleep(10);
    
        gpio_pin_configure(gpio_dev, DS_PIN, GPIO_INPUT);
        k_usleep(30);
    
        //if(nrf_gpio_pin_read(DS_PIN))
        if (gpio_pin_get_raw(gpio_dev, DS_PIN))
        {
            presence = 1;
        }
        else
        {
            presence = 0;
        }
    
        printf("\npresence = %d\n", presence);
        
        return presence;
    }
    
    
    /**@brief Function for sending one byte to bus.
     */
    void ds18b20_send_byte(uint8_t data)
    {
        printf("In send_byte func, the byte of data in hex is %x\n and int %d\n", data, data);
        uint8_t i;
        uint8_t x;
        for(i=0;i<8;i++)
        {
          x = data>>i;
          x &= 0x01;
          printf("x=%d\n",x);
          ds18b20_send(x);
        }
        //nrf_delay_us(100);
        //k_usleep(100);
    }
    
    
    /**@brief Function for reading one byte from bus.
     */
    unsigned char ds18b20_read_byte(void)
    {
        printf("entering ds18b20_read_byte function\n");
        unsigned char i;
        unsigned char data = 0;
        for (i=0;i<8;i++)
        {
            if(ds18b20_read()) data|=0x01<<i;
            //nrf_delay_us(15);
            k_usleep(15);
        }
        printf("data = %c", data);
        return(data);
    }
    
    
    /**@brief Function for sending reset pulse.
     */
    unsigned char  ds18b20_reset(void)
    {
      printf("entering reset loop");
      int presence=0;
      printf("presence before = %d\n", presence);
    
      //nrf_gpio_cfg_output(DS_PIN);
      //nrf_gpio_pin_clear(DS_PIN);
    
      //nrf_delay_us(500);
      //nrf_gpio_pin_set(DS_PIN);
    
      //nrf_gpio_cfg_input(DS_PIN,NRF_GPIO_PIN_NOPULL); // usikkert p? pull her. m? sjekkes
      //nrf_delay_us(30);
    
        gpio_pin_set(gpio_dev, DS_PIN, 0);
        gpio_pin_configure(gpio_dev, DS_PIN, GPIO_OUTPUT);
        
    
        k_usleep(480);
        gpio_pin_set(gpio_dev, DS_PIN, 1);
        gpio_pin_configure(gpio_dev, DS_PIN, GPIO_INPUT);
        k_usleep(30);
    
        if(gpio_pin_get_raw(gpio_dev, DS_PIN) == 0)
        {
            presence = 1;
        }
        else
        {
            presence = 0;
        }
        printf("presence after 30 us = %d", presence);
    
        //nrf_delay_us(470);
        k_usleep(470);
    
        if(gpio_pin_get_raw(gpio_dev, DS_PIN) == 1)
        {
            presence = 1;
        }
        else
        {
            presence = 0;
        }
      printf("presence after 470 us is %d", presence);
      return presence;
    
    }
    
    
    /**@brief Function for reading temperature.
     */
    float ds18b20_get_temp(void)
    {
        printf("ENtering get_temp method\n");
    
        unsigned int check;
        uint8_t temp1=0, temp2=0;
    
        check=ds18b20_reset();
        printf("check from reset = %d\n", check);
        if(check)
        {
            ds18b20_send_byte(SKIPROM); //Skip ROM.
            ds18b20_send_byte(0x44); //Start temp conversion.
            //nrf_delay_ms(600UL);
            k_msleep(600UL);
            check=ds18b20_reset();
            ds18b20_send_byte(SKIPROM); //Skip ROM.
            ds18b20_send_byte(0xBE); //Read temp from Scratchpad.
            temp1=ds18b20_read_byte();
            temp2=ds18b20_read_byte();
            check=ds18b20_reset();
            printf("temp1=%d and temp2 = %d\n", temp1, temp2);
            float temp=0;
            temp=(float)(temp1+(temp2*256))/16;
            printf("temp = %6f\n", temp);
            return temp;
        }
          return 0;
    }
    
    
    /**@brief Function for reading bit.
     */
    uint8_t OneWire_read_bit(void)
    {
        printf("Inside OneWire_read_bit \n");
        uint8_t r;
    
        //nrf_gpio_cfg_output(DS_PIN);
        //nrf_gpio_pin_clear(DS_PIN);
        //nrf_delay_us(3);
        //nrf_gpio_cfg_input(DS_PIN,NRF_GPIO_PIN_NOPULL);
        //nrf_delay_us(10);
        //r =nrf_gpio_pin_read(DS_PIN);
        //nrf_delay_us(53);
        gpio_pin_set(gpio_dev, DS_PIN, 0);
        gpio_pin_configure(gpio_dev, DS_PIN, GPIO_OUTPUT);
        k_usleep(3);
        //gpio_pin_set(gpio_dev, DS_PIN, 1);
        gpio_pin_configure(gpio_dev, DS_PIN, GPIO_INPUT);
        k_usleep(10);
        r = gpio_pin_get_raw(gpio_dev, DS_PIN);
        printk("\nr = %d", r); // COMMENTED THIS
        k_usleep(53);
        return r;
    }
    
    
    /**@brief Function for reading.
     */
    uint8_t OneWire_read()
    {
        printf("inside OneWire_read function\n");
    
        uint8_t bitMask;
        uint8_t r = 0;
        //bitMask = 0x00;
     
        /*for (int i=0; i<8; i++) {
          //bitMask = 0x01<<i;
          bitMask = 0x01 & OneWire_read_bit();
          bitMask = bitMask << i;
          r |= bitMask;
        }*/
    
        for (bitMask = 0x01; bitMask; bitMask <<= 1) {
    	if ( OneWire_read_bit()) r |= bitMask;
        }
        printf("the byte in hex is %x\n", r);
        return r;
    }
    
    
    /**@brief Function for reading scratchpad value
     */
    void ds18b20_readScratchPad(uint8_t *scratchPad, uint8_t fields)
    {
        printf("Inside readScratcpad function\n");
        ds18b20_reset();
        ds18b20_send_byte(SKIPROM);
        ds18b20_send_byte(READSCRATCH);
    
        for(uint8_t i=0; i < fields; i++)
        {
            scratchPad[i] = OneWire_read();
            printf("Scratcpad[%d] = %x", i, scratchPad[i]);
    
        }
        ds18b20_reset();
    }
    
    
    /**@brief Function for request temperature reading
     */
    void ds18b20_requestTemperatures(void)
    {
        printf("inside Request Temperatures function\n");
        ds18b20_reset();
        ds18b20_send_byte(SKIPROM);
        ds18b20_send_byte(STARTCONVO);
        k_msleep(750);
    }
    
    
    /**@brief Function for reading temperature method 2
     */
    float ds18b20_get_temp_method_2(void)
    {
        //printf("entering get_temp_method_2");
        //ds18b20_requestTemperatures();
        //unsigned char check;
    
        ScratchPad scratchPad;
        ds18b20_readScratchPad(scratchPad, 5);
        int16_t rawTemperature = (((int16_t)scratchPad[TEMP_MSB]) << 8) | scratchPad[TEMP_LSB];
        //printf("Raw temperature = %d\n", rawTemperature);
        //float temp = 0.0625 * rawTemperature;
        //printf("real temperature = %6f\n", temp);
    
        return temp;
    }
    
    
    /**@brief Function for setting temperature resolution
     */
    void ds18b20_setResolution(uint8_t resolution)
    {
        ds18b20_reset();
        printf("sending skip rom\n");
        ds18b20_send_byte(SKIPROM);
        printf("end of sending skip rom\n");
        printf("sending write scratch\n");
        ds18b20_send_byte(WRITESCRATCH);
        printf("end of sending write scratch\n");
        printf("sending T_H\n");
        // two dummy values for LOW & HIGH ALARM
        ds18b20_send_byte(0x7D); // 125 C
        printf("sending T_L\n");
        ds18b20_send_byte(0xC9); // -55C
        printf("sending conversion resolution\n");
        switch (resolution)
        {
            case 12:
                ds18b20_send_byte(TEMP_12_BIT);
                break;
    
            case 11:
                ds18b20_send_byte(TEMP_11_BIT);
                break;
    
            case 10:
                ds18b20_send_byte(TEMP_10_BIT);
                break;
    
            case 9:
            default:
                ds18b20_send_byte(TEMP_9_BIT);
                break;
        }
        ds18b20_reset();
        printf("exit set_Resolution() function");
    }
    
    void main()
    {
        gpio_dev = device_get_binding(GPIO0_LABEL);
    
        if (!gpio_dev) {
    	    printk("Error getting GPIO_0: failed.\n");
        }
        
        
        //ds18b20_reset();
        
        
        ds18b20_setResolution(10);
    
        /*
        temp = ds18b20_get_temp_method_2();
        //temp = ds18b20_get_temp();
        printf("Temperature: %.3f \r\n", temp);
    
        
        while(1)
        {
            k_msleep(2000);
            temp = ds18b20_get_temp_method_2();
            //temp = ds18b20_get_temp();
            printf("Temperature: %.3f \r\n", temp);
        }*/
    }
    
    
        
    
    
    /** @} */
    

  • Hello Nandini,

    nrffan18 said:

    So now I know why it was sending me wrong values but I have no idea how to fix it. Can anyone please provide some guidance on what I can do to make the delays in my code execute more accurately without so much delay in switching between setting the pin High/Low?

    Is the issue that the clock is too slow? Or is there something else I should be doing?

    Here are my suggestions:

    • Debug through the driver layer of your code and see if you can find something suspicious. For this, I recommend you to use nRF Connect for VS Code.
    • Use the blinky sample as reference and connect the probe to the pin controlling the LED. Do you see the same delay there?

    Regards,

    Markus

  • Hi

    I tried running the blinky code that access info directly from the devicetree while placing a 2000us delay after setting on and a 1000 us delay after setting it off. When doing the delay in ms, there is not much delay, but when doing in us, there is a delay of 50 us when going high, and 100 us when going low. 

    I also noticed that the delay increases when I increase the clock speed to 25 kHz. Do you know why that is? And I also noticed that it briefly goes low when its high sometimes. (3rd screenshot below) Does anyone know why that is too?

    I also didn't notice anything weird when I debugged through the code. 

    I am approaching my deadline for my project really soon so any help would be really appreciated. Thank you!

  • Hello Nandini,

    nrffan18 said:
    When doing the delay in ms, there is not much delay, but when doing in us, there is a delay of 50 us when going high, and 100 us when going low. 

    Are you using k_usleep() for this? As documented, you should use the function with caution and probably adjust CONFIG_SYS_CLOCK_TICKS_PER_SEC as well.

    nrffan18 said:
    I also noticed that the delay increases when I increase the clock speed to 25 kHz. Do you know why that is? And I also noticed that it briefly goes low when its high sometimes. (3rd screenshot below) Does anyone know why that is too?

    The default low frequency clock should be 32 kHz. Which value did you increase it from?

    nrffan18 said:
    I am approaching my deadline for my project really soon so any help would be really appreciated. Thank you!

    Have you tried to define a timer that indicates a toggle of the GPIO pin in its handler?

    Regards,

    Markus

  • Hi, 

    I tried your suggestions. Changing the CONFIG_SYS_CLOCK_TICKS_PER_SEC did reduce the delay, but the code would not run when I left debug mode. And since I needed this project to be portable, I couldn't use that. 

    The timer suggestion works if you want to repeat something over the same interval, but my issue had a lot of delays and kind of made it difficult to incorporate this. 

    What ended up working for me was replacing all the k_usleep()/k_sleep with k_busy_wait(). Its able to get down to 3 us accurately (when I do k_busy_wait(1), so there is a 2us delay) and that was enough for me to incorporate the ds18b20 sensor. If you need a 1us delay, I found not putting any delay seems to do the trick, though it might be a little inconsistent. 

    So it works now! thank you so much for all the help and helping me narrow down the issue. I really appreciate it. 

Related