Translate

sábado, 10 de enero de 2009

Interacción del Usuario via Terminal

El programa anterior, envía la temperatura al Terminal y al LCD mientras este presionado el botón conectado en RA0; esto puede ser un tanto molesto si el dispositivo esta un poco alejado de donde se encuentra la PC, así que sería bueno añadir un acceso desde el terminal cuando el botón no este presionado.


Para eso podremos usar la función getcUSART();  la cual nos permite leer un byte proveniente del buffer de recepción. También vamos a usar la función DataRdyUSART(); la cual nos permite saber cuando hay un dato en el buffer de recepción, resulta útil usarla ya que esperara hasta que llegue un dato, lo cual servirá para esperar la orden del usuario.


La idea general del programa es: Si no esta presionado el botón que nos llegue un mensaje al terminal via serie para indicarnos como tomar la lectura, si se preiona el boton tener una lectura continua o salir del modo pasivo.


Para ello podemos basarnos en el siguiente código


Con esto obtenemos el resultado deseado y pueden descargar de aquí el vídeo de la simulación.

jueves, 8 de enero de 2009

Añadiendo un RTC DS1307

Un reloj de tiempo real (RTC por sus siglas en ingles), es un dispositivo que nos ayuda a llevar la cuenta de la fecha y la hora, además que gracias a su tecnología aun sin la prescencia de la energía principal del circuito puede guardar la fecha y hora con exactitud, además de seguir tomándola, para ello se ayuda de una bateráa de 3V.

El RTC que vamos a usar es el de la casa maxim-ic el DS1307, aquí tenemos el diagrama básico de conexión:



Este dispositivo se comunica mediante el protocolo I2C, por lo que solo necesitamos 2 lineas del PIC, además de que el PIC18f4520 posee le modulo I2C por Hardware. Como se aprecia en la imagen los pines que se conectan al PIC son SDA y SCL y estos deberán llevar cada uno una resistencia de pullup para que el bus I2C  funcione correctamente.


El DS1307 funciona en modo esclavo solamente, es decir, solo responde a peticiones externas y este no manda ninguna petición. La forma de pedir los datos al DS1307 es generando una condición de inicio al bus I2C, posteriormente enviando la dirección del esclavo que corresponde al DS1307 y de manera secuencial los registros internos a escribir. Esto se ve mejor en la siguiente imagen:



Y del mismo modo para la lectura solo que cambiando el bit de RW:



Así que podemos notar que la dirección de un DS1307 es 0b11010000 que equivale a 208 decimal o 0xD0 hexadecimal, este valor es de suma importancia pues es el identificador del dispositivo en el bus I2C.


Es importante notar que la información que va a ser leída o escrita en los registros del DS1307 debe ser BCD o hexadecimal, los registros y sus direcciones del RTC son los siguientes:



Como se aprecia en la imagen la primer columna es la dirección del registro a escribir y los bits que mas importan son los bit0:bit3 que es el valor del registro a grabar, y la ultima columna nos habla del rango máximo de cada registro.


Con esta información podemos empezar a programar. Lo único que se desea es añadir la fecha y hora en que se hizo la lectura de la temperatura, para esto usaremos la librería i2c.h.


Esta librería posee un 2 instrucciones que nos van a servir para evitar un largo procedimiento de inicio, las instrucciones que vamos a usar son EEByteWrite();  EERandomRead();


Antes de utilizar estas instrucciones es necesario inicializar el BUS y esto se hace con la función OpenI2C(); Esta función lleva como argumento el tipo de esclavo o maestro a usar y se define si el slew rate se habilita o no, para nuestro caso sera en maestro y con slew off ya que pretendemos usar un bus a 100Khz.


EEByteWrite();


Esta instrucción envía a una dirección especifica, un valor. Mediante el protocolo I2C. y sus argumentos son: dirección de dispositivo, dirección de registro, datos. Por ejemplo:


   EEByteWrite(0xd0, 0x00, 128);       // dummy byte


EERandomRead();


Esta función lee los datos del dispositivo especificado, en  la posición de memoria indicada. Sus argumentos son: dirección de dispositivo, dirección de registro. Un ejemplo es:


  Sec = EERandomRead(0xd0,0x00);  // Leemos Los Segundos


Así pues podemos basarnos en el siguiente código para nuestros programas:
 


Hay que notar que cuando enviamos el valor al terminal se envía en modo HEX para poder leer correctamente la fecha y la hora, es decir que concuerde con formato humano.

El circuito propuesto es el siguiente:



Y el vídeo de la simulación descargar de aquí.

lunes, 5 de enero de 2009

Sensando Temperatura con LM35DZ

Ahora que podemos mostrar datos analógicos en un LCD y enviarlos vía serie, podemos usar un sensor y cual otro podría ser si no el famosísimo LM35DZ. Este sensor se encuentra por todas partes, debido a su bajo costo y su funcionalidad.

