jueves, 6 de junio de 2019

Temperatura y Humedad con DHT-11/22

Sensor Humedad/Temperatura DHT con PIC

Fig1. Circuito con Sensor DHT11

Muchas gracias por tu visita a este blog relacionado con la programación de micro-controladores PIC, en esta entrada quiero mostrarles como utilizar los sensores DHT para medir la humedad relativa y temperatura ambiental que nos servirán para implementar aplicaciones y/o estaciones de información meteorología.

El objetivo de esta entrada es realizar la lectura adecuada del sensor DHT con un microcontrolador PIC16F en la que se establece una comunicación serial asíncrona por un solo cable, con un protocolo similar a 1-Wire conforme a las especificaciones técnicas del sensor.

La programación del microcontrolador PIC se lleva a cabo con el software  de diseño  MPLABX  y el compilador de lenguaje C para PIC XC8, ambos disponibles en la pagina de microchip de forma gratuita. Aquí dejo los enlaces de las versiones utilizadas para nuestro ejemplo:   
 
Acerca del Sensor DHT

Es un sensor digital para medir la Humedad relativa y Temperatura ambiental, cuenta con un procesador interno que realiza la medición de un elemento capacitivo y un termistor, proporcionando el resultado a través de una señal digital. La interfaz de comunicación con el PIC utiliza una linea bidireccional en modo half-duplex. Seguidamente describiremos los dos modelos identificados como DHT11 y DHT22 que trabajan entre 3.3 a 5.0V y poseen un encapsulado y disposición de pines compatible con las siguientes diferencias  técnicas:


Fig2. Descripción de pines DHT11/22

  • DHT11: Trabaja con un rango de medición de temperatura de 0 a 50 °C con una exactitud de ±2.0 y 1°C de precisión y el rango de medición para la humedad relativa es de 20% a 80% con una exactitud del 5% y 1% de precisión. En ambos casos el resultado esta conformado por 16-bit siendo un byte para el valor entero y el otro byte para el decimal, pero este modelo posee una resolución de 8-bit por que únicamente se emplea la parte entera del resultado. Los ciclos de lectura debe ser como mínimo 2 segundos.

  • DHT22: El rango de  medición de temperatura es de  -40°C a 80 °C con exactitud de ±0.5 °C y precisión de 0.1°C. El rango de humedad es de 0 a 100% RH con exactitud del 2% y precisión del 0.1%. El resultado de ambas mediciones esta conformado por 16-bit,  el tiempo entre lecturas debe ser de 2 segundos.

A simple vista podemos destacar que la principal diferencia entre ambos modelos es el rango de operación y la exactitud pero también hay diferencias en el proceso para establecer la comunicación con el sensor y el resultado de una medición, además que los ciclos de lectura en un DHT22 son mas lentos (2 a 5 segundos) debido a su mayor precisión en el resultado.


Protocolo de comunicación DHT

Como ya mencionamos previamente el voltaje de operación nominal para estos sensores es de 5V, pero pueden trabajar a menor voltaje 3.3V considerando que la distancia entre el sensor y el MCU sera mucho menor, adames en el pin de comunicación SDA(DATA) es necesario adicionar una resistencia en modo pull-up de 4.7k con la que es posible conectar a una distancia de 30 metros, una resistencia de mayor reduce esta distancia de conexión, también es recomendable agregar una capacitor de 100nF entre VDD y GND  para un mejor filtrado en el voltaje de alimentación, la figura 3 muestra la conexión necesaria entre el sensor y el MCU.


Fig3. Conexión entre el Sensor y el MCU
 

Para establecer la comunicación bidireccional a través de la linea SDA(DATA) el microcontrolador (MCU) utilizara un pin configurado como salida al momento de establecer un nivel bajo en SDA y como entrada tri-state para leer los niveles de SDA, utilizando el siguiente procedimiento de señalización y su respectiva temporización:

