David Ruiz Hernández DSM 06/2007 Introducción La base de esta práctica es el desarrollo de un proyecto utilizando como elemento base un PIC. En un principio se iba a trabajar con el PIC 16f84, pero tras plantear la idea a desarrollar, se descubrió que sería más fácil trabajar con un 18f1320, ya que posee un conversor analógico/digital interno. La idea planteada fue la siguiente; el desarrollo de un sensor de aparcamiento, el cual, a partir de la señal devuelta por un sensor de distancia por infrarrojos, detectara la distancia a la que está situado el obstáculo y mostrara por pantalla el valor de dicha distancia. Materiales y su descripción PIC18f1320 Este PIC tiene una serie de particularidades que lo diferencian del PIC16f84, pero en esta práctica, lo más señalado que nos incumbe es el A/D converter, ya que el objetivo principal es tomar la medida de un sensor y mostrar por pantalla la distancia a la que se encuentra un objeto. Este conversor está integrado en el PIC y requiere una configuración básica, que consiste en la modificación de los registros ADCON0 (para indicar las tensiones ref., el canal utilizado y habilitar el conversor), ADCON1 (para indicar que puertos serán utilizados como entradas analógicas), ADCON2 (para determinar el tiempo de adquisición y la frecuencia)1 Todo lo anterior es antes de comenzar la adquisición. Una vez queremos tomar datos, debemos esperar por el bit GO/DONE (ADCON0, 1) y esperar a que se ponga a 0, ya que esto indica que la toma de datos ha terminado, y luego mirar los registros ADRESH y ADRESL, que es el lugar donde se almacena la salida dada por el conversor y dicha salida es almacenada en 2 registros ya que su valor se devuelve en 10 bits. *Nota: Se adjunta el diagrama de bloque del conversor 1 La configuración utilizada se explicará junto al código Sensor de distancia por Infrarrojos: Sharp GP2D12 Para este proyecto se utilizo el mencionado sensor a causa de que fue del que se disponía en el laboratorio. En las especificaciones del sensor podemos encontrar que el rango de sensibilidad está entre los 10 cm. y los 80 cm. y su curva de calibración “original” es la siguiente: Para resumir, se adjunta la tabla de especificaciones del sensor, donde podemos observar sus rangos de trabajo, tanto de tensión como de distancia: Placa PICDEM4 Programador T20 Desarrollo Como en un principio se ignoraba el funcionamiento de la pantalla LCD, y esta era una parte muy importante para el desarrollo del proyecto, se optó por crear un pequeño programa el cuál utilizara dicha pantalla. Este programa consistía básicamente en un contador del número de veces que se pulsaba el botón correspondiente al RB0 y mostrar dicho valor por pantalla2, aunque parecía un ejercicio relativamente sencillo, se encontraron muchas dificultades que se comentan en el apartado de dificultades. Durante el desarrollo de esta “prueba” se descubre que la librería facilitada con la placa para el manejo del LCD nos facilita una serie de funciones que nos permiten, desde elegir la línea en la que se quiere escribir, hasta el lugar en el que se desea situar el cursor. Una vez se consigue escribir de una forma coherente en pantalla, comenzamos con el calibrado del sensor, es decir que se tomaron una serie de entradas y acorde a las salidas se mide la distancia. El calibrado no se realizó tomando unos voltajes de referencia, sino que directamente se conectó el sensor al circuito en el que estaba el PIC y con la ayuda del conversor A/D del microcontrolador se calibró el sensor. Al hacer las conexiones nos dimos cuenta que se debía conectar la salida a una resistencia (0,5 K) conectada con tierra porque si no la respuesta siempre era constante, además de esto, se observó que el voltaje de referencia debía ser menor que el de entrada ya que las medidas eran demasiado imprecisas y para ello se necesitó un divisor de tensión que consistía en dos resistencias en serie (R1=1,5 K y R2=1 K). 2 El código se adjunta en los anexos Tras insertar el divisor de tensión, las conexiones quedan de la siguiente manera: la salida del sensor se conectó a una resistencia (como se menciona anteriormente) y los puertos que se encargan de los valores de referencia quedan conectados al divisor de tensión (uno a 5 V, y otro a 3 V), y por último, los puntos de alimentación de la placa se conectan también al circuito en el que se encuentra el divisor, para así no tener que utilizar dos fuentes Antes de explicar cómo se realizó el calibrado, indicar que en el PIC se guardaba la respuesta en 3 registros, ya preasignados al convertidor A/D. Una vez aclarado esto, comenzamos con el calibrado, con la ayuda de un flexómetro, comenzamos a medir desde 10 cm hasta 80 cm, ya que ese era el rango que las especificaciones del sensor nos indicaban que este funcionaba correctamente, pero durante las pruebas tuvimos que cambiar dichas “medidas de referencia”, ya que a partir de 15 cm hacia abajo y 50 cm hacia arriba el sensor daba problemas en el circuito montado. Por lo tanto decidimos que las medidas devueltas por el sensor estarían dentro de ese rango, y las respuestas variarían de 5 en 5 cm, salvo en los casos que las medidas se salieran de rango, ya que si estábamos muy cerca, simplemente indicaba que la distancia era menor a 15 cm y si estábamos muy lejos, no indicaba nada “-- centimetros”. Ya una vez calibramos, utilizamos los valores almacenados en los 3 registros del conversor para averiguar cual era la distancia a la que nos encontrábamos y a partir de esto ir mostrando los mensajes en pantalla, aunque durante la ejecución del programa, lo único que varía es la distancia, ya que al principio se inicializa la pantalla con el texto: ---------------------------------------| Esta usted a menos de: | | centimetros | ---------------------------------------y luego, simplemente se varía el valor del número de centímetros a los que estamos. Antes de proseguir, aclarar que se eligen intervalos de 5 cm, ya que el sensor no daba medidas claramente diferenciadas en un rango menor. A nivel de código, el PIC adquiría los datos a partir de una interrupción la cual se encargaba de comprobar si el sensor había leído y si lo había hecho, se encargaba de volcar los datos en unos registros para así poderlos evaluar. Un ejemplo de funcionamiento del sensor es: para una medida de 23 cm, el PIC mostrará por pantalla ---------------------------------------| Esta usted a menos de: | | 25 centimetros | ---------------------------------------Quedando la tabla de la salida del sensor de la siguiente manera: viéndose que en los “puntos críticos” el sensor puede dar unos valores “varaibles”. Una vez se calibró el sensor se desarrolló el código para unir la parte del LCD con la adquisición de datos para ya dar por terminado. CODIGO Primero, a parte de los includes y de las inicializaciones se establece le valor de los registros de configuración __CONFIG _CONFIG1H, _IESO_OFF_1H & _FSCM_OFF_1H & _INTIO2_OSC_1H __CONFIG _CONFIG2L, _PWRT_ON_2L & _BOR_OFF_2L & _BORV_27_2L __CONFIG _CONFIG2H, _WDT_OFF_2H & _WDTPS_32_2H __CONFIG _CONFIG3H, _MCLRE_ON_3H __CONFIG _CONFIG4L, _DEBUG_OFF_4L & _LVP_OFF_4L & _STVR_OFF_4L __CONFIG _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L __CONFIG _CONFIG5H, _CPB_OFF_5H & _CPD_OFF_5H __CONFIG _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L __CONFIG _CONFIG6H, _WRTC_OFF_6H & _WRTB_OFF_6H & _WRTD_OFF_6H __CONFIG _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L __CONFIG _CONFIG7H, _EBTRB_OFF_7H Luego, se realizan las inicializaciones, destacando el trabajo con el TIMER para controlar el tiempo de lanzamiento de la interrupción. bcf RCON, 7 bsf INTCON, 7 bsf INTCON, 5 movlw 0C7h movwf T0CON ;TMR0 hab, 8bit, presc0 Tras esto entramos en el bucle que inicializa el cursor y manda los datos al selector de mensajes (tra) para que este mande la distancia acordada. Po movlw 0x00 movwf vIOExpLCD_X movlw 0x00 call IOExpLCDSetCursor movff tenx, ten movff totx, tot movff interx, inter goto tra Otro punto a destacar del código es la interrupción, que además de comprobar si se esta realizando una medida, almacena en 3 variables el resultado de dicha medida in bsf ADCON0, 1 movwf auxw movf STATUS, 0 bu ne movwf auxs btfss ADCON0, 1 goto ne goto bu movlw B'00001111' andwf ADRESL, 0 movwf interx movlw B'11110000' andwf ADRESL, 0 movwf totx rrncf totx rrncf totx rrncf totx rrncf totx movlw B'00000011' andwf ADRESH, 0 movwf tenx bcf INTCON, 2 movf auxs, 0 movwf STATUS movf auxw, 0 retfie Dificultades Las principales dificultades reencontraron en el momento de trabajar con el LCD, ya que se facilitaban una serie de librerías para hacerlo funcionar a través del PIC 18f1320 pero no se explicaba su funcionamiento por ningún lado. Otra dificultad añadida, fue el comenzar a trabajar sobre un PIC (el 18f1320) del que se tenia muy poca información, y gran parte del tiempo de desarrollo del proyecto lo llevó la documentación sobre dicho microcontrolador Por otro lado, y no menos lioso, apareció un problema con el sensor, ya que la variación era muy pequeña a largas distancias, y la calibración se izo muy difícil para dichas distancias. En cuestión del código, no fue muy costoso, ya que tras el trabajo extra que supuso el conflicto con el LCD, y que la prueba utilizada para que este elemento funcionara era muy similar al funcionamiento del proyecto. ANEXOS Codigo utilizado para probar el LCD ;###################################################################### ############ ;# TITLE "I/O Expander Driven LCD Display Test Software ;# ;# ;# Program: MAIN.ASM ;# Version: 1.0 ;# Revision Date: ;# Author: CG ;# ;# ;# Program demonstrates use of an I/O expander to manage an LCD Interface ;###################################################################### ############ tot equ 0x20 sum equ 0x21 temp equ 0x22 ten equ 0x23 inter equ 0x24 auxw equ 0x25 auxs equ 0x26 at equ 0x27 tota equ 0x28 #define PIC18 ;set the test to use PIC16 device ;#define _ADD_PROC_INC_FILE #ifdef PIC16 list p=16f819 include <P16F819.INC> #else list p=18f1320 include <P18F1320.INC> #endif include "IOExpLCD.inc" include "LCDMsgs.inc" include "SPImb.inc" ;-------------------------------------------------------------------;COPIADO DEL PICDEM18 __CONFIG _CONFIG1H, _IESO_OFF_1H & _FSCM_OFF_1H & _INTIO2_OSC_1H __CONFIG _CONFIG2L, _PWRT_ON_2L & _BOR_OFF_2L & _BORV_27_2L __CONFIG _CONFIG2H, _WDT_OFF_2H & _WDTPS_32_2H __CONFIG _CONFIG3H, _MCLRE_ON_3H __CONFIG _CONFIG4L, _DEBUG_OFF_4L & _LVP_OFF_4L & _STVR_OFF_4L __CONFIG _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L __CONFIG _CONFIG5H, _CPB_OFF_5H & _CPD_OFF_5H __CONFIG _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L __CONFIG _CONFIG6H, _WRTC_OFF_6H & _WRTB_OFF_6H & _WRTD_OFF_6H __CONFIG _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L __CONFIG _CONFIG7H, _EBTRB_OFF_7H ;--------------------------------------------------------------------STARTUP CODE 0x0000 goto start CODE 0x0008 goto in Real_Code_Start CODE start #ifdef PIC18 ;bsf ADCON1,PCFG5 for I2C as digital ;bsf ADCON1,PCFG6 movlw B'0111000' movwf OSCCON setf ADCON1 ;call LongDelay #endif clrf inter clrf tota bcf RCON, 7 ;bsf INTCON2, 2 bsf INTCON, 7 bsf INTCON, 5 movlw 0C5h movwf T0CON ;TMR0 hab, 8bit, presc0 ;bcf T0CON, 6 clrf tot clrf ten movlw 030h movwf sum call IOExpLCDInit call IOExpLCDHideCursor call IOExpLCDLine1 mIOExpLCDSendMessage Prueba call IOExpLCDLine2 goto Po aux movlw 09h cpfseq tot goto I goto Ix Ix movlw 0x06 movwf vIOExpLCD_X ;set pins used movlw 0x01 call IOExpLCDSetCursor movf ten, 0 addwf sum, 0 call IOExpLCDWriteData movlw 030h call IOExpLCDWriteData incf inter goto Po I movlw 0x07 movwf vIOExpLCD_X movlw 0x01 call IOExpLCDSetCursor movf tot, 0 addwf sum, 0 call IOExpLCDWriteData incf inter goto Po Po movf tota, 0 cpfseq inter goto aux goto Po i incf tot incf tota goto fi ix incf ten clrf tot incf tota goto fi ax2 movlw 09h cpfseq tot goto i goto ix ps btfss temp, 0 ; Comprueba si el pulsador fue pulsado goto fi goto ax2 bot btfsc PORTB, 0 ; Comprueba si el pulsador esta pulsado o no goto ps bsf temp, 0 goto bot in movwf auxw movf STATUS, 0 movwf auxs clrf temp goto bot fi bcf INTCON, 2 bcf temp, 0 movf auxs, 0 movwf STATUS movf auxw, 0 retfie goto $ END Codigo del Proyecto tot equ 0x20 ten equ 0x21 inter equ 0x22 sum equ 0x23 totx equ 0x24 tenx equ 0x25 interx equ 0x26 auxw equ 0x27 auxs equ 0x28 #define PIC18 ;#define _ADD_PROC_INC_FILE ;set the test to use PIC16 device #ifdef PIC16 list p=16f819 include <P16F819.INC> #else list p=18f1320 include <P18F1320.INC> #endif include "IOExpLCD.inc" include "LCDMsgs.inc" include "SPImb.inc" ;-------------------------------------------------------------------;COPIADO DEL PICDEM18 __CONFIG _CONFIG1H, _IESO_OFF_1H & _FSCM_OFF_1H & _INTIO2_OSC_1H __CONFIG _CONFIG2L, _PWRT_ON_2L & _BOR_OFF_2L & _BORV_27_2L __CONFIG _CONFIG2H, _WDT_OFF_2H & _WDTPS_32_2H __CONFIG _CONFIG3H, _MCLRE_ON_3H __CONFIG _CONFIG4L, _DEBUG_OFF_4L & _LVP_OFF_4L & _STVR_OFF_4L __CONFIG _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L __CONFIG _CONFIG5H, _CPB_OFF_5H & _CPD_OFF_5H __CONFIG _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L __CONFIG _CONFIG6H, _WRTC_OFF_6H & _WRTB_OFF_6H & _WRTD_OFF_6H __CONFIG _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L __CONFIG _CONFIG7H, _EBTRB_OFF_7H ;--------------------------------------------------------------------STARTUP CODE 0x0000 goto start CODE 0x0008 goto in Real_Code_Start CODE start #ifdef PIC18 ;bsf ADCON1,PCFG5 for I2C as digital ;bsf ADCON1,PCFG6 movlw B'0111000' movwf OSCCON setf ADCON1 ;call LongDelay #endif goto S ;ADRESH ;ADRESL in bsf ADCON0, 1 movwf auxw movf STATUS, 0 movwf auxs bu btfss ADCON0, 1 goto ne goto bu ne movlw B'00001111' andwf ADRESL, 0 movwf interx movlw B'11110000' andwf ADRESL, 0 movwf totx rrncf totx rrncf totx rrncf totx rrncf totx movlw B'00000011' andwf ADRESH, 0 movwf tenx bcf INTCON, 2 movf auxs, 0 movwf STATUS movf auxw, 0 retfie cerca call IOExpLCDLine2 mIOExpLCDSendMessage crqui goto Po quive call IOExpLCDLine2 mIOExpLCDSendMessage quiven goto Po vevc call IOExpLCDLine2 mIOExpLCDSendMessage veci goto Po ;set pins used vctre call IOExpLCDLine2 mIOExpLCDSendMessage vctrei goto Po tretc call IOExpLCDLine2 mIOExpLCDSendMessage tretci goto Po tccu call IOExpLCDLine2 mIOExpLCDSendMessage tccua goto Po cucc call IOExpLCDLine2 mIOExpLCDSendMessage cucci goto Po cccq call IOExpLCDLine2 mIOExpLCDSendMessage ccci goto Po cqse call IOExpLCDLine2 mIOExpLCDSendMessage cqses goto Po sesc call IOExpLCDLine2 mIOExpLCDSendMessage sesci goto Po sest call IOExpLCDLine2 mIOExpLCDSendMessage sestn goto Po scst call IOExpLCDLine2 mIOExpLCDSendMessage sctn goto Po maxim call IOExpLCDLine2 mIOExpLCDSendMessage maxi goto Po atr movlw 05H cpfslt inter goto cccq goto cqse ads movlw 05H cpfslt inter goto cqse goto sesc aun movlw 05h cpfslt inter goto sesc goto scst ace movlw 08h cpfslt tot goto scst goto maxim uno movlw 0AH cpfslt tot goto tccu movlw 06h cpfslt tot goto cucc movlw 03h cpfslt tot goto atr movlw 02H cpfslt tot goto ads movlw 01H cpfslt tot goto aun goto ace dos movlw 0Bh cpfslt tot goto vctre movlw 03h cpfslt tot goto vctre goto tretc tres movlw 06H cpfslt tot goto cerca goto quive tra movlw 03H cpfslt ten goto tres movlw 02h cpfslt ten goto dos goto uno S clrf totx clrf tenx clrf interx movlw 030h movwf sum bcf ADCON1, 4 bcf ADCON1, 3 movlw B'01010001' movwf ADCON0 movlw B'10000011' movwf ADCON2 call IOExpLCDInit call IOExpLCDHideCursor call IOExpLCDLine1 mIOExpLCDSendMessage Prueba call IOExpLCDLine2 mIOExpLCDSendMessage cntm bcf RCON, 7 bsf INTCON, 7 bsf INTCON, 5 movlw 0C7h movwf T0CON ;TMR0 hab, 8bit, presc0 Po movlw 0x00 movwf vIOExpLCD_X movlw 0x00 call IOExpLCDSetCursor movff tenx, ten movff totx, tot movff interx, inter goto tra END