Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

displaying temp on lcd

Status
Not open for further replies.

dawson

New Member
I have recently used nigel goodwins lcd tutorial to display a message on an lcd.

Now I would like to integrate a ds18s20 into my cicuit and display the outcome on the lcd display, but cant figure out howto do it.

I currently have this asm from nigel goodwin to display a message:
Code:
;LCD text demo - 4 bit mode
;Nigel Goodwin 2002

	LIST	p=16F628		;tell assembler what chip we are using
	include "P16F628.inc"		;include the defaults for the chip
	ERRORLEVEL	0,	-302	;suppress bank selection messages
	__config 0x3D18			;sets the configuration settings (oscillator type etc.)




		cblock	0x20			;start of general purpose registers
			count			;used in looping routines
			count1			;used in delay routine
			counta			;used in delay routine
			countb			;used in delay routine
			tmp1			;temporary storage
			tmp2
			templcd			;temp store for 4 bit mode
			templcd2	
		endc

LCD_PORT	Equ	PORTA
LCD_TRIS	Equ	TRISA
LCD_RS		Equ	0x04			;LCD handshake lines
LCD_RW		Equ	0x06
LCD_E		Equ	0x07

		org	0x0000

		movlw	0x07
		movwf	CMCON			;turn comparators off (make it like a 16F84)

Initialise	clrf	count
		clrf	PORTA
		clrf	PORTB



SetPorts	bsf 	STATUS,		RP0	;select bank 1
		movlw	0x00			;make all pins outputs
		movwf	LCD_TRIS
		bcf 	STATUS,		RP0	;select bank 0

		call	Delay100		;wait for LCD to settle


		call	LCD_Init		;setup LCD


		clrf	count			;set counter register to zero
Message		movf	count, w		;put counter value in W
		call	Text			;get a character from the text table
		xorlw	0x00			;is it a zero?
		btfsc	STATUS, Z
		goto	NextMessage
		call	LCD_Char
		call	Delay255
		incf	count, f
		goto	Message

NextMessage	call	LCD_Line2		;move to 2nd row, first column

		clrf	count			;set counter register to zero
Message2	movf	count, w		;put counter value in W
		call	Text2			;get a character from the text table
		xorlw	0x00			;is it a zero?
		btfsc	STATUS, Z
		goto	EndMessage
		call	LCD_Char
		incf	count, f
		goto	Message2

EndMessage	
		
Stop		goto	Stop			;endless loop




;Subroutines and text tables

;LCD routines

;Initialise LCD
LCD_Init	movlw	0x20			;Set 4 bit mode
		call	LCD_Cmd

		movlw	0x28			;Set display shift
		call	LCD_Cmd

		movlw	0x06			;Set display character mode
		call	LCD_Cmd

		movlw	0x0d			;Set display on/off and cursor command
		call	LCD_Cmd

		call	LCD_Clr			;clear display

		retlw	0x00

; command set routine
LCD_Cmd		movwf	templcd
		swapf	templcd,	w	;send upper nibble
		andlw	0x0f			;clear upper 4 bits of W
		movwf	LCD_PORT
		bcf	LCD_PORT, LCD_RS	;RS line to 0
		call	Pulse_e			;Pulse the E line high

		movf	templcd,	w	;send lower nibble
		andlw	0x0f			;clear upper 4 bits of W
		movwf	LCD_PORT
		bcf	LCD_PORT, LCD_RS	;RS line to 0
		call	Pulse_e			;Pulse the E line high
		call 	Delay5
		retlw	0x00

LCD_CharD	addlw	0x30
LCD_Char	movwf	templcd
		swapf	templcd,	w	;send upper nibble
		andlw	0x0f			;clear upper 4 bits of W
		movwf	LCD_PORT
		bsf	LCD_PORT, LCD_RS	;RS line to 1
		call	Pulse_e			;Pulse the E line high

		movf	templcd,	w	;send lower nibble
		andlw	0x0f			;clear upper 4 bits of W
		movwf	LCD_PORT
		bsf	LCD_PORT, LCD_RS	;RS line to 1
		call	Pulse_e			;Pulse the E line high
		call 	Delay5
		retlw	0x00