Fig4. Protocolo de comunicación MCU - Sensor
 
  • Señal de Establecimiento (Start signal): Normalmente la linea SDA se encuentra en un estado ALTO, entonces en esta etapa el MCU establece la linea SDA en nivel BAJO por un tiempo de 1ms(DHT22) o 18ms(DHT11) para luego liberar la linea a su estado inicial es decir un nivel ALTO.

  • Señal de Respuesta (Response signal): En esta etapa el MCU tiene configurado el pin como entrada tri-state esperando a que el sensor coloque la linea SDA en nivel BAJO como respuesta al Start Signal, la duración este cambio sera al menos 80us y luego el sensor libera la linea SDA por un tiempo mínimo de 80us. A partir de este momento el sensor empezar a enviar los datos de la ultima medición efectuada.

  • Datos (Data transfer): En esta etapa el MCU mantiene el pin como entrada tr-state para recibir los 40-bits de datos por parte del sensor, cada bit se interpretara conforme a la siguiente regla de tiempos:

    • (Bit 0) Nivel BAJO por 50us y ALTO por 25 a 28us.

    • (Bit 1) Nivel BAJO por 50us y ALTO por 70us.

Una vez completado el procedimiento de comunicación, el resultado de 40 bits recibidos del sensor mantienen el formato de campos que se muestra en la figura 5, donde los dos bytes mas significativos representan el valor de la humedad, los siguientes dos bytes corresponden a la temperatura y finalmente el ultimo byte se utiliza para verificar error de paridad y es un resultado de sumar los cuatro primeros bytes del dato.

 
Fig5. Trama con los datos recibidos del sensor
 
El MCU deberá procesar la trama de datos recibido de acuerdo al modelo del sensor, conforme a los siguiente ejemplo:
Trama de 40-bit recibidos del sensor DHT11
 <00110101><00000000>  <00011000><00000000><01001101> 
      RHint          RHdec              TEint        TEdec       Paridad    
 
Para verificar si hay error de paridad, bastara sumando los cuatro primeros bytes de la trama y si este resultado es igual al ultimo byte nos indicaría que no hay error en los datos. Para obtener el valor de Humedad relativa solo cambiamos la representación del primer byte que es un numero entero a su equivalente decimal.
<00110101> = 35h = 53 %
Para obtener el valor de Temperatura aplicamos al byte 3 el paso anterior, es decir.
<00011000> = 18h = 24 °C.
Otro ejemplo considerando ahora la respuesta del un sensor DHT22 es la siguiente Trama.  
Trama de 40-bit recibidos del sensor DHT22
 <00000010><10010010>  <00000001><00001101><01001101> 
      RHint          RHdec              TEint        TEdec       Paridad    
La verificacion del error de paridad es similar al caso anterior, en cuanto los demás datos para obtener la humedad relativa se puede efectuar el siguiente calculo tomando los dos bytes (16-bit) juntos.
<00000010 10010010> = 292h, entonces cada dígito 2 * 256 + 9 * 16 + 2 = 658 / 10 = 65.8 %
La temperatura se obtiene aplicando el siguiente calculo.
 <00000001 00001101> =10Dh = 1 * 256 + 0 * 16 + 13 =  269 / 10 = 26.9 °C.
 
Un punto a tomar en cuenta con el modelo DHT22, es a temperaturas bajo cero el primer bit correspondiente al campo de temperatura (TEint) indica el signo del resultado, en tal sentido el MCU deberá efectuar la verificacion correspondiente para la correcta interpretación de la magnitud.

Esquema del Circuito PIC16F
El circuito que utilizaremos para la prueba de este sensor se muestran en la figura 6, en primera instancia hay únicamente un sensor DHT conectado al pin RB4 y un modulo convertidor USB/UART a los pines de comunicación del modulo UART a fin de enviar los recibidos del sensor y mostrar los valores de temperatura y humedad considerando los cálculos que vimos previamente.
 
 
Fig6. Esquema del circuito PIC
Notara que en el esquema del circuito no se observa la resistencia pull-up que requiere la linea SDA del sensor, esto es así porque activaremos la resistencia interna que posee el pin del MCU, el circuito tampoco la etapa de alimentación y reinicio que necesita el PIC16F, dando por hecho que ya están implementadas estas conexiones. Finalmente el diodo LED1 servirá para indicar el funcionamiento adecuado del programa mediante un destello por cada segundo. 
 
Programación del PIC
A fin de facilitar el uso de este sensor utilizaremos un grupo de funciones incluidas en la librería dht.c/dht.h que forman parte de los ficheros del proyecto MPLABX.
Antes de describir las funciones que utilizaremos con el sensor, se deberán personalizar en el archivo de cabecera dht.h las siguientes definiciones:
#define _XTAL_FREQ 8000000
/* USER PORT DEFINITION */
#define DHT_PORT    PORTB  
//Puerto asociado al Sensor
#define DHT_TRIS    TRISB  
//Registro de Configuración del Puerto
#define DHT_DEV1 0x10      
//Mascara del pin RB4 conectado al DHT 
/* END USER PORT DEFINITION */ 

Ahora mostraremos la lista de los procedimientos que podemos utilizar para hacer uso de este sensor:

DHTSetup(devmask): Este procedimiento configura los pines definidos en la cabecera para su posterior uso con el sensor DHT, el pin colocar por defecto la linea SDA en nivel ALTO. Siendo posible iniciar uno o mas pines a los que se conectara un sensor, por ejemplo:

DHTSetup(DHT_DEV1); //Configura un pin DHT
DHTSetup(DHT_DEV1|DHT_DEV2|DHT_DEV3);
//Configura tres pines DHT

DHTStart(devmask, type): Es una función que establece el pulso de inicio y retorna uno (1) al finalizar el pulso ya cuando el nivel de la linea SDA es ALTO. Es importante recalcar que esta función debe llamarse consecutivamente hasta que devuelva un uno (1) y luego de esto recién iniciar la lectura del sensor.

DHTRead(devmask, type, dst): Esta es la función encargada de recibir los 40-bits del sensor DHT, el resultado estará almacenado en la dirección dado por el parámetro dst (puntero a byte) y retorna uno (1) solo si la verificacion de paridad es correcta. Debe tomar en cuenta que esta función es bloqueante y se deberia evitar interrupciones mientras se ejecuta. A continuación veremos el siguiente ejemplo de uso.

if(DHTStart(DHT_DEV1, DHT11)) //Emite pulso de inicio DHT11
{
     INTCONbits.GIE = 0;
//Desactiva interrupción global
    res = DHTRead(DHT_DEV1, DHT11, buffer); //Lectura de los 40-bits
    INTCONbits.GIE = 1; //Activa interrupción global
    if(res) //Valido solo si la paridad es correcta
    {
        //Se procesan los datos almacenados en buffer 
        printf("Raw Hu=%X%X Te=%X%X\r\n",buffer[0],buffer[1],buffer[2],buffer[3]);  
     }
}

DHTUpdate(type, src): Este procedimiento es el encargado de procesar el resultado de 40-bits de una lectura previa, y obtener los valores de humedad relativa y temperatura en el sistema decimal, para esto la librería utiliza una estructura de datos DHT con los siguientes campos:

typedef struct
{
    uint8_t tem;
//Temperatura parte entera
    uint8_t temr;
//Temperatura parte decimal (fracción)
    uint8_t hum;
//Humedad parte entera
    uint8_t humr;
//Humedad parte decimal
} DHT_t;

 
El uso del procedimiento es bastante simple y se refleja en el siguiente ejemplo:
if(DHTStart(DHT_DEV1, DHT11))
{
    INTCONbits.GIE = 0;
    if(DHTRead(DHT_DEV1, DHT11, buffer))
    {
      printf("Raw Hu=%X%X Te=%X%X\r\n",buffer[0],buffer[1],buffer[2],buffer[3]);
      DHTUpdate(DHT11, buffer);
      printf("Final Hu=%u Te=%u\r\n",DHT.hum, DHT.tem);
    }
    INTCONbits.GIE = 1;
}

