Monday, September 8, 2014

A DS18B20 1-wire digital thermometer AVR ATmega library

--ref 2012

updated to version 02

DS18B20 is a programmable resolution 1-wire digital thermometer.
It has an operating temperature range of -55°C to +125°C and is accurate to ±0.5°C over the range of -10°C to +85°C.

This library is an AVR implementation to retrive temperature from DS18B20.

Built using the reference document: "Using DS18B20 digital temperature sensor on AVR microcontrollers" by Gerard Marull Paretas, 2007.


You just have to select the port where the temperature sensor is connected.
This library was developed on Eclipse, built with avr-gcc on Atmega8 @ 1MHz.

Changelog
  • 02: fixed negative temperature readings
  • 01b: fixed schematics
  • 01: first relase
Code
Notes
  • read risk disclaimer
  • excuse my bad english

66 comments:

  1. Non è necessario mettere la resistenza di pull-up sui pin positivo e uscita del ds18b20 ?
    Dove si viene definito il pin del micro come ingresso del ds18b20 ?

    ReplyDelete
    Replies
    1. Si, in effetti è meglio farlo, ho fixato il circuito, grazie per la segnalazione.
      In ds18b20.h (//setup connection) definisci i pin

      Delete
    2. Grazie a te per gli ottimi tutorial sugli Atmega

      Delete
    3. Grazie per il feedback! Fa sempre piacere riceverne di questo tipo :)

      Delete
    4. Ho realizzato lo schema indicato sostituendo l'Atmega 8 con Atmega 32, ed utilizzando al posto di un DS18b20 un DS1820.
      Purtroppo la porta seriale mi indica un valore che varia dai 2.850 e i 3.300 toccando il sensore con un dito.
      Un indicazione questa molto lontana da quella che dovrebbe essere la temperatura ambiente o quella corporea.
      Dove potrebbe essere lo sbaglio ?

      Delete
    5. Se hai un analizzatore logico potresti checkare il bus per trovare quello che passa.
      Debugga i due byte di output raw temperature[0] = ds18b20_readbyte(); temperature[1] = ds18b20_readbyte(); per cercare se la conversione è poi eseguita correttamente.

      Delete
  2. Hi!! my name is Alan, i have a question... this library support negative temperatures?

    thanks, regards :)

    ReplyDelete
    Replies
    1. Hello,
      it should, but i've never try it with negative temperatures. Let me know if this works.

      Delete
    2. Hello, tested with negative temperature, version 01 does not works. Version 02 it is tested for negative temperature

      Delete
  3. Hi!
    I want to know, how can i display a float value into LCD, im using a Peter Fleury library, and i use a sprintf function, but when i programming a microcontroller, only i see a question mark (?) into LCD, any idea?

    PD: im using a Eclipse IDE with AVR plug-in

    thanks, regards

    ReplyDelete
    Replies
    1. Hello, try the dtostrf from the stdlib.h

      double x = 1.22;
      char buf10];
      dtostrf(x, 3, 5, buf);
      uart_puts(buf);

      Delete
  4. Hi, thanks for your prompt response, I managed to do this using the function dtostrf

    thanks :D

    ReplyDelete
  5. Hi Davide,

    I have used your library with an AT90S8515. It showed weird values, like 90C instead of 30. After a short look at the datasheet, I have increased the delays between bytes, from 1us to 2us and everything went fine. Just wanted to let you know about this.

    ReplyDelete
    Replies
    1. Thank you! It may help other people.

      Delete
    2. I have found out the error in my code, it was showed to me by Philipp Klaus while browsing my blog.
      It is interesting, many people reading weird values, or 85C or 127C might be affected by the same thing.

      The _delay_us() function is tied to the CPU frequency definition to work properly.

      I have defined it like this, for 8MHz:

      #define F_CPU 8000000

      this is wrong, the frequency must be defines like this:

      #define F_CPU 8000000L

      I hope it helps some other guys searching for errors everywhere but in the right place.

      Delete
    3. Well done, and thank you for the feedback!

      Delete
  6. I've been having trouble with negative temperatures using this library. I see this is a common issue for the Arduino libs as well. I believe that temperature[] is overflowing inside the ds18b20_gettemp() code. If you have a freezer or hold a upside down can of compressed air against the probe this is easy to recreate.

    ReplyDelete
    Replies
    1. Hello, thank you for feedback. I've never check this library against negative temperature. I put a not about this. As soon as possible I will check this. If in the meantime you fix this, please let me know.

      Delete
    2. Hello,
      i've fixed the negative temperature reading problem. The version 02 it is not tested against negative temperatures too.

      Delete
    3. Davide,

      Thank you for the fix. I've just integrated the new version into my freezer controller. I have been traveling all summer so I've not tested it with negative temperatures yet. I will know more next week when I have access to a freezer again. The code builds and I see extensive changes have been made to ds18b20_gettemp() so thank you for that.

      Delete
    4. Great. Let me know if it works.

      Delete
  7. Hello Davide,
    thank you for your example.

    why do you need to disable interrupt on the line#112:
    #if DS18B20_STOPINTERRUPTONREAD == 1
    cli();
    #endif

    ReplyDelete
    Replies
    1. Hello. The read and write byte functions of this libarry needs precise timing, Interrupt is disabled to prevent timing errors. It may works even without disabling the interrupt, it depends on the micro resource usage of your firmware. Hope this helps.

      Delete
  8. Hello Davide Gironi.
    Thanks for the block. I am using this library with Atmega1280. the DS18B20 is connected in PJ2, so I modified the pin in ds18b20.c but when I run the function ds18b20_gettemp() and always I get the value: -0.06
    thanks in advance.

    ReplyDelete
    Replies
    1. Hello. Are you using avr-gcc as compiler? Also double check your F_CPU compiler time with your mega1280 fuse CPU settings. If you've got a scope check that the pin output is complaint to the DS18B20 timing, look at the Maxim Integrated datasheet from page 15.

      Delete
    2. Hello. Thanks for your answer. Unfortunately I don't have a scope to check that.
      I am using avr-gcc. In the code I have defined F_CPU 8000000L and the ISP clock is 125Khz

      Delete
    3. I am using Atmel Studio 6.2 for programming and debugging

      Delete
    4. Without any scope on output debug get's complicated. Anyway, try at first without any interrupt, try just a simple code. Try the DS18B20 on other platform, like Arduino, just to make shure the sensor is working.

      Delete
    5. Hi again, I tried in Arduino and it works.
      Back in Atmega1280, when I run ds18b20_gettemp(), from ds18b20_reset() function I get 4. what that means?

      Delete
    6. well, the value 4=0b00000100 means that (DS18B20_PIN & (1<<DS18B20_DQ)) is 1 so I get a error from reset function.
      But I don´t know how to solve.

      Delete
    7. It could an incorrect timing problem. The _delay_us needs F_CPU directive and micro speed to be consistent. Unluckly, the only way to check it is to scope on that pin. You could also take a look to the Arduino library you are using, and see if there are differences between this and the Arduino code.

      Delete
    8. I will check the arduino code. But I configured the atmega1280 F_CPU 8000000L and the Arduino micro speed is 16Mhz.

      Delete
    9. sorry to double post, I just posted below as well. Oscar did you solve your errors? I also get 0.-6 reads from the DS18B20. My mcu is 16Mhz clock

      Delete
  9. This comment has been removed by the author.

    ReplyDelete
  10. Hi,
    library doesn't work when using parasite mode.
    Solution is very simple, just put line high and wait 750ms after start of temp conversion :
    ds18b20_writebyte(DS18B20_CMD_CONVERTTEMP); //start temperature conversion
    DS18B20_DDR |= (1<<DS18B20_DQ); //output
    DS18B20_PORT |= (1<<DS18B20_DQ); //low
    _delay_ms(750);
    while(!ds18b20_readbit()); //wait until conversion is complete

    ReplyDelete
  11. Hi I hope there is still someone monitoring this blog! I am having the same problem as Oscar who posted on August 24th. My mcu is 16Mhz, what do I need to change in delay.c to make this code compatible?

    Thank you!

    ReplyDelete
    Replies
    1. Hello, please see reply above (Alex T - November 17, 2015)

      Delete
  12. I made a typo above I meant to say ds18b20.c* not delay.c

    The temperature continually reads -0.0625 which means somehow I am getting a negative one in this section of the code in ds18b20.c

    //convert the 12 bit value obtained
    retd = ( ( temperature_h << 8 ) + temperature_l ) * 0.0625;

    I have defined F_CPU as 16Mhz in both my main and the ds18b20.c file.

    ReplyDelete
    Replies
    1. Hello.
      At first, try at 1Mhz, or 8Mhz. Does it works?
      Have you check the bus with a logical analyzer to see if the signal has the right timing?

      Delete
  13. Hello Davide thank you for the quick response. I tried defining F_CPU as both 8 and 1 Mhz, neither worked. I do not know how to see if the signal has the proper timing on the bus(newbie) and I don't have an oscilloscope available. Previously I did check to ensure that the ext clk was 16mhz. Are there any other possible sources of the error?

    ReplyDelete
    Replies
    1. Hello, the most obvious that comes into my mind it's timing, if you take a look to the ds18b20 datasheet you can read the timing procedures to make this IC works. But there could of course be other causes. Are you using the same power supply of the micro? Can you try this IC with an Arduino, PIC or other hardware and library?

      Delete
    2. Unfortunately I do not have any other hardware to test it on. Are you familiar with atmel studio? Can I define the CPU speed in the compiler without having to use define statements in each source file?

      Delete
    3. I'm sorry but my reference avr toolchain it's Eclipse IDE + the AVR plugin, compiled with avrgcc.

      Delete
    4. Davide, I fixed the error. For anyone whose F_CPU is running at 16Mhz, what I did to fix it:

      #define F_CPU 1000000UL in both ds18b20.c and main

      and in main, I scaled my clock down to 1mHz:
      CLKPR = 0x80;
      CLKPR = 0x04;

      Awesome library Davide thank you for your helpfulness

      Delete
    5. Hello, I'm happy to hear that! And thank you for sharing your feedback and your solution. I hope it can help someone else.

      Delete
    6. The degrees C returned from the ds18b20.c are in increments of 0.5 degrees how can I make it more accurate?

      Delete
    7. It's a matter of how it's configured. Take a look to DS18B20_CMD_WSCRATCHPAD and Figure 8. Configuration Register on DS18B20 datasheet from from MI, REV: 042208

      Delete
    8. Thank you, problem solved. I researched a bit and added these lines before start temp conversion:
      ds18b20_writebyte(DS18B20_CMD_WSCRATCHPAD);
      ds18b20_writebyte(0xFF);//th buffer
      ds18b20_writebyte(0xFF);//tl buffer
      ds18b20_writebyte(0x7F);//the values I want in config register
      ds18b20_reset(); //reset
      ds18b20_writebyte(DS18B20_CMD_SKIPROM);

      Delete
    9. Well done! And thank you for sharing your answer!

      Delete
  14. Hello,
    I want to connect multiple sensors,
    and I have tried your code but it works only on one sensor,
    so can anyone help me please.
    Thank you

    ReplyDelete
    Replies
    1. Hello, you could setup multiple PIN using array, and a struct, like it is done here: http://davidegironi.blogspot.it/2012/12/drive-up-to-3-stepper-motors-on-atmega.html

      Delete
  15. This comment has been removed by the author.

    ReplyDelete
  16. I appreciate your job sir. just to comment something here. the manufature provides a unique address code for each sensor and its possible to connect multiple sensors on the same pin and access each sensor by its address.can this be fixed in the library,it could save pins for othe purpose.

    ReplyDelete
    Replies
    1. Hello, thank you. You should try this, change the ds18b20_gettemp() to ds18b20_gettemp(unsigned char* ds18b20_address). Then between ds18b20_writebyte(DS18B20_CMD_SKIPROM); ds18b20_writebyte(DS18B20_CMD_RSCRATCHPAD); put this code
      ds18b20_writebyte(0x55); for (int i = 0; i < 8; i++) ds18b20_writebyte(ds18b20_address[i]);
      Now i can not try this code, you have to make some tests.

      Delete
  17. Hi! Davide,
    Im Alan.... excellent work!... i have a question?, your library works for a 8MHz frequency? using external crystal or internal clock in AVR

    thanks... and sorry for my bad english

    regards!

    ReplyDelete
    Replies
    1. Yes, it will work at 8Mhz too using both internal or external clock. Just keep in mind that changing fuse settings may block your micro. So apply fusy settings carefully.

      Delete
  18. It sounds like your version of the dallas library can be configured to work with 1Mhz cpu? i have an attiny85 using the Miles Burton library at 8Mhz where it works just fine, but if i drop to 1Mhz it stops working. i'd prefer the lower cpu to save on battery. thanks for any help. Ric G.

    ReplyDelete
    Replies
    1. Hello, this library should work at 1Mhz. Have you try to compile it with avrgcc?

      Delete
  19. Hi Davide, I've used an external crystal 7.3728Mhz with F_CPU = 7372800UL on the Atmega644pa chip. The readings works initially and after say after 20-30 readings, (temperature range average ~-20oC)the reading stops responding. Where could it be wrong? Is the setting correct?? Thanks.

    ReplyDelete
    Replies
    1. Hello, have you check with a logic analyzer the bus? Check it something going wrong with a uart debugger or use a watchdog. I've never test it with you crystal freq I'm sorry.

      Delete
    2. This comment has been removed by the author.

      Delete
  20. Hi Davide,

    tempH = 0xFC; tempL = 0x90;
    retd = ((tempH << 8) + tempL) * 0.0625;

    to get you -55oC.

    How do you do it?

    Thanks.
    Steve.

    ReplyDelete
    Replies
    1. Hello, it's due to the float representation on avrgcc.
      Take a look here: https://circuits.io/circuits/2758039-ds18b20-temp-func-test

      Delete
  21. I am using an atmega128a to mcu. The temperature sensor is connected to a display and it reads 127.9375C at all times and doesn't ever change. This value is obviously not reflecting a temperature, but have yet to find a resolution

    ReplyDelete
    Replies
    1. Hello, have you check that your micro frequency meets the frequency you have compiled for? Also you can check the bus of the sensor.

      Delete