LCD_Line1	movlw	0x80			;move to 1st row, first column
		call	LCD_Cmd
		retlw	0x00

LCD_Line2	movlw	0xc0			;move to 2nd row, first column
		call	LCD_Cmd
		retlw	0x00

LCD_Line1W	addlw	0x80			;move to 1st row, column W
		call	LCD_Cmd
		retlw	0x00

LCD_Line2W	addlw	0xc0			;move to 2nd row, column W
		call	LCD_Cmd
		retlw	0x00

LCD_CurOn	movlw	0x0d			;Set display on/off and cursor command
		call	LCD_Cmd
		retlw	0x00

LCD_CurOff	movlw	0x0c			;Set display on/off and cursor command
		call	LCD_Cmd
		retlw	0x00

LCD_Clr		movlw	0x01			;Clear display
		call	LCD_Cmd
		retlw	0x00

LCD_HEX		movwf	tmp1
		swapf	tmp1,	w
		andlw	0x0f
		call	HEX_Table
		call	LCD_Char
		movf	tmp1, w
		andlw	0x0f
		call	HEX_Table
		call	LCD_Char
		retlw	0x00

Delay255	movlw	0xff		;delay 255 mS
		goto	d0
Delay100	movlw	d'100'		;delay 100mS
		goto	d0
Delay50		movlw	d'50'		;delay 50mS
		goto	d0
Delay20		movlw	d'20'		;delay 20mS
		goto	d0
Delay5		movlw	0x05		;delay 5.000 ms (4 MHz clock)
d0		movwf	count1
d1		movlw	0xC7			;delay 1mS
		movwf	counta
		movlw	0x01
		movwf	countb
Delay_0
		decfsz	counta, f
		goto	$+2
		decfsz	countb, f
		goto	Delay_0

		decfsz	count1	,f
		goto	d1
		retlw	0x00

Pulse_e		bsf	LCD_PORT, LCD_E
		nop
		bcf	LCD_PORT, LCD_E
		retlw	0x00

;end of LCD routines

HEX_Table  	ADDWF   PCL       , f
            	RETLW   0x30
            	RETLW   0x31
            	RETLW   0x32
            	RETLW   0x33
            	RETLW   0x34
            	RETLW   0x35
            	RETLW   0x36
            	RETLW   0x37
            	RETLW   0x38
            	RETLW   0x39
            	RETLW   0x41
            	RETLW   0x42
            	RETLW   0x43
            	RETLW   0x44
            	RETLW   0x45
            	RETLW   0x46


Text		addwf	PCL, f
		retlw	'H'
		retlw	'e'
		retlw	'l'
		retlw	'l'
		retlw	'o'
		retlw	0x00

Text2		ADDWF   PCL, f
            	RETLW   'R'
            	RETLW   'e'
            	RETLW   'a'
            	RETLW   'd'
            	RETLW   'y'
            	RETLW   '.'
            	RETLW   '.'
            	RETLW   '.'
            	RETLW   0x00


		end

and found this code to retrieve the temp from the maxim website:
Code:
; *******************************************
;
; Dallas Semiconductor PIC code
;
; This code will interface a PIC16F628 microcontroller to
; a DS2761 High-Precision Li+ Battery Monitor
;
; *******************************************;
;
;                   VCC
;                     ^
;                    |
;                    |
;                    /
;                    \ Rpup
;                    /
;                    \
;                    |
; 16F628             |                   DS2761
; RB1 (pin 7) ------------------------------ DQ (pin 7)
;
; *******************************************;

;---------------------------------------------------------
; List your processor here.

      list p=16F628

; Include the processor header file here.

      #include <p16F628.inc>
;---------------------------------------------------------
; Assign the PORTB with Constants

      constant DQ=1                             ; Use RB1 (pin7) for 1-Wire
;--------------------------------------------------------
; These constants are standard 1-Wire ROM commands

      constant SRCHROM=0xF0
      constant RDROM=0x33
      constant MTCHROM=0x55
      constant SKPROM=0xCC
;---------------------------------------------------------
; These constants are used throughout the code

      cblock        0x20
             IOBYTE
             TMP0                               ; Address 0x23
             COUNT                              ; Keep track of bits
             PICMSB                             ; Store the MSB
             PICLSB                             ; Store the LSB
             PDBYTE                             ; Presence Detect Pulse
      endc
;---------------------------------------------------------
; Setup your configuration word by using __config.

; For the 16F628, the bits are:
; CP1,CP0,CP1,CP0,N/A, CPD, LVP, BODEN, MCLRE, FOSC2, PWRTE, WDTE, FOSC1, FOSC0
; CP1 and CP0 are the Code Protection bits
; CPD: is the Data Code Protection Bit
; LVP is the Low Voltage Programming Enable bit
; PWRTE is the power-up Timer enable bit
; WDTE is the Watchdog timer enable bit
; FOSC2, FOSC1 and FOSC0 are the oscillator selection bits.

; CP disabled, LVP disabled, BOD disabled, MCLR enabled, PWRT disabled, WDT disabled, INTRC I/O oscillator
; 11111100111000

      __config 0x3F38
;---------------------------------------------------------
; Set the program origin for subsequent code.

      org 0x00
      GOTO          SETUP
      NOP
      NOP
      NOP
      GOTO          INTERRUPT                   ; PC 0x04...INTERRUPT VECTOR!
;---------------------------------------------------------
INTERRUPT:
      SLEEP
;---------------------------------------------------------
; Option Register bits
; ____
; RBPU,INTEDG,TOCS,TOSE,PSA,PS2,PS1,PS0
; 7=PORTB Pullup Enable, 6=Interrupt Edge Select, 5=TMR0 Source,
; 4=TMR0 Source Edge, 3=Prescaler Assign, 2-0=Prescaler Rate Select

; 11010111
; PORTB pullups disabled,rising edge,internal,hightolow,TMR0,1:256

SETUP:
      BCF           STATUS,RP1
      BSF           STATUS,RP0                  ; Select Bank 1 of data memory
      MOVLW         0xD7
      MOVWF         OPTION_REG
      BCF           STATUS,RP0                  ; Select Bank 0 of data memory
;---------------------------------------------------------

      BCF           INTCON,7                    ; Disable all interrupts.

;---------------------------------------------------------
      GOTO          START
;---------------------------------------------------------
; Include the 1-Wire communication routines and macros

      #INCLUDE 1w_16f6x.inc
;---------------------------------------------------------
START:
;---------------------------------------------------------
GET_TEMP:
      CALL          OW_RESET                    ; Send Reset Pulse and read for Presence Detect Pulse
      BTFSS         PDBYTE,0                    ; 1 = Presence Detect Detected
      GOTO          NOPDPULSE
      MOVLW         SKPROM
      CALL          DSTXBYTE                    ; Send Skip ROM Command (0xCC)
      MOVLW         0x69
      CALL          DSTXBYTE                    ; Send Read Data Command (0x69)
      MOVLW         0x0E
      CALL          DSTXBYTE                    ; Send the DS2761 Current Register MSB address (0x0E)
      CALL          DSRXBYTE                    ; Read the DS2761 Current Register MSB
      MOVF          IOBYTE,W
      MOVWF         PICMSB                      ; Put the Current MSB into file PICMSB
      CALL          DSRXBYTE                    ; Read the DS2761 Current Register LSB
      MOVF          IOBYTE,W
      MOVWF         PICLSB                      ; Put the Current LSB into file PICLSB
      CALL          OW_RESET

NOPDPULSE:                                      ; Add some error processing here!
      SLEEP                                     ; Put PIC to sleep
;---------------------------------------------------------
      end

how can I combine the two so that I just add the ds18s20 into the current lcd project and display the temprature on it?
 

dawson

New Member
I have also interfaced a DS1820 to a PIC16F628A, and displayed the temperature on a LCD screen. But I used mikroC compiler. Check here: Experiments with PIC16F628A: Experiment No. 4 : Reading Temperature Values from DS1820 using 1-Wire Protocol - Raj
Hi, i have had a look at your site and it looks like your project does what i need, but i am new to pics and am just trying to learn assembly. I dont know how to use or compile c. can anyone help me with the assembly or is c the best way?
 

rajbex

Member
I would say, if you have some knowledge of digital systems and microprocessor architecture, then it is easy to learn assembly language. Otherwise, if you know programming in any high level languages, I would say you could do C too. Compiling in C using mikroC is just a piece of cake. Download the free version of mikroC compiler and try it.
-Raj
Experiments with PIC16F628A
 

dawson

New Member
Will download mikroc and give it a try.

I have a few queries about your circuit though.

You use RB4 for one of your data lines to LCD, is this easily changed as I only have a LVP programmer, meaning I cannot use RB4.

Why do you use an external crystal when the pic has one built in?

thanks
 

Mr RB

Well-Known Member
If you download the MikroC code examples for the EasyPIC5 or EasyPIC6, the LCD example, at the top of code it uses bit defines to set the PIC pins that the LCD is connected to. You can just change these bit defines to use whatever PIC pins you prefer.

External xtal gives a better timing accuracy, so if you want any clock like features or accurate timed periods it's a better option. But you can use the DS1820 and LCD without needing a xtal.
 

rajbex

Member
Yes, you can easily make changes. You can use RB0-RB3 for data lines, and connect DS1820 to any of the other remaining PORTB pins. You have to change the pin definitions in the code. Example,
For LCD connections,
// LCD connections definitions
sbit LCD_RS at RA0_bit;
sbit LCD_EN at RA1_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;
sbit LCD_RS_Direction at TRISA0_bit;
sbit LCD_EN_Direction at TRISA1_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD connections definitions


and for DS1820

Ow_Reset(&PORTB, 5); // If you are going to use RB.5 for DS1820 data read.

You can also use internal oscillator, I have got an external because it is my general purpose development board, I may need it for better accuracy in my future projects.

- Raj
Experiments with PIC16F628A
 

dawson

New Member
Hi a ga in,
First I tried your experiment 3 interfacing the LCD on its own but with the above changes. This worked :)

Then I decided to add the ds18s20 and tried the following without success:

Code:
/* Project name:
     One Wire Communication Test between PIC16F628A and DS1820
 * Copyright:
     (c) Rajendra Bhatt, 2009.
 * Description:
     This code demonstrates how to use One Wire Communication Protocol
     between PIC16F628A and a 1-wire peripheral device. The peripheral
     device used here is DS1820, digital temperature sensor.
     MCU:             PIC16F628A
     Oscillator:      XT, 4.0 MHz
*/
// LCD connections definitions
sbit LCD_RS at RA0_bit;
sbit LCD_EN at RA1_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;
sbit LCD_RS_Direction at TRISA0_bit;
sbit LCD_EN_Direction at TRISA1_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD connections definitions

// String array to store temperature value to display
char *temp = "000.00";

// Temperature Resolution : No. of bits in temp value = 9
const unsigned short TEMP_RES = 9;

// Variable to store temperature register value
unsigned temp_value;

void Display_Temperature(unsigned int temp2write) {
  const unsigned short RES_SHIFT = TEMP_RES - 8;

  // Variable to store Integer value of temperature
  char temp_whole;

  // Variable to store Fraction value of temperature
  unsigned int temp_fraction;

  // check if temperature is negative
  if (temp2write & 0x8000) {
     temp[0] = '-';
     // Negative temp values are stored in 2's complement form
     temp2write = ~temp2write + 1;
     }

  // Get temp_whole by dividing by 2 (DS1820 9-bit resolution with
  // 0.5 Centigrade step )
  temp_whole = temp2write >> RES_SHIFT ;

  // convert temp_whole to characters
  if (temp_whole/100)
  // 48 is the decimal character code value for displaying 0 on LCD
     temp[0] = temp_whole/100  + 48;
  else
     temp[0] = '0';

  temp[1] = (temp_whole/10)%10 + 48;             // Extract tens digit
  temp[2] =  temp_whole%10     + 48;             // Extract ones digit

  // extract temp_fraction and convert it to unsigned int
  temp_fraction  = temp2write << (4-RES_SHIFT);
  temp_fraction &= 0x000F;
  temp_fraction *= 625;

  // convert temp_fraction to characters
  temp[4] =  temp_fraction/1000    + 48;         // Extract tens digit
  temp[5] = (temp_fraction/100)%10 + 48;         // Extract ones digit

  // print temperature on LCD
  Lcd_Out(2, 5, temp);
}

void main() {
  CMCON  |= 7;                       // Disable Comparators
  Lcd_Init();                                    // Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);                           // Clear LCD
  Lcd_Cmd(_LCD_CURSOR_OFF);                      // Turn cursor off
  Lcd_Out(1, 3, "Temperature:   ");
  // Print degree character, 'C' for Centigrades
  Lcd_Chr(2,11,223);
 // different LCD displays have different char code for degree
 // if you see greek alpha letter try typing 178 instead of 223

  Lcd_Chr(2,12,'C');

  //--- main loop
  do {
    //--- perform temperature reading
    Ow_Reset(&PORTB, 5);      // Onewire reset signal
    Ow_Write(&PORTB, 5, 0xCC);   // Issue command SKIP_ROM
    Ow_Write(&PORTB, 5, 0x44);   // Issue command CONVERT_T
    Delay_ms(600);
    // If this delay is less than 500ms, you will see the first reading on LCD
    //85C which is (if you remember from my article on DS1820)
    //a power-on-reset value.

    Ow_Reset(&PORTB, 5);
    Ow_Write(&PORTB, 5, 0xCC);    // Issue command SKIP_ROM
    Ow_Write(&PORTB, 5, 0xBE);    // Issue command READ_SCRATCHPAD

    // Read Byte 0 from Scratchpad
    temp_value =  Ow_Read(&PORTB, 5);
    // Then read Byte 1 from Scratchpad and shift 8 bit left and add the Byte 0
    temp_value = (Ow_Read(&PORTB, 5) << 8) + temp_value;

    //--- Format and display result on Lcd
    Display_Temperature(temp_value);

    } while (1);
}

Have I forgot to change anything?
 

rajbex

Member
The primary difference between DS1820 and DS18S20 is the temperature conversion time: DS1820 = 500ms (max) and DS18S20 = 750ms (max). Try replacing Delay_ms(600) by Delay_ms(800) and see if you can get any good luck. I would also recommend you to search online for other differences. Make sure you have used a 4.7K pull up resistor to the data line. See the diagrams on my blog for this. Experiments with PIC16F628A: The 1-Wire Communication Protocol

- Raj
Experiments with PIC16F628A
 

dawson

New Member
I have not tried to change the delay but I have now pulled the data line up with a 4.7K r esistor and it now works. Thank you

And thank you for showing me pic programming with c, this way seems better for me.

One more thing, is it possible to display temp in 0.1 degrees instead of 0.5? example 24.7 degrees. Or would I require a different sensor?
 

dawson

New Member
Yes thanks I will look into the other sensor. Will the code need to be changed if I get the other sensor?
 

rajbex

Member
Dawson,
Yes, you can use DS18B20 to get higher resolution. With 12-bit temperature value, you will be able to get 0.0625 degree C resolution. You have to program the configuration register in DS18B20 to set the resolution of the temperature-to-digital conversion to 9, 10, 11, or 12 bits. But, fortunately, the default resolution at power up is 12-bit. So you don't have to program the config register to get 12-bit accuracy.

Further, you don't have to do major changes in the code, except change

const unsigned short TEMP_RES = 9; to const unsigned short TEMP_RES = 12;

This will make the value of RES_SHIFT = 4, which means shift the 12 bit binary temperature value to right by 4-bits. This is required to get the whole number of temp value. When you have 12-bit temperature value, you have to divide it by 16 to get the integer part of the real temperature (because 16*0.0625 = 1 degree C). In binary operations, divide by 2 is obtained by shifting the number right by 1-bit. So, Right Shift by 4-bit gives you divide by 16.
Hope this will help you, and good luck.

- Raj
Experiments with PIC16F628A
 
Status
Not open for further replies.

EE World Online Articles

Loading
Top