Si el código descrito previamente se ejecuta de manera continua con un periodo mayor a los dos segundos, el resultado que obtenemos conectando un terminal serie desde nuestro ordenador sera como muestra la figura 7.
 
Fig7. Resultado de la lectura de un sensor DHT11

Un programa completo para llevar a cabo la lectura del sensor DHT11 con intervalos de dos segundos, tendría la siguiente estructura:

void main(void)
{
    MCUSetup();
    DHTSetup(DHT_DEV1);
    while(1)
    {
        if(tickms)
//Valida cada ms
        {
            tickms = 0;
            taskLED();
//Destellar LED
           
taskDHT(); //Lectura y envío datos Sensor
        }
    }
}

Donde la tarea para efectuar la lectura taskDHT que es llamada continuamente cada un milisegundo, controlara su estado de ejecución a través del siguiente código:

void taskDHT(void) //Periodo de ejecución 1ms
{
    static uint8_t state = 0;
    static uint16_t cnt = 0;
    uint8_t res;
    cnt++;
    switch(state)
    {
            case 0:
//Lectura y muestra del sensor DEV1
            if(DHTStart(DHT_DEV1, DHT11))
            {
                INTCONbits.GIE = 0;
                res = DHTRead(DHT_DEV1, DHT11, buffer);
                INTCONbits.GIE = 1;
                if(res)
//Si paridad es correcta
                {
                    DHTUpdate(DHT11, buffer);
                    print("Final Hu=");
                    printByte(DHT.hum);
                    print("% Te=");
                    printByte(DHT.tem);
                    print("\'C\r\n");                  
                }
                state = 1;
//próxima espera
            }
            break;
        case 1:
//Espera nuevo ciclo dos segundos
            if(cnt == 2000)
            {
                cnt = 0;
                state = 0;
            }
            break;   
    }
}

Una vez compilado y preparado el código en el PIC, se llevaran a cabo las conexiones del circuito incluido la comunicación con una terminal serial desde el ordenado (PC), entonces el resultado que nos arrojara el MCU sera el que se muestra en la figura 8.

Fig8. Datos obtenidos del sensor DHT11

Los procedimientos que se mostraron con antelación son parte del archivo principal main.c que contiene el proyecto, este archivo contiene código adicional que no se ha detallando en la presente publicación, por esta razón dejo el enlace para que puedas descargarlo y analizar con mas detalles desde el IDE MPLABX. <Proyecto DHT11 con PIC16>

Si quieres ver como compilar e implementar los proyectos de este blog, elaborados con MPLABX mira este vídeo.<Compilando proyectos MPLABX> 

Mas abajo de dejo el enlace de  vídeo de mi canal en el que se realiza una practica utilizando mas de un sensor DHT.

 
Conclusiones y Recomendaciones

Luego de hacer la demostración del programa podemos concluir que podemos implementar fácilmente cualquiera de estos dos sensores.
Una desventaja con estos sensores es la velocidad de las lecturas y el tiempo de espera para realizar una lectura nueva que es mayor a dos segundos, aunque en muchos casos puede no ser un inconveniente debido a que la Temperatura y Humedad relativa son variables que no cambian de forma rápida.

Sin mas que mencionar agradezco tu visita al blog y espero que el ejemplo visto pueda ser útil en tu formación y el proyecto que desarrollas.

Atentamente, Pablo Zárate Arancibia  email: pablinza@me.com / pablinzte@gmail.com, @pablinzar

Santa Cruz de la Sierra - Bolivia


miércoles, 5 de junio de 2019

I2C Utilizar un LCD con PCF8574

Modulo PCF8574x con el PIC16F
Fig1. Modulo PCF8574 y LCD

Antes que nada quiero agradecer tu visita a este blog relacionado con la programación de micro-controladores PIC, En esta ocasión veremos como utilizar un circuito integrado (CI) de expansión bastante practico y económico para conectar un modulo LCD con nuestro microcontrolador (MCU), utilizando únicamente dos lineas de comunicación gracias al protocolo serial I2C y el CI PCF8574x. El objetivo de esta sección es enviar mensajes a la pantalla LCD utilizando el protocolo de comunicación I2C entre el PIC16F887 y el PCF8574x.
 
La programación se realizara utilizando MPLABX y el compilador XC8 ambos disponibles en la pagina de microchip. Aquí dejo los enlaces de las versiones utilizadas para nuestro ejemplo:  <MPLABX v6.20>   <XC8 v2.45>
Mencionar también que es necesario contar con conocimientos mínimos sobre programación en lenguaje C y el uso de microcontroladores PIC16. Al finalizar la sección les dejare el enlace para descargar la carpeta del proyecto que contiene todos los archivos citados en la presente publicación, también te recomiendo revisar los siguientes enlaces donde se explicar con mayor detalle el <Uso del TMRO> y la <Comunicación I2C>

Modulo PCF8574x con el PIC16F
 
El PC8574x es básicamente un modulo de conversion serie a paralelo, utilizado con el objetivo de expandir los puertos de entrada y salida de un sistema electrónico, como es el caso de un MCU que no dispone de puertos suficientes.
La comunicación con el PCF8574x se establece utilizando el conocido protocolo I2C, el caso de los microcontroladores PIC de gama media, estos disponen de un modulo de comunicación serial síncrono denominado SSP/MSSP,  que facilitan la implementación los protocolos SPI(Serial Peripheral Interface) e I2C(Inter-Integrated Circuit). En la codificación de nuestro programa utilizaremos la librería pcflcd donde se incluyen los procedimientos I2C necesarios para comunicarnos con el chip PCF8754x.

Paso 1. Sobre el Módulo PCF8574x.
I2C es un protocolo serial desarrollado por Phillips Semiconductors en la década de los 80, y fue concebido principalmente para comunicar dispositivos que están montados en un mismo sistema o circuito impreso.

Fig2. Pinout del PC8574x

El chip PCF8574 fabricado por Texas Instrument es un expansor paralelo de 8 bits controlado por I2C que opera a una velocidad estándar de 100KHz, diseñados para proveer monitoreo y control serial de forma fácil y económica. Existen dos variantes de este chip que son el PCF8574 y PCF8574A que se diferencian únicamente por el rango o mapa de dirección que pueden utilizar conforme a los valores lógicos en sus pines A2:A0.
 
Fig3. Tabla de direccionamiento PCF8574

Una gran ventaja de este protocolo es que establece una interfaz bidireccional maestro esclavo de hasta 128 dispositivos, aunque en la practica cada dispositivo limita su rango de asignación a un determinado mapa que puede ser configurado de forma externa o mediante instrucciones sobre el mismo protocolo.

Fig4. Conexión del Bus I2C
 
Implementar el bus I2C con el chip PCF es bastante simple, si observa la figura 4, solo se requiere utilizar resistencias pull-up por cada pin del microcontrolador, establecer la dirección de cada dispositivo conectado y su respectiva alimentación.

La figura 5, muestra el esquema de circuito necesario para la conexión del PCF8574A con las ocho lineas requeridas por el modulo LCD y las dos lineas de comunicación I2C del MCU.
 
Fig5. Esquema de conexión PCF8574A
Algo interesante es que este circuito esta disponible como un modulo genérico producido para aplicaciones de prototipo rápido, y que goza de bastante popularidad por su bajo costo económico($us. 3), incluso planteando comprar los elementos por separados no se justifica el precio por el trabajo y tiempo necesario para el montaje. Salvo que se trate de un producto final.

Fig6. Modulo PCF8574x
 
Por defecto este modulo tiene las lineas A2:A0 con nivel lógico alto que define una dirección de 27h (PCF8574) y 3Fh(PCF8574A); Si requiere agregar mas dispositivos o modificar la dirección necesitara soldar o conectar las siguientes lineas o pads en la parte posterior del modulo, de acuerdo a la figura 7.

Fig7. Pads para direccionamiento

Otro detalle es que el modulo ya cuenta con las resistencias pull-up requeridas por la interfaz y no sera necesario agregar estas resistencias incluso si utiliza otros dispositivos o sensores I2C.


Paso 2. Conectar el Modulo al PIC16F.
Fig8. Conexión al PIC16F

Solo necesitara identificar y conectar las cuatro lineas que posee el modulo, dos corresponden a la alimentación(5V/GND), y dos para la comunicación SDA(datos) y SCL(reloj). Muchas pantallas LCD cuentan con una luz de retroiluminacion(Backlight) que puede ser controlador a través de la interfaz siempre que coloque un puente(jumper) en el conector J2. 
 
El modulo también posee un potenciómetro que permite ajustar el contraste que la pantalla, deberá establecer un valor adecuado al momento de ensayar el programa.


Paso 3. Programación y envió de mensajes.

A fin de facilitar la rápida implementación del modulo en nuestra aplicación, se crearon los siguientes procedimientos y funciones incluidas en la cabecera pcdlcd.h. Debe revisar este archivo para efectuar algunas configuraciones necesarias antes de proceder a llamar cualquier procedimiento o función de esta librería.

Recuerde que el campo de dirección definido en el programa como PCFADDR dependerá de los valores lógicos que tienen los pines A2:A0 del chip PCF8574, estos pines por defecto tiene nivel logico 1, por lo tanto la dirección resultando sera de acuerdo al siguiente formato I2C.
 1. Para un Modulo PCF8574A PCFADDR=7Eh
 

 2. Para un Modulo PCF8574 PCFADDR=4Eh

Ahora mostraremos la lista de los procedimientos que podemos utilizar para enviar mensajes a nuestra pantalla LCD.
  • PCFSetupLCD(): Este procedimiento lleva a cabo la inicialización del modulo LCD, siendo por defecto la siguiente configuracion:
    1) Bus de datos en modo 4-bit y multi-linea;
    2) Incremento de posición automático;
    3) Muestra el cursor sin destellar;
    4) Limpia la pantalla e inicializa el cursor.
    La definición del puerto asociado a los pines del LCD y los valores de temporización se lleva a cabo modificando las siguientes lineas de código en la cabecera pcflcd.h.

    /* USER PORT DEFINITION */
    #define PCFADDR 0x7E //PCF8574A
    #define _XTAL_FREQ 8000000

    /* END USER PORT DEFINITIONS */

  • PCF_WriteCmd(): Este procedimiento permite enviar un comando al LCD, siendo algunos ejemplos de uso, los siguientes:
PCF_WriteCmd(LCD_CLEAR); //Limpia la pantalla LCD
PCF_WriteCmd(LCD_DISPLAY & LCD_DCURSOROFF); //Sin cursor
PCF_WriteCmd(LCD_DISPLAY & LCD_DBLINKOFF); //Sin destello
PCF_WriteCmd(LCD_FUNCTIONSET & LCD_FSET4BIT & FSETLINE1); //Una linea
PCF_WriteCmd(LCD_HOME); //Iniciliza el cursor

  • PCF_WriteMsg(*p): Este procedimiento sirve mostrar un mensaje en la pantalla LCD, se entiende que el mensaje iniciara en la posición actual que tiene el cursor. 
  • PCF_WriteChar(val): El procedimiento muestra en la pantalla LCD, el carácter val, se debe considerar la posición que tiene el cursor antes de llamar a este procedimiento.
  • PCF_GotoXY(x,y): El procedimiento permite posicionar el cursor en la pantalla, siendo x,y la combinación fila, columna de la pantalla.
  • PCFSetLED(): Permite encender la luz de fondo de la pantalla.
  • PCFClearLED(): Permite apagar la luz de fondo de la pantalla
Paso 4. Prueba y Simulación.
Ahora escribiremos un pequeño programa para poner en practica y demostrar el uso de una pantalla LCD donde utilizaremos los procedimientos previamente descritos, el programa se codifica considerando que la frecuencia del oscilador interno del PIC es de 8MHz.

El siguiente código es parte del programa que muestra un mensaje inicial en la primera linea y el valor de un contador de segundos en la segunda linea, adicionalmente se tiene un LED conectado al pin RE2 con el fin de generar un destello cada segundo, el destello es indicador de que el programa esta corriendo de manera regular. Aclarar que el código que se muestra solo corresponde con la funcionalidad básica del programa, por lo tanto te recomiendo que descargues el proyecto MPLABx y revises los archivos donde se encuentra el código completo.

#include <xc.h>
#include <stdint.h>
#include <stdio.h>
#define LEDpin PORTEbits.RE2
volatile uint8_t tick1ms = 0;
uint16_t cntms = 0;
#include "i2c.h"
#include "pcflcd.h"
char msg[8];
//Char array

void main(void)
{
    setupMCU();
//Inicializa el Microcontrolador
    PCFSetupLCD();
//Inicia el LCD
    PCFSetLED();  
//Enciende la luz de fondo
    PCFGotoXY(0,2);
//Coloca el cursor en la posición 2 de la fila 0
    PCFWriteMsg("** U.E.B **");
//Muestra el mensaje
    PCFWriteCMD(LCD_DISPLAY & LCD_DBLINKOFF);
//Muestra el cursor
    while(1)
    {
        if(tick1ms)
//Validacion en cada ms
        {
            tick1ms = 0;
            taskLED();
//Ajecuta la tarea para destellar el LED
            taskAPP();
//Muestra el contador de segundos
        }
    }
}

void taskAPP(void)
{
    static uint16_t cnt = 0;
    static uint8_t seg = 0;
    if(cnt++ > 999)
//Se valida cada segundo.
    {
        cnt = 0;
        seg = seg + 1;
//Incrementa el contador de segundos
        if(seg > 59) seg = 0;
//Reinicia el contador de segundos
        PCFGotoXY(1,0);
//Coloca el cursor en la posición 0 de la fila 2
        sprintf(msg, "SEG:%02u", seg);
//Cadena personalizada
        PCFWriteMsg(msg);
//Muestra la cadena con valores del segundo   
    }


Fig9. Montaje del circuito PIC16F

Paso 5. Conclusiones y Recomendaciones.
Luego de hacer la demostración del programa podemos concluir que podemos implementar fácilmente este modulo I2C para ahorrarnos entre 4 y 6 lineas o pines del PIC. Si bien la librería solo contiene procedimientos básicos para mostrar mensajes, con un mayor conocimiento de las instrucciones del controlador LCD es posible realizar modificaciones que permitan efectuar operaciones menos frecuentes como ser desplazamientos y generación de caracteres personalizados.
 
Este es el enlace para descargar el proyecto MPLABX  <PCFLCDP16F>
También de dejo vídeo donde explico como abrir el proyecto MPLABX y compilar con otro PIC diferente al utilizado. 

Sin mas que mencionar agradezco tu visita al blog y espero que el ejemplo visto pueda ser útil en tu formación y el proyecto que desarrollas.
Atte. Pablo Zárate Arancibia
email: pablinza@me.com / pablinzte@gmail.com, @pablinzar
Santa Cruz de la Sierra - Bolivia