Este es el circuito básico de conexión de LM35:


Como podemos apreciar en el circuito la salida analógica del sensor es de 10mV por cada grado centígrado que registra; por otra parte la resolución de nuestro ADC es de 10 bits y como nuestras fuentes de referencia son las misma que alimentan al PIC,  tenemos que:


  5V / 1024 = .0048 V 


De este modo nosotros tenemos una resolución de @5mV en cada paso de nuestro canal analógico. Esta resolución es más que perfecta para usar ese sensor, de tal modo que usando la lógica cada grado centígrado equivaldrá a 2 pasos de nuestro ADC.


Con los datos anteriores podemos realizar el siguiente programa:




Como podemos apreciar el programa es muy sencillo, aunque C18 soporta el uso de flotantes, la conversión a cadena de texto no se puede, y en la parte serial no soporta %f  por esta razón se trabaja directamente con enteros y se logra una conversión similar. No es exacta falla por unas decimas pero para este programa no viene ningún problema en ello.


El circuito es el mismo del programa anterior solo habrá que sustituir el potenciómetro por el sensor.


Y por último la simulación:


domingo, 4 de enero de 2009

Usando un LCD

Al programa anterior le vendría bien mostrar el valor del ADC sin usar un PC, para ello podemos usar un LCD de 16x2.


Para este fin será necesario usar la libreria xlcd.h,  esta se encarga de mostrar los textos por nosotros. Esta librería posee varias funciones, pero nosotros nos enfocaremos especifcamente en 3 de ellas: openXLCD(); putrsXLCD(); putsXLCD;


Antes de empezar a usar esta función es necesario hacer unos cambios a la librería, pero antes debemos pasarla a nuestra carpeta de proyecto.


Lo primero sera copiar la librería que se encuentra en Directorio_de_instalación\MCC18\h\xlcd.h a nuestra carpeta en mi caso será E:\Microchip Solutions\Proyectoblog\h\xlcd.h.


Después de eso copiaremos los archivos fuente de la libreria que se encuentran en Directorio_de_instalación\MCC18\src\extended\pmc\XLCD\*.c  a la carpeta de nuestro proyecto en nuestro caso será E:\Microchip Solutions\Proyectoblog\src\XLCD\ Nos aseguramos de copiar todos los archivos *.c a nuestra carpeta de proyecto.


Esto se hace para respaldar la libreria original y realizar modificaciones sin moderación alguna en nuestro proyecto, así evitamos daños a la librería original.


Posteriormente debemos configurar nuestro proyecto para que compile desde nuestra ruta la librería recien copiada. Para ello accedemos a Menú Project--->Build Option-->Project y se abrira la siguiente ventana:



Daremos click en la opción Show directories for  y posteriormente en Include search path:



Eliminaremos el path default y añadimos uno nuevo con nuestra ruta.

Posteriormente vamos añadir las fuentes de la librería, esto lo hacemos dando click derecho sobre la carpeta de y click en add:



Y seleccionaremos todos los archivos en ..\src\XLCD\  Por último añadimos el Header xlcd.h con el mismo procedimiento.


Ahora que ya tenemos preparado el entorno de trabajo lo primero que vamos a hacer es modificar la libreria para poder usar el LCD en el PORTD a 4 bits para eso abrimos el archivo xlcd.h  dando doble click. Una vez abierto es muy sencillo ya que esta completamente comentado los modos de trabajo asi que para nuestro ejemplo el archivo queda de la siguiente forma. Ubicamos esta porcion de codigo en la librería:



En este caso la librería ya fue editada para que trabaje como deseamos, pero es tan transparente que es bastante sencillo poder modificarla para llevarla a otro puerto del PIC.


Una vez que hemos modificado nuestra librería a nuestro gusto podemos empezar a programar. La idea es mostrar un mensaje incial, despues presionar el boton y mostrar el valor del ADC tanto serialmente como en el lcd, podemos basarnos en el siguiente codigo:



Como podemos apreciar en el código las funciones de la librería xlcd.h  que mas usamos fueron: openXLCD(); putrsXLCD(); putsXLCD;


openXLCD(); Sirve para incializar el LCD con los argumentos de 4bits y el tamaño de cada caracter. Una vez que se llama esta función es necesario añadir 3 pausas para inicializar el LCD, estas pausas estan debajo del alias de nuestro botón.


putrsXLCD(); Sirve para poner una cadena de texto desde la memoria de nuestro programa.


putsXLCD; Sirve para poner una cadena de texto desde la memoria de datos, estas dos funciones se implementaron en una funciçon que cree para poder usar el mismo comando sin atascar la memoria del PIC con la función writeLCD.


El circuito propuesto para este programa es el siguiente:



Y el video de la simulación:


sábado, 3 de enero de 2009

Leyendo un Canal AD y enviando el valor vía Serie

Es momento de hacer algo un poco mas elaborado que prender simples LEDS, así que vamos a leer una entrada analógica y el valor lo mandaremos vía serie al terminal.


Hay 3 librerías nuevas que vamos a utilizar: stdio.h, adc.h y usart.h. La librería stdio.h  nos va a servir para enviar los datos al terminal de la PC haciendo uso del comando printf


printf:

Este comando es util para enviar texto y/o numero formateados vía el hardware serial, la sintaxis es:

printf(sentencias/formato,valor de formato)


Las sentencias son las palabras o cadenas que enviaremos vía serie, el formato es opcional, pero a la ves muy útil, para utilizar el formato es necesario usar el símbolo para poder anexar un valor numérico después.

Por ejemplo podemos enviar la palabra hola usando el comando printf:

 

printf("hola");  


Como podrán ver el texto debe ir entrecomillado para poder enviarse, en este ejemplo solo enviamos la palabra hola, no usamos ningún formato ni nada. Para enviar un texto con un formato podemos usar el siguiente ejemplo:

  i=10;

  printf("el valor de i es: %d",i);


Como se puede apreciar, esta vez usamos un formato el cual fue %d  con esto estamos diciendo que ira un numero decimal en el lugar que corresponde a %d. Este numero decimal pertenece a  y es declarado seguido y dentro de la instrucción printf. Tenemos que notar que a diferencia del ansi C no se usa el operado &i, ya que seria un puntero solamente se pone la variable deseada y también es necesario decir que printf no soporta el formateo de flotantes con %f como el ansi C.

La librería adc.h

Esta librería nos permitira configurar los registros del ADC sin acceder a ellos directamente, es decir, en lugar de asiganr valores individuales a los tres registros que componen la función de ADC del PIC usaremos una sola instrucción para ello.


OpenADC ();

Será quién nos permita configurar los 3 registros de nuestro de nuestro PIC, tenemos que tomar en cuenta que los argumentos de la función openadc(); cambien con respecto al PIC que usamos, es por ello que debemos revisar con calma la ayuda de esta libreria.


Para nuestro caso usamos un PIC18F4520, por lo que la función openadc(); llevará 8 argumentos. de este forma podemos construir la función de la siguiente manera:


 OpenADC ( ADC_FOSC_8 &             // Configuramos el FOSC a 8 
                      ADC_RIGHT_JUST &  // Sera 10 bits de 0-1024
                      ADC_4_TAD,                 // TAD en 4
                      ADC_CH0 &                   // Solo Canal0, RA0
                      ADC_INT_OFF &         // Sin interrupciones AD
                      ADC_VREFPLUS_VDD &   // Sin VREF+
                      ADC_VREFMINUS_VSS,   // Sin Vref- 
                      14 );                                        // Bits digitales de ADCON1



Como se puede apreciar en el codigo anterior, con los 8 argumento configuramos los 3 registros y los argumentos los podemos cambiar conforme nos convenga. Cabe destacar que el ultimo numero el 14  corresponde a los bits0-3 del registro ADCON1 donde seleccionamos el tipo de I/O de los pines para este caso solo RA0 es analógico los demás son digitales.



La Librería usart.h

Con esta librería vamos a configurar el modo de transmision serie de nuestro PIC, usaremos la función OpenUSART (); esta función esta dada por 7 argumentos, que corresponden a la configuración de nuestra transmisión, para este ejemplo buscamos una transmisión asyncrona de 8 bits sin paridad y con una velocidad de 9600KBps. De esta forma tenemos que:

OpenUSART ( USART_TX_INT_OFF &   // Sin interrupcion de TX  
                          USART_RX_INT_OFF &   // Sin interrupcion de RX  
                          USART_ASYNCH_MODE & // Modo Asincrono
                          USART_EIGHT_BIT &      // Solo 8 bits de transmision
                          USART_CONT_RX &         // Recepcion continua
                          USART_BRGH_HIGH,      // BRG HIGH
                          129 );                                     // 9600Kbps @ 20MHZ


Dependiendo de la frecuencia de nuestro crystal es como asiganaremos el ultimo valor decimal, que en este caso es 129 ya que segun la hoja del PIC como esta activado BRGH, solo es cuestion de buscar en la tabla correspondiente el valor de FOSC.

Una vez que tenemos el resumen de esas librerias podemos crear el programa. el cual cada que presionemos un boton conectado a RB0 enviara la lectura del ADC con una pausa de medio segundo. Para ello podemos basarnos en el siguiente programa:

El diagrama de conexion que vamos a usar:



La salida serie pueden usar un max232 o algunos componentes discretos lo que les convenga y funcione.

Y por útimo la simulacion del programa: