I got my hands on a few of these DS18B20 1-wire digital temperature sensors. They’re really awesome. They’re small, easy to work with, and they run on the 1-wire bus which means they can run on a minimum of two wires. However, I found it easier to just run these devices with 3 lines: +5V, GND, Bus – saves a lot of design complexity.
I found a few good 1-wire drivers for CCS C (especially for these devices):
dallas onewire primitives library and ds1822 driver code
I then took ideas from them and made my own little driver. Some of the code is copied, some of it isn’t. Here it is:
main.c
#include "main.h" #include "1wire.c" #include "ds1820.c" float value = 0.0; void main() { setup_adc_ports(NO_ANALOGS|VSS_VDD); setup_adc(ADC_OFF); setup_spi(SPI_SS_DISABLED); setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); setup_timer_1(T1_DISABLED); setup_timer_2(T2_DISABLED,0,1); setup_oscillator(OSC_8MHZ); setup_uart(9600); delay_ms(1000); printf("Starting...\t\n"); while(TRUE) { value = ds1820_read(); printf("%f\t\n", value); } }
main.h
#ifndef MAIN_H #define MAIN_H #include <16F690.h> #device adc=8 #FUSES NOWDT //No Watch Dog Timer #FUSES INTRC_IO //Internal RC Osc, no CLKOUT #FUSES NOPROTECT //Code not protected from reading #FUSES NOBROWNOUT //No brownout reset #FUSES NOMCLR //Master Clear pin used for I/O #FUSES NOCPD //No EE protection #FUSES PUT //Power Up Timer #FUSES IESO //Internal External Switch Over mode enabled #FUSES FCMEN //Fail-safe clock monitor enabled #use delay(clock=8000000) #use rs232(baud=9600, parity=N, UART1, bits=8, stop=1) #endif /*MAIN_H*/
1wire.c
#ifndef ONE_WIRE_C #define ONE_WIRE_C /* * One wire (1-wire) driver for CCS C compiler. Suitable for use with devices * such as the DS18B20 1-wire digital temperature sensor. */ #define ONE_WIRE_PIN PIN_C5 /* * onewire_reset() * Description: Initiates the one wire bus. */ // OK if just using a single permanently connected device void onewire_reset() { output_low(ONE_WIRE_PIN); // pull the bus low for reset delay_us(500); output_float(ONE_WIRE_PIN); // float the bus high delay_us(500); // wait-out remaining initialisation window output_float(ONE_WIRE_PIN); } /* * onewire_write(int8 data) * Arguments: a byte of data. * Description: writes a byte of data to the device. */ void onewire_write(int8 data) { int8 count; for(count = 0; count < 8; ++count) { output_low(ONE_WIRE_PIN); delay_us(2); // pull 1-wire low to initiate write time-slot. output_bit(ONE_WIRE_PIN, shift_right(&data, 1, 0)); // set output bit on 1-wire delay_us(60); // wait until end of write slot. output_float(ONE_WIRE_PIN); // set 1-wire high again, delay_us(2); // for more than 1us minimum. } } /* * onewire_read() * Description: reads and returns a byte of data from the device. */ int onewire_read() { int count, data; for(count = 0; count < 8; ++count) { output_low(ONE_WIRE_PIN); delay_us(2); // pull 1-wire low to initiate read time-slot. output_float(ONE_WIRE_PIN); // now let 1-wire float high, delay_us(8); // let device state stabilise, shift_right(&data, 1, input(ONE_WIRE_PIN)); // and load result. delay_us(120); // wait until end of read slot. } return data; } #endif /*ONE_WIRE_C*/
ds1820.c
#ifndef DS1820_C #define DS1820_C #include "1wire.c" float ds1820_read(); void ds1820_configure(int8 TH, int8 TL, int8 config); /* * ds1820_read() * Description: reads the ds18x20 device on the 1-wire bus and returns * the temperature */ float ds1820_read() { int8 busy=0, temp1, temp2; signed int16 temp3; float result; //ds1820_configure(0x00, 0x00, 0x00); //9 bit resolution onewire_reset(); onewire_write(0xCC); //Skip ROM, address all devices onewire_write(0x44); //Start temperature conversion while(busy == 0) //Wait while busy (bus is low) busy = onewire_read(); onewire_reset(); onewire_write(0xCC); //Skip ROM, address all devices onewire_write(0xBE); //Read scratchpad temp1 = onewire_read(); temp2 = onewire_read(); temp3 = make16(temp2, temp1); //result = (float) temp3 / 2.0; //Calculation for DS18S20 with 0.5 deg C resolution result = (float) temp3 / 16.0; //Calculation for DS18B20 delay_ms(200); return(result); } /* * ds1820_configure(int8 TH, int8 LH, int8 config) * Description: writes configuration data to the DS18x20 device * Arguments: alarm trigger high, alarm trigger low, configuration */ void ds1820_configure(int8 TH, int8 TL, int8 config) { onewire_reset(); onewire_write(0xCC); //Skip ROM, address all devices onewire_write(0x4E); //Write to scratchpad onewire_write(TH); onewire_write(TL); onewire_write(config); } #endif /*DS1820_C*/
All you have to do is set the define to the appropriate pin you’re using for the 1-wire bus. Remember to attach a 4.7k pullup resistor on the bus to VDD. The value of the pullup resistor is not critical. If I remember correctly, I tested resistors anywhere from 1k to 10k and they worked fine. If not, just stick with the 4.7k pullup as recommended in the DS18B20 datasheet.
Thanks Man, Really!!!
ReplyDeleteCut, Paste, working...
You, ROCK...
Thanks for posting, you saved me a lot of time, and memory ;)
Hi, I'm using a pic 18F4550 with the CCS compiler, I modified the file in the main.h # include <16F690.h> to # include <18f4550.h> and compile error mark me, I have to make further modifications libraries?
ReplyDeleteI used some other sensor drivers ds18b20.cy program if errors are compiled, but the LCD is shown as TEMP: 0.0, does not change the temperature value, even to approximate the environment.
I would greatly appreciate some help regarding the correct use of this sensor, because it's really interesting because it requires no calibration and is very small, my email is snoopdog_06@hotmail.com.
Greetings.
Hi, I'm having the same problem, I've hours searching for other libraries, but nothing change, I just do not know where is the problem, I made the same change that you did and nothing, did you have answer ?I would really apreciate your help
DeleteVery good, my frend, work fine thanks
ReplyDeletehi, i am using 16f877a with lcd ds18b20, and i controlled by hand help me
ReplyDeleteThis may be a little dangerous:
ReplyDeletewhile(busy == 0)
busy = onewire_read();
I've just converted this code to HITECH C. The following project is for the PIC16F88, but it could easily be converted to something else.
ReplyDeletehttp://jwandrews.co.uk/files/controller.zip
I'm using PIC18F4550 and it works perfectly in simulation but it doesn't work on protoboard, can you tell me what i need to change in the code to make it run on 18F4550?
ReplyDeletei m using Atmega16, can u plz tell me at which port should i connect this temp sensor..plz
ReplyDeleteThanks man:) I have used this library of yours before and somehow I lost it. Now I'm back on track. It is quite neat and memory efficient :)
ReplyDelete