PIC16F1619 help connecting LM35 temperature-sensor

Find out how to setup your programmer's software and how to solve many common problems.

Moderator: phalanx

Post Reply
burton666
Posts: 3
Joined: Tue May 16, 2017 9:16 am

PIC16F1619 help connecting LM35 temperature-sensor

Post by burton666 » Tue May 16, 2017 9:52 am

I am really new to PIC microcontrollers and have purchased a Microship curiosity bord http://www.microchip.com/Developmenttoo ... O=DM164137which uses a PIC16F1619 managed to get the value of a potentiometer displayed in a LCD using the code below. But I want to connect a LM35 http://www.ti.com/lit/ds/symlink/lm35.pdf temperature-sensor to the board and show the temperature instead of the potentiometer.

I have changed this part:

TRISCbits.TRISC3 = 1; //Sensor is connected to RC3...set as input
ANSELCbits.ANSC3 = 1; //analog
ADCON0 = 0b00011101; //select RC3 as source of ADC and enable the module (AN7)

But I guess that I need to alter the sketch some more. Can anyone help me with the code for adding the sensor and showing it in the lcd?

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <htc.h> 
#define _XTAL_FREQ 500000
 
#define E_bit PORTAbits.RA0
#define RS_bit PORTAbits.RA2
#define CLEAR 0x01
#define ADDRESS 0x80 

void init (void);
void init_display(void);
void print_char(char data);
void print_instr(char instr);
void print_text(const char *data);
void EE(void);
void E(void);


void main(void)
    {
    unsigned char digits[5];
    unsigned int adcval;
   
    init();
    print_instr(CLEAR);
    
    TRISCbits.TRISC0 = 1;         //Potentiometer is connected to RC0...set as input
    ANSELCbits.ANSC0 = 1;         //analog
    ADCON0 = 0b00010001;          //select RC0 as source of ADC and enable the module (AN4)
    ADCON1 = 0b00010000;          //left justified - FOSC/8 speed - Vref is Vdd

    
    for(;;)
        {
	adcval = adc();             //grab the top 8 MSbs
        __delay_ms(5);             //delay for AT LEAST 5ms
        digits[0] = adcval / 1000 + 48;
        digits[1] = (adcval / 100) % 10 + 48;
        digits[2] = (adcval / 10) % 10 + 48;
        digits[3] = adcval % 10 + 48;
        digits[4] = '\0';

        print_text(digits);

        
        }
    }
    
	int adc(void) {
    __delay_us(5);                //wait for ADC charging cap to settle
    GO = 1;
    while (GO) continue;          //wait for conversion to be finished

    return (ADRESH << 8) | ADRESL;                
}


void init (void)
    {
    LATA=0;
    LATB=0;
    PORTA=0;
    PORTB=0;
    ANSELA=0;
    ANSELB=0;
    TRISA=0;
    TRISB=0;
    init_display();
    }
  


void init_display(void)
	{
		// See the datasheet flow chart for the procedure below
		// This part initiates the LCD in 4-bit mode...
                __delay_ms(25);
		PORTB=0x30;
		EE();
		PORTB=0x30;
		EE();
		PORTB=0x30;
		EE();
		PORTB=0x20;
		EE();
	
		// Set LCD properties...
		print_instr(0x28);	// 2: Dual line (even though it is single line)
		print_instr(0x0C);	// 3: Display on, cursor, blink
		print_instr(CLEAR);	// 4: Clear
		print_instr(0x06);	// 5: Entry mode set

// LCD is now initialized...
	}

/*******************************************/
// Print chars to LCD with 4-bit method
/*******************************************/
void print_char(char data)
	{
		//PORTC = (data >> 4) & 0x0F;
                PORTB = data & 0xF0;
		RS_bit=1; // RS
		E();

		//PORTC = data & 0x0F;
                PORTB = (data << 4) & 0xF0;
		RS_bit=1; // RS
		E();
                PORTB=0;
                PORTA=0;
	}

/*******************************************/
// Print instruction to LCD with 4-bit method
/*******************************************/
void print_instr(char instr)
	{
		//PORTC = (instr >> 4) & 0x0F;
                PORTB = instr & 0xF0;
		E();

		//PORTC = instr & 0x0F;
                PORTB = (instr << 4) & 0xF0;
		E();
                PORTB=0;
                PORTA=0;
	}

/*******************************************/
// Toggle E to execute command/instruction
// With a litle bit longer delay than std.
/*******************************************/
void EE(void)
	{
		__delay_ms(5);
		E_bit=0;
		__delay_ms(5);
		E_bit=1;
		__delay_ms(5);
		E_bit=0;
		__delay_ms(5);
	}

/*******************************************/
// Toggle E to execute command/instruction
/*******************************************/
void E(void)
	{
		__delay_us(25);
		E_bit=0;
		__delay_us(25);
		E_bit=1;
		__delay_us(25);
		E_bit=0;
		__delay_us(25);
	}

void print_text(const char *data)
    {
    char i=0;
    while(data[i])
        {
        print_char(data[i++]);
        }
    print_instr(ADDRESS+0x60);
    i=0;
    while(data[i]&&(i<8))
        {
        print_char(data[i++]);
        }
    if (i==8)
        {
        print_instr(ADDRESS+0x40);
        while(data[i])
            {
            print_char(data[i++]);
            }
        }

    }

User avatar
phalanx
Non-SFE Guru
Posts: 1958
Joined: Sun Nov 30, 2003 8:57 am
Location: Candia, NH

Re: PIC16F1619 help connecting LM35 temperature-sensor

Post by phalanx » Wed May 17, 2017 9:29 am

A couple quick questions.

The code you posted still shows the ADC configured for the potentiometer. Is the code you're testing updated with the "changed" part you listed?

When running the potentiometer code work properly and display values on the LCD?

Your adc() function returns a signed integer but the value you return is built from ADRESH and ADRESL which would need to be unsigned for proper use. The returned signed value is then stored in an unsigned variable. Have you checked with the debugger to see if the ADRESH and ADRESL values are being returned correctly?

What's the expected voltage output range from the temperature sensor?

Your integer to ascii conversion routine doesn't account for a full range value from the ADC which could have digits in the ten-thousands range. The ADC can return a maximum value 65472 (0xFFC0) so the first step in your conversion would be (65427/1000)+48 = 113 or an ascii "q". Have a look at the ITOA function (Integer-TO-Ascii) which can handle this for you.

-Bill

burton666
Posts: 3
Joined: Tue May 16, 2017 9:16 am

Re: PIC16F1619 help connecting LM35 temperature-sensor

Post by burton666 » Wed May 17, 2017 11:55 am

Thanks for the answer. No the code that I posted was only to get a value from the potentiometer at RC0 and I think I made the digits-array a little bigger in my last attempt so that I got a value from like 20-65000. But I can't say that I really understand the workings of this. Can I skip the array and just get the value directly? I did use a unsigned int at first in the adc() function but I always got some error that only dissapeared when removing the "unsigned" -part.

According to the temperature-sensor datasheet :
VOUT = 250 mV at 25°C
0 mV + 10.0 mV/°C

And it is only supposed to measure temperatures from 20-35 °C

As you might see I am struggeling with the basics but am trying to learn. I only want the easiest way to connect the LCD and to have it show the temp value. After this works I was planning to experiment to get some more functionality using buttons and other devices.

User avatar
phalanx
Non-SFE Guru
Posts: 1958
Joined: Sun Nov 30, 2003 8:57 am
Location: Candia, NH

Re: PIC16F1619 help connecting LM35 temperature-sensor

Post by phalanx » Sun May 21, 2017 3:21 pm

Sorry for the delay in getting back to you. Have you successfully made the potentiometer display values on the LCD? It will be easier to get that up and running properly and then adapt the code to your temperature sensor.

One thing you need to consider is the very small change in value of your temperature sensor relative to the full 5V range of the A/D converter on the PIC. The PIC has a 10-bit converter which gives you 1024 discrete points. 5V/1024 = approx. 4.9mV per count. This doesn't give you any wiggle room for noise in your circuit since you are at the low end of the voltage scale and your entire range may only use 30ish counts (out of 1024) from the A/D. Ideally you would use an opamp to amplify the signal so that the maximum value you expect to measure, plus some additional headroom will be close to the maximum input of the A/D. This gives you significantly higher resolution and better immunity to noise. It can also be set up to handle negative temperatures which output negative voltages. The PIC's A/D isn't designed for negative inputs.

-Bill

Post Reply