OneWire temperature sensor DS18B20 and I2C LCD display

This sketch shows how to connect I2C LCD display and OneWire temperature sensor DS18B20 to the Z-Uno board. Temperature values is read from sensor, printed on the display and is periodically report to channel Multilevel Sensor.
  • Z-Uno board
  • Breadboard
  • LCD display 16x2 (like this)
  • I2C/SPI LCD Backpack (like this)
  • DS18B20 temperature sensor (like this or waterproof variant like this)
  • 1 220 Ω resistor
  • 4 wires

Download Fritzing project
// demo sketch for connecting I2C LCD display and OneWire temperature sensor DS18B20 to Z-Uno

// add library Wire.h
#include "Wire.h"
#include "Print.h"

// add library ds18b20
#include "ZUNO_DS18B20.h"

// i2c address
#define LC_I2CADDR 0x27

// commands
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80

// flags for display entry mode
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00

// flags for display on/off control
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00

// flags for display/cursor shift
#define LCD_DISPLAYMOVE 0x08
#define LCD_CURSORMOVE 0x00
#define LCD_MOVERIGHT 0x04
#define LCD_MOVELEFT 0x00

// flags for function set
#define LCD_8BITMODE 0x10
#define LCD_4BITMODE 0x00
#define LCD_2LINE 0x08
#define LCD_1LINE 0x00
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00

// flags for backlight control
#define LCD_BACKLIGHT 0x08
#define LCD_NOBACKLIGHT 0x00

#define En 0x4  // Enable bit
#define Rw 0x2  // Read/Write bit
#define Rs 0x1  // Register select bit

int  cols;
int  rows;
int  numlines;
int  backlightval;
int  displayfunction;
int  displaycontrol;
int  displaymode;

// pin connection ds18b20
#define PIN_DS18B20 11
// add library OneWire
OneWire ow(11);
// onewire connection temperature sensors
DS18B20Sensor  ds1820(&ow); 

byte addr1[8];
int temp; 

// set up channel
ZUNO_SETUP_CHANNELS(
   ZUNO_SENSOR_MULTILEVEL(ZUNO_SENSOR_MULTILEVEL_TYPE_TEMPERATURE, 
                          SENSOR_MULTILEVEL_SCALE_CELSIUS, 
                          SENSOR_MULTILEVEL_SIZE_TWO_BYTES, 
                          SENSOR_MULTILEVEL_PRECISION_ONE_DECIMAL,
                          getterTemp)
);

void setup() {
  Serial.begin();
  Serial.println("start");
  lcdbegin(16,2);  
 }

void loop() {
    // obtaining readings from the sensor ds18b20
    temp=getTempds18b20();
    // print temp display
    printTempds18b20(temp);
    // send data to channel
    zunoSendReport(1);     
    // send every 30 second
    delay(30000);
  }

int getTempds18b20() {
    // search OneWire device
    if(ds1820.scanAloneSensor(addr1)==1) { 
       for(int i = 0; i < 8; i++) {
          // print OneWire kod
          Serial.print(addr1[i], HEX);
          Serial.print(" ");
          }
       Serial.println();
       Serial.print("t=");
       // receiving data from the sensor      
       temp=ds1820.getTempC100(addr1)/10;
       Serial.println(temp);       
       } else {
       Serial.println("error");
       temp=1000;       
       }
    return temp;
    }

 word getterTemp() {
  return temp;
}


void printTempds18b20(int temp) {
  clear();
  setCursor(0,0);
  write('T');
  write('=');  
  if(temp<100) {
     write(32);
  } else {
     write(temp/100+48);
  }
  write((temp%100)/10+48); 
  write(44);   
  write((temp%100)%10+48);  
  write(32);  
  write('C');  
  return;
}

void lcdbegin(int c,int r) {
  //
  cols=c;
  rows=r;
  backlightval = LCD_BACKLIGHT;
  //
  Wire.begin();
  displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
  //  
  if (rows > 1) {
    displayfunction |= LCD_2LINE;
  }
  numlines = rows;

  // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
  // according to datasheet, we need at least 40ms after power rises above 2.7V
  // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50
  delay(50); 
  
  // Now we pull both RS and R/W low to begin commands
  expanderWrite(backlightval); // reset expanderand turn backlight off (Bit 8 =1)
  delay(1000);

  //put the LCD into 4 bit mode
  // this is according to the hitachi HD44780 datasheet
  // figure 24, pg 46
  
   // we start in 8bit mode, try to set 4 bit mode
   write4bits(0x03 << 4);
   delayMicroseconds(4500); // wait min 4.1ms
   
   // second try
   write4bits(0x03 << 4);
   delayMicroseconds(4500); // wait min 4.1ms
   
   // third go!
   write4bits(0x03 << 4); 
   delayMicroseconds(150);
   
   // finally, set to 4-bit interface
   write4bits(0x02 << 4); 


  // set # lines, font size, etc.
  command(LCD_FUNCTIONSET | displayfunction);  
  
  // turn the display on with no cursor or blinking default
  displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
  display();
  
  // clear it off
  clear();
  
  // Initialize to default text direction (for roman languages)
  displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
  
  // set the entry mode
  command(LCD_ENTRYMODESET | displaymode);
  
  home();

  }

/********** high level commands, for the user! */
void clear(){
  command(LCD_CLEARDISPLAY);// clear display, set cursor position to zero
  delayMicroseconds(2000);  // this command takes a long time!
}

void home(){
  command(LCD_RETURNHOME);  // set cursor position to zero
  delayMicroseconds(2000);  // this command takes a long time!
}

void setCursor(uint8_t col, uint8_t row){
  int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
  if ( row > numlines ) {
    row = numlines-1;    // we count rows starting w/0
  }
  command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
}

// Turn the display on/off (quickly)
void noDisplay() {
  displaycontrol &= ~LCD_DISPLAYON;
  command(LCD_DISPLAYCONTROL | displaycontrol);
}
void display() {
  displaycontrol |= LCD_DISPLAYON;
  command(LCD_DISPLAYCONTROL | displaycontrol);
}




inline void command(uint8_t value) {
  send(value, 0);
}

inline size_t write(uint8_t value) {
  send(value, Rs);
  return 0;
}
/************ low level data pushing commands **********/

// write either command or data
void send(uint8_t value, uint8_t mode) {
  uint8_t highnib=value&0xf0;
  uint8_t lownib=(value<<4)&0xf0;
  write4bits((highnib)|mode);
  write4bits((lownib)|mode); 
}

void write4bits(uint8_t value) {
  expanderWrite(value);
  pulseEnable(value);
}

void expanderWrite(uint8_t _data){                                        
  Wire.beginTransmission(LC_I2CADDR);
  Wire.write((int)(_data) | backlightval);
  Wire.endTransmission();   
}

void pulseEnable(uint8_t _data){
  expanderWrite(_data | En);  // En high
  delayMicroseconds(1);   // enable pulse must be >450ns
  
  expanderWrite(_data & ~En); // En low
  delayMicroseconds(50);    // commands need > 37us to settle
}
Download this sketch
	// demo sketch for connecting I2C LCD display and OneWire temperature sensor DS18B20 to Z-Uno
	
	// add library Wire.h
	#include "Wire.h"
	#include "Print.h"
	
	// add library ds18b20
	#include "ZUNO_DS18B20.h"
	
	// i2c address
	#define LC_I2CADDR 0x27
	
	// commands
	#define LCD_CLEARDISPLAY 0x01
	#define LCD_RETURNHOME 0x02
	#define LCD_ENTRYMODESET 0x04
	#define LCD_DISPLAYCONTROL 0x08
	#define LCD_CURSORSHIFT 0x10
	#define LCD_FUNCTIONSET 0x20
	#define LCD_SETCGRAMADDR 0x40
	#define LCD_SETDDRAMADDR 0x80
	
	// flags for display entry mode
	#define LCD_ENTRYRIGHT 0x00
	#define LCD_ENTRYLEFT 0x02
	#define LCD_ENTRYSHIFTINCREMENT 0x01
	#define LCD_ENTRYSHIFTDECREMENT 0x00
	
	// flags for display on/off control
	#define LCD_DISPLAYON 0x04
	#define LCD_DISPLAYOFF 0x00
	#define LCD_CURSORON 0x02
	#define LCD_CURSOROFF 0x00
	#define LCD_BLINKON 0x01
	#define LCD_BLINKOFF 0x00
	
	// flags for display/cursor shift
	#define LCD_DISPLAYMOVE 0x08
	#define LCD_CURSORMOVE 0x00
	#define LCD_MOVERIGHT 0x04
	#define LCD_MOVELEFT 0x00
	
	// flags for function set
	#define LCD_8BITMODE 0x10
	#define LCD_4BITMODE 0x00
	#define LCD_2LINE 0x08
	#define LCD_1LINE 0x00
	#define LCD_5x10DOTS 0x04
	#define LCD_5x8DOTS 0x00
	
	// flags for backlight control
	#define LCD_BACKLIGHT 0x08
	#define LCD_NOBACKLIGHT 0x00
	
	#define En 0x4  // Enable bit
	#define Rw 0x2  // Read/Write bit
	#define Rs 0x1  // Register select bit
	
	int  cols;
	int  rows;
	int  numlines;
	int  backlightval;
	int  displayfunction;
	int  displaycontrol;
	int  displaymode;
	
	// pin connection ds18b20
	#define PIN_DS18B20 11
	// add library OneWire
	OneWire ow(11);
	// onewire connection temperature sensors
	DS18B20Sensor  ds1820(&ow); 
	
	byte addr1[8];
	int temp; 
	
	// set up channel
	ZUNO_SETUP_CHANNELS(
	   ZUNO_SENSOR_MULTILEVEL(ZUNO_SENSOR_MULTILEVEL_TYPE_TEMPERATURE, 
							  SENSOR_MULTILEVEL_SCALE_CELSIUS, 
							  SENSOR_MULTILEVEL_SIZE_TWO_BYTES, 
							  SENSOR_MULTILEVEL_PRECISION_ONE_DECIMAL,
							  getterTemp)
	);
	
	void setup() {
	  Serial.begin();
	  Serial.println("start");
	  lcdbegin(16,2);  
	 }
	
	void loop() {
		// obtaining readings from the sensor ds18b20
		temp=getTempds18b20();
		// print temp display
		printTempds18b20(temp);
		// send data to channel
		zunoSendReport(1);     
		// send every 30 second
		delay(30000);
	  }
	
	int getTempds18b20() {
		// search OneWire device
		if(ds1820.scanAloneSensor(addr1)==1) { 
		   for(int i = 0; i < 8; i++) {
			  // print OneWire kod
			  Serial.print(addr1[i], HEX);
			  Serial.print(" ");
			  }
		   Serial.println();
		   Serial.print("t=");
		   // receiving data from the sensor      
		   temp=ds1820.getTempC100(addr1)/10;
		   Serial.println(temp);       
		   } else {
		   Serial.println("error");
		   temp=1000;       
		   }
		return temp;
		}
	
	 word getterTemp() {
	  return temp;
	}
	
	
	void printTempds18b20(int temp) {
	  clear();
	  setCursor(0,0);
	  write('T');
	  write('=');  
	  if(temp<100) {
		 write(32);
	  } else {
		 write(temp/100+48);
	  }
	  write((temp%100)/10+48); 
	  write(44);   
	  write((temp%100)%10+48);  
	  write(32);  
	  write('C');  
	  return;
	}
	
	void lcdbegin(int c,int r) {
	  //
	  cols=c;
	  rows=r;
	  backlightval = LCD_BACKLIGHT;
	  //
	  Wire.begin();
	  displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
	  //  
	  if (rows > 1) {
		displayfunction |= LCD_2LINE;
	  }
	  numlines = rows;
	
	  // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
	  // according to datasheet, we need at least 40ms after power rises above 2.7V
	  // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50
	  delay(50); 
	  
	  // Now we pull both RS and R/W low to begin commands
	  expanderWrite(backlightval); // reset expanderand turn backlight off (Bit 8 =1)
	  delay(1000);
	
	  //put the LCD into 4 bit mode
	  // this is according to the hitachi HD44780 datasheet
	  // figure 24, pg 46
	  
	   // we start in 8bit mode, try to set 4 bit mode
	   write4bits(0x03 << 4);
	   delayMicroseconds(500); // wait min 4.1ms
	   delay(4);
	   
	   // second try
	   write4bits(0x03 << 4);
	   delayMicroseconds(500); // wait min 4.1ms
	   delay(4);
	   
	   // third go!
	   write4bits(0x03 << 4); 
	   delayMicroseconds(150);
	   
	   // finally, set to 4-bit interface
	   write4bits(0x02 << 4); 
	
	
	  // set # lines, font size, etc.
	  command(LCD_FUNCTIONSET | displayfunction);  
	  
	  // turn the display on with no cursor or blinking default
	  displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
	  display();
	  
	  // clear it off
	  clear();
	  
	  // Initialize to default text direction (for roman languages)
	  displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
	  
	  // set the entry mode
	  command(LCD_ENTRYMODESET | displaymode);
	  
	  home();
	
	  }
	
	/********** high level commands, for the user! */
	void clear(){
	  command(LCD_CLEARDISPLAY);// clear display, set cursor position to zero
	  delay(2);  // this command takes a long time!
	}
	
	void home(){
	  command(LCD_RETURNHOME);  // set cursor position to zero
	  delay(2);  // this command takes a long time!
	}
	
	void setCursor(uint8_t col, uint8_t row){
	  int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
	  if ( row > numlines ) {
		row = numlines-1;    // we count rows starting w/0
	  }
	  command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
	}
	
	// Turn the display on/off (quickly)
	void noDisplay() {
	  displaycontrol &= ~LCD_DISPLAYON;
	  command(LCD_DISPLAYCONTROL | displaycontrol);
	}
	void display() {
	  displaycontrol |= LCD_DISPLAYON;
	  command(LCD_DISPLAYCONTROL | displaycontrol);
	}
	
	
	
	
	inline void command(uint8_t value) {
	  send(value, 0);
	}
	
	inline size_t write(uint8_t value) {
	  send(value, Rs);
	  return 0;
	}
	/************ low level data pushing commands **********/
	
	// write either command or data
	void send(uint8_t value, uint8_t mode) {
	  uint8_t highnib=value&0xf0;
	  uint8_t lownib=(value<<4)&0xf0;
	  write4bits((highnib)|mode);
	  write4bits((lownib)|mode); 
	}
	
	void write4bits(uint8_t value) {
	  expanderWrite(value);
	  pulseEnable(value);
	}
	
	void expanderWrite(uint8_t _data){                                        
	  Wire.beginTransmission(LC_I2CADDR);
	  Wire.write((int)(_data) | backlightval);
	  Wire.endTransmission();   
	}
	
	void pulseEnable(uint8_t _data){
	  expanderWrite(_data | En);  // En high
	  delayMicroseconds(1);   // enable pulse must be >450ns
	  
	  expanderWrite(_data & ~En); // En low
	  delayMicroseconds(50);    // commands need > 37us to settle
	}
Download this sketch