Ejemplo de aplicacin con Arduino: medida de caudal.
TITULACIN: Ingeniera Tcnica Industrial en Electrnica Industrial
AUTOR: Josep Fernandez Daroca DIRECTOR: Jos Lus Ramrez Falo
FECHA: Septiembre / 2012.
2 ndice de contenido
1 OBJETIVO DEL PFC ................................................................................................................. 6 2 ARDUINO ..................................................................................................................................... 6 2.1 INTRODUCCIN A ARDUINO ................................................................................................... 6 2.1.1 Qu es Arduino? ........................................................................................................ 6 2.1.2 Qu significa que Arduino sea Open Hardware?[4] ................................................ 6 2.1.3 Por qu Arduino? ...................................................................................................... 7 2.2 LAS PLACAS ARDUINO ........................................................................................................... 8 2.2.1 Qu significa que una placa sea Arduino? ................................................................ 8 2.2.2 Placas de entradas y salidas ....................................................................................... 8 2.2.3 "Shields" y otras placas de terceros .......................................................................... 10 2.2.4 Construir nuestro propio Arduino ............................................................................. 12 2.2.5 Cmo obtener una placa Arduino? ......................................................................... 12 2.2.6 Nuestra eleccin: El Arduino UNO ........................................................................... 12 2.2.6.1 El porqu de nuestra eleccin ................................................................................................ 12 2.2.6.2 Caractersticas ........................................................................................................................ 13 2.2.6.3 Esquema y pines .................................................................................................................... 14 2.3 EL ENTORNO DE TRABAJO .................................................................................................... 15 2.3.1 El entorno de desarrollo y los drivers de la placa para Windows ............................ 15 2.3.2 Descargar y ejecutar un ejemplo de aplicacin Arduino .......................................... 18 2.3.2.1 Editor ..................................................................................................................................... 18 2.3.2.2 Compilador ............................................................................................................................ 19 2.3.2.3 Cargar y depurar .................................................................................................................... 20 2.4 LENGUAJE DE PROGRAMACIN ARDUINO ............................................................................ 22 2.4.1 Introduccin e historia .............................................................................................. 22 2.4.2 Funciones bsicas y operadores ............................................................................... 22 2.4.2.1 Estructuras ............................................................................................................................. 23 2.4.2.2 Variables ................................................................................................................................ 24 2.4.2.3 Funciones ............................................................................................................................... 25 2.4.3 Uso de libreras ......................................................................................................... 27 2.4.3.1 Libreras Estndar .................................................................................................................. 27 2.4.3.2 Libreras de terceros .............................................................................................................. 28 3 NUESTRO PROYECTO ARDUINO ....................................................................................... 30 3.1 MEDIDOR DE CAUDAL .......................................................................................................... 30 3.2 REQUERIMIENTOS INICIALES ............................................................................................... 30 3.3 ELECCIN DE LOS COMPONENTES ........................................................................................ 31 3.4 LISTA DE MATERIAL Y PRESUPUESTO ................................................................................... 32 3.5 EL HARDWARE ..................................................................................................................... 33 3.5.1 Caractersticas tcnicas de los componentes ............................................................ 33 3.5.1.1 Shield LCD color ................................................................................................................... 33 3.5.1.2 Sensor de caudal .................................................................................................................... 34 3.5.2 El ensamblado ........................................................................................................... 35 3.6 EL SOFTWARE ...................................................................................................................... 37 3.6.1 Diseo de la pantalla ................................................................................................ 37 3.6.1.1 Uso de la librera del shield LCD a color de Sparkfun .......................................................... 37 3.6.1.2 Informacin a mostrar e interfaz ............................................................................................ 39 3.6.2 El programa de control de Arduino .......................................................................... 40 3.6.3 El programa de control del PC ................................................................................. 43 3.7 JUEGO DE PRUEBAS .............................................................................................................. 44 3.7.1 Test sobre el caudalmetro ........................................................................................ 44 3.7.2 Test sobre la captura de pulsos ................................................................................. 45 3 3.7.3 Test de funcionamiento general................................................................................. 47 4 USO DE ARDUINO EN ENTORNOS LECTIVOS ................................................................ 48 4.1 EDUCACIN SECUNDARIA .................................................................................................... 48 4.2 EDUCACIN TCNICA SUPERIOR .......................................................................................... 48 4.2.1 Usar AVRStudio, cdigo C y Arduino ....................................................................... 49 4.2.2 Simular y ejecutar el cdigo C en nuestro microcontrolador ................................... 52 4.2.2.1 Simular el cdigo en el PC. AVRSimulator........................................................................... 53 4.2.2.2 Descargar el cdigo en nuestra placa Arduino. AVRDude. ................................................... 53 4.2.2.3 Uso de entornos de depuracin y programacin .................................................................... 54 4.2.3 El ATmega328P ........................................................................................................ 55 4.2.3.1 Un breve resumen .................................................................................................................. 55 4.2.3.2 Puertos de entrada y salida digital ......................................................................................... 55 4.2.3.3 Uso de la USART/comunicacin serie .................................................................................. 58 4.2.3.4 Las interrupciones en los ATmega328P ................................................................................ 60 4.2.3.5 Interrupciones por cambio de PIN ......................................................................................... 64 4.2.3.6 Uso de temporizadores y PWM ............................................................................................. 66 4.2.3.7 Uso del conversor ADC ......................................................................................................... 74 4.2.4 Codificacin del medidor de caudal en C ................................................................. 75 5 PRESUPUESTO ......................................................................................................................... 78 5.1 PRECIOS UNITARIOS ............................................................................................................. 78 5.2 PRECIOS DESCOMPUESTOS ................................................................................................... 78 5.2.1 Captulo 1: Estudios previos ..................................................................................... 78 5.2.2 Captulo 2: Diseo y montaje del hardware ............................................................. 79 5.2.3 Captulo 3: Diseo del firmware ............................................................................... 79 5.2.4 Captulo 4: Diseo del software de PC ..................................................................... 79 5.2.5 Captulo 5: Documentacin ...................................................................................... 80 5.3 RESUMEN DEL PRESUPUESTO ............................................................................................... 80 6 CONCLUSIONES Y VALORACIN PERSONAL ............................................................... 81 ndice de ilustraciones Ilustracin 1: Logo oficial de Arduino ......................................................................... 8 Ilustracin 2: En la parte superior Arduino MEGA y en la inferior Arduino UNO .... 9 Ilustracin 3: Arduino con tres "shields" ................................................................... 10 Ilustracin 4: RobotShop Rover ................................................................................. 11 Ilustracin 5: Arduino Single-Sided Serial o Severino .............................................. 12 Ilustracin 6: Arduino UNO, vista frontal ................................................................. 13 Ilustracin 7: Arduino UNO, vista trasera ................................................................. 13 Ilustracin 8: Pines de Arduino contra ATmega328 .................................................. 14 Ilustracin 9: Arduino en el administrador de dispositivos de Windows .................. 16 Ilustracin 10: Entorno SW de Arduino..................................................................... 17 Ilustracin 11: Acceso a los ejemplos a travs del men ........................................... 19 Ilustracin 12: Acceso a los ejemplos a travs de la barra de herramientas .............. 19 Ilustracin 13: Ejemplo de cdigo Arduino ............................................................... 19 Ilustracin 14: Resultado de verificacin correcto. .................................................... 20 Ilustracin 15: Resultado de verificacin incorrecto. ................................................ 20 Ilustracin 16: Ubicacin del LED de test en la placa Arduino ................................. 21 4 Ilustracin 17: Monitor de comunicacin serie integrado en el entorno Arduino ..... 22 Ilustracin 18: Diagrama de bloques del caudalmetro .............................................. 31 Ilustracin 19: Shield LCD a color ............................................................................ 33 Ilustracin 20: Punto a cortocircuitar para activar la retro iluminacin..................... 34 Ilustracin 21: Sensor de caudal Koolance ................................................................ 34 Ilustracin 22: Relacin entre litros y frecuencia del medidor de caudal .................. 34 Ilustracin 23: Esquema de montaje .......................................................................... 35 Ilustracin 24: Esquema de conexionado del caudalmetro ....................................... 36 Ilustracin 25: Vista lateral del montaje final ............................................................ 36 Ilustracin 26: Vista frontal del montaje final ........................................................... 37 Ilustracin 27: Listado de las libreras en el entorno Arduino ................................... 38 Ilustracin 28: Uso de una librera una vez instalada en el entorno Arduino ............ 38 Ilustracin 29: Pantalla principal ............................................................................... 40 Ilustracin 30: Pantalla contadores parciales 1 .......................................................... 40 Ilustracin 31: Pantalla contadores parciales 2 .......................................................... 40 Ilustracin 32: Diagrama de flujo del firmware ......................................................... 41 Ilustracin 33: Diagrama temporal del firmware ....................................................... 42 Ilustracin 34: Salida del programa de visualizacin en el PC .................................. 43 Ilustracin 35: Tren de pulsos del caudalmetro girando a baja velocidad ................ 44 Ilustracin 36: Tren de pulsos del caudalmetro girando a media velocidad ............. 45 Ilustracin 37: Tren de pulsos del caudalmetro girando a alta velocidad ................. 45 Ilustracin 38: Respuesta ante un tren de pulsos de 31Hz ......................................... 46 Ilustracin 39: Muestra de la pantalla principal ante una entrada de 31Hz ............... 46 Ilustracin 40: Secuencia de acciones en funcionamiento normal............................. 47 Ilustracin 41: Prueba de precisin del contador de segundos .................................. 48 Ilustracin 42: Vista inicial del AVR Studio ............................................................. 49 Ilustracin 43: Seleccin de dispositivo en AVR Studio ........................................... 50 Ilustracin 44: Vista de codificacin del AVR Studio ............................................... 51 Ilustracin 45: Resultado de la compilacin en el AVR Studio ................................. 52 Ilustracin 46: Vista del simulador integrado en AVR Studio .................................. 53 Ilustracin 47: Vista de ensamblador en AVRSimulator ........................................... 57 Ilustracin 48: Puerto general de entrada/salida digital ............................................. 58 Ilustracin 49: Ejemplo de uso del temporizador en modo CTC ............................... 71 Ilustracin 50: Generacin PWM en modo Fast PWM .......................................... 72 Ilustracin 51: Generacin PWM en modo Phase Correct PWM .......................... 72 5 Ilustracin 52: Generacin PWM en modo Phase and Frequency Correct PWM.. 73 Ilustracin 53: Uso del temporizador como Input capture ..................................... 73 Ilustracin 54: Configuracin opciones de optimizacin del compilador ................. 76 Ilustracin 55: Configuracin opciones de optimizacin del linker .......................... 76 Ilustracin 56: Resultado de la construccin del proyecto en AVRStudio ................ 77 Ilustracin 57: Modificacin del fichero ColorLCDShield.cpp. 1era parte ............... 84 Ilustracin 58: Modificacin del fichero ColorLCDShield.cpp. 2da parte ................ 85 Ilustracin 59: Configuracin de una herramienta externa en AVRStudio ............... 99 Ilustracin 60: Vista para crear un botn para las herramientas externas en AVRStudio ........................................................................................................................ 100 Ilustracin 61: Cuadro de opciones para botn en la barra de herramientas. I ........ 100 Ilustracin 62: Cuadro de opciones para botn en la barra de herramientas. II ....... 101 Ilustracin 63: Vista del botn en la barra de herramientas ..................................... 101 Ilustracin 64: Estructura de carpetas del soporte digital ........................................ 112
ndice de anexos ANEXOS ............................................................................................................................................. 83 ANEXO 1: INFORMACIN USO LIBRERA LCD ................................................................................ 83 Modificaciones sobre la librera................................................................................................. 84 ANEXO 2: PROGRAMA DE CONTROL DE ARDUINO. ......................................................................... 86 ANEXO 3: PROGRAMA DE CONTROL DEL PC. ................................................................................. 91 ANEXO 4: CONFIGURACIN DEL AVRSTUDIO PARA DESCARGAR EL CDIGO EN ARDUINO. .......... 97 Contenido de Upload.cmd ...................................................................................................... 97 Contenido de UploadFromAVRStudio.cmd ............................................................................ 98 Uso de herramientas externas en AVRStudio ............................................................................. 98 ANEXO 5: LIBRERA DE USO DE LA COMUNICACIN SERIE EN AVRSTUDIO ................................. 101 Contenido de Arduino_SERIAL_API.h ................................................................................ 101 Contenido de Arduino_SERIAL.c ......................................................................................... 102 ANEXO 6: COMUNICACIN SERIE CON INTERRUPCIONES DE RECEPCIN ...................................... 103 Contenido de Arduino_SERIAL_INTRx_API.h .................................................................... 103 Contenido de Arduino_SERIAL_INTRx.c ............................................................................ 103 Contenido de Arduino_SERIAL_INTERRUPT_example.c ................................................... 104 ANEXO 7: MEDIDOR DE CAUDAL IMPLEMENTADO CON AVRSTUDIO ........................................... 105 Contenido de medidorCaudal_AVR.cpp .............................................................................. 105 Parte del contenido modificado de ColorLCDShield.h ........................................................ 110 ANEXO 8: CONTENIDO DEL SOPORTE DIGITAL DEL PFC ............................................................... 111 6 1 Objetivo del PFC El objetivo principal de este proyecto fin de carrera es conocer Arduino con todo su ecosistema de herramientas y accesorios, y evaluar sus capacidades y posibilidades. Se ha definido como segundo objetivo la evaluacin de las capacidades formativas/lectivas de la plataforma Arduino en el mbito de la educacin tanto secundaria como universitaria. Para alcanzar tales objetivos propongo la realizacin de un medidor de caudal como hilo conductor para poder conocer y evaluar tanto el hardware como el software, as como conocer los distintos canales de distribucin. 2 Arduino 2.1 Introduccin a Arduino La mayor parte de esta seccin es una recopilacin de la informacin disponible en la pgina web del proyecto Arduino y de la entrada de la Wikipedia que hace referencia a Arduino. 2.1.1 Qu es Arduino? Arduino es una plataforma de electrnica abierta para la creacin de prototipos basada en software y hardware flexibles y fciles de usar. Se cre para artistas, diseadores, aficionados y cualquiera interesado en crear entornos u objetos interactivos.(Pgina principal de la web del proyecto Arduino [1]) Arduino es una plataforma de hardware libre (Open Source Hardware, OSHW) basada en una placa con un microcontrolador y un entorno de desarrollo. El hardware consiste en una placa con un microcontrolador Atmel AVR y varios puertos de entrada/salida, tanto digitales como analgicos, as como salidas PWM y de comunicaciones, para el control de objetos fsicos (LEDs, servos, botones, etc.). Los microcontroladores ms usados son el ATmega328 y el ATmega168 para las placas bsicas, el ATmega1280 para la de mayor capacidad y el ATmega8 para las placas ms antiguas. Todos estos microcontroladores incluyen un cargador de arranque (boot loader) de manera que sea lo ms simple posible empezar a trabajar con ellos. El microcontrolador en la placa Arduino se programa mediante el lenguaje de programacin Arduino (basado en Wiring[2]) y el entorno de desarrollo Arduino (basado en Processing[3]). 2.1.2 Qu significa que Arduino sea Open Hardware?[4] El hardware open-source (de fuente abierta o libre) comparte muchos de los principios y metodologas del software libre y de cdigo abierto. Algunos de los principios que se pretenden promover para considerar productos fsicos como open hardware son los siguientes: 7 Publicar la documentacin, incluyendo los archivos de los diseos mismos, que debe permitir su modificacin y distribucin. Especificar que porcin del diseo es abierta en caso de que no se liberen todos sus componentes. Ofrecer el software para el visionado de los archivos de diseo y de la documentacin, para que se pueda escribir el cdigo open-source fcilmente. Ofrecer una licencia que permita producir derivados y modificaciones, adems de su re-distribucin bajo la licencia original, as como su venta y manufactura. La licencia no debe restringir que se venda o comparta la documentacin necesaria. No pide una tarifa por su venta o la de sus derivados. La licencia no debe discriminar a ningn grupo o persona La licencia no debe de restringir a ningn campo o actividad el uso de la obra. Es decir, no se puede limitar su uso nicamente para negocios o prohibir sea utilizado para investigacin nuclear. El licenciamiento de la obra no puede depender de un producto en particular. La licencia no debe restringir otro hardware o software, es decir que no puede insistir en que otros componentes de hardware o software externos a los dispositivos sean tambin open-source. La licencia tiene que ser neutral, ninguna disposicin de la misma debe de basarse en una tecnologa especfica, parte o componente, material o interfaz para su uso.
Cumpliendo con estas premisas, los diseos y esquemas de Arduino se distribuyen bajo licencia Creative Commons Attribution-ShareAlike 2.5[5]. Al seguir este tipo de licencias, donde toda la informacin es pblica, todas las placas pueden ser construidas por uno mismo o bien comprarlas ya montadas. El software puede ser descargado de forma gratuita. Los ficheros de diseo de referencia (CAD), al estar disponibles bajo una licencia abierta, pueden ser libremente adaptados a las necesidades particulares. 2.1.3 Por qu Arduino? Hay distintas soluciones comerciales que facilitan el trabajo de programar un microcontrolador y poder interactuar con ellos, como podran ser Parallax Basic Stamp[6], BX-24 de Netmedia[7], Phidgets[8] o Handyboard del MIT[9] por citar algunos. Arduino, adems de simplificar este proceso intenta ofrecer otras ventajas: Asequible Las placas Arduino son ms asequibles comparadas con otras plataformas de microcontroladores. La versin ms cara de un modulo de Arduino puede ser montada a mano, e incluso ya montada cuesta bastante menos de 60 Multi-Plataforma - El software de Arduino funciona en los sistemas operativos Windows, Macintosh OSX y Linux. La mayora de los entornos para microcontroladores estn limitados a Windows. Entorno de programacin simple y directo - El entorno de programacin de Arduino es fcil de usar para principiantes y lo suficientemente flexible para los usuarios avanzados. Software ampliable y de cdigo abierto - El software Arduino esta publicado bajo una licencia libre, y preparado para ser ampliado por programadores experimentados. El lenguaje puede ampliarse a travs de 8 libreras de C++, y si se est interesado en profundizar en los detalles tcnicos, se puede dar el salto a la programacin en el lenguaje C en el que est basado. De igual modo se puede aadir directamente cdigo en C en los programas. Hardware ampliable y de Cdigo abierto - Arduino est basado en los microcontroladores ATMEGA168, ATMEGA328 y ATMEGA1280. Los planos de los mdulos estn publicados bajo licencia Creative Commons, por lo que diseadores de circuitos con experiencia pueden hacer su propia versin del mdulo, amplindolo u optimizndolo. Incluso usuarios relativamente inexpertos pueden construir la versin para placa de desarrollo para entender cmo funciona y ahorrar algo de dinero. 2.2 Las placas Arduino 2.2.1 Qu significa que una placa sea Arduino?
Ilustracin 1: Logo oficial de Arduino Arduino es el nombre del proyecto microcontrolador Arduino oficial, alojado en http://arduino.cc. Aunque el nombre "Arduino" no est oficialmente registrado, generalmente es respetado por la comunidad como propiedad del equipo Arduino. Al tratarse de OSHW existen multitud de proyectos y placas basadas en Arduino que pueden ser totalmente compatibles con este, o que han sufrido ligeras modificaciones, ya sea para hacerlas especificas para ciertos trabajos o bien para reducir su coste. "Freeduino"[10] es un nombre que identifica las variantes del proyecto Arduino que no fueron creadas por el equipo oficial de desarrollo Arduino. Algunos de estos freeduinos serian Boarduino, uDUINO, iDuino, ArduPilot,...[11] 2.2.2 Placas de entradas y salidas Existe una gran variedad de placas Arduino, y de todas ellas se han hecho varias revisiones. 9
Ilustracin 2: En la parte superior Arduino MEGA y en la inferior Arduino UNO Las placas Arduino oficiales a da de hoy son[12]: Arduino UNO. Es una placa Arduino que se conecta al PC a travs de un cable USB estndar. A travs de esta conexin la alimentacin y, adems, permite programarla y utilizarla. Arduino UNO es la ltima revisin de este tipo de placas que se conectan al USB. Entre las mltiples revisiones que se han hecho encontraramos la Duemilanove, Diecimila, NG (Nuova Generazione) o Extreme. Arduino Mega Es una placa Arduino similar a la USB, pero ms grande y potente. La ltima revisin posee el chip ATmega2560. Tiene mayor nmero de pines de entradas y salidas digitales, ms pines PWM, entradas analgicas, etc. Arduino Mega ADK El Arduino ADK es una placa similar al Arduino Mega, pero con una interface USB para conectar con telfonos basados en Android. Arduino Pro Es una placa similar al Arduino UNO, pero diseada con la intencin de instalaciones semipermanentes. La placa se entrega sin los distintos conectores o headers, es compatible con las distintas extensiones de Arduino, y existe una versin de 3.3V para ser alimentado con bateras. Arduino Ethernet Similar al Arduino UNO, sin soporte USB, pero con un conector RJ-45 para dar soporte Ethernet. Existe la posibilidad de tomar la alimentacin de la propia Ethernet. Arduino Fio Un Arduino orientado para usarlo como nodo inalmbrico. Posee conectores para un mdulo Xbee (mdulo inalmbrico)[13], un conector para una batera LiPo (Polmeros de litio), y un circuito para cargar la batera. Arduino LilyPad 10 Una placa Arduino circular, reducida al mximo, diseada para ser cosida a la ropa o a otro tipo de soporte flexible. Necesita un adaptador adicional para comunicarse con el PC. Arduino BT El Arduino BT contiene un mdulo bluetooth integrado para las comunicaciones mviles. Arduino Nano El Arduino Nano es un todo-en-uno, diseo compacto para usar en una placa de prototipo. Arduino Serial Las versiones serial de Arduino se vendieron principalmente como kits no ensamblados o solo PCBs para que lo montara uno mismo, ya sea a modo de aprendizaje o para reducir costes. Arduino Mini El Arduino Mini es la placa compacta de Arduino. Para reducir espacio, la comunicacin con el PC se hace a travs de un adaptador de USB a Arduino Mini. Arduino Pro Mini Igual que el Arduino Mini, pero sin los headers ni lo conectores montados, con la intencin de tenerlo en instalaciones semipermanentes o permanentes. Arduino Single-Sided Serial Tambin conocido como "Severino". Esta es la versin de la placa Arduino de una sola cara, hacindola fcil de hacer a mano. No fue manufacturada, sino que fue publicada en la web de Arduino para que la gente se la pudiese hacer ellos mismos a modo de aprendizaje de todo el proceso de grabacin de PCB. El objetivo de Arduino y sus placas es ofrecer a la gente la posibilidad de seguir la filosofa DIY (Do it yourself). 2.2.3 "Shields" y otras placas de terceros Las shields son placas que se colocan encima de la placa Arduino y que amplan una nueva funcin para que sea controlada desde Arduino, para controlar diferentes aparatos, adquirir datos, etc.
Ilustracin 3: Arduino con tres "shields" 11
A continuacin se citan las shields oficiales de Arduino, pero existe multitud de shields de terceros. Arduino Ethernet Shield Esta shield permite a una placa Arduino conectarse a una red Ethernet y tener acceso a y desde Internet. Arduino Wireless Proto Shield Esta shield le da a una placa Arduino la posibilidad de comunicarse de manera inalmbrica basndose en los mdulos Xbee[13], y ofrece al usuario una pequea rea para soldar componentes (prototipage). Arduino Wireless SD Shield Igual que la anterior, pero dando soporte para acceder a una tarjeta de memoria tipo SD. Arduino Motor Shield Esta shield permite a Arduino controlar motores elctricos de corriente continua, servos y motores paso a paso, y leer encoders. Arduino Proto Shield Esta shield ofrece al usuario un rea para soldar componentes. Uno de los principales distribuidores y desarrolladores de shields es Sparkfun, aunque no el nico. Esta pgina web http://shieldlist.org/ intenta mantener una lista de todas las shields de Arduino, tanto las oficiales como las no oficiales. A parte de las shields existe un buen nmero de plataformas que estn listas para ser controladas por una placa Arduino[14]. Entre estas plataformas, quizs una de las ms vistosas seria: RobotShop Rover Es una pequea plataforma mvil diseada entorno a Arduino. Los usuarios pueden personalizar su mvil aadiendo funcionalidad.
Ilustracin 4: RobotShop Rover 12 2.2.4 Construir nuestro propio Arduino Al ser OSHW puede montarse los distintos mdulos uno mismo. La placa Arduino Single-Sided Serial (cara simple y mono capa) o Severino ha sido diseada para que sea especialmente fcil de grabar el PCB y montar los distintos componentes.
Ilustracin 5: Arduino Single-Sided Serial o Severino Se puede encontrar una extensa documentacin, incluyendo un detallado manual, en la pgina web oficial [23]. 2.2.5 Cmo obtener una placa Arduino? Se puede adquirir una placa Arduino desde uno de los distribuidores oficiales, o a travs de mltiples tiendas online de electrnica. En la pgina principal de Arduino se puede encontrar una extensa lista de distribuidores en funcin del pas o regin. Despus de evaluar la mayora de ellos por variedad, disponibilidad, precio y gastos de envo, me inclino por recomendar las siguientes: Tienda BricoGeek.com [24] ELECTAN Electrnica y Robtica [25] 2.2.6 Nuestra eleccin: El Arduino UNO 2.2.6.1 El porqu de nuestra eleccin El principal objetivo de este proyecto es evaluar las capacidades de Arduino a travs de la realizacin de un pequeo proyecto. Para lograr este objetivo se deba trabajar con un mdulo real, pero no era el caso de estudio el montaje ni la depuracin de los posibles errores del hardware, con lo que se opt por la compra de mdulo ya montado. Como punto de partida, teniendo en cuenta que no necesitabamos gran cantidad de entradas y salidas, se decidi usar una placa Arduino que tuviera todo lo necesario para empezar a trabajar al coste ms acotado posible. La actual revisin que mejor encaja con estas caractersticas es el Arduino UNO. 13
Ilustracin 6: Arduino UNO, vista frontal
Ilustracin 7: Arduino UNO, vista trasera 2.2.6.2 Caractersticas La descripcin completa del Arduino UNO se puede encontrar en su pgina web oficial. Este es un resumen de las principales caractersticas: Microcontrolador ATmega328 Voltaje de funcionamiento 5V Voltaje de entrada (recomendado) 7-12V Voltaje de entrada (limite) 6-20V Pines E/S digitales 14 (6 proporcionan salida PWM) Pines de entrada analgica 6 Intensidad mxima por pin 40 mA Intensidad en pin 3.3V 50 mA Memoria Flash 32 KB (ATmega328) de las cuales 0,5 KB las usa el gestor de arranque (boot loader) SRAM 2 KB (ATmega328) EEPROM 1 KB (ATmega328) Velocidad de reloj 16 Mhz El Arduino UNO puede ser alimentado va la conexin USB o con una fuente de alimentacin externa. El origen de la alimentacin se selecciona automticamente. Adems, algunos de los pines tienen funciones especializadas: Serie: Pin 0 (RX) y 1 (TX). Usados para recibir (RX) y transmitir (TX) datos a travs de puerto serie TTL. Estos pines estn conectados a los pines correspondientes del chip de FTDI responsable de la conversin USB-to- TTL. Interrupciones Externas: Pin 2 y 3. Estos pines se pueden configurar para que interrumpan la ejecucin del programa al detectar un flanco o un nivel. PWM: Pin 3, 5, 6, 9, 10, y 11. Proporciona una salida PWM (Pulse-width modulation, modulacin por ancho de pulsos) con temporizadores de 8 bits de resolucin. 14 SPI: Pin 10 (CS/SS), 11 (MOSI), 12 (MISO), 13 (SCK). Estos pines proporcionan comunicacin SPI (Serial Peripheral Interface). LED: Pin 13. Hay un LED integrado en la placa conectado al pin digital 13, cuando este pin tiene un valor HIGH(5V) el LED se enciende y cuando este tiene un valor LOW(0V) el LED se apaga. 6 entradas analgicas, cada una de ellas proporciona una resolucin de 10bits (1024 valores). Por defecto se mide de tierra a 5 voltios, aunque es posible cambiar la cota superior de este rango usando el pin AREF I2C: Pin 4 (SDA) y 5 (SCL). Soporte del protocolo de comunicaciones I2C /TWI. AREF. Este pin proporciona un voltaje de referencia para las entradas analgicas. Reset. Si en este pin se suministra un valor bajo (0V) se reinicia el microcontrolador. El ATmega328 en las placas Arduino UNO viene precargado con un gestor de arranque (boot loader) que permite cargar nuevo cdigo sin necesidad de un programador por hardware externo. La carga de un nuevo cdigo se realiza a travs del entorno de desarrollo Arduino y la conexin serie/USB. Tambin es posible saltar el gestor de arranque y programar directamente el microcontrolador a travs del puerto ICSP (In Circuit Serial Programming). En tal caso, se debe utilizar un programador externo. 2.2.6.3 Esquema y pines Los esquemas completos del Arduino UNO se pueden encontrar en su pgina web oficial. En la siguiente imagen se puede ver la correspondencia de pines entre el ATmega168/328 y Arduino.
Ilustracin 8: Pines de Arduino contra ATmega328 15 2.3 El entorno de trabajo Para empezar a trabajar debemos instalar todo el entorno necesario en el PC. Vamos a describir brevemente este proceso en un entorno Windows. Existe gran cantidad de guas acerca de cmo realizar este proceso, incluyendo una explicacin en la propia pgina del proyecto Arduino[22]. Debo indicar que este proyecto se ha realizado con la versin 1.0 del entorno de programacin Arduino. Esta es la primera versin no Alfa del entorno Arduino, y presenta grandes cambios en comparacin de las anteriores. La mayora de cambios son a nivel esttico (distribucin de iconos en las barra de herramientas, esquema de colores,), pero hay un gran cambio a nivel funcional, los ficheros Arduino han pasado de tener extensin .pde a extensin .ino Estos ltimos cambios implican que la mayor parte de la documentacin que se encuentra en internet a da de hoy es incorrecta o desfasada con la revisin actual del entorno software de Arduino. 2.3.1 El entorno de desarrollo y los drivers de la placa para Windows La descarga: Descargamos la ltima versin del software Arduino de la pgina oficial [26]. El paquete de software Arduino est contenido en un nico fichero comprimido. No es necesario instalarlo, simplemente lo extraemos en la carpeta deseada asegurndonos que mantenemos la estructura de subcarpetas. Los controladores (drivers): Seguiremos instalando los drivers de nuestro Arduino. Para realizar este paso necesitaremos conectar el Arduino a nuestro PC, simplemente con un cable USB tipo A-B (el comnmente usado por las impresoras). Los drivers necesarios para utilizar la placa Arduino junto con su entorno se encuentran en la subcarpeta \drivers del paquete que acabamos de extraer. Una vez conectemos nuestra placa Arduino en nuestro PC, deberemos indicarle a Windows que debe buscarlos en esta carpeta. Dependiendo de la versin de Windows usada, y de la variante de la placa Arduino, este proceso puede variar e incluso no funcionar del modo esperado (especialmente Windows 7). En tal caso, nos dirigimos al Administrador de dispositivos y veremos algo parecido a esto: 16
Ilustracin 9: Arduino en el administrador de dispositivos de Windows En este caso, nos dirigiremos al dispositivo desconocido, el Arduino Uno. Con el botn derecho actualizaremos el software del controlador indicndole la ruta donde hemos extrado el software de Arduino\drivers. Deberemos aceptar la advertencia de que este software no est firmado por Microsoft. Una vez finalizado este proceso, deberamos ver un nuevo puerto de comunicaciones, en nuestro caso el COM3, que ser nuestro Arduino, ya que este driver se comporta como un puerto serie en el PC, con lo que nos aade uno nuevo sobre el ltimo. El IDE (Integrated Development Environment o "entorno de desarrollo integrado"): Ya tenemos nuestro PC y nuestra placa Arduino listos para trabajar. En la raz de la carpeta donde hemos extrado el software Arduino deberamos encontrar un arduino.exe, lo ejecutamos y nos abrir el entorno de trabajo: el IDE. Para facilitar futuros accesos podemos crear un acceso directo. Una vez abierto el entorno Arduino deberamos ver algo como esto: 17
Ilustracin 10: Entorno SW de Arduino Antes que nada debemos saber que un sketch, o boceto, es el nombre que usa Arduino para un programa. Es la unidad de cdigo que se sube y se ejecuta en la placa Arduino. El concepto de sketch o boceto, sera el equivalente a proyecto. Un sketch puede contener mltiples archivos (pestaas). Cuando un sketch es compilado, todas las pestaas sern concatenadas juntas para formar el archivo principal del sketch. Arduino puede utilizar libreras y cdigo C/C++. Las pestaas .c o .cpp se compilaran por separado y debern ser incluidas en el sketch usando #include. Es importante configurar correctamente la placa Arduino que vamos a utilizar, y a travs de qu puerto de comunicaciones estar conectada. Para tal efecto, debemos ir al men Tools escoger el submen Board e indicar la placa que usaremos, en nuestro 18 caso Arduino Uno. En el mismo men Tools, submen Serial Port, seleccionaremos el puerto correspondiente, en nuestro caso COM3. La barra de herramientas nos proporciona un acceso rpido a las siguientes funciones:
Verify - Verificar/Compilar Se utiliza para compilar y as comprobar que nuestro boceto es correcto antes de cargarlo a la placa Arduino.
Upload - Cargar/Programar Cargar el boceto actual a la placa Arduino. Debemos asegurarnos que la placa y el puerto seleccionado (en el men Herramientas) es correcto antes de cargar el cdigo.
New - Nuevo Crear un nuevo boceto para poder empezar a introducir cdigo.
Open - Abrir Presenta una lista de bocetos almacenados en su entorno, as como una lista de bocetos de ejemplo. Estos se pueden utilizar para comprobar que los perifricos funcionan correctamente.
Save - Guardar Guarda el boceto de la ventana en el archivo de boceto. Una vez finalizado muestra un mensaje en el rea de estado, debajo de la zona de edicin de cdigo.
Serial monitor - Monitor serie Abre una ventana con un monitor del bus serie al que est conectado nuestro Arduino. Esta es una herramienta muy til, especialmente para depurar el cdigo. El monitor muestra datos serie que se envan desde la placa Arduino (USB o RS232) y tambin puede enviar datos serie de vuelta a la placa Arduino. En la parte inferior izquierda del monitor serie se puede seleccionar la velocidad de transmisin de datos. La configuracin por defecto es 9600 baud. 2.3.2 Descargar y ejecutar un ejemplo de aplicacin Arduino Tenemos conectado la placa Arduino en nuestro PC. Hemos instalado los drivers y ejecutado el IDE de Arduino. Conocemos los conceptos bsicos acerca de los bocetos de Arduino. Verifiquemos ahora que nuestra placa y el PC funcionan correctamente. 2.3.2.1 Editor En el IDE Arduino, seleccionaremos el men File, submen Examples (o bien directamente, el icono Open ) y dentro de 1.Basics seleccionaremos el boceto (sketch) Blink. 19
Ilustracin 11: Acceso a los ejemplos a travs del men
Ilustracin 12: Acceso a los ejemplos a travs de la barra de herramientas Esto nos abrir una nueva ventana con el cdigo de este boceto, el objetivo del cual no es ms que encender y apagar el LED de test, montado en la placa Arduino, cada segundo (secuencia infinita de un segundo encendido, un segundo apagando. Blink).
Ilustracin 13: Ejemplo de cdigo Arduino 2.3.2.2 Compilador Como se puede observar en la Ilustracin 13: Ejemplo de cdigo Arduino, el cdigo necesario para realizar tal accin es bastante simple. Ahora solo falta comprobar que realmente es correcto. Para tal cosa, simplemente pulsando sobre el icono Verify , el IDE de Arduino va a verificar y compilar el cdigo escrito en la ventana activa. El entorno Arduino siempre compila el cdigo de las pestaas de la ventana activa como un nico boceto. 20 El resultado debera ser correcto y lo veremos en el rea de estado o de notificaciones: Aqu nos indica el estado del proceso, el tamao de memoria usada y la disponible en nuestra placa Arduino.
Ilustracin 14: Resultado de verificacin correcto. Si modificamos el cdigo del ejemplo para forzar un error en la fase de verificacin/compilacin, nos encontraramos con esto:
Ilustracin 15: Resultado de verificacin incorrecto. Hemos remplazado la llamada a la funcin PinMode por PinModo, y hemos eliminado el ; del final de la llamada a la funcin delay(1000). Al compilar, el entorno Arduino nos advierte de estos errores en la zona de estado, indicando los errores detectados, as como las lneas en que se encuentran. 2.3.2.3 Cargar y depurar Si volvemos al cdigo original, y lo compilamos, ya solo nos falta un paso para poder probarlo en nuestra placa Arduino: Cargar el cdigo. Con la placa Arduino conectada al PC a travs del puerto USB, y teniendo configurado correctamente en el entorno nuestra placa Arduino y el puerto de comunicaciones, pulsaremos sobre el icono Upload . 21
Ilustracin 16: Ubicacin del LED de test en la placa Arduino En breves instante, la barra de estado se completar y nos indicar que el proceso ha finalizado. En ese momento, el entorno genera un reset a la placa Arduino, y el cdigo empieza a ejecutarse. En nuestro caso, veremos como el LED de test montado en la placa Arduino empieza a encenderse y apagarse cada segundo. Para poder depurar el cdigo, y as ver en qu punto de la ejecucin se encuentra, Arduino nos brinda un gran herramienta: el monitor serie. El monitor serie sirve para que nos podamos comunicar entre el PC y nuestra placa Arduino. Las posibilidades de este pueden ser enormes, pero de momento lo usaremos de la forma ms simple posible. Modificaremos el cdigo del ejemplo de Blink aadiendo unas llamadas al monitor serie, de manera que durante la ejecucin podremos ver en el PC qu punto del cdigo se est ejecutando en la placa Arduino. Cdigo Blink original Cdigo Blink con depuracin a travs del monitor serie void setup() { pinMode(13, OUTPUT);
void loop() { digitalWrite(13, HIGH); Serial.println(HIGH); delay(1000); digitalWrite(13, LOW); Serial.println(LOW); delay(1000); } Compilamos y cargamos el cdigo de nuevo, y ahora pulsamos sobre el icono del serial monitor . Esto nos ha abierto el monitor serie y, en l, podemos ver como escribe un 1 o un 0 al ejecutar la funcin correspondiente. 22
Ilustracin 17: Monitor de comunicacin serie integrado en el entorno Arduino 2.4 Lenguaje de programacin Arduino 2.4.1 I ntroduccin e historia La plataforma Arduino se programa mediante el uso de un lenguaje propio basado en el lenguaje de programacin de alto nivel Processing[3], este a su vez est basado en Java. El compilador usado por la plataforma de Arduino es el GNU AVR, bajo Windows es el WinAVR [27]. Este compilador est dedicado para los procesadores AVR y est configurado para compilar C y C++. Las libreras del estndar C implementadas en este compilador son avr-libc[15] y estn optimizadas para los procesadores AVR. Adicionalmente Arduino tiene un gran conjunto de funciones ya implementadas para realizar de un modo fcil tareas comunes como hacer una espera activa, leer un puerto digital o escribir en l, entre muchas otras. 2.4.2 Funciones bsicas y operadores Todo programa Arduino debe contener, de manera obligatoria, al menos dos funciones bsica: setup() y loop(). La funcin setup() se ejecuta cuando se inicia un boceto (el programa o sketch). Se emplea para iniciar variables, establecer el estado de las entradas y salidas, inicializar libreras, etc. Esta funcin se ejecutar una nica vez despus de que se conecte la placa Arduino a la fuente de alimentacin, o cuando se pulse el botn de reinicio de la placa. Despus de ejecutar la funcin setup(), la funcin loop() se ejecuta de manera consecutiva e ininterrumpida. Cuando se llega al final de esta funcin, se vuelve a ejecutar desde el principio hasta que se vuelva a reiniciar la placa. En el interior de esta funcin es donde se pone el cdigo para controlar de forma activa la placa Arduino. Los siguientes subapartados tienen el objetivo de dar una visin rpida acerca del lenguaje de programacin Arduino, pero no se pretende entrar en el detalle del lenguaje de programacin. Para tal efecto hay multitud de manuales disponibles por la red, entre ellos y por citar algunos: Pgina de referencia del lenguaje del proyecto Arduino [28] Seccin de tutoriales de TronixStuff [29] Manual del Starter Kit de Earthshine Electronics. [30] 23 2.4.2.1 Estructuras Al estar basado en Processing, Java y/o C, las estructuras de control son muy similares a ellos y entre ellos.
Sintaxis bsica ; (punto y coma. Delimitador de lnea de cdigo) {} (llaves. Delimitador de bloques de cdigo) // (comentarios en una lnea) /* */ (comentarios en mltiples lneas) #define (definicin de precompilador) #include (inclusin de cdigo externo) Estructuras de control if (comparador si-entonces) if...else (comparador si...si no) for (bucle con contador) switch case (comparador mltiple) while (bucle por comparacin booleana) do... while (bucle por comparacin booleana) break (salida de bloque de cdigo) continue (continuacin en bloque de cdigo) return (devuelve valor a programa) goto (salta a una etiqueta) Operadores Aritmticos = (asignacin) + (suma) - (resta) * (multiplicacin) / (divisin) % (resto) ++ (incremento en uno) -- (decremento en uno) += (suma y asignacin) -= (resta y asignacin) *= (multiplicacin y asignacin) /= (divisin y asignacin) Operadores de comparacin == (igual a) != (distinto de) < (menor que) > (mayor que) <= (menor o igual que) >= (mayor o igual que) Operadores Booleanos && (y) || (o) ! (negacin) Operadores de acceso a punteros * operador de indireccin & operador de referencia Operaciones a nivel de bits & (and - 'y' a nivel de bits) | (or - 'o' a nivel de bits) ^ (xor a nivel de bits) ~ (not a nivel de bits) << (desplazamiento de bits a la izquierda) 24 >> (desplazamiento de bits a la derecha) &= (and - 'y' a nivel de bits y asignacin) |= (or - 'o' a nivel de bits y asignacin) 2.4.2.2 Variables Los tipos de los datos, su uso y declaracin, es muy similar a otros lenguajes de programacin, como el C o Java. Constantes Las constantes que vienen predefinidas en el lenguaje de Arduino se usan para facilitar la lectura de los programas. HIGH | LOW (estado de un pin de E/S digital) INPUT | OUTPUT (comportamiento de un pin de E/S digital) true | false (estado de un resultado lgico) Tipos de Datos Las variables pueden ser declaradas en cualquier punto del programa y, si no se indica lo contrario, valen cero. boolean (Booleano. Puede ser cierto o falso. Ocupa 8 bits en memoria) char (Carcter. Almacena un nico ASCII, tiene signo y ocupa 8 bits en memoria) unsigned char (Carcter sin signo). byte (Dato de 8 bits, sin signo) int (Entero de 16 bits, con signo) unsigned int (Entero de 16 bits, sin signo) word (Palabra. Equivalente a unsigned int) long (Entero de 32 bits con signo) unsigned long (Entero de 32 bits sin signo) float (Valor en coma flotante de 32 bits. Se debe evitar usar estos tipos ya que consumen mucho tiempo de CPU, espacio de cdigo y pueden ocasionar problemas en comparaciones, ya que por ejemplo 6.0 dividido por 3.0 puede no ser igual a 2.0 1 ) double (En Arduino, es lo mismo que float) array (Vector de elementos) void (Vaco) String (Des de la versin 0019 existe la clase String() que permite manipular cadenas de caracteres de un modo sencillo, permitiendo concatenaciones o
1 Se debe tener en cuanta que el uso de float se realiza a travs de libreras sw, y que adems la propia codificacin IEEE-754 que usa el tipo float tiene limitaciones.
25 gestin automtica del fin de cadena. Hasta ese momento el uso de string se limitaba a vectores de caracteres sobre los cuales se deba tener en cuenta el final de cadena /0 para poder usarlo con funciones tipo print()) Conversin Estas son una serie de funciones que permiten el cambio entre tipos. char(x) Convierte el valor de tipo x a carcter. byte(x) Convierte el valor de tipo x a byte. int(x) Convierte el valor de tipo x a int. long(x) Convierte el valor de tipo x a long. float(x) Convierte el valor de tipo x a float. mbito de las variables y calificadores Las variables en el lenguaje de programacin usado por Arduino, al igual que el C, tienen una propiedad llamada mbito. Al contrario de lo que pasa en lenguajes como BASIC en los que todas las variables son globales. En Arduino solo las declaradas fuera de una funcin son globales. En el caso de declararse dentro de una seccin de cdigo delimitada por llaves {}, como el caso de una funcin, la variable se libera al salir de esta seccin y se vuelve a crear con el valor inicial al volver a entrar en esta seccin. Esto se debe tener especialmente en cuenta al declarar variables dentro de la funcin loop(). static Esttica Las variables que se declaran como estticas slo se crearan e inicializarn la primera vez que se ejecute el bloque de cdigo en el que estn contenidas. volatile Voltil Una variable debe ser declarada volatile siempre que su valor pueda ser modificado por algo ms all de la seccin del cdigo en el que aparece. En Arduino, el nico lugar en el que se podra dar el caso es en secciones de cdigo asociadas a interrupciones. const Constante Es un calificador de variable que modifica el comportamiento de la misma, haciendo una variable de "slo-lectura". Sera equivalente a utilizar #define. 2.4.2.3 Funciones Aqu se muestran muchas funciones ya implementadas en el entorno Arduino para simplificar la tarea de desarrollo para problemas comunes. Muchas de ellas estn limitadas a ser usadas en pines concretos y pueden necesitar de argumentos que no se detallan en este apartado. Para informacin adicional se puede consultar la pgina de referencia del lenguaje del proyecto Arduino [28]. E/S Digital pinMode(pin, modo) configura el pin a modo de entrada o salida digitalWrite(pin, valor) - escritura digital digitalRead(pin) devuelve una lectura digital E/S Analgica
26 analogReference(tipo) configura el tipo de referencia analgica analogRead(pin) devuelve una lectura analgica analogWrite(pin, valor) escritura analgica. Generar una onda cuadrada con el ciclo de trabajo que se le indique como parmetro (0-255 implica un ciclo de trabajo de 0 a 100%). La frecuencia de la seal PWM ser de 490 Hz por diseo de Arduino. Proporciona una manera simple de implementar un control de intensidad luminosa sobre un LED. E/S Avanzada tone(pin, frecuencia) - Genera una onda cuadrada de la frecuencia en Hz especificada. Opcionalmente se puede definir la duracin del tono en ms. noTone(pin) Deja de generar el tono en el pin especificado shiftOut(pinDatos, pinReloj, ordenBits, valor) - Desplaza un byte de datos bit a bit a travs del SPI. pulseIn(pin, value) - Devuelve la anchura de un pulso en microsegundos empezando a medir cuando el pin se encuentra al nivel definido en value. Tiempo millis(). Tiempo des del arranque en ms. micros(). Tiempo des del arranque en us. delay(ms). Espera activa en ms. delayMicroseconds(us). Espera activa en us. Clculo min(x, y) Devuelve el mnimo de dos nmeros. max(x, y) Devuelve el mximo de dos nmeros. abs(x) - Devuelve el valor absoluto constrain(x, a, b) Devuelve x siempre que este entre a y b. En caso contrario devuelve los lmites a o b. map(value, fromLow, fromHigh, toLow, toHigh) Devuelve el valor de un re-mapeo de un rango hacia otro. Por ejemplo para realizar un cambio de escala de un valor de 0 a 1024 a un rango de 0 a 255. pow(base, exponente) Devuelve el valor de un nmero elevado a otro nmero. sqrt(x) Devuelve la raz cuadrada Trigonometra sin(rad) Devuelve el seno cos(rad) - Devuelve el coseno tan(rad) - Devuelve la tangente Nmeros aleatorios
27 randomSeed(seed) Inicializa el generador de nmeros pseudoaleatorios. Se puede usar como semilla una entrada mnimamente aleatoria como analogRead() en un pin desconectado. random() Devuelve un valor pseudoaleatorio. Bits y Bytes lowByte(x) Devuelve el byte de menor peso (big-endian, el de ms al derecha) de una variable highByte(x) - Devuelve el byte de mayor peso (big-endian, el de ms al izquierda) de una variable bitRead(x, n) Devuelve el valor del bit n en x. bitWrite(x, n, b) Escribe b en el bit n de x. bitSet(x, n) Pone a 1 el bit n de x. bitClear(x, n) Pone a 0 el bit n de x. bit(n) Devuelve un byte con sus bits a cero a excepcin del bit n. Por ejemplo, bit(0) devolvera un 1 en decimal, bit(1) un 2, bit(2) un 4 en decimal. Interrupciones externas attachInterrupt(inter, funcion, modo) Con el parmetro inter indicamos que ISR externa vamos a configurar. Con el parmetro modo indicamos el motivo que la va a disparar (CHANGE, LOW, RISING o FALLING) y con el parmetro funcin, la funcin que va a ejecutarse al ser disparada. detachInterrupt(inter) Desactiva la interrupcin inter Interrupciones interrupts() - Habilita las interrupciones noInterrupts() - Desactiva las interrupciones Comunicacin (estas dos son clases, con lo que no se pueden invocar directamente, sino que se debe invocar el mtodo que necesitemos) Serial Stream 2.4.3 Uso de libreras El propio entorno Arduino contiene una serie de libreras integradas que facilitan enormemente las tareas ms comunes en el mundo del hobby electrnico. Las Libreras proveen funcionalidad extra a nuestro sketch al trabajar con hardware o al manipular datos. Para usar una librera dentro de un sketch, puedes seleccionarla desde Sketch > Import Library (Importar Librera)[16]. 2.4.3.1 Libreras Estndar EEPROM - Para leer y escribir en memorias "permanentes".
28 Ethernet - Para conectarse a una red usando el shield Ethernet. Firmata Para comunicarse con aplicaciones en un PC que se comporta como servidor (host) usando el protocolo Firmata. LiquidCrystal - Para controlar Displays de cristal lquido (LCD) Servo - Para controlar servomotores. SoftwareSerial - Para la comunicacin seria utilizando cualquier pin digital. Stepper - Para controlar motores paso a paso (Stepper motors). Wire - Interfaz de dos cables, Two Wire Interface (TWI/I2C), para enviar y recibir datos a travs de una red de dispositivos y sensores. 2.4.3.2 Libreras de terceros Si se desean usar libreras que no vienen junto con Arduino, es necesario instalarlas. Las libreras suelen entregarse en un fichero comprimido y suelen contener una carpeta propia con dos archivos, uno con sufijo ".h" y otro con sufijo ".cpp". Para instalarla se debe copiar el contenido del fichero comprimido en la carpeta libraries que se debera encontrar dentro de la carpeta sketchbook de Arduino. Al reiniciar el IDE de Arduino debera aparecer la nueva librera en el men Sketch > Import Library. Estas son algunas de las libreras que se pueden encontrar y que estn referenciadas en la propia pgina web del proyecto Arduino [16]. Tambin se puede encontrar una lista alternativa en la Wiki de Arduino [31]. Comunicacin (networking y protocolos): Messenger - Para procesar mensajes de texto mandados des del PC. NewSoftSerial - Versin mejorada de la librera SoftwareSerial. OneWire - Controla dispositivos (de Dallas Semiconductor) que usan el protocolo One Wire. PS2Keyboard - Lee caracteres de un teclado PS2. Simple Message System - Enva mensajes entre Arduino y la computadora. SSerial2Mobile - Enva mensajes de texto o emails usando un telfono mvil (va comandos AT a travs de SoftwareSerial) Webduino - Librera de web server extensible (para usar con Arduino Ethernet Shield) X10 - Para enviar seales X10 a travs de lneas de corriente AC. XBee - Para comunicaciones entre XBees en modo API. SerialControl - Para controlar remotamente otras Arduino a travs de una conexin serial. Sensores:
29 Capacitive Sensing Implementa un sensor tctil capacitivo uniendo un pin de escritura con una resistencia relativamente alta (100kOhm 50MOhm), una lamina de metal o cable y un condensador pequeo (20 - 400 pF) a un pin de lectura, detectando cambios en este al acercarse o tocar la lmina con el dedo. Debounce - Para una lectura filtrada de entradas digitales con rebotes (tpicamente las entradas conectadas a botones). Displays y LEDs: Improved LCD library - Arregla errores de inicializacin del LCD de la librera LCD oficial de Arduino. GLCD - Rutinas grficas para LCDs basados en el chipset KS0108 o equivalentes. LedControl - Para controlar matrices de LEDs o displays de siete segmentos con MAX7221 o MAX7219. LedDisplay - Control para marquesina de LED HCMS-29xx. Matrix - Librera para manipular displays de matrices de LED bsicas. Sprite - Librera bsica para manipulacin de sprites para usar en animaciones con matrices de LEDs. Motores y PWM: TLC5940 - Manejador para el chip TLC5940 de Texas Instruments implementando el control de hasta 16 servomotores a la vez. Medicin de Tiempo: DateTime - Librera para llevar registro de fecha y hora actual en el software. Metro - til para cronometrar acciones en intervalos regulares. MsTimer2 - Utiliza la interrupcin del temporizador 2 para disparar una accin cada N milisegundos. Utilidades de cadenas de texto: TextString, PString, Streaming Implementan mtodos de salida ms completos para cadenas de texto. Adicionalmente, muchos de los desarrolladores y distribuidores de shields generan sus propias libreras para utilizar las shields, de modo que la cantidad de libreras disponibles es enrome. Adems, nosotros podemos crear nuestras propias libreras y utilizarlas para nuestros proyectos e incluso distribuirlas[17]. A raz del cambio mayor de versin (de alfa a 1.0) en el entorno de programacin Arduino, muchas de las libreras de terceros han quedado obsoletas/desactualizadas por la inclusin de ficheros de encabezados (.h) que han sido renombrados en esta nueva versin, entre ellos Wprogram.h ha sido renombrado a Arduino.h, con lo que nos obligar a modificar el cdigo de estas libreras incluyendo el nuevo fichero.
30 3 Nuestro proyecto Arduino 3.1 Medidor de caudal La medicin del consumo de un recurso que tiene unidades de volumen puede ser ms complicada de lo que parece. Recursos como el agua o el gas se suele medir por indicadores que determinan el volumen acumulado en el tiempo, como los contadores domsticos. Pero tambin puede interesar tener el caudal instantneo. En estos casos la medicin se realiza a pequeos intervalos y se van acumulando las lecturas durante un tiempo determinado. Hay varios tipos de medidores de flujo o de caudal. Para medir lquidos, un diseo muy comn son los que se disponen en lnea con el recurso a medir. Estos suelen tener algn tipo de molinillo que gira al pasar el recurso a travs de l y genera una serie de pulsos proporcionales al caudal instantneo. Para interpretarlo es necesario implementar un frecuencmetro. Este mtodo es similar a como funcionan los velocmetros en muchos vehculos: un sensor de la rueda genera un pulso por cada giro de una rueda que significa que la frecuencia del pulso vara proporcionalmente a la velocidad del vehculo. En el velocmetro se muestra una interpretacin de la frecuencia de los pulsos para mostrar la velocidad instantnea, mientras que el odmetro muestra un contador de pulsos acumulativo para mostrar la distancia recorrida. 3.2 Requerimientos iniciales La idea es utilizar un medidor de caudal que genere un tren de pulsos a una frecuencia proporcional al caudal. En el diseo se incluye un mdulo LCD, de modo que la unidad pueda informar del caudal y del volumen tanto a travs de una conexin serie a un host (PC) o directamente a travs de la pantalla LCD. El medidor de caudal debe calcular y mostrar el caudal actual. Tambin se calcular el volumen y el tiempo absoluto. Otros dos contadores acumulativos independientes mostraran el volumen que ha fluido a travs del sensor. Dos pulsadores deben permitir poner a cero los contadores de forma independiente, de manera que podamos tener un contador acumulativo a largo plazo y restablecer los otros para tener medidas diferenciales a corto plazo. Un ejemplo de uso real seria para conocer el agua que se consume para rellenar un bao, programar un sistema de riego o en el funcionamiento de una lavadora.
31
Ilustracin 18: Diagrama de bloques del caudalmetro 3.3 Eleccin de los componentes Para la realizacin de este pequeo proyecto, se ha partido de la placa Arduino UNO; la ms bsica, pero no por ello menos verstil, de las placas Arduino. La pantalla LCD usada, es una a color de 132x132 puntos. Se distribuye en formato de "shield" para ser utilizada directamente con Arduino sin necesidad de realizar ms soldadura, la comunicacin es va SPI y los propios fabricantes te ofrecen las libreras de control[18]. El mismo proyecto se podra realizar usando simplemente un LCD de 16x2 como el "Arduino Shield LCD DFRobot" por unos 25 (contra los 38 del LCD 128x128), o simplemente un LCD 16x2 que se podra montar por unos 15. Finalmente, para poder realizar la medicin de caudal, se necesita un sensor. Los sensores de caudal no son fciles de conseguir a un bajo coste, ya que la gran mayora son para usos industriales de gran precisin, algo innecesario para la realizacin de un proyecto de demostracin como este. Una alternativa de bajo coste es re-usar un caudalmetro utilizado para la refrigeracin lquida de PCs. El rango de trabajo de estos suele ser de 1.0 a 15 litros por minuto, con lo que para una aplicacin de monitorizacin del flujo de agua de un grifo domestico, debera ser suficiente ya que estos suelen tener un mximo entre 15-20 l/min. Encontramos que el caudalmetro Koolance INS-FM17N [32] cubre con los requerimientos que nos habamos marcado, y se encontr a un precio asequible. Alternativas a este caudalmetro, podran haber sido los usados en los lavavajillas [33] el precio es similar, pero no se encontraron datos acerca del la relacin caudal/frecuencia.
32 3.4 Lista de material y presupuesto Una vez identificado el material necesario, se ha lanzado la orden de compra a los distintos proveedores: En la tienda Electan [25] se ha realizado el pedido de la placa Arduino y la pantalla:
1 x Arduino UNO con ATMega328 21.90 1 x Arduino Shield LCD Color Sparkfun 32.90 Subtotal: 54.80 Correo Pennsula y Baleares (Entrega en aprox. 7 das. Solo pago con tarjeta o transferencia): 3.50 IVA 18%: 9.86 IVA Transporte 18%: 0.63 Total: 68.79
Y el sensor de caudal en la tienda HellFire ToyZ [34] de eBay para pagar lo mnimo en gastos de envo.
1 x Koolance INS-FM17N Coolant Flow Meter for LCS $22,99 USD Envo y manipulacin $11,68 USD Total $34,67 USD Tipo de cambio: 1 Euro = 1,34016 Dlares Total Euros 25,87 EUR
El total del material asciende a 94.66
33 3.5 El hardware 3.5.1 Caractersticas tcnicas de los componentes 3.5.1.1 Shield LCD color
Ilustracin 19: Shield LCD a color El shield LCD a color proporciona un mtodo fcil de conectar el LCD de un Nokia 6100 a un Arduino. La placa viene como una pantalla mini LCD de 128x128 color, as como un circuito de control para la retro-iluminacin (utiliza un elevador a 7V), y tres pulsadores (vinculados a travs de un puente a los pines D3-5). El LCD del Nokia 6100 se controla a travs un interfaz SPI de 9-bits. Los pines de control de la pantalla LCD se conectan a los pines de hardware SPI de la placa Arduino (D13-SCK, D11 - DIO), el pin CS est ligado a D9 y el pin de reset est conectado a D8. La tensin del pin de '5V' de la placa Arduino se eleva a 7 V para alimentar la retro- iluminacin de la LCD. En el enlace siguiente, se puede encontrar un manual acerca de como comunicarse con el LCD y toda la informacin tcnica necesaria para poder dibujar en la pantalla. https://docs.google.com/viewer?url=http://www.sparkfun.com/tutorial/Nokia%25206 100%2520LCD%2520Display%2520Driver.pdf [35] Este otro enlace explica un error de diseo en el shield que provoca que la retro- iluminacin no funcione correctamente. http://richardkaufman.org/blog/how-to-fix-it-backlight-on-sparkfuns-color-lcd- shield-not-working [36] Este defecto se ha detectado en nuestro Shield. Para activar la retro-iluminacin debemos realizar un cortocircuito entre dos resistencias cada vez que se alimenta por primera vez.
34
Ilustracin 20: Punto a cortocircuitar para activar la retro iluminacin 3.5.1.2 Sensor de caudal
Ilustracin 21: Sensor de caudal Koolance El sensor de caudal usado es el Koolance INS-FM17N. Este est compuesto por un interruptor magntico normalmente abierto que responde al paso de un imn situado en la aspa de rotacin interna. El movimiento generado por el lquido que circula por su interior nos da una serie de pulsos, que de acuerdo a la hoja de caractersticas del fabricante[19], sigue una relacin lineal entre litros por minuto (LPM) y pulsos por segundo (expresado en Hz), en funcin del dimetro del tubo conectado, en nuestro caso 6mm.
Ilustracin 22: Relacin entre litros y frecuencia del medidor de caudal
35 Ya que simplemente mide a qu velocidad fluye el lquido por el interior del sensor, el hecho que el sensor no est totalmente lleno (presencia de bolsas de aire) provocar una falta de precisin en la lectura del caudal. Para no perder pulsos conectaremos el sensor de caudal en una entrada de interrupcin externa de la placa Arduino, en el pin 2. 3.5.2 El ensamblado Despus de estudiar como ensamblar la shield y decidir a travs de que pines conectaremos el caudalmetro, el montaje quedara as.
Ilustracin 23: Esquema de montaje Los shields son diseados para montarse encima de la placa Arduino, con lo que los pines se corresponden uno a uno. El caudalmetro se conecta con un cable a masa y el otro a una entrada digital con pullUp. El ATmega tiene una resistencia de pullUp interna de 20k ohmios con lo que no necesitamos circuitera extra. Cada vez que el aspa del caudalmetro pasa por el interruptor normalmente abierto provoca un cortocircuito a masa. En este momento se lee un cero en la entrada digital. Si la entrada del caudalmetro la situamos en una entrada digital con interrupcin por flanco de Arduino, nos aseguramos no perder ningn pulso durante el contaje.
36
Ilustracin 24: Esquema de conexionado del caudalmetro El otro cable del caudalmetro se ha conectado al pin digital D6. Este pin se configura como salida a cero dando as la masa al caudalmetro. Esta distribucin se ha hecho para simplificar las conexiones y poder realizar ciertas pruebas sin el caudalmetro. Si configuramos el pin D6 como salida PWM nos permite emular el funcionamiento del caudalmetro. Para tal fin utilizaremos la funcin tone() de Arduino. En la siguiente fotografa se puede apreciar el montaje del shield LCD sobre la placa Arduino.
Ilustracin 25: Vista lateral del montaje final Finalmente, aqu se puede ver el montaje final, con la pantalla LCD y el sensor de caudal.
37
Ilustracin 26: Vista frontal del montaje final 3.6 El software 3.6.1 Diseo de la pantalla 3.6.1.1 Uso de la librera del shield LCD a color de Sparkfun En la mayora de shields comerciales, el propio fabricante ofrece un set mnimo de software para poder controlar el shield y/o verificar que este funciona correctamente una vez ensamblado con la placa Arduino. Este tipo de software se conoce como libreras. En nuestro caso la librera de control la proporciona Sparkfun y se pude encontrar en la pgina de descripcin del producto [18]. Estas suelen venir empaquetadas en un fichero tipo Zip. Para poder usarla en nuestro entorno es necesario instalarla. Copiamos el contenido del Zip en una subcarpeta dentro de la carpeta libraries de nuestra instalacin de Arduino en el PC.
38
Ilustracin 27: Listado de las libreras en el entorno Arduino En nuestro caso, hemos extrado los ficheros .cpp y .h del fichero Zip de la librera en una carpeta a la que hemos llamado ColorLCDShield dentro de libraries. Una vez reiniciado el entorno Arduino, se puede ver como la nueva librera ya est disponible.
Ilustracin 28: Uso de una librera una vez instalada en el entorno Arduino Para usarla en nuestro sketch debemos incluirla al igual como se hara en C. #include <ColorLCDShield.h> Normalmente, dentro de las libreras hay un fichero de texto donde se nos explica cmo se puede o debe usar la librera, as como programas con ejemplos de uso. En nuestra librera hay un fichero llamado Readme, donde nos indica la licencia de uso de esta
39 librera y como usarla 2 . En un modo resumido, nos indica que debemos instar el constructor de la librera usando la declaracin: LCDShield lcd; Una vez declarado el objeto de la librera, nos indica varios mtodos a usar, entre ellos el mtodo de inicializacin lcd.init(EPSON); o mtodos para escribir en ella lcd.clear(int color); lcd.setStr(char *pString, int x, int y, int fColor, int bColor);
Como ya se ha indicado, a raz de la ltima actualizacin del entorno Arduino, hay una gran cantidad de libreras que han dejado de funcionar, entre ellas la proporcionada para nuestra pantalla LCD. Para solucionar los problemas de compatibilidad y compilacin, en el fichero ColorLCDShield.h se ha remplazado la inclusin de WProgram.h por Arduino.h; y en ColorLCDShield.cpp se ha eliminado la inclusin de wiring.h, ya que el contenido de este fichero ha sido incluido en Arduino.h y a su vez, este ya lo habamos incluido en ColorLCDShield.h. Se ha detectado que la librera que nos proporciona el fabricante necesita mucha memoria RAM debido al el tipo de fuente que utiliza. La fuente original de la librera es de 8x16 puntos de tamao y se ha remplazado por otra de 8x8 para reducir el tamao de RAM requerido. Existe la posibilidad de indicar al entorno Arduino que una variable tipo constante la aloje directamente en la FLASH. Para ello se debe usar el modificador de tipo PROGMEM de la librera pgmspace.h. Esta podra haber sido otra modificacin a hacer sobre la librera para reducir el uso de RAM[38]. 3.6.1.2 Informacin a mostrar e interfaz Se han definido tres pantallas distintas para mostrar la informacin relativa a las mediciones absolutas y a las parciales. Para conmutar de una pantalla a otra se va a utilizar el pulsador superior de la pantalla. Los dos pulsadores inferiores servirn para borrar los dos contadores parciales. Este es el aspecto deseado de las distintas pantallas:
2 Vase ANEXO 1
40
Ilustracin 29: Pantalla principal
Ilustracin 30: Pantalla contadores parciales 1
Ilustracin 31: Pantalla contadores parciales 2 3.6.2 El programa de control de Arduino Este sera el diagrama de flujo del programa de control que hemos implementado.
41
Ilustracin 32: Diagrama de flujo del firmware La tarea peridica se lanza cada 1 segundo. Aqu se pone a cero el contador de pulsos detectados y lleva la cuenta en cada contador. Tambin es la responsable de refrescar los valores que se muestran en la pantalla LCD y los valores instantneos que se mandan por el puerto serie. De manera asncrona, y con mayor prioridad, el cdigo asociado a la interrupcin de flanco se encarga de contar los pulsos generados por el caudalmetro.
42 Loop() Tarea_1sec() Interrupcin()
Ilustracin 33: Diagrama temporal del firmware La variable que se utiliza dentro de la funcin de la interrupcin debe ser declarada como volatile para indicar al compilador que puede ser modificada des de diferentes contextos y as evitar optimizaciones. Esto obliga al compilador a acceder siempre a la direccin de memoria donde se encuentra la variable y no copiarla en registros para mejorar la velocidad de acceso. Los accesos a esta variable desde el contexto de menos prioridad (la tarea peridica) se deben realiza a travs de una seccin crtica. Esto implica que los accesos a esta variable se harn con las interrupciones deshabilitadas. volatile unsigned int contadorPulsos = 0;
tarea_periodica(){ /* Inicio zona segura intercambio de datos / noInterrupts(); unsigned int contadorPulsosLocal = contadorPulsos; contadorPulsos = 0; interrupts(); /* Fin zona segura intercambio de datos */ }
Esto debe hacerse porque al tratarse de una variable de 16 bits, y el microcontrolador de Arduino de 8 bits, implica que como mnimo necesitaremos dos instrucciones para acceder a este dato. Si mientras se esta ejecutando la primera instruccin de acceso a la variable recibimos una nueva interrupcin, el valor de esta variable se modificar por la interrupcin. Al volver a la tarea peridica se ejecutar la segunda instruccin de acceso a la variable pero el valor ya ser distinto. Por ejemplo: La variable es igual a 0x00FF. Mientras leemos la parte baja (0xFF) se ejecuta la interrupcin y la incrementa en 1 (ahora valdra 0x0100), al volver a la tarea peridica y leer la parte alta del dato, veramos un 0x01. Entonces nuestra variable valdra 0x01FF y no 0x0100 que seria el valor correcto. El cdigo fuente del programa Arduino se puede encontrar en el ANEXO 2.
43 3.6.3 El programa de control del PC El programa de control de Arduino nos manda cada segundo, a travs del puerto serie, el caudal instantneo. En el PC hemos realizado un programa capaz de interpretar estos datos y dibujar en la pantalla una grfica en tiempo real de las mediciones realizadas por nuestro Arduino. La pantalla de nuestro programa de PC es la siguiente:
Ilustracin 34: Salida del programa de visualizacin en el PC Esta aplicacin ha sido realizada en python. Este es un lenguaje interpretado de muy alto nivel, lo que nos permite establecer una comunicacin con nuestra placa Arduino con muy pocas lneas de cdigo. Lo primero es importar la librera: import serial
Luego procedemos a conectarnos al puerto de serie con una sencilla funcin y encapsulamos dicha conexin en un objeto: ser = serial.Serial(port='\\.\COM3', baudrate=9600)
Ahora es el momento de leer lo que Arduino nos dice: while 1: ser.readline()
La parte de crear una ventana y dibujar la grfica se realiza a travs de una librera python con lo que la totalidad del programa se puede reducir a unas 300 lneas de cdigo. 3
3 Vase ANEXO 3
44 3.7 Juego de pruebas Para verificar que nuestro sistema funciona como esperamos se han realizado una serie de pruebas a distintos niveles. 3.7.1 Test sobre el caudalmetro Para verificar que la configuracin de los pines es la correcta, se ha monitorizado la entrada del caudalmetro (D2) con un osciloscopio mientras hacamos girar las aspas. El resultado debera ser un tren de pulsos de una frecuencia entre 0 Hz y poco ms de 30 Hz, ya que es el rango de trabajo del caudalmetro. El tiempo a nivel bajo de este tren de pulsos, debera ser del 15-20% del pulso. Esto se debe a que el caudalmetro tiene 4 aspas y solo una de ellas activa el interruptor magntico. A continuacin se pueden ver distintas capturas de osciloscopio verificando que el montaje funciona.
Ilustracin 35: Tren de pulsos del caudalmetro girando a baja velocidad
45
Ilustracin 36: Tren de pulsos del caudalmetro girando a media velocidad
Ilustracin 37: Tren de pulsos del caudalmetro girando a alta velocidad 3.7.2 Test sobre la captura de pulsos El objetivo de esta prueba es asegurar que capturamos los pulsos que esperamos.
46 El hecho de dar la masa del caudalmetro a travs de una salida digital nos permite testear la captura de pulsos si configuramos este pin como salida PWM. Para genera un PWM de 31Hz en el pin D6 aadimos la siguiente lnea al principio de la funcin loop(): tone(caudalGNDPin,31); Si quitamos el caudalmetro y cortocircuitamos los dos pines, el programa de control debera detectar 31 pulsos cada segundo. Lo verificamos viendo que por la comunicacin serie est mandando continuamente un 31.
Ilustracin 38: Respuesta ante un tren de pulsos de 31Hz En la pantalla del LCD debe reportar que el consumo actual es de 9.52 litros por minuto (31Hz x 0.302 = 9.517 LPM), acorde con la hoja de caractersticas del caudalmetro.
Ilustracin 39: Muestra de la pantalla principal ante una entrada de 31Hz
47 3.7.3 Test de funcionamiento general Con el cdigo final y el caudalmetro conectado, verificamos que al pulsar el 1er botn cambiamos de pantalla a mostrar. Al pulsar el segundo botn, el contador de litros y tiempo parcial 1 se pone a cero. Al pulsar el tercer botn, el contador de litros y tiempo parcial 2 se pone a cero.
Ilustracin 40: Secuencia de acciones en funcionamiento normal Con la ayuda de un cronmetro verificamos que el contador de segundos funciona con suficiente precisin. Esperaremos unos 10 minutos para poder detectar mejor las desviaciones.
48
Ilustracin 41: Prueba de precisin del contador de segundos En la pantalla principal soplamos sobre el caudalmetro y vemos que el contador de consumo actual incrementa y que los litros totales tambin crecen. 4 Uso de Arduino en entornos lectivos 4.1 Educacin secundaria Arduino fue diseado para que personas sin un conocimiento profundo de electrnica pudieran realizar pequeos proyectos donde se necesita un microcontrolador. Encontramos en internet varios ejemplos de proyectos hechos con Arduino, desde un simple caudalmetro a un cuadricoptero[20], robots seguidores, controlar un Arduino con un mvil Android[21], y cualquier cosa que encaje en la filosofa DYI (Do It Yourself). En apartados anteriores hemos visto como sin tener demasiados conocimientos acerca de microcontroladores y con una sintaxis bsica hemos podido realizar un proyecto relativamente complejo. Esto ofrece un gran potencial en entornos lectivos, especialmente en secundaria, ya que es posible despertar la curiosidad por la tecnologa, instruir conceptos de electrnica bsica de un modo prctico y hacer una buena introduccin a la algoritmia de un modo ameno y visual. 4.2 Educacin tcnica superior Arduino no deja de ser una placa con un microcontrolador y todo lo necesario para interactuar con l. Esto implica que no solo se puede utilizar como pequea plataforma para proyectos, sino que en el aprendizaje de microcontroladores puede tener un gran potencial, ya que en la red existen varias herramientas para el microcontrolador Atmel AVR. Hasta este punto apenas se ha mencionado el Atmel AVR ya que las placas Arduino, y todo su entorno software, ha sido desarrollado para no tener que entrar en este tipo de
49 detalles. Pero estos detalles son precisamente lo que nos va a interesar a partir de este punto. Para ello empezaremos configurando un entorno de desarrollo que nos permita trabajar de un modo ms directo con el microcontrolador. 4.2.1 Usar AVRStudio, cdigo C y Arduino En primer lugar vamos a instalar AVRStudio, que es el IDE y el conjunto de herramientas oficial de Atmel (el fabricante de los microcontroladores utilizados en la Arduinos). Podemos obtenerlo des de la propia pgina web de Atmel [37]. La versin sobre la que se ha trabajado se ha adjuntado en el soporte digital del PFC. Nosotros instalamos el paquete AVR Studio 5.1 Installer - Full. Para realizar la descarga es necesario registrarse en la web de Atmel, pero el proceso es simple y rpido. Una vez instalado todo lo necesario, el proceso es el tpico de Windows, perfectamente guiado a travs de ventanas. Ejecutamos el AVRStudio y deberamos ver algo como en la Ilustracin 42
Ilustracin 42: Vista inicial del AVR Studio Aqu seleccionamos New project, en la nueva ventana seleccionamos de los Installed templates el AVR GCC C C Executable Project, indicndole en el campo nombre Arduino_Blink, como el tpico ejemplo Arduino, y OK.
50 Una vez hecho esto, tenemos que seleccionar con que dispositivo Atmel vamos a trabajar. Nuestro Arduino tiene el ATmega328P, con lo que seleccionaremos este.
Ilustracin 43: Seleccin de dispositivo en AVR Studio Como se puede ver, en la parte derecha de la pantalla de seleccin nos proporciona el acceso a la hoja de caractersticas (datasheet) y las herramientas que tendremos disponibles para este dispositivo. Entre ellas la que quizs ms nos puede interesar para nuestros desarrollos: el AVR Simulator. Al darle OK, el entorno nos va a crear un proyecto listo para introducir el cdigo C que queramos.
51
Ilustracin 44: Vista de codificacin del AVR Studio El ejemplo que queremos implementar es uno de los ms tpicos en las placas Arduino. Aprovechando que la propia placa tiene el pin D13 conectado a un LED, vamos a hacer que este LED este encendindose y apagndose para siempre, 1 segundo encendido y 1 segundo apagado. Este sera el cdigo a implementar: /* * Arduino_blink.c */
#include <avr/io.h> //Esta libreria contiene la definicin de todos los registros, SIEMPRE DEBE SER INCLUIDA #define F_CPU 16000000UL //F_CPU indica al compilador que nuestro cristal es de 16Mhz. Debe ser declarado antes que la libreria delay.h #include <util/delay.h> //Contiene funciones de espera en ms y us
int main(void) { DDRB |= (1<<PB5); //Definimos el pin13/PORTB5 como salida para poder encender y apagar nuestro LED
while(1) //Este es el bucle infinito obligatorio en la programacin de micro-controladores. Todo nuestro cdigo estar aqu dentro { PORTB |= (1<<PB5); //Enciende el LED, este es el LED incluido en la placa Arduino, en el pin digital 13
52 _delay_ms(1000); //Espera 1 segundo PORTB &= ~(1<<PB5); //Apaga el LED _delay_ms(1000); //Espera 1 segundo } }
Como podamos ver en la Ilustracin 8 (Pines de Arduino contra ATmega328) debemos tener en cuenta la correspondencia entre los pines del ATMEGA con los de la placa Arduino. Pulsamos la tecla F7, o en men Build Build Solution, para iniciar el proceso de generacin de los ficheros ejecutables (compilado, ensamblado y enlazado). Si todo ha ido bien, deberamos ver en la parte inferior del IDE un mensaje indicando que no hay errores y un resumen de memoria usada; y en la parte derecha los ficheros que se han generado durante el proceso:
Ilustracin 45: Resultado de la compilacin en el AVR Studio 4.2.2 Simular y ejecutar el cdigo C en nuestro microcontrolador En este punto deberamos ser capaces de compilar, enlazar y generar un fichero .hex. Este fichero ser el ejecutable en el microcontrolador, el equivalente a un .exe en un PC. Ahora querremos ejecutar nuestro cdigo, y verificar que se comporta como nosotros esperamos. Para tal fin tenemos distintas opciones, entre ellas simular el cdigo en el PC, descargarlo en nuestro Arduino o utilizar herramientas de depuracin ms avanzadas.
53 4.2.2.1 Simular el cdigo en el PC. AVRSimulator. El AVRSimulator es una herramienta grfica integrada en el propio AVRStudio que nos permite ejecutar nuestro cdigo viendo e interactuando con todos los registros internos del microcontrolador, as como sus pines de entrada y salida. Al mismo tiempo nos sirve como depurador, ya que nos permite poner breakpoints en el cdigo y ver el valor de las variables, as como modificarlas y forzar otras ramas de ejecucin, pudiendo probar mejor nuestro cdigo.
Ilustracin 46: Vista del simulador integrado en AVR Studio 4.2.2.2 Descargar el cdigo en nuestra placa Arduino. AVRDude. Nuestro ATmega por el hecho de estar en una placa Arduino lleva grabado un gestor de descarga o boot loader. El AVRStudio no soporta la comunicacin con este gestor de descarga de manera nativa, ya que no ha sido diseado para entornos Arduino. El AVRDude es una herramienta que nos permite descargar nuestro cdigo una vez compilado a nuestra placa Arduino a travs de su propio gestor de descarga. Esto significa que no necesitamos ningn tipo de hardware adicional para poder trabajar con el ATmega, ni con la placa Arduino. El AVRDude forma parte del software de Arduino, para utilizarlo de una manera cmoda des de nuestro entorno integrado, se han copiado los ficheros necesarios a una nueva carpeta llamada ArduinoUpload en la misma carpeta que los proyectos del AVRStudio. Esta suele ser una carpeta llamada AVRStudio 5.1, en la carpeta de
54 documentos del usuario que ha instalado el AVRStudio. Dentro de esta carpeta AVRStudio 5.1. Los archivos necesarios para poder usar el AVRDude se encuentran en la ruta de instalacin del entrono Arduino bajo las siguientes rutas relativas: arduino-1.0\hardware\tools\avr\bin\avrdude.exe arduino-1.0\hardware\tools\avr\bin\libusb0.dll arduino-1.0\hardware\tools\avr\etc\avrdude.conf El siguiente fichero, aun no siendo obligatorio, contiene la informacin necesaria para poder usar el AVRDude con la configuracin apropiada. arduino-1.0\hardware\arduino\boards.txt arduino-1.0\hardware\tools\avr\doc\avrdude\avrdude.pdf La lnea de comandos a ejecutar para descargar nuestro cdigo sera la siguiente: avrdude -F -V -c arduino -p ATMEGA328P -P COM3 -b 115200 -D -U flash:w:Arduino_Blink.hex
El significado de esos parmetros esta descrito en la documentacin del propio AVRDude que hemos copiado en nuestra carpeta, el fichero avrdude.pdf. Para facilitar esta tarea se ha creado un fichero por lotes de MS-DOS llamado upload.cmd como el que se puede encontrar en el ANEXO 4, donde solo le deberemos indicar el puerto serie a utilizar y el nombre del binario a descargar A su vez, crearemos otro fichero por lotes de MS-DOS que ser llamado desde el propio AVRStudio, como una herramienta externa, que ser incluida en la barra de botones, de manera que el proceso de descargar el cdigo en la placa ser similar al utilizado en el propio entorno Arduino. Este otro fichero por lotes, llamado uploadFromAVRStudio.cmd, tambin se puede encontrar en el ANEXO 4, as como la manera de configurar la herramienta externa en el AVRStudio. 4.2.2.3 Uso de entornos de depuracin y programacin Existen distintas herramientas de Atmel para programar sus microcontroladores e incluso poder depurar el cdigo realizando ejecuciones paso a paso en el propio microcontrolador. Muchas de estas herramientas son simples programadores, fciles de montar uno mismo y de bajo coste, que nos permitiran poder descargar el boot loader o directamente nuestra aplicacin en un microcontrolador virgen. Alguno de estos seria el USBtinyISP, USBasp entre muchas otras propuestas disponibles en internet. En cuanto a los depuradores (debuggers) que permiten programar y ejecutar cdigo paso a paso en el dispositivo real y utilizar mltiples breakpoints son bastante costosos siendo quizs el ms econmico el AVR Dragon (50 aprox.).
55 4.2.3 El ATmega328P La intencin de este bloque es mostrar cmo se pueden usar los distintos perifricos del microcontrolador de nuestro Arduino y realizar en C el mismo proyecto realizado en lenguaje Arduino. No se entrar en detalle en todos los perifricos, ya que la hoja de caractersticas (datasheet) del microcontrolador contiene todos los detalles. La hoja de caractersticas del ATmega328P se puede abrir fcilmente des del propio IDE del AVRStudio o en la pgina web del fabricante [37]. 4.2.3.1 Un breve resumen El ATmega328P es el microcontrolador que lleva el Arduino UNO, forma parte de la familia de procesadores Atmel AVR. Los AVR son una familia de microcontroladores RISC, la arquitectura de los cuales fue concebida por dos estudiantes en el Norwegian Institute of Technology, y posteriormente refinada y desarrollada en Atmel Norway, la empresa subsidiaria de Atmel, fundada por los dos arquitectos del chip. Los AVR son CPUs con arquitectura Harvard. Tiene 32 registros de propsito general de 8 bits. Estos registros de propsito general, los registros de perifricos y la memoria de datos forman un solo espacio de direcciones unificado, que se acceden mediante operaciones de carga y de almacenamiento. A diferencia de los microcontroladores PIC, la pila se ubica en este espacio de memoria unificado, y no est limitado a un tamao fijo. Los microcontroladores AVR tienen una caera o pipeline con dos etapas (traer y ejecutar), que les permite utilizar un ciclo de reloj en la mayora de instrucciones, lo que los hace relativamente rpidos entre los microcontroladores de 8 bits. El conjunto de instrucciones es ms regular que la de la mayora de los microcontroladores de 8 bits. Sin embargo, no es completamente ortogonal. 4.2.3.2 Puertos de entrada y salida digital Hay distintos registros del microcontrolador que sirven para indicar como debe comportarse cada pin, ya sea como un pin de entrada digital, de salida digital, de entrada analgica, salida PWM En el ATmega328P los registros para configurar y acceder a los pines estn agrupados por puertos. En nuestro Arduino tenemos un ATmega de 28 pines, esto hace que solo dispongamos el puerto B, C y D. En la Ilustracin 8: Pines de Arduino contra ATmega328 (Pines de Arduino contra ATmega328), se puede ver la correspondencia entre los pines del ATmega y del Arduino, as como los distintos modos en los que puede funcionar cada uno de los pines. Para cada uno de los puertos tenemos un registro DDRx asociado, donde la 'x' indica el puerto al que hacemos referencia, por ejemplo DDRB hace referencia al puerto B. Este registro nos permite configurar los distintos pines de puerto como entrada o salida digital. El acrnimo DDR significa Data Direction Register, y cada bit dentro del registro hace referencia al pin correspondiente. Escribir un 1 implica configurar el pin como salida y 0 como entrada.
56 Por ejemplo, para configurar como salida el pin digital 5 de nuestro Arduino vemos que corresponde con el pin 5 del puerto B, haremos lo siguiente: DDRB = 0b00100000;
Con esta instruccin tambin se ha configurado como entrada los dems pins del puerto B. Ms adelante se comenta como evitar modificar todo el puerto para configurar un nico pin. Si ahora queremos asignar un valor de salida a este puerto debemos utilizar el registro PORTx, donde 1 implica un nivel alto y 0 un nivel bajo. PORTB = 0b00100000;
En este ejemplo tenemos configurados todos los pines del puerto B como entradas menos el pin 5 que lo tenemos como salida a nivel alto. Para conocer el nivel de los pines leeremos los registros PINx. Estos registros se pueden consultar independientemente de la configuracin del pin, ya sea como entrada o como salida. Esto se puede utilizar para saber el estado real en que se encuentra un pin. char contenidoPuertoB = 0u; contenidoPuertoB = PIND;
El ATmega tiene funcionalidad real de lectura-modificacin-escritura para todos los registros de entrada/salida (concretamente los registros del 0x00 al 0x1F). Esto significa que tiene una instruccin que permite cambiar un bit de un registro sin modificar los dems. Estas instrucciones en ensamblador son SBI y CBI. La manera en C ms estndar de actuar sobre un pin en concreto es utilizando mascaras y desplazamientos de bits. Para tal efecto el compilador AVR lib-c tiene una serie de constantes definidas para tal fin, como Px0..7. Utilizando estas constantes y la lgica de bits, tenemos que para poner a nivel alto el pin 5 y no modificar los dems pines podemos hacer: PORTB |= (1<<PB5);
y si quisiramos ponerlo a nivel bajo: PORTB &= ~(1<<PB5);
Del mismo modo, si quisiramos actuar en funcin de una entrada haramos: if ((PINB & (1<<PB2)) != 0){ /* Pin a nivel alto */ }else{ /* Pin a nivel bajo */ }
Utilizando el AVRStudio y ejecutando estas instrucciones en el AVRSimulator, utilizando la vista de Disassembly fcilmente podemos ver el cdigo en ensamblador que ha generado el compilador. DDRB |= (1<<PB5); 00000040 SBI 0x04,5 Set bit in I/O register PORTB |= (1<<PB5); 00000041 SBI 0x05,5 Set bit in I/O register
y podemos ver como se comportara el cdigo en el microcontrolador real.
57
Ilustracin 47: Vista de ensamblador en AVRSimulator Si asignamos un valor a un pin en PORTx y luego lo leemos desde PINx, se debe esperar un ciclo para que PINx se sincronice, por ejemplo, unsigned char val; PORTD = (1 << PD3 | 1 << PD5); /*Esperamos un ciclo para sincronizacin */ asm volatile("nop"); /*Leemos los pines */ val = PINB;
Esto es debido al diseo de la circuitera de un pin de entrada y salida, donde en el registro de entrada hay un latch que se comporta como sincronizador para evitar metaestabilidad si hay cambios en el nivel del pin cerca del flanco del reloj interno.
58
Ilustracin 48: Puerto general de entrada/salida digital 4.2.3.3 Uso de la USART/comunicacin serie El entorno Arduino utiliza bsicamente el puerto serie para depurar el cdigo e interaccionar con el PC. En este apartado se mostrar cmo realizar las operaciones equivalentes a travs del perifrico del ATmega y cdigo C. El protocolo de comunicacin serie utiliza 2 cables, uno para recibir datos y otro para enviar. La masa debe ser comn entre la placa Arduino/micro-controlador y el otro dispositivo. La interfaz serie permite enviar entre 5 y 9 bits de datos con un bit de inicio y uno o dos de parada, as como un bit de paridad. La USART hace todo el trabajo acerca de la configuracin de inicio, del bit de parada y de la paridad. La comunicacin es asncrona y slo es necesario indicar a la USART la velocidad de reloj que queremos usar, la velocidad de transmisin. La propia documentacin del microcontrolador (datasheet) nos indica una serie de funciones en ensamblador y en cdigo C a modo de ejemplo para utilizar la USART. A partir de estos ejemplos, aqu podemos ver un ejemplo de cdigo para mandar y recibir a travs del puerto serie. /* * Arduino_USART.c */
#include <avr/io.h> /* Esta libreria contiene la definicin de todos los registros, SIEMPRE DEBE SER INCLUIDA */ #define F_CPU (16000000UL) /* F_CPU indica al compilador que nuestro cristal es de 16Mhz. Debe ser declarado antes que la libreria delay.h */
59 #include <util/delay.h> /* Contiene funciones de espera en ms y us */
#define BAUDRATE (9600u) /* Definimos a que velocidad queremos utilizar la comunicacin serie */ #define BAUD_RATE_REGISTER ((F_CPU / (BAUDRATE * 16ul)) - 1u) /* Datasheet. Tabla 20-1. Equations for Calculating Baud Rate Register Setting */
char String[]="Hola mundo!!";
/* Funcin de inicializacin. Datasheet 20.5 USART Initialization */ void USART_Init( unsigned int ubrr) { /* Configuramos la velocidad de la comunicacin (baud rate) */ UBRR0H = (unsigned char)(ubrr>>8); UBRR0L = (unsigned char)ubrr; /* Valores por defecto despus de reset en el registre USCR0A. Esta escritura no esta definida en el datasheet, pero parece necesaria ya que de lo contrario el bit de "Double USART Transmission Speed" parece activo, de modo que no configura el baud rate como esperamos. Posiblemente el bootloader de Arduino est configurando este bit, ya que usa el perifrico para descargar el cdigo. */ UCSR0A = (1<<TXC0); /* Activar la recepcin y la transmisin */ UCSR0B = (1<<RXEN0)|(1<<TXEN0); /* Configuramos el formato de la trama: 8data, 2stop bit */ UCSR0C = (1<<USBS0)|(3<<UCSZ00); }
/* Funcin de transmisin. Datasheet 20.6 Data Transmission The USART Transmitter */ void USART_Transmit( unsigned char data ) { /* Esperamos a vaciar el buffer de transmisin */ while ( !( UCSR0A & (1<<UDRE0) ) ); /* Ponemos el dato en el buffer y mandamos el dato */ UDR0 = data; }
/* Funcin de recepcin. Datasheet 20.7 Data Reception The USART Receiver */ unsigned char USART_Receive( void ) { /* Esperamos a recibir todo el dato */ while ( !(UCSR0A & (1<<RXC0) ) ); /* Devolvemos el dato del buffer */ return UDR0; }
/* Esta funcin transmite una cadena de caracteres */ void USART_putstring(char* StringPtr){ while(*StringPtr != 0x00){ /* Mientras la cadena no esta vacia transmite */ USART_Transmit(*StringPtr); StringPtr++; } }
int main( void ) { USART_Init(BAUD_RATE_REGISTER); /* Inicializamos la comunicacin */
while(1){ USART_putstring(String); /* Mandamos Hola mundo!!! */ _delay_ms(5000); /* Esperamos 5 seg y volvemos a re-enviar el mensaje cada 5 seg */ }
return 0;
60 }
Estas funciones son muy bsicas y no utilizan las interrupciones que el perifrico ofrece para indicar que los buffers de recepcin y/o transmisin estn vacos/llenos, o si ha detectado errores, Este cdigo sirve a modo de ejemplo para implementar una funcionalidad similar a la que ofrece el mdulo Arduino. En el ANEXO 5, se puede ver como estas funciones han sido exportadas a una librera, de modo que en futuros proyectos simplemente hay que incluirla indicando la velocidad de transmisin deseada y llamar a las funciones de transmisin/recepcin, de manera que facilita enormemente el desarrollo y hace el cdigo ms legible: /* * Arduino_SERIAL_example.c */ #include <avr/io.h> /* Esta libreria contiene la definicin de todos los registros, SIEMPRE DEBE SER INCLUIDA */ #define F_CPU (16000000UL) /* F_CPU indica al compilador que nuestro cristal es de 16Mhz. Debe ser declarado antes que la libreria delay.h */ #include <util/delay.h> /* Contiene funciones de espera en ms y us */
#include "Arduino_SERIAL_Api.h" /* Contiene funciones para trbajar con la comunicacin serie */
char String[]="Hola mundo!!";
int main( void ) { SERIAL_Init(); /* Inicializamos la comunicacin */
while(1){ SERIAL_PutString(String); /* Mandamos Hola mundo!!! */ _delay_ms(5000); /* Esperamos 5 seg y volvemos a re-enviar el mensaje cada 5 seg */ }
return 0; }
La configuracin de la velocidad de la comunicacin serie se encuentra definida en el fichero Arduino_SERIAL_API.h. Se ha implementado de este modo para que el clculo del valor del registro lo haga el pre-compilador, de manera que no se aada ms cdigo innecesario en la aplicacin final. Para poder comunicar el PC y nuestra placa con la comunicacin serie, necesitaremos un programa en el PC que haga de monitor. Hay infinidad, pero por simplicidad, y por la no necesidad de instalacin, yo recomendara Terminal, que se puede encontrar en https://sites.google.com/site/terminalbpp/ y se ha aadido en el soporte digital del PFC. De igual modo como hemos creado una herramienta externa en AVRStudio para el AVRDude, ahora podemos hacer lo mismo para el monitor serie, copiando as las facilidades del entrono de desarrollo de Arduino. 4.2.3.4 Las interrupciones en los ATmega328P Una interrupcin es una llamada inesperada, urgente e inmediata a una funcin especial denominada Interrupt Service Routine (ISR).
61 El mecanismo funciona as: sin importar lo que est haciendo nuestro cdigo, cuando ocurra la interrupcin la CPU har una pausa y pasar a ejecutar el cdigo de la ISR. Tras terminarlo, la CPU regresar a la tarea que estaba realizando antes de la interrupcin, justo donde la haba suspendido. Las interrupciones son disparadas (llamadas) por eventos del hardware del microcontrolador. El evento puede ser algn cambio en cierto pin de E/S, el desbordamiento de un temporizador, la llegada de un dato serie, etc. Se puede deducir por tanto que las fuentes de interrupcin estn relacionadas con la cantidad de recursos del microcontrolador. 4.2.3.4.1 Los Vectores de Interrupcin Cada interrupcin est identificada por un Vector de Interrupcin, que no es otra cosa que una direccin particular en la memoria FLASH. Todos los Vectores estn ubicados en posiciones consecutivas de la memoria FLASH y forman la denominada Tabla de Vectores de Interrupcin. El RESET no es una interrupcin pero su direccin 0x0000 tambin se conoce como Vector de Reset. Por defecto, la Tabla de Vectores de Interrupcin est ubicada en las primeras posiciones de la memoria, tal como se ve abajo. Solo cuando se habilita el uso de la Seccin de Boot Loader toda la tabla se desplazar al inicio de dicha seccin. Aqu se presenta la tabla con las 26 interrupciones posibles en los ATmega328: Num Vector Direccin de Programa Nombre de Vector de Interrupcin Fuente de interrupcin 1 0x0000 RESET External Pin, Power-on Reset, Brown-out Reset and Watchdog System Reset 2 0x0002 INT0 External Interrupt Request 0 3 0x0004 INT1 External Interrupt Request 1 4 0x0006 PCINT0 Pin Change Interrupt Request 0 5 0x0008 PCINT1 Pin Change Interrupt Request 1 6 0x000A PCINT2 Pin Change Interrupt Request 2 7 0x000C WDT Watchdog Time-out Interrupt 8 0x000E TIMER2_COMPA Timer/Counter2 Compare Match A 9 0x0010 TIMER2_COMPB Timer/Counter2 Compare Match B 10 0x0012 TIMER2_OVF Timer/Counter2 Overflow 11 0x0014 TIMER1_CAPT Timer/Counter1 Capture Event 12 0x0016 TIMER1_COMPA Timer/Counter1 Compare Match A 13 0x0018 TIMER1_COMPB Timer/Coutner1 Compare Match B 14 0x001A TIMER1_OVF Timer/Counter1 Overflow 15 0x001C TIMER0_COMPA Timer/Counter0 Compare Match A 16 0x001E TIMER0_COMPB Timer/Counter0 Compare Match B 17 0x0020 TIMER0_OVF Timer/Counter0 Overflow 18 0x0022 SPI_STC SPI Serial Transfer Complete 19 0x0024 USART_RX USART Rx Complete 20 0x0026 USART_UDRE USART, Data Register Empty 21 0x0028 USART_TX USART, Tx Complete
62 22 0x002A ADC ADC Conversion Complete 23 0x002C EE_READY EEPROM Ready 24 0x002E ANALOG_COMP Analog Comparator 25 0x0030 TWI 2-wire Serial Interface 26 0x0032 SPM_READY Store Program Memory Ready
Para entender cmo funciona el mecanismo de las interrupciones debemos saber que el Contador de Programa es un registro que dirige cada una de las instrucciones que ejecuta la CPU. Al dispararse una interrupcin el hardware guardar en la pila el valor actual del Contador de Programa y lo actualizar con el valor del Vector de Interrupcin respectivo. De este modo la CPU pasar a ejecutar el cdigo que se encuentre a partir de esa direccin. Al final del cdigo de la interrupcin debe haber una instruccin de retorno que restaure el Contador de Programa con el valor que se haba guardado en la pila. La instruccin es RETI. Esta instruccin la pone el compilador si le indicamos que la funcin ejecutada es una interrupcin. Si se llegara a producir el evento excepcional en que se disparen dos o ms interrupciones al mismo tiempo, se ejecutarn las interrupciones en orden de prioridad. Tiene mayor prioridad la interrupcin cuyo Vector se ubique ms abajo, es decir, entre todas, la interrupcin INT0 tiene siempre las de ganar. 4.2.3.4.2 Las Funciones de Interrupcin
La Funcin de Interrupcin o ISR va siempre identificada por su Vector de Interrupcin. Su esquema vara ligeramente entre un compilador y otro, puesto que no existe en el lenguaje C un formato estndar. Lo nico seguro es que es una funcin que no puede recibir ni devolver ningn parmetro. En el compilador AVR GCC (WinAVR) la funcin de interrupcin se escribe utilizando la palabra reservada ISR. En el caso de nuestro compilador, el Vector de Interrupcin debe tener la terminacin _vect. En caso de dudas acerca de cmo est declarada se puede buscar en la carpeta include del directorio de instalacin de WinAVR. ISR (Vector_de_Interrupcion) { // Cdigo de la funcin de interrupcin. // No requiere limpiar el flag respectivo. El flag se limpia por hardware }
4.2.3.4.3 Control de las Interrupciones Hay dos tipos de bits para controlar las interrupciones: los Bits Enable, que habilitan las interrupciones, y los Bits de Flag, que notifican cul ha sido la interrupcin que se ha producido. Hay un bit de habilitacin individual para cada interrupcin y adems hay un bit de habilitacin general, ubicado en el registro SREG, que afecta a todas las interrupciones. Para habilitar una interrupcin hay que poner un 1 en su bit de habilitacin individual y en el bit de habilitacin general. Ninguna habilitacin individual tendr efecto si el bit de habilitacin general est a 0.
63 Por otro lado, cada interrupcin tiene un bit de notificacin nico. Este se pone a 1 automticamente por hardware cuando ocurre el evento de dicha interrupcin. Eso pasar independientemente de si la interrupcin est habilitada o no. Cada interrupcin habilitada y disparada, saltar a su correspondiente Funcin de Interrupcin o ISR. El bit de notificacin se limpia automticamente justo cuando se empieza a ejecutar la funcin de interrupcin. La nica excepcin es la interrupcin de recepcin de la USART que se limpia automticamente al leer el registro con el dato recibido. Este comportamiento evita perder una interrupcin mientras se est atendiendo a ella misma, ya que al acabar volvera a ejecutarse la funcin al encontrarse de nuevo el bit de notificacin a 1. Puesto que los bits de notificacin se activan independientemente de si las interrupciones estn habilitadas o no, al momento de activarlas, puede ser necesario limpiarlos manualmente para evitar entrar directamente por algn evento anterior. Para borrar el bit de notificacin se debe escribir un 1 en el bit respectivo. Al ejecutarse la funcin de interrupcin tambin se limpia por hardware el bit de habilitacin general para evitar que se disparen otras interrupciones cuando se est ejecutando la interrupcin actual. Sin embargo, si queremos interrupciones recurrentes o anidadas podemos poner a 1 el bit de habilitacin general dentro de la ISR actual. El bit de habilitacin general se puede escribir como cualquier otro bit de un registro de E/S. Pero dada su especial importancia, existen dos instrucciones exclusivas de ensamblador llamadas SEI (para habilitarlas) y CLI (para deshabilitarlas). El archivo avr_compiler.h ofrece las macros sei() y cli() para usar estas instrucciones. 4.2.3.4.4 Recepcin de una trama serie por interrupcin En el apartado anterior se ha visto como utilizar la USART sin las interrupciones. Esto es una prdida de eficiencia, ya que nos obliga a estar escuchando el bus para recibir una trama. La alternativa a esto es utilizar las interrupciones de recepcin de trama. Para utilizar la interrupcin del puerto serie, es necesario configurar el bit RXCIE (bit 7 del registro UCSRB) a 1, lo que activa la interrupcin. Tambin es necesario activar las interrupciones globalmente. El vector correspondiente a la interrupcin de recepcin de datos a travs del puerto serie es USART_RX_vect. El cdigo que deberamos aadir en la funcin SERIAL_init() sera: /* Activar la interrupcin del puerto serie */ UCSR0B |= (1<<RXCIE0); /* Activar interrupciones generales */ sei();
Tambin deberamos incluir la librera de interrupciones en nuestro fichero API: #include <avr/interrupt.h> Y la Funcin de Interrupcin debe ser parecida a: ISR(USART_RX_vect) { read = SERIAL_Receive(); SERIAL_Transmit(read); /* Mandamos lo que recivimos a modo de eco */
}
64
Desde la funcin principal, o en cualquier parte del cdigo, podramos consultar el contenido del dato recibido sin depender de en qu momento nos han mandado el mensaje. En el ANEXO 6 se puede ver un ejemplo completo de la librera para la comunicacin serie utilizando interrupciones de recepcin para realizar un eco del dato recibido y la recepcin de Ctr + x para finalizar el programa. 4.2.3.5 Interrupciones por cambio de PIN Existen dos tipos de interrupcin por cambio de PIN, las INTx y las PCINTx. Las primeras son disparadas por un flanco (de subida y/o de bajada) o un nivel bajo detectado en el pin INTx del micro controlador. La PCINTx se dispara cada vez que se detecta un cambio de nivel lgico 1 a 0, o viceversa, en cualquiera de los pines de los puertos del ATmega. 4.2.3.5.1 Las Interrupciones INT0 e INT1 El evento que puede disparar la interrupcin INTx es un flanco (de subida y/o de bajada) o un nivel bajo detectado en el pin INTx del ATmega, sin importar si ese pin est configurado como entrada o como salida. Esto es relevante en el caso de querer tener interrupciones va software. En el ATmega368, estas dos interrupciones estn vinculadas a los pines PD2 y PD3 respectivamente (corresponden al digitalPin 2 y 3 de Arduino). Los bits de habilitacin (enable) y notificacin (flag) de estas interrupciones se encuentran en los registros EIMSK = External interrupts Mask Register. Contiene los bits de habilitacin. EIFR = External Interrupts Flags Register. Contiene los bits de notificacin. EICRA = External Interrupts Control Register A. Configura la seal externa que va a generar la interrupcin. Es A porque hay AVRs ms grandes con ms interrupciones INTx donde adems existe el registro EICRB. EIMSK --- --- --- --- --- --- INT1 INT0 EIFR --- --- --- --- --- --- INTF1 INTF0 EICRA --- --- --- --- ISC11 ISC10 ISC01 ISC00 Para habilitar la interrupcin INTx hay que poner a 1 el bit INTx, del registro EIMSK, adems del bit de habilitacin general de las interrupciones en el registro SREG Una vez producido el evento, el hardware pondr a 1 la notificacin INTFx del registro EIFR, y luego se disparar la interrupcin. Este evento se debe configurar previamente en el registro EICRA y hay cuatro opciones posibles. Modo ISCx1 ISCx0 Evento de la Interrupcin 0 0 0 Nivel bajo en el pin INTx. 1 0 1 Cualquier flanco (de subida y/o de bajada) detectado en el pin INTx. 2 1 0 Flanco de bajada detectado en el pin INTx.
65 Modo ISCx1 ISCx0 Evento de la Interrupcin 3 1 1 Flanco de subida detectado en el pin INTx.
EICRA --- --- --- --- ISC11 ISC10 ISC01 ISC00
Configuracin de interrupcin INT 1 Configuracin de interrupcin INT 0
Como la mayora de los registros, EICRA inicia con todos sus bits a cero lo que significa que por defecto la interrupcin INTx habilitada se disparar cuando dicho pin est a nivel bajo. La interrupcin externa INTx tiene la capacidad de despertar al AVR, es decir, de sacarlo del modo sleep. Este modo sleep, es un modo de muy bajo consumo, muy apropiado para aplicaciones que funcionan con bateras, donde el microcontrolador y todos sus perifricos estn parados esperando un evento que lo despierte. 4.2.3.5.2 Interrupciones de Cambio de Pin, PCINTx Esta interrupcin se dispara cada vez que se detecta un cambio de nivel lgico 1 a 0, o viceversa, en cualquiera de los pines de los puertos del ATmega, sin importar si estn configurados como entrada o como salida. Se podra decir que se dispara con los flancos de subida y de bajada en los pines de puertos. En ese sentido, se parece bastante a las interrupciones INTx. La interrupcin de Cambio de Pin tambin puede sacar al AVR del modo Sleep. En el ATmega368 los PCINTx corresponden a los puertos siguientes: PCINT0 corresponde al PUERTO B, PCINT[7:0] PB[7:0] PCINT1 corresponde al PUERTO C, PCINT[14:8] PC[6:0] PCINT2 corresponde al PUERTO D, PCINT[23:16] PD[7:0]. Las interrupciones de cambio de pin se habilitan poniendo a 1 correspondiente para los respectivos puertos que se encuentran en el registro PCICR (Pin Change Interrupt Control Register).
PCICR --- --- --- --- --- PCIE2 PCIE1 PCIE0
Habilita interrupciones de PORT D Habilita interrupciones de PORT C Habilita interrupciones de PORT B
Despus se deben poner a 1 los bits de habilitacin que identifican individualmente los pines de los puertos. Estos bits se encuentran en los registros de mscara PCMSK (Pin Change Mask Register).
66 Registro de mscara Puerto PCMSK0 PORTB PCMSK1 PORTC PCMSK2 PORTD Otra forma de seleccionar los pines de interrupcin es ubicndolos directamente por sus nombres PCINTx. PCMSK0 PCINT7 PCINT6 PCINT5 PCINT4 PCINT3 PCINT2 PCINT1 PCINT0 PCMSK1 --- PCINT14 PCINT13 PCINT12 PCINT11 PCINT10 PCINT9 PCINT8 PCMSK2 PCINT23 PCINT22 PCINT21 PCINT20 PCINT19 PCINT18 PCINT17 PCINT16 Una vez producido el cambio de nivel en uno o varios de los pines habilitados para interrupcin, se activar el bit de notificacin respectivo PCIF (Pin Change Interrupt Flag) del registro PCIFR y luego se llamar a la funcin de interrupcin ISR . As como hay un bit de habilitacin para cada puerto, tambin hay un bit de notificacin para uno. PCIFR --- --- --- --- --- PCIF2 PCIF1 PCIF0
Flag de interrupciones de PORT D Flag de interrupciones de PORT C Flag de interrupciones de PORT B
El bit de notificacin PCIF es puesto a cero (limpiado) por el hardware al ejecutarse el gestor de interrupcin ISR. Sin embargo, como esta notificacin se puede activar sin necesidad de que est habilidato el bit de habilitacin general del registro SREG, a veces se tendr que limpiar por software. En este caso se limpia escribiendo un 1. Es recomendable habilitar la Interrupcin de Cambio de Pin despus de realizar en los puertos todas las operaciones necesarias que pudieran ocasionar cambios de nivel en sus pines, por ejemplo, activar las pullUps. 4.2.3.6 Uso de temporizadores y PWM El ATmega328p tiene 3 temporizadores, el timer 0, el timer 1 y el timer 2. La principal diferencia entre ellos es que el 0 y el 2 son de 8 bits y el 1 de 16 bits. Todos los temporizadores tienen tres valores/conceptos asociados el TOP, el BOTTOM y el MAX: TOP define el valor mximo que se puede contar con el temporizador, que puede ser el valor mximo u otro valor definido por el usuario en el registro OCRxA, en funcin del modo seleccionado. BOTTOM es el valor mnimo y siempre es 0. MAX es siempre el valor mximo que un temporizador puede contar, en el temporizador de 16 bits 65535 y en los de 8bits 255. La fuente de reloj para los temporizadores puede ser el propio reloj del sistema u una fuente externa. En nuestro Arduino el reloj del sistema es de 16MHz, pero se pueden usar divisores para conseguir distintos rangos de frecuencias segn nuestras necesidades. El divisor del reloj se puede ajustar a 1, 8, 64, 256 o 1024.
67 TCCRxB --- --- --- --- --- CSx2 CSx1 CSx0
CSx2 CSx1 CSx0 Seleccin de la funte de reloj 0 0 0 No hay reloj (Timer/Counter parado) 0 0 1 Reloj del sitema (No divisor) 0 1 0 Reloj del sitema / 8 (Divisor interno) 0 1 1 Reloj del sitema / 64 (Divisor interno) 1 0 0 Reloj del sitema / 256 (Divisor interno) 1 0 1 Reloj del sitema / 1024 (Divisor interno) 1 1 0 Reloj externo en pin T0. Flanco de bajada 1 1 1 Reloj externo en pin T0. Flanco de subida
Los temporizadores tienen distintos modos de operacin, los 4 principales son phase correct PWM, fast PWM, CTC(Clear Timer on Compare Match) y modo normal, donde este se comporta como un simple contador. Dependiendo si usamos temporizadores de 8 o 16 bits pueden tener distintos sub-modos de funcionamiento. TCCRxA --- --- --- --- --- --- WGMx1 WGMx0 TCCRxB --- --- --- --- WGMx2 --- --- ---
Modo de operacin WGMx2 WGMx1 WGMx0 Descripcin TOP Actualiza OCRx en Activa el flag TOV 0 0 0 0 Normal 0xFF/0xFFFF Inmediato MAX 1 0 0 1 PWM, Phase Correct 0xFF/0xFFFF TOP BOTTOM 2 0 1 0 CTC OCRxA Inmediato MAX 3 0 1 1 Fast PWM 0xFF/0xFFFF BOTTOM MAX 4 1 0 0 Reservado --- --- --- 5 1 0 1 PWM, Phase Correct OCRxA TOP BOTTOM 6 1 1 0 Reservado --- --- --- 7 1 1 1 Fast PWM OCRxA BOTTOM TOP
La cantidad de registros y los distintos modos de funcionamiento hacen obligatorio el uso de la documentacin del microcontrolador (datasheet). Aqu solo se pretende explicar cmo se comporta en cada modo y realizar algn pequeo ejemplo demostrativo. 4.2.3.6.1 Modo normal Este es el modo bsico de funcionamiento y el que est configurado despus de reset. Simplemente configurando la fuente del reloj este temporizador empezara a contar. Si configuramos la fuente de reloj para que utilice el reloj de sistema sin divisor, esto implicara que en el registro TCNTx incrementara en uno a cada 0.0625us (1/16MHz),
68 llegando a desbordarse en 15,9375us en el caso de utilizar el 0 o el 2, ya que son de 8bits; o en poco ms de 4ms en el caso de usar el de 16bits. Esta es la importancia del divisor. Si nosotros quisiramos realizar una espera de 1 segundo nos quedaramos fuera de escala. Si dividimos por 1024 obtenemos incrementos del temporizador de 64us con lo que nos dara para contar hasta 16.320ms con 8bits o 4.18424 segundos con 16bits. Esta configuracin nos permite poder leer el estado del TCNTx en distintos momentos. Sabiendo que tiempo ha transcurrido podemos implementar nuestra propia funcin de espera, similar a la de la librera delay. En este ejemplo se implementa el ejemplo del parpadeo del LED de nuestra placa Arduino utilizando el timer 1 en lugar de usar la librera delay.h /* * Arduino_blink_timer.c * * Parpadeo del LED de Arduino cada 0.5seg usando timers en lugar de la * libreria delay.h */ #include <avr/io.h>
// Frequencia de la fuente de reloj en Hz #define F_CPU (16000000) // Frequencia deseada en Hz. 2Hz => 0.5 sec #define F_DESEADA (2) /* Para seleccionar el divisor comprobamos cuantas cuentas del contador necesitamos: NUM_CUENTAS = (((F_CPU / DIVISOR) / F_DESEADA) - 1)
Nuestros contadores son de 8 o 16 bits, con lo que como mximo pueden contar hasta 255 o 65365. Con las cuentas hechas anteriormente nos obliga a usar un contador de 16bits (el TCNT1) y un divisor configurado a 256, de manera que cuando el contador alcance 31249 habr transcurrido 0.5 seg (2 Hz) */ #define TIEMPO_A_ESPERAR (31249)
int main(void) { //Definimos el pin13/PORTB5 como salida DDRB |= (1<<PB5);
//Configuramos el divisor del timer. El timer empieza a contar TCCR1B = (1<<CS12); //1:256
while(1){ PORTB |= (1<<PB5); //Enciende el LED
while(TCNT1 <= TIEMPO_A_ESPERAR); // Esperamos el tiempo deseado TCNT1 = 0; //Limpiamos el timer para que vuelva a empezar
PORTB &= ~(1<<PB5); //Apaga el LED
while(TCNT1 <= TIEMPO_A_ESPERAR); // Esperamos el tiempo deseado TCNT1 = 0; //Limpiamos el timer para que vuelva a empezar
69 } }
En este ejemplo en particular utilizamos un temporizador de 16 bits cuando la palabra del microcontrolador es de 8bits, esto hace que el registro TCNT1 en realidad sean dos registros del micro controlador. El compilador de AVRStudio ya nos proporciona unas libreras de manera que nosotros no nos tengamos de preocupar de esto. La configuracin del divisor involucra a 3 bits, el CS12, CS11 y CS10. Para modificar los tres bits a la vez utilizaremos mascaras. TCCR1B &= 0b11111000; // Limpiamos los 3 bits del CS TCCR1B |= 0b00000100; // Configuramos el divisor 1:256 (CS = 100) Cada vez que el temporizador alcanza su valor mximo (TOP) pone a 1 el bit de notificacin TOVx (Timer Overflow Flag) en el registro TIFRx (Timer Interrupt Flag Register). Activando el bit TOIEx (Timer Overflow Interrupt Enable) del TIMSKx (Timer Interrupt Mask Register) genera una interrupcin al alcanzar este punto. Este comportamiento es muy til para ampliar el contaje del temporizador incrementando una variable en la funcin de atencin de la interrupcin. 4.2.3.6.2 Modo CTC El modo Clear Time on Compare match (CTC) nos activa una interrupcin cuando el contador a alcanzado un valor pre-definido y vuelve a empezar el contaje. Este modo de funcionamiento nos aporta una gran ventaja en el diseo de las aplicaciones, ya que no debemos detener el flujo de ejecucin de nuestro programa para realizar alguna accin. Volviendo al ejemplo del LED que parpadea, lo que haremos es cargar el valor a contar en el registro OCRxA (Output Compare Register A) y lo configuraremos para que nos dispare una interrupcin cuando alcance el valor definido pone a 1 el bit OCIExA (Output Compare Match A Interrupt Enable) del registro TIMSKx (Timer Interrupt Mask Register). /* * Arduino_blink_timer_INTERRUPT.c * * Parpadeo del LED de Arduino cada 0.5seg usando interrupciones de timers * en lugar de la libreria delay.h */ #include <avr/io.h> #include <avr/interrupt.h> // Frequencia de la fuente de reloj en Hz #define F_CPU (16000000) // Frequencia deseada en Hz. 2Hz => 0.5 sec #define F_DESEADA (2) /* Para seleccionar el divisor comprobamos cuantas cuentas del contador necesitamos: NUM_CUENTAS = (((F_CPU / DIVISOR) / F_DESEADA) - 1)
Nuestros contadores son de 8 o 16 bits, con lo que como mximo pueden contar hasta 255 o 65365. Con las cuentas hechas anteriormente nos obliga a usar un contador de 16bits (el TCNT1) y un divisor configurado a 256, de manera que cuando
70 el contador alcance 31249 habr transcurrido 0.5 seg (2 Hz) */ #define TIEMPO_A_ESPERAR (31249)
int main(void) { //Definimos el pin13/PORTB5 como salida DDRB |= (1<<PB5);
//Configuramos el timer en modo CTC y el divisor del timer. //El timer empieza a contar TCCR1B = (1<<WGM12)|(1<<CS12); // CTC y 1:256 // Cargamos el valor a contar OCR1A = TIEMPO_A_ESPERAR; // Habilitamos las interrupciones del timer TIMSK1 = (1<<OCIE1A); // Habilitamos las interrupciones generales sei();
while(1){ /* * Ahora podemos implementar otras funcionalidades sin * preocuparnos del parpadeo del LED, ya que se gestiona des * de la interrupcin del timer */ } }
ISR(TIMER1_COMPA_vect){ PORTB ^= (1<<PB5); // Invertimos el estado del LED a cada ejecucin }
Dependiendo de cmo se configura los bits COMxA (Compare Match Output A Mode) del registro TCCRxA (Timer Control Register A), el pin OCxA puede realizar una accin pre configurada cuando se alcance el valor configurado. TCCRxA COMxA1 COMxA0 --- --- --- --- --- ---
COMxA1 COMxA0 Comportamiento del pin OCxA 0 0 Puerto Normal, OCxA desconectado 0 1 Inversin del OCxA al alcanzar el valor 1 0 Poner a zero elOCxA al alcanzar el valor 1 1 Poner a uno el OCxA al alcanzar el valor
Por ejemplo se puede generar un parpadeo (invertir su estado) cada vez que alcancemos el valor configurado en OCRxA siempre que este pin este configurado como salida. Todo esto gestionado por el propio micro controlador y sin que interrumpa el flujo de ejecucin de nuestro programa.
71
Ilustracin 49: Ejemplo de uso del temporizador en modo CTC 4.2.3.6.3 Generacin de PWMs Existe la posibilidad de generar dos tipos de PWM para los temporizadores de 8bits, el Fast PWM y el Phase Correct PWM; y el de 16bits adicionalmente puede generar Phase and Frequency Correct PWM. La diferencia entre ambos es muy sutil y es muy particular para cada aplicacin. El comportamiento de los distintos modos se podra resumir como: Fast aplica el nuevo periodo, ciclo de trabajo (duty) y/o frecuencia a continuacin del periodo en curso.
Phase Correct se podra decir que la salida est centrada. Aplica el nuevo periodo, ciclo de trabajo (duty) y/o frecuencia de manera que el punto medio del semiciclo de ON caiga en la mitad del periodo.
Phase and Frequency Correct. Este modo es igual al anterior pero garantizando que el pulso siempre es correcto incluso cuando la frecuencia va variando. Este uso es muy particular y solo est disponible en el temporizador de 16bits. Aqu se puede ver el comportamiento de los tres modos.
72
Ilustracin 50: Generacin PWM en modo Fast PWM
Ilustracin 51: Generacin PWM en modo Phase Correct PWM
73
Ilustracin 52: Generacin PWM en modo Phase and Frequency Correct PWM Como norma general el modo Fast PWM es suficiente para la mayora de aplicaciones como regulacin de potencia, rectificacin, 4.2.3.6.4 Uso del Input capture El temporizador de 16bits tambin incorpora una unidad de input capture que permite capturar eventos externos asociados a cambios en el pin ICP1 y ofrecer una marca temporal de frecuencia de ejecucin. Tpicamente esta funcionalidad se utiliza para calcular la frecuencia y/o el ciclo de trabajo (duty cycle) de una seal.
Ilustracin 53: Uso del temporizador como Input capture
74 4.2.3.7 Uso del conversor ADC El conversor analgico digital permite que convirtamos los niveles analgicos de tensin a una representacin digital. Esto nos permite leer cosas como la salida de un potencimetro, sensores de temperatura, sensores de humedad, acelermetros y giroscopios que tienen una tensin de salida analgica, sensores de presin y mucho ms las cosas. El ADC interno de nuestro microcontrolador tiene una resolucin de 10 bits. Esto significa que el voltaje de entrada se convierte en un valor numrico entre 0 y 1023. El ATmega328P dispone de 6 pines que son capaces de ser utilizados como pines de entrada analgicos pero slo hay un ADC en el microcontrolador de modo que entre los pines y el conversor hay un multiplexor analgico. El ATmega se alimenta con 5v con lo que podemos conectar cualquier seal de entre 0 y 5V en la entrada. Tambin podemos cambiar la tensin mxima que el ADC utiliza como tensin de referencia, en el pin Aref. Hay que tener en cuenta que la frecuencia mxima de trabajo del ADC es de 200Khz. Esta se genera a partir del reloj del sistema de 16MHz y un divisor (2, 4, 8, 16, 32, 64 y 128). Dada la alta frecuencia a la que trabaja nuestro Arduino y la limitacin del ADC, solo podemos configurar el divisor a 128 y as obtener una frecuencia de trabajo del conversor analgico de 125kHz. En caso de configurar una frecuencia mayor se pierde mucha precisin. Por ejemplo a 250kHz (divisor a 64) la precisin esta alrededor de 8bits. Por defecto el ADC est deshabilitado. Hasta que no lo habilitamos, la seleccin de la tensin de referencia o de canal, no surge ningn efecto. Para reducir el consumo se recomienda deshabilitarlo cuando no se necesite o antes de entrar en modos de bajo consumo. A continuacin podemos ver un ejemplo bsico donde va convirtiendo cclicamente las distintas entradas analgicas: #include <avr/io.h> int adc_value[5]; //Valor leido del ADC
int main(void) {
ADCSRA |= ((1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)); //Divisor a 128 frec. del ADC a 125Khz ADMUX |= (1<<REFS0); ADMUX &= ~(1<<REFS1); //Avcc(+5v) como tensin de referencia ADCSRA |= (1<<ADEN); //Alimentamos el ADC ADCSRA |= (1<<ADSC); //Empezamos la conversin
while(1){ for (channel=0;channel<=5;channel++){ ADMUX &= 0xF0; //Borramos el anterior canal del multiplexor ADMUX |= channel; //Definimos el nuevo canal a convertir ADCSRA |= (1<<ADSC); //Empezamos una nueva conversin while(ADCSRA & (1<<ADSC)); //Esperamos a finalizar la conversin adc_value[channel] = ADCW; //Guardamos el valor de la conversin } }
return 0; }
75 4.2.4 Codificacin del medidor de caudal en C Una vez revisados los perifricos que necesitamos para realizar el caudalmetro vamos a proceder a ensamblar las distintas partes de cdigo que hemos visto. Para controlar la pantalla LCD se utilizar la librera que nos proporciona el fabricante como ya hicimos con el proyecto de Arduino. Esta librera est escrita en C++ cosa que nos obliga a crear un proyecto C++ en AVRStudio. El hecho de crear un proyecto en C++ tiene muy poco impacto para nosotros. Solo que si queremos aprovechar, a modo de librera, parte del cdigo que hemos creado en C, deberemos incluirlo dentro de un bloque indicando que es C. extern "C" { /* Indica que la librera es en C */ #include "Arduino_SERIAL_Api.h" /* Contiene funciones para trabajar con la comunicacin serie */ }
/* Librera en C++ */ #include "ColorLCDShield.h"
Para desligar la librera del fabricante del entorno Arduino, y evitar dependencias durante la compilacin, la editaremos comentando la inclusin de Arduino.h y corrigiendo los errores de dependencias aadiendo las libreras necesarias del entorno AVRStudio, como por ejemplo math.h o delay.h. La nica librera que utilizaremos del entorno Arduino es la de pins_arduino.h, que la copiaremos del entorno Arduino a nuestra carpeta del proyecto AVRStudio, ya que esta simplemente es la definicin de los puertos de entrada y salida, y nos ahorra el tener que redefinirlos dentro de la propia librera. En el ANEXO 7 se puede ver la codificacin del medidor de caudal en C++ as como las libreras usadas. Si utilizamos libreras de terceros es importante cambiar las opciones del compilador y del enlazador (linker) para que el binario generado sea lo ms optimo posible. Las siguientes opciones del compilador fuerzan al compilador a alojar cada funcin en una seccin de memoria interna separada. -ffunction-sections -fdata-sections Con las opciones del compilador anteriores y la siguiente opcin del enlazador (linker) le indicamos que no incluya las funciones que no se utilizan. Estas opciones son de gran ayuda para reducir tamao en memoria al usar libreras genricas ya que no solemos usar todas las funciones que esta proporciona. gc-sections Para realizar esta modificaciones en el AVRStudio, iremos a Porperties en el men Project. Esto nos abrir una nueva pestaa donde veremos las opciones de configuracin de nuestro proyecto. En la pestaa ToolChain encontraremos las configuraciones del compilador C, del C++ y del enlazador (linker).
76
Ilustracin 54: Configuracin opciones de optimizacin del compilador
Ilustracin 55: Configuracin opciones de optimizacin del linker Una vez configurado el compilador y el enlazador (linker) construimos el proyecto. En el men Build seleccionamos la opcin Rebuil Solution. Como resultado veremos en la ventana Output que todo ha ido bien. As como el resumen de memoria necesaria en el microcontrolador.
77 Ilustracin 56: Resultado de la construccin del proyecto en AVRStudio El propio entorno de compilacin del AVR-GCC nos proporciona una herramienta que determina las necesidades de memoria flash y RAM de un fichero .elf. Este fichero es el binario a descargar. Este tambin contiene toda la informacin de depuracin y la distribucin de la memoria. Ejecutando esta herramienta sobre el fichero que hemos generado con el AVRStudio obtenemos el siguiente resultado: avr-size.exe -C --mcu=atmega328p medidorCaudal_AVR.elf AVR Memory Usage ---------------- Device: atmega328p
Data: 1070 bytes (52.2% Full) (.data + .bss + .noinit) Si la misma herramienta la ejecutamos sobre el fichero resultado del proyecto en el entorno Arduino, obtenemos lo siguiente: avr-size.exe -C --mcu=atmega328p medidorCaudal_Arduino.cpp.elf AVR Memory Usage ---------------- Device: atmega328p
78 Se puede observar que al desarrollar en C y teniendo mayor control sobre las opciones a aplicar al compilador y al enlazador (linker) conseguimos usar un 10% menos de memoria, tanto flash como RAM. 5 Presupuesto En este presupuesto se pretende mostrar el coste de la realizacin del proyecto en s mismo, pero diferenciando claramente el coste de realizarlo en entorno Arduino y en AVRStudio y C. El objetivo es poder ver de una forma clara la diferencia en la curva de aprendizaje de Arduino vs AVRStudio. 5.1 Precios unitarios CDIGO UD DESCRIPCIN PRECIO IT001 h Ingeniero Tcnico Industrial 25,00 VEINTICINCO EUROS HW001 u Arduino UNO con ATMega328 21,90 VENTIN EUROS con NOVENTA cntimos HW002 u Arduino Shield LCD Color Sparkfun 32,90 TRENTIDS EUROS con NOVENTA cntimos HW003 u Koolance INS-FM17N Coolant Flow Meter for LCS 25,87 VEINTICINCO EUROS con OCHENTA Y SIETE cntimos HW004 u Tira de pines macho 40 pines paso 2,54 mm 0,53 CINCUENTA Y TRES cntimos HW005 u Rollo de cable de 10Mts seccin 0,5 mm2 2,70 DOS EUROS con SETENTA cntimos 5.2 Precios descompuestos 5.2.1 Captulo 1: Estudios previos CDIGO UD DESCRIPCIN CANTIDAD PRECIO SUBTOTAL IT001 h Ingeniero Tcnico Industrial recopilando informacin acerca de Arduino y su entorno de programacin 80,00 25,00 2.000,00 IT001 h Ingeniero Tcnico Industrial recopilando informacin acerca de ATmega328P y AVRStudio 220,00 25,00 5.500,00
Suma de la Partida 7.500,00 2,00 % Costes Indirectos 150,00 TOTAL PARTIDA 7.650,00
79 5.2.2 Captulo 2: Diseo y montaje del hardware CDIGO UD DESCRIPCIN CANTIDAD PRECIO SUBTOTAL IT001 h Ingeniero Tcnico Industrial 20,00 25,00 500,00 HW001 u Arduino UNO con ATMega328 1,00 21,90 21,90 HW002 u Arduino Shield LCD Color Sparkfun 1,00 32,90 32,90 HW003 u Koolance INS-FM17N Coolant Flow Meter for LCS 1,00 25,87 25,87 HW004 u Tira de pines macho 40 pines paso 2,54 mm 0,25 0,53 0,13 HW005 u Rollo de cable de 10Mts seccin 0,5 mm2 0,25 2,70 0.68
Suma de la Partida 581,48 Envo y manipulacin 10,00 TOTAL PARTIDA 591,48 5.2.3 Captulo 3: Diseo del firmware CDIGO UD DESCRIPCIN CANTIDAD PRECIO SUBTOTAL IT001 h Ingeniero Tcnico Industrial. Diseo en entorno y lenguaje Arduino 10,00 25,00 250,00 IT001 h Ingeniero Tcnico Industrial. Testeo y correccin de errores en entorno Arduino 25,00 25,00 625,00 IT001 h Ingeniero Tcnico Industrial. Diseo en entorno AVRStudio y C 15,00 25,00 375,00 IT001 h Ingeniero Tcnico Industrial. Testeo y correccin de errores en entorno AVRStudio 20,00 25,00 500,00
Suma de la Partida 1.750,00 2,00 % Costes Indirectos 35,00 TOTAL PARTIDA 1.785,00 5.2.4 Captulo 4: Diseo del software de PC CDIGO UD DESCRIPCIN CANTIDAD PRECIO SUBTOTAL IT001 h Ingeniero Tcnico Industrial. 12,00 25,00 300,00
80 Implementacin de aplicacin en Python IT001 h Ingeniero Tcnico Industrial. Testeo y correccin de errores 25,00 25,00 625,00
Suma de la Partida 925,00 2,00 % Costes Indirectos 18,50 TOTAL PARTIDA 943,50 5.2.5 Captulo 5: Documentacin CDIGO UD DESCRIPCIN CANTIDAD PRECIO SUBTOTAL IT001 h Ingeniero Tcnico Industrial Documentacin de todo el proceso de estudio. 80,00 25,00 2.000,00
Suma de la Partida 2.000,00 2,00 % Costes Indirectos 40,00 TOTAL PARTIDA 2.040,00 5.3 Resumen del presupuesto CAPTULO RESUMEN IMPORTE Captulo 1 Estudios previos 7.650,00 Captulo 2 Diseo y montaje del hardware 591,48 Captulo 3 Diseo del firmware 1.785,00 Captulo 4 Diseo del software de PC 943,50 Captulo 5 Documentacin 2.040,00
TOTAL EJECUCIN MATERIAL 13.009,98 13,00 % Gastos Generales 1,691,30 6,00 % Beneficio Industrial 780,60
TOTAL EJECUCIN POR CONTRATO 15.481,87 18,00 % IVA 2.786,74
TOTAL PRESUPUESTO LICITACIN 18.268,61
81 6 Conclusiones y valoracin personal El objetivo principal de este PFC ha sido conocer Arduino a travs del montaje de un caudalmetro. Despus de realizar este proyecto se puede concluir que Arduino es una muy buena plataforma para realizar pequeos proyectos de sistemas basados en microcontrolador. La curva de aprendizaje de Arduino es realmente rpida. Dispone de gran cantidad de documentacin oficial y no oficial. La comunidad de usuarios es muy grande, accesible y colaborativa. Hay gran cantidad de ejemplos de uso y proyectos hechos con licencia abierta, cosa que permite reaprovechar todo lo que ya funciona. Hay una gran cantidad de canales de distribucin, tanto a nivel nacional como internacional. El coste de las placas es realmente ajustado y no suele haber problemas de aprovisionamiento. Esto facilita mucho el poder disponer del hardware necesario para nuestros proyectos en plazos de tiempo pequeos y a un coste muy reducido. El hecho de haber definido una manera estndar de crear extensiones, las shields, ha permitido crear una gran cantidad de placas accesorias para cubrir la mayora de necesidades habituales en proyectos de electrnica. Estas extensiones se consiguen a travs de los mismos canales de distribucin. Estas suelen entregarse con ejemplos de uso o incluso libreras de cdigo integrables en el entorno Arduino, con lo que amplifican mucho el potencial de la plataforma. El nivel de abstraccin de cmo funcionan los circuitos electrnicos o como se deben programar los dispositivos es muy alto. Esto permite realizar operaciones complejas sin gran esfuerzo. En contra, estas limitado al comportamiento proporcionado por las libreras o por la funcionalidad de la circuitera de la que dispones. El desempeo de estas libreras o extensiones no siempre es el ms ptimo y hay veces que es necesario realizar modificaciones. Pero incluso en estos casos el soporte que se puede encontrar en la comunidad de usuarios es muy grande y no debe suponer un gran escollo para la realizacin del proyecto. En cualquier caso, siempre podemos crear nuestras propias libreras, dando as soporte a nuevas funcionalidades o mejoras de rendimiento. En estos casos s que es necesario un mayor nivel de conocimientos de electrnica o de programacin, pero el alcanzar este nivel puede hacerse de un modo muy progresivo. Enlazando con el segundo objetivo que nos habamos marcado en la realizacin de este PFC, podemos decir que las capacidades lectivas o formativas de la plataforma Arduino son muy grandes. Los aplicativos para el PC son simples y fciles de usar. La sintaxis necesaria para el desarrollo de aplicaciones es simple y tiene muchas funciones que ya implementan operaciones habituales y relativamente complejas, como la generacin de un PWM o lecturas analgicas. Esto permite poder introducir conceptos de programacin y algoritmia a niveles de educacin secundaria. El hecho de interactuar con el mundo real de un modo directo, puede generar una mayor curiosidad en el alumnado. Esto permite adquirir unos conocimientos de electrnica o programacin de un modo muy ameno. El hecho que el coste de una placa sea razonablemente bajo, y el hardware muy robusto, puede facilitar el acceso a este por gran parte de centros, permitiendo su uso durante un largo camino formativo. Se podra decir que tiene un bajo coste por el rendimiento que puede ofrecer.
82 En mbitos ms tcnicos o superiores, la plataforma ofrece la posibilidad seguir aprendiendo implementando nuestras propias libreras. Esto obliga a tener un mayor conocimiento de los dispositivos con los que se va a trabajar. Si queremos abandonar las herramientas software que nos proporciona Arduino, el propio fabricante del microcontrolador ofrece un gran nmero de herramientas para permitir el desarrollo ensamblador, C y C++. Esto permite que sobre el mismo hardware Arduino se pueda aprender cmo funciona un microcontrolador des de cero, ofreciendo una plataforma continuista hacia nuevos niveles de conocimiento. Las placas Arduino, el microcontrolador usado en estas y el conjunto de recursos gratuitos disponibles, permiten aprender todo lo relativo a un proyecto de electrnica y software embebido de una manera progresiva y sin perder visibilidad en ningn punto. Se puede definir un camino formativo que pase des del diseo de la placa, su funcionalidad y el algoritmo de control; hasta las optimizaciones del compilador, la definicin del mapa de memoria o todo el proceso de construccin (make). Ha sido muy enriquecedor trabajar y conocer una plataforma tan verstil y fcil de usar como Arduino. Siempre aparecen contratiempos pero son fciles de superar gracias a la gran comunidad que existe. El potencial de la plataforma es enorme y las limitaciones iniciales del software Arduino se pueden superar fcilmente al poder trabajar en C. Es realmente una plataforma muy recomendable para todo aquel que tenga una mnima inquietud para hacerse el mismo las cosas. DIY!!!
83 ANEXOS ANEXO 1: Informacin uso librera LCD ************************************ * * * ColorLCDShield * * * * an Arduino Library * * * * by Jim Lindblom * * SparkFun Electronics * * * ************************************
License: CC-BY SA 3.0 - Creative commons share-alike 3.0 use this code however you'd like, just keep this license and attribute. Let me know if you make hugely, awesome, great changes.
Huge thanks to Jim Lynch, Mark Sproul, and Peter Davenport. If I'm missing anyone, I apologize, all of this code's been through the ringer more than a few times.
This is a (hopefully) simple Arduino library for use specifically with SparkFun Electronics' Color LCD Shield (http://www.sparkfun.com/products/9363). It'll no doubt work with other incarnations of LCD breakouts and what not, you just might have to do some modifying of the pin defintions.
The code gives you access to the following LCD functions:
LCDShield(); - The library's constructor. An instance of the lcd must be created at the beginning of any code. e.g: LCDShield lcd;
void init(int type); - This initializes an LCD. Either EPSON or PHILLIPS should be passed as the type variable. This function should be called near the beginning of any function (setup()!). Turns on the display, sets the contrast and uinitializes the LCD into 12-bit RGB color mode.
void clear(int color); - Clears the entire screen, filling it with the 12- bit RGB color passed to it. There are a number of predefined colors in ColorLCDShield.h
void contrast(char setting); - Manually adjusts the contrast. A value between 0 and 60 should be passed. 40 works pretty well for me.
void setPixel(int color, unsigned char x, unsigned char y); - Draws a single pixel at the specified x, y location. Color is a 12-bit RGB value.
void setCircle (int x0, int y0, int radius, int color); - Draws a circle centered around x0, y0, of the specified radius and color. Radius is in pixels, color is a 12-bit RGB value.
void setChar(char c, int x, int y, int fColor, int bColor); - Sets a single character down at the specified x/y coordinate. You can pick both the foreground and background color, they're 12-bit RGB values. Only one font is
84 available in this library. Definitely room for growth, though at an added cost of memory.
void setStr(char *pString, int x, int y, int fColor, int bColor); - Sets a string of characters down, beginning at x/y coordinates. You can pick both the foreground and background color, they're 12-bit RGB values. Only one font is available in this library. Definitely room for growth, though at an added cost of memory.
void setLine(int x0, int y0, int x1, int y1, int color); - Draws a line from x0,y0 to x1,y1. Color is a 12-bit RGB value.
void setRect(int x0, int y0, int x1, int y1, unsigned char fill, int color); - Draws a rectangle with opposing corners at x0,y0 and x1,y1. A 1 for fill will fill the entire rectangle, a 0 will only draw the border. Color is a 12-bit RGB value.
void printLogo(void); - One trick pony. Prints the SparkFun logo.
void on(void); - Turns the display on.
void off(void); - Turns the display off. You'll still see the backlight on! Modificaciones sobre la librera En el fichero de librera ColorLCDShield.cpp se han modificado las siguientes lneas para poder utilizar un tipo de fuente que requiera menos RAM. Se ha pasado de utilizar una tipografa de 8x16 puntos a otra de 8x8.
Ilustracin 57: Modificacin del fichero ColorLCDShield.cpp. 1era parte
86 {0x7F,0x31,0x34,0x3C,0x34,0x31,0x7F,0x00}, // E {0x7F,0x31,0x34,0x3C,0x34,0x30,0x78,0x00}, // F {0x1E,0x33,0x60,0x60,0x67,0x33,0x1F,0x00}, // G {0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00}, // H {0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // I {0x0F,0x06,0x06,0x06,0x66,0x66,0x3C,0x00}, // J {0x73,0x33,0x36,0x3C,0x36,0x33,0x73,0x00}, // K {0x78,0x30,0x30,0x30,0x31,0x33,0x7F,0x00}, // L {0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00}, // M {0x63,0x73,0x7B,0x6F,0x67,0x63,0x63,0x00}, // N {0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00}, // O {0x7E,0x33,0x33,0x3E,0x30,0x30,0x78,0x00}, // P 0x50 {0x3C,0x66,0x66,0x66,0x6E,0x3C,0x0E,0x00}, // Q {0x7E,0x33,0x33,0x3E,0x36,0x33,0x73,0x00}, // R {0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00}, // S {0x7E,0x5A,0x18,0x18,0x18,0x18,0x3C,0x00}, // T {0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x00}, // U {0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00}, // V {0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00}, // W {0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00}, // X {0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00}, // Y {0x7F,0x63,0x46,0x0C,0x19,0x33,0x7F,0x00}, // Z {0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00}, // [ {0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00}, // \ (back slash) {0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00}, // ] {0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00}, // ^ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF}, // _ {0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00}, // ` 0x60 {0x00,0x00,0x3C,0x06,0x3E,0x66,0x3B,0x00}, // a {0x70,0x30,0x3E,0x33,0x33,0x33,0x6E,0x00}, // b {0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00}, // c {0x0E,0x06,0x3E,0x66,0x66,0x66,0x3B,0x00}, // d {0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00}, // e {0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00}, // f {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C}, // g {0x70,0x30,0x36,0x3B,0x33,0x33,0x73,0x00}, // h {0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00}, // i {0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C}, // j {0x70,0x30,0x33,0x36,0x3C,0x36,0x73,0x00}, // k {0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // l {0x00,0x00,0x66,0x7F,0x7F,0x6B,0x63,0x00}, // m {0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00}, // n {0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00}, // o {0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78}, // p 0x70 {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F}, // q {0x00,0x00,0x6E,0x3B,0x33,0x30,0x78,0x00}, // r {0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00}, // s {0x08,0x18,0x3E,0x18,0x18,0x1A,0x0C,0x00}, // t {0x00,0x00,0x66,0x66,0x66,0x66,0x3B,0x00}, // u {0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00}, // v {0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00}, // w {0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00}, // x {0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x7C}, // y {0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00}, // z {0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00}, // { {0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x0C,0x00}, // | {0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00}, // } {0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00} // ~ }; ANEXO 2: Programa de control de Arduino. /* * Medidor de caudal * * Recibe una serie de pulsos proporcionales al caudal detectado por un caudalimetro
87 * en un linea de interrupcion. * Muestra en una pantalla LCD la cantidad de litros detectados y el flujo instantaneo. * El LCD tiene tres botones con distintas acciones programadas: * - 1er boton: Cambia la informacion a mostrar en la pantalla. * - 2do boton: Pone a zero un primer contador parcial. * - 3er boton: Pone a zero un segundo contador parcial. */
/* * Incluye la libreria de la pantalla LCD */ #include <ColorLCDShield.h>
/* * Variables y constantes usadas para el LCD y los botones */ LCDShield lcd; // Objeto LCD const byte lcdContraste = 40; // Valor del contraste par el LCD char lcdStr[16]; // Cadena usada para mostrar textos en el LCD /* Mapeo de los botones del LCD contra los pines del Arduino */ const int lcdBotones[3] = {3, 4, 5}; // S1 = PIN 3, S2 = PIN 4, S3 = PIN 5 const byte botonAntirebote = 10; // Numero de veces que se debe leer un valor estable en los botones
/* * Variables y constantes usadas para el temporizado */ /* Las siguientes variables son tipo long ya que mediremos el tiempo en milisegundos y en seguida creceran y un integer no seria suficiente. */ const unsigned int intervalo_1000ms = 1000; // Intervalo de ejecucion de la tarea periodica (ms) unsigned long previoMilis = 0; // instante anterior de ejecucion int contadorSegundos = 0; int contadorSegundosParcial_1 = 0; int contadorSegundosParcial_2 = 0;
/* * Variables y constantes usadas para el contaje de volumen */ const float contadorRelacion = 0.307; // Relacion entre pulsos y litros por minuto volatile unsigned int contadorPulsos = 0; // volatile ya que se accede des de interrupcion unsigned int contadorPulsosLocal = 0; float litrosMinuto = 0.0; float litrosTotales = 0.0; float litrosParcial_1 = 0.0; float litrosParcial_2 = 0.0;
/* * Variables y constantes usadas para la gestion de las pantallas */ const byte numeroPantallas = 2; // Numero de distintas pantallas a mostrar byte pantalla = 0; // Pantalla inicial a mostrar
/*
88 * Funcion de inicializacion del sistema */ void setup() { /* Configuracion puerto serie (USB) */ Serial.begin(9600); Serial.println("Empecemos...");
/* Configuracion del LCD */ lcd.init(EPSON); // Inicializa el LCD, utilizar PHILLIPS si no funciona lcd.contrast(lcdContraste); // Inicializamos el contraste lcd.clear(WHITE); // Fondo de pantalla en blanco (sin color)
/* Configuracion del sensor */ /* Configuramos el pin de entrada del sensor como entrada con un pullUp */ pinMode(caudalPin, INPUT); // Configuramos como entrada digitalWrite(caudalPin, HIGH); // Activamos pullUp pinMode(caudalGNDPin, OUTPUT); // Configuramos como salida digitalWrite(caudalGNDPin, LOW); // Le damos GND al sensor /* La linea del interruptor del caudalimetro esta conectada al pin 2 que utiliza la intterupcion 0. Configuramos para capturar los flancos de bajada (transicion de HIGH a LOW) */ attachInterrupt(caudalInt, isr_caudalimetro, FALLING); contadorPulsos = 0; }
/* * Funcion principal */ void loop() { unsigned long currentMillis = millis(); /* Variables para gestion del anti rebote (debouncing) de los botones */ static byte boton0 = 0; static byte boton1 = 0; static byte boton2 = 0;
/* Para ser usado como test. Remplazamos el caudalimetro por un corto circuito entre las lineas del Arduino. Pin2 y Pin6. Esto equivaldria a que el sensor nos entrega una seoal de 31Hz */ // tone(caudalGNDPin,31); // Al utilizar contadores de 8 bits, 31Hz es la menor freq que nos permite esta funcion directamente.
/* Acciones a realizar cada segundo */ if (currentMillis - previoMilis > intervalo_1000ms) { previoMilis = currentMillis; task_1000ms(); }
/* Lectura continua sobre los pulsadores con debouncing */ if (!digitalRead(lcdBotones[0])){ // Pulsado if (boton0 < 255){ // Control de rangos boton0++; } }else{ // No pulsado if (boton0 > botonAntirebote){ // Ha estado pulsado al menos "botonAntirebote" veces /* Ponemos a zero el contador parcial 2 */ contadorSegundosParcial_2 = 0; litrosParcial_2 = 0.0; } boton0 = 0; } if (!digitalRead(lcdBotones[1])){ // Pulsado
89 if (boton1 < 255){ // Control de rangos boton1++; } }else{ // No pulsado if (boton1 > botonAntirebote){ // Ha estado pulsado al menos "botonAntirebote" veces /* Ponemos a zero el contador parcial 1 */ contadorSegundosParcial_1 = 0; litrosParcial_1 = 0.0; } boton1 = 0; } if (!digitalRead(lcdBotones[2])){ // Pulsado if (boton2 < 255){ // Control de rangos boton2++; } }else{ // No pulsado if (boton2 > botonAntirebote){ // Ha estado pulsado al menos "botonAntirebote" veces lcd.clear(WHITE); // Limpiamos la pantalla pantalla++; // Cambiamos la pantalla a mostrar if (pantalla > numeroPantallas){ pantalla = 0; } } boton2 = 0; } }
/* * Funcion periodica cada 1 segundo. * Cada segundo leemos los pulsos recibidos por el cuadalimetro, * actualizamos los contadores de volumen acumulado e instantaneo, * mandamos por la linea serie los pulsos detectados * y refrescamos la pantalla a mostrar */ void task_1000ms() { float litrosUltimoMinuto; /* Inicio zona segura intercambio de datos. No hay interrupciones */ noInterrupts(); contadorPulsosLocal = contadorPulsos; contadorPulsos = 0; // Se escribe el la interrupcin y se limpia una vez leido interrupts(); /* Fin zona segura intercambio de datos */
Serial.println(contadorPulsosLocal); // Mandamos los pulsos x segundo a la linea serie
/* Convertimos los pulsos a litros por minuto y acumulamos los totales */ litrosMinuto = contadorPulsosLocal * contadorRelacion; litrosUltimoMinuto = (litrosMinuto / 60); litrosTotales += litrosUltimoMinuto; litrosParcial_1 += litrosUltimoMinuto; litrosParcial_2 += litrosUltimoMinuto;
/* Incrementamos los contadores de tiempo */ contadorSegundos++; contadorSegundosParcial_1++; contadorSegundosParcial_2++;
/* Mostramos la pantalla que corresponda */ switch (pantalla){ case 0: pantalla_principal();
90 break; case 1: pantalla_parcial_1(); break; case 2: pantalla_parcial_2(); break; default: break; } }
/* * Funcion llamada por la interrupcion 0 a cada deteccion de flanco de bajada * del caudalimetro. */ void isr_caudalimetro() { contadorPulsos++; // Incrementamos el contador de pulsos }
ANEXO 3: Programa de control del PC. """ This demo demonstrates how to draw a dynamic mpl (matplotlib) plot in a wxPython application.
It allows "live" plotting as well as manual zooming to specific regions.
Both X and Y axes allow "auto" or "manual" settings. For Y, auto mode sets the scaling of the graph to see all the data points. For X, auto mode makes the graph "follow" the data. Set it X min to manual 0 to always see the whole data from the beginning.
Note: press Enter in the 'manual' text box to make a new value affect the plot.
Eli Bendersky (eliben@gmail.com) License: this code is in the public domain Last modified: 31.07.2008 """ import os import pprint import random import sys import wx
92 import serial
# The recommended way to use wx with mpl is with the WXAgg # backend. # import matplotlib matplotlib.use('WXAgg') from matplotlib.figure import Figure from matplotlib.backends.backend_wxagg import \ FigureCanvasWxAgg as FigCanvas, \ NavigationToolbar2WxAgg as NavigationToolbar import numpy as np import pylab
class DataGet(object): """ Get the number of pulses received from serial port """ def __init__(self, init=0): self.data = self.init = init self.ser = serial.Serial( port='\\.\COM3', baudrate=9600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=1 )
def next(self): test = self.ser.readline() if (test != '') and (test[0].isdigit()): self.data = int(test,10)*0.307 return self.data
class BoundControlBox(wx.Panel): """ A static box with a couple of radio buttons and a text box. Allows to switch between an automatic mode and a manual mode with an associated value. """ def __init__(self, parent, ID, label, initval): wx.Panel.__init__(self, parent, ID)
# plot the data as a line series, and save the reference # to the plotted line series # self.plot_data = self.axes.plot( self.data, linewidth=1, color=(1, 1, 0), )[0]
def draw_plot(self): """ Redraws the plot """ # when xmin is on auto, it "follows" xmax to produce a # sliding window effect. therefore, xmin is assigned after # xmax. # if self.xmax_control.is_auto(): xmax = len(self.data) if len(self.data) > 50 else 50 else: xmax = int(self.xmax_control.manual_value())
# for ymin and ymax, find the minimal and maximal values # in the data set and add a mininal margin. # # note that it's easy to change this scheme to the # minimal/maximal value in the current display, and not # the whole data set. # if self.ymin_control.is_auto(): ymin = round(min(self.data), 0) - 1 else: ymin = int(self.ymin_control.manual_value())
if self.ymax_control.is_auto(): ymax = round(max(self.data), 0) + 1
# anecdote: axes.grid assumes b=True if any other flag is # given even if b is set to False. # so just passing the flag into the first statement won't # work. # if self.cb_grid.IsChecked(): self.axes.grid(True, color='gray') else: self.axes.grid(False)
# Using setp here is convenient, because get_xticklabels # returns a list over which one needs to explicitly # iterate, and setp already handles this. # pylab.setp(self.axes.get_xticklabels(), visible=self.cb_xlab.IsChecked())
if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() self.canvas.print_figure(path, dpi=self.dpi) self.flash_status_message("Saved to %s" % path)
97
def on_redraw_timer(self, event): # if paused do not add data, but still redraw the plot # (to respond to scale modifications, grid change, etc.) # if not self.paused: self.data.append(self.dataget.next())
ANEXO 4: Configuracin del AVRStudio para descargar el cdigo en Arduino. Contenido de Upload.cmd @ECHO OFF cls Set micro=ATMEGA328P REM Chequeamos los argumentos de la linea de comandos If "%~1"=="" goto NoParam If "%~2"=="" goto NoParam If NOT "%~3"=="" goto Error Set port=%~1 Set file=%~2 Goto CheckPort
:NoParam Set /P port=Introduce el puerto serie al que esta conectado el Arduino [COM3]: If "%port%"=="" goto Error Set /P file=Introduce el binario a descargar: If "%file%"=="" goto Error Goto CheckPort
:CheckPort IF /I NOT %port:~0,3%==COM GOTO Error Goto Execute
98 :Error echo. echo Debes indicar el puerto serie de Arduino y el binario a descargar. echo upload SERIAL_PORT FILE_TO_FLASH echo. echo Si la ruta del binario incluye espacios en blanco, encierralo entre comillas. echo. echo Ejemplo: echo upload COM3 "Arduino Blink.hex" echo. PAUSE GOTO End
:End Pause Contenido de UploadFromAVRStudio.cmd echo off cls REM Detectamos des de donde debemos ejecutarnos set currentFolder=%~dps0 REM Vamos a la unidad correcta %~d0 REM Vamos a la carpeta donde tenemos el avrdude cd %currentFolder% REM Eliminamos la '\' extra que aade AVRStudio en el path de donde se encuentra nuestro proyecto set folder=%~1 set folder=%folder:~0,-1% set fileNameWithExt=%~2 REM Eliminamos la extensin del fichero que nos proporciona AVRStudio set fileName=%fileNameWithExt:.atsln=% echo %fileName% REM Componemos la ruta donde se encuentra el binario a descargar con el parametro Debug o Release del AVRStudio set binaryFile=%folder%%fileName%\%3\%fileName%.hex REM Copiamos el fichero a descargar en esta misma carpeta copy "%binaryFile%" REM Lanzamos el batch que tenemos preparado para el avrdude des de la linea de comandos call upload "%4" "%fileName%.hex" REM Borramos el binario que hemos descargado del /F /Q "%fileName%.hex"
Uso de herramientas externas en AVRStudio Para la creacin de una herramienta externa y su correspondiente botn en la barra de herramientas en el AVRStudio, debemos definirlas en el men Tools, External Tools
99
Ilustracin 59: Configuracin de una herramienta externa en AVRStudio En el cuadro de dialogo que se nos aparece, debemos usar el botn Add y rellenar los siguientes campos de este modo: Title: El nombre que le queramos poner a la herramienta, en mi caso: Program Arduino Debug Command: Ruta completa de donde tengamos el fichero uploadFromAVRStudio.cmd que hemos creado anteriormente, en mi caso: d:\Mis documentos\Documents\My Dropbox\Arduino\Code\AVRStudio 5.1\ArduinoUpload\uploadFromAVRStudio.cmd Arguments: Aqu utilizamos las variables que tiene configuradas el propio AVRStudio para indicarle al fichero por lotes donde se encuentra el fichero a descargar, el nombre que tiene, si utilizamos una compilacin Debug o Release y el puerto en que se encuentra nuestro puerto serie. En mi caso: $(SolutionDir) $(SolutionFileName) Debug COM12 Una vez tenemos esto, podemos aadir esta llamada a la barra de herramientas, de modo que tendramos un acceso parecido al que ofrece el propio entorno Arduino. Pulsamos con el botn izquierdo del ratn sobre el desplegable de la barra de herramientas del AVRStudio, seleccionado Customize
100
Ilustracin 60: Vista para crear un botn para las herramientas externas en AVRStudio Una vez dentro de las opciones, debemos aadir un nuevo comando, y seleccionar External Command 1 o la posicin en la que hayamos definido nuestra external tool.
Ilustracin 61: Cuadro de opciones para botn en la barra de herramientas. I
101
Ilustracin 62: Cuadro de opciones para botn en la barra de herramientas. II Donde obtendremos como resultado un nuevo botn para programar nuestro Arduino de manera cmoda y sin tener que salir del AVRStudio.
Ilustracin 63: Vista del botn en la barra de herramientas
ANEXO 5: Librera de uso de la comunicacin serie en AVRStudio Contenido de Arduino_SERIAL_API.h Este es el contenido de la API se ha creado para poder interactuar con la comunicacin serie en C de un modo cmodo. /* * Arduino_SERIAL_API.h */
/* Inicializacin de la comunicacin serie */ void SERIAL_Init( void );
/* Funcin de transmisin de un caracter */ void SERIAL_Transmit( unsigned char data );
/* Funcin de recepcin de un caracter */ unsigned char SERIAL_Receive( void );
/* Funcin de transmisin de una cadena de caracteres */ void SERIAL_PutString(char* StringPtr);
102 Contenido de Arduino_SERIAL.c /* * Arduino_SERIAL.c */ #include <avr/io.h> /* Esta libreria contiene la definicin de todos los registros, SIEMPRE DEBE SER INCLUIDA */
/* Inicializacin de la comunicacin serie */ void SERIAL_Init( void ) { /* Configuramos la velocidad de la comunicacin (baud rate) */ UBRR0H = (unsigned char)(BAUD_RATE_REGISTER>>8); UBRR0L = (unsigned char)BAUD_RATE_REGISTER; /* Valores por defecto despus de reset en el registre USCR0A. Esta escritura no esta definida en el datasheet, pero parece necesaria ya que de lo contrario el bit de "Double USART Transmission Speed" parece activo, de modo que no configura el baud rate como esperamos. Posiblemente el bootloader de Arduino est configurando este bit, ya que usa el perifrico para descargar el cdigo. */ UCSR0A = (1<<TXC0); /* Activar la recepcin y la transmisin */ UCSR0B = (1<<RXEN0)|(1<<TXEN0); /* Configuramos el formato de la trama: 8data, 2stop bit */ UCSR0C = (1<<USBS0)|(3<<UCSZ00); }
/* Funcin de transmisin de un caracter */ void SERIAL_Transmit( unsigned char data ) { /* Esperamos a vaciar el buffer de transmisin */ while ( !( UCSR0A & (1<<UDRE0) ) ); /* Ponemos el dato en el buffer y mandamos el dato */ UDR0 = data; }
/* Funcin de recepcin de un caracter */ unsigned char SERIAL_Receive( void ) { /* Esperamos a recibir todo el dato */ while ( !(UCSR0A & (1<<RXC0) ) ); /* Devolvemos el dato del buffer */ return UDR0; }
/* Funcin de transmisin de una cadena de caracteres */ void SERIAL_PutString(char* StringPtr){ while(*StringPtr != 0x00){ /* Mientras la cadena no esta vacia transmite */ SERIAL_Transmit(*StringPtr); StringPtr++; } /* Aadimos salto de linea y retorno de carro al final de la cadena */ SERIAL_Transmit(0x0Du); SERIAL_Transmit(0x0Au); }
103 ANEXO 6: Comunicacin serie con interrupciones de recepcin Contenido de Arduino_SERIAL_I NTRx_API.h Este es el contenido de la API se ha creado para poder interactuar con la comunicacin serie en C de un modo cmodo. /* * Arduino_SERIAL_INTRx_API.h */ #include <avr/interrupt.h>
/* Inicializacin de la comunicacin serie */ void SERIAL_Init( void );
/* Funcin de transmisin de un caracter */ void SERIAL_Transmit( unsigned char data );
/* Funcin de recepcin de un caracter */ unsigned char SERIAL_Receive( void );
/* Funcin de transmisin de una cadena de caracteres */ void SERIAL_PutString(char* StringPtr); Contenido de Arduino_SERIAL_I NTRx.c /* * Arduino_SERIAL_INTRx.c */ #include <avr/io.h> /* Esta libreria contiene la definicin de todos los registros, SIEMPRE DEBE SER INCLUIDA */
/* Inicializacin de la comunicacin serie */ void SERIAL_Init( void ) { /* Configuramos la velocidad de la comunicacin (baud rate) */ UBRR0H = (unsigned char)(BAUD_RATE_REGISTER>>8); UBRR0L = (unsigned char)BAUD_RATE_REGISTER; /* Valores por defecto despus de reset en el registre USCR0A. Esta escritura no esta definida en el datasheet, pero parece necesaria ya que de lo contrario el bit de "Double USART Transmission Speed" parece activo, de modo que no configura el baud rate como esperamos. Posiblemente el bootloader de Arduino est configurando este bit, ya que usa el perifrico para descargar el cdigo. */ UCSR0A = (1<<TXC0); /* Activar la recepcin y la transmisin */ UCSR0B = (1<<RXEN0)|(1<<TXEN0); /* Configuramos el formato de la trama: 8data, 2stop bit */ UCSR0C = (1<<USBS0)|(3<<UCSZ00); /* Activar la interrupcin del puerto serie */ UCSR0B |= (1<<RXCIE0); /* Activar interrupciones generales */ sei(); }
/* Funcin de transmisin de un caracter */
104 void SERIAL_Transmit( unsigned char data ) { /* Esperamos a vaciar el buffer de transmisin */ while ( !( UCSR0A & (1<<UDRE0) ) ); /* Ponemos el dato en el buffer y mandamos el dato */ UDR0 = data; }
/* Funcin de recepcin de un caracter */ unsigned char SERIAL_Receive( void ) { /* Esperamos a recibir todo el dato */ while ( !(UCSR0A & (1<<RXC0) ) ); /* Devolvemos el dato del buffer */ return UDR0; }
/* Funcin de transmisin de una cadena de caracteres */ void SERIAL_PutString(char* StringPtr){ while(*StringPtr != 0x00){ /* Mientras la cadena no esta vacia transmite */ SERIAL_Transmit(*StringPtr); StringPtr++; } } Contenido de Arduino_SERIAL_INTERRUPT_example.c /* * Arduino_SERIAL_INTERRUPT_example.c */ #include <avr/io.h> /* Esta libreria contiene la definicin de todos los registros, SIEMPRE DEBE SER INCLUIDA */ #define F_CPU (16000000UL) /* F_CPU indica al compilador que nuestro cristal es de 16Mhz. Debe ser declarado antes que la libreria delay.h */ #include <util/delay.h> /* Contiene funciones de espera en ms y us */
#include "Arduino_SERIAL_INTRx_Api.h" /* Contiene funciones para trbajar con la comunicacin serie */
volatile unsigned char read;
int main( void ) { int index = 0; char indexCh[2];
SERIAL_Init(); /* Inicializamos la comunicacin */
/* Ejemplo de como escribir enteros en el terminal a modo de cuenta atras */ for(index=3;index>0;index--){ itoa(index,indexCh,10); SERIAL_PutString(indexCh); SERIAL_PutString("\r\n"); _delay_ms(500); } SERIAL_PutString("Empieza a escribir en el terminal. \r\n");
read = 0; while(read != 0x18){ /* Para salir Ctr + x */ /* Solo romperemos este bucle des de la interrupcin de recepcin */ }
SERIAL_PutString("\r\n Buen trabajo !!!");
return 0; }
105
ISR(USART_RX_vect) { read = SERIAL_Receive(); SERIAL_Transmit(read); /* Mandamos lo que recivimos a modo de eco */ }
ANEXO 7: Medidor de caudal implementado con AVRStudio Este es el programa de control del Arduino codificado en C++ y compilado por el AVRStudio. El proyecto completo se puede encontrar en el soporte digital de este PFC. Contenido de medidorCaudal_AVR.cpp /* * Medidor de caudal * * Recibe una serie de pulsos proporcionales al caudal detectado por un caudalimetro * en un linea de interrupcion. * Muestra en una pantalla LCD la cantidad de litros detectados y el flujo instantaneo. * El LCD tiene tres botones con distintas acciones programadas: * - 1er boton: Cambia la informacion a mostrar en la pantalla. * - 2do boton: Pone a zero un primer contador parcial. * - 3er boton: Pone a zero un segundo contador parcial. * * Este codigo esta implementado en C y no utiliza las "facilidades" del entorno Arduino */
/* * Importacin de librerias */ #include <avr/io.h> /* Esta libreria contiene la definicin de todos los registros, SIEMPRE DEBE SER INCLUIDA */ #define F_CPU (16000000UL) /* F_CPU indica al compilador que nuestro cristal es de 16Mhz. Debe ser declarado antes que la libreria delay.h */ #include "string.h" #include "stdlib.h" #include "math.h" #include <util/delay.h> /* Contiene funciones de espera en ms y us */ #include <avr/interrupt.h> #include "ColorLCDShield.h" extern "C" { /* Importamos las librerias definidas en C */ #include "Arduino_SERIAL_Api.h" /* Contiene funciones para trabajar con la comunicacin serie */ }
/* * Variables y constantes usadas para el LCD */ static LCDShield lcd; // Objeto LCD #define LCD_CONTRASTE (40) // Valor del contraste par el LCD char lcdStr[16]; // Cadena usada para mostrar textos en el LCD #define LIMITE_ANTIRREBOTE (10) // Numero de veces que se debe leer un valor estable en los botones
/* * Variables y constantes usadas para el temporizado */ /* NUM_CUENTAS = (((F_CPU / DIVISOR) / F_DESEADA) - 1) */
106 #define F_DESEADA (1) // 1Hz => 1 segundo #define DIVISOR (256) #define TIEMPO_A_ESPERAR (((F_CPU / DIVISOR) / F_DESEADA) - 1) #if TIEMPO_A_ESPERAR >= 65535 // Mximo del contador de 16bits #error El tiempo a esperar es demasiado grande #endif volatile unsigned char segundos = 0; // Se actualiza en la interrupcin del timer static unsigned int contadorSegundos = 0; static unsigned int contadorSegundosParcial_1 = 0; static unsigned int contadorSegundosParcial_2 = 0;
/* * Variables y constantes usadas para el contaje de volumen */ #define CONTADOR_RELACION (0.307F) // Relacion entre pulsos y litros por minuto volatile unsigned int contadorPulsos = 0; // volatile ya que se accede des de interrupcion static unsigned int contadorPulsosLocal = 0; static float litrosMinuto = 0.0; static float litrosTotales = 0.0; static float litrosParcial_1 = 0.0; static float litrosParcial_2 = 0.0;
/* * Variables y constantes usadas para la gestion de las pantallas */ #define NUMERO_PANTALLAS (3) // Numero de distintas pantallas a mostrar unsigned char pantalla = 0; // Pantalla inicial a mostrar
/* * Definicin de funciones */ /* * Funcin principal */ int main(void){ inicializacion();
while(1){ if (segundos >= 1){ /* Inicio zona segura intercambio de datos. No hay interrupciones */ cli(); // DesHabilitamos las interrupciones generales segundos--; sei(); // Habilitamos las interrupciones generales /* Fin zona segura intercambio de datos */ task_1000ms(); } lecturaPulsadorLCD(); }
return 0; }
107 /* * Inicializacin de perifricos (puerto serie, timer, LCD e interrupciones) */ void inicializacion(void){ /* Configuramos la comunicacin serie */ SERIAL_Init(); SERIAL_PutString("Empecemos...");
/* Configuracion del LCD */ lcd.init(EPSON); // Inicializa el LCD, utilizar PHILLIPS si no funciona lcd.contrast(LCD_CONTRASTE); // Inicializamos el contraste lcd.clear(WHITE); // Fondo de pantalla en blanco (sin color)
/* Configuracin del sensor */ DDRD = (1<<PORTD6); // Pin digital 6 - PD6 como salida las demas como entrada PORTD = ((1<<PORTD2) | (1<<PORTD3)|(1<<PORTD4)|(1<<PORTD5)); // PullUp en las entradas contadorPulsos = 0; /* Configuramos interrupciones del pin INT 0 */ EIMSK = (1<<INT0); // INT 0 EICRA = (1<<ISC01); // Flanco de bajada
/* Configuramos el timer en modo CTC y el divisor del timer. El timer empieza a contar */ TCCR1B = ((1<<WGM12)|(1<<CS12)); // CTC y 1:256 OCR1A = TIEMPO_A_ESPERAR; // Cargamos el valor a contar TIMSK1 = (1<<OCIE1A); // Habilitamos las interrupciones del timer
sei(); // Habilitamos las interrupciones generales }
/* * Chequea el estado de los switches del LCD */ void lecturaPulsadorLCD(void){ /* Variables para gestion del anti rebote (debouncing) de los botones */ static unsigned char boton0 = 0; static unsigned char boton1 = 0; static unsigned char boton2 = 0;
/* Lectura continua sobre los pulsadores con debouncing */ if ((PIND & (1<<PORTD3)) == 0){ // Pulsado if (boton0 < 255){ // Control de rangos boton0++; } }else{ // No pulsado if (boton0 > LIMITE_ANTIRREBOTE){ // Ha estado pulsado al menos "LIMITE_ANTIRREBOTE" veces /* Ponemos a zero el contador parcial 2 */ contadorSegundosParcial_2 = 0; litrosParcial_2 = 0.0; } boton0 = 0; } if ((PIND & (1<<PORTD4)) == 0){ // Pulsado if (boton1 < 255){ // Control de rangos boton1++; } }else{ // No pulsado if (boton1 > LIMITE_ANTIRREBOTE){ // Ha estado pulsado al menos "LIMITE_ANTIRREBOTE" veces /* Ponemos a zero el contador parcial 1 */ contadorSegundosParcial_1 = 0;
108 litrosParcial_1 = 0.0; } boton1 = 0; } if ((PIND & (1<<PORTD5)) == 0){ // Pulsado if (boton2 < 255){ // Control de rangos boton2++; } }else{ // No pulsado if (boton2 > LIMITE_ANTIRREBOTE){ // Ha estado pulsado al menos "LIMITE_ANTIRREBOTE" veces lcd.clear(WHITE); // Limpiamos la pantalla pantalla++; // Cambiamos la pantalla a mostrar if (pantalla >= NUMERO_PANTALLAS){ pantalla = 0; } } boton2 = 0; } }
/* * Funcion periodica cada 1 segundo. * Cada segundo leemos los pulsos recibidos por el cuadalimetro, * actualizamos los contadores de volumen acumulado e instantaneo, * mandamos por la linea serie los pulsos detectados * y refrescamos la pantalla a mostrar */ void task_1000ms(void){ float litrosUltimoMinuto; /* Inicio zona segura intercambio de datos. No hay interrupciones */ cli(); // DesHabilitamos las interrupciones generales contadorPulsosLocal = contadorPulsos; contadorPulsos = 0; // Se escribe el la interrupcion y se limpia una vez leido sei(); // Habilitamos las interrupciones generales /* Fin zona segura intercambio de datos */
itoa(contadorPulsosLocal,lcdStr,10); SERIAL_PutString(lcdStr); // Mandamos los pulsos x segundo a la linea serie
/* Convertimos los pulsos a litros por minuto y acumulamos los totales */ litrosMinuto = contadorPulsosLocal * CONTADOR_RELACION; litrosUltimoMinuto = (litrosMinuto / 60); litrosTotales += litrosUltimoMinuto; litrosParcial_1 += litrosUltimoMinuto; litrosParcial_2 += litrosUltimoMinuto;
/* Incrementamos los contadores de tiempo */ contadorSegundos++; contadorSegundosParcial_1++; contadorSegundosParcial_2++;
/* Mostramos la pantalla que corresponda */ switch (pantalla){ case 0: pantalla_principal(); break; case 1: pantalla_parcial_1(); break; case 2: pantalla_parcial_2(); break; default:
/* * Incrementa el contador de segundos */ ISR(TIMER1_COMPA_vect){ segundos++; }
/* * Incrementa el contador de pulsos */ ISR(INT0_vect){ contadorPulsos++; }
Parte del contenido modificado de ColorLCDShield.h Para compilar la librera sin depender del entorno Arduino, se han modificado los ficheros a incluir, y se ha redefinido las libreras de delay para que utilice las del AVRStudio. /* ColorLCDShield.h - Arduino Library to control a Nokia 6100 LCD, specifically that found on SparkFun's Color LCD Shield. This code should work for both Epson and Phillips display drivers normally found on the Color LCD Shield.
License: CC BY-SA 3.0: Creative Commons Share-alike 3.0. Feel free to use and abuse this code however you'd like. If you find it useful please attribute, and SHARE-ALIKE!
This is based on code by Mark Sproul, and Peter Davenport. */
#ifndef ColorLCDShield_H #define ColorLCDShield_H
#define PHILLIPS 0 #define EPSON 1
/* The content of this include had been joined at "Arduino.h" */ /* #include <WProgram.h> */ //#include "Arduino.h" #include "pins_arduino.h"
#include <inttypes.h> /* Para aseguranos que trabajamos con la frequencia correcta para nuestro Arduino */ #ifdef F_CPU
111 #undef F_CPU #endif #include "math.h" #define F_CPU 16000000UL #include <util/delay.h> /* Contiene funciones de espera en ms y us */ #define delayMicroseconds(x) _delay_us(x) #define delay(x) _delay_ms(x)
A partir de este punto se ha mantenido el contenido del fichero utilizado en el entorno Arduino. ANEXO 8: Contenido del soporte digital del PFC En el soporte digital del PFC se ha aadido el cdigo fuente, los programas a instalar y la documentacin tcnica referente a los componentes. El objetivo es poder configurar un PC de manera que pueda reproducirse cualquier punto del PFC con las versiones de las aplicaciones aqu descritas. En la raz del soporte digital podemos encontrar el documento del PFC, su resumen y tres carpetas. La primera carpeta contiene el cdigo fuente del PFC para ser ejecutado en entorno Arduino, AVRStudio y la aplicacin python para el PC. Tambin contiene una serie de ejemplos y libreras para el AVRStudio. Y utilidades para programar directamente el Arduino des del AVRStudio, calcular el tamao en RAM y FLASH de un binario y un monitor serie para Windows que no necesita ser instalado. La segunda contiene los instaladores y programas para Windows necesarios para poder compilar y ejecutar el cdigo del proyecto, tanto en Arduino, como AVRStudio como en python. El entorno Arduino se ha entregado con las libreras del PFC configuradas, y listo para ser ejecutado y lanzar el proyecto Arduino sin necesidad de ser instalado. El AVRStudio es un paquete que contiene todas las dependencias necesarias para poder ser instalado sin necesidad de conexin a internet. La carpeta python contiene el aplicativo python para ser instalado y libreras adicionales que se deben instalar para poder ejecutar la aplicacin de PC. La tercera carpeta contiene la documentacin tcnica referente al microcontrolador, el LCD y caudalmetro utilizada durante el desarrollo del proyecto. Esta es la estructura de carpetas del soporte digital:
112
Ilustracin 64: Estructura de carpetas del soporte digital
113 Bibliografa y referencias Bibliografa Arduino team. Arduino homepage [En lnea] Pgina web del equipo de Arduino [Fecha consulta: 01-01-2012] [Acceso gratuito] <http://arduino.cc/> Wikipedia. Arduino [En lnea] Enciclopedia digital [Fecha consulta: 01-01- 2012] [Acceso gratuito] <http://es.wikipedia.org/wiki/Arduino> Arduino team. Arduino Uno. [En lnea] Artculo digital [Fecha consulta: 01- 01-2012] [Acceso gratuito] <http://arduino.cc/en/Main/ArduinoBoardUno> HeKilledMyWire. How to start using AvrStudio, C code and Arduino. [En lnea] Artculo digital [Fecha consulta: 01-01-2012] [Acceso gratuito] <http://hekilledmywire.wordpress.com/2010/12/04/22/> Arduino team. Referencia del Lenguaje [En lnea] Artculo digital [Fecha consulta: 01-01-2012] [Acceso gratuito] <http://arduino.cc/es/Reference/HomePage> tronixstuff, Arduino Tutorials [En lnea] Artculo digital [Fecha consulta: 01- 01-2012] [Acceso gratuito] <http://tronixstuff.wordpress.com/tutorials/> www.EarthshineElectronics.com, A Complete Beginners Guide to the Arduino [En lnea] Artculo digital [Fecha consulta: 10-02-2012] [Acceso gratuito] <http://www.earthshineelectronics.com/files/ASKManualRev5.pdf> Atmel Corporation, AVR Studio 5 Overview [En lnea] Artculo digital [Fecha consulta: 12-04-2012] [Acceso gratuito] <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=17212&source =avr_5_studio_overview> Atmel Corporation, ATmega328P [En lnea] Artculo digital [Fecha consulta: 10-01-2012] [Acceso gratuito] <http://www.atmel.com/dyn/products/product_card.asp?PN=ATMEGA328P #datasheets> cursomicros.com, Las Interrupciones en los AVR [En lnea] Artculo digital [Fecha consulta: 20-05-2012] [Acceso gratuito] <http://www.cursomicros.com/avr/interrupciones/interrupciones.html> EngBlaze, Tutorial: Using AVR Studio 5 with Arduino projects [En lnea] Artculo digital [Fecha consulta: 10-03-2012] [Acceso gratuito] <http://www.engblaze.com/tutorial-using-avr-studio-5-with-arduino- projects/> tty1.net, Optimisations of AVR programs using avr-gcc [En lnea] Artculo digital [Fecha consulta: 12-06-2012] [Acceso gratuito] <http://www.tty1.net/blog/2008-04-29-avr-gcc-optimisations_en.html> Practical Arduino, Projects [En lnea] Artculo digital [Fecha consulta: 01-08- 2012] [Acceso gratuito] < http://www.practicalarduino.com/projects/water- flow-gauge>
114 Teague Labs, DIY Arduino Water Meter [En lnea] Artculo digital [Fecha consulta: 15-11-2011] [Acceso gratuito] <http://labs.teague.com/?p=722> Referencias [1] Arduino team. Arduino homepage [En lnea] Pgina web del equipo de Arduino [Fecha consulta: 10-11-2011] [Acceso gratuito] <http://arduino.cc/> [2] Wiring programming framework, Homepage [En lnea] Artculo digital [Fecha consulta: 10-11-2011] [Acceso gratuito] <http://wiring.org.co/> [3] Processing programming language, Homepage [En lnea] Artculo digital [Fecha consulta: 10-11-2011] [Acceso gratuito] <http://www.processing.org/> [4] Definition of free cultural works, OSHW [En lnea] Artculo digital [Fecha consulta: 10-11-2011] [Acceso gratuito] <http://freedomdefined.org/OSHW > [5] Creative Commons, Attribution-ShareAlike 2.5 Generic [En lnea] Artculo digital [Fecha consulta: 10-11-2011] [Acceso gratuito] <http://creativecommons.org/licenses/by-sa/2.5/> [6] Parallax Inc, The BASIC Stamp [En lnea] Artculo digital [Fecha consulta: 10-11-2011] [Acceso gratuito] <http://www.parallax.com/tabid/295/Default.aspx> [7] BasicX, Home [En lnea] Artculo digital [Fecha consulta: 10-11-2011] [Acceso gratuito] <http://www.basicx.com/> [8] Phidgets, Products for USB Sensing and Control [En lnea] Artculo digital [Fecha consulta: 10-11-2011] [Acceso gratuito] <http://www.phidgets.com/ > [9] The Handy Board, About [En lnea] Artculo digital [Fecha consulta: 10-11- 2011] [Acceso gratuito] <http://handyboard.com/hb/about/> [10] Freeduino, Home [En lnea] Artculo digital [Fecha consulta: 10-11-2011] [Acceso gratuito] <http://www.freeduino.org/> [11] Arduino team. Arduino compatible hardware [En lnea] Artculo digital [Fecha consulta: 10-11-2011] [Acceso gratuito] <http://www.arduino.cc/playground/Main/SimilarBoards#goArdComp> [12] Arduino team. Hardware [En lnea] Artculo digital [Fecha consulta: 10-11- 2011] [Acceso gratuito] <http://www.arduino.cc/en/Main/hardware> [13] Digi, XBee-PRO 802.15.4 OEM RF Modules [En lnea] Artculo digital [Fecha consulta: 01-01-2012] [Acceso gratuito] <http://www.digi.com/products/wireless-wired-embedded-solutions/zigbee- rf-modules/point-multipoint-rfmodules/xbee-series1-module#overview> [14] Arduino team. Hardware for connecting to Arduino [En lnea] Artculo digital [Fecha consulta: 01-01-2012] [Acceso gratuito] <http://www.arduino.cc/playground/Main/SimilarBoards#goConn> [15] NonGNU, AVR Libc Home Page [En lnea] Artculo digital [Fecha consulta: 01-01-2012] [Acceso gratuito] <http://www.nongnu.org/avr-libc/>
115 [16] Arduino team. Libraries [En lnea] Artculo digital [Fecha consulta: 01-01- 2012] [Acceso gratuito] <http://arduino.cc/en/Reference/Libraries> [17] Arduino team. Writing a Library for Arduino [En lnea] Artculo digital [Fecha consulta: 01-01-2012] [Acceso gratuito] <http://arduino.cc/en/Hacking/LibraryTutorial> [18] Sparkfun electronics, Color LCD Shield [En lnea] Artculo digital [Fecha consulta: 15-08-2012] [Acceso gratuito] <http://www.sparkfun.com/products/9363> [19] Koolance Superior Liquid Cooling Solutions, Product manual v1.3 [En lnea] Artculo digital [Fecha consulta: 15-08-2012] [Acceso gratuito] < http://koolance.com/files/products/manuals/manual_ins- fm17,18_d130eng.pdf> [20] RC Electronic World, ARDUIMU V2 QUADROTOR [En lnea] Artculo digital [Fecha consulta: 01-01-2012] [Acceso gratuito] <http://www.rcelectronicworld.co.cc/p/quadrotor.html> [21] Android Arduino Handbag, Main [En lnea] Artculo digital [Fecha consulta: 01-01-2012] [Acceso gratuito] <http://www.labradoc.com/i/follower/p/android-arduino-handbag> [22] Arduino team. Getting Started w/ Arduino on Windows [En lnea] Artculo digital [Fecha consulta: 01-01-2012] [Acceso gratuito] <http://arduino.cc/en/Guide/Windows> [23] Arduino team. Placa Arduino monocapa [En lnea] Artculo digital [Fecha consulta: 01-01-2012] [Acceso gratuito] <http://arduino.cc/es/Main/ArduinoBoardSerialSingleSided3> [24] BricoGeek, Tienda [En lnea] Artculo digital [Fecha consulta: 01-01-2012] [Acceso gratuito] <http://www.bricogeek.com/shop/> [25] Electan, electrnica y robtica, Home [En lnea] Artculo digital [Fecha consulta: 01-01-2012] [Acceso gratuito] <http://www.electan.com> [26] Proyecto Arduino, Download the Arduino Software [En lnea] Artculo digital [Fecha consulta: 01-01-2012] [Acceso gratuito] <http://arduino.cc/en/Main/Software> [27] SourceForge, WinAVR [En lnea] Artculo digital [Fecha consulta: 01-01- 2012] [Acceso gratuito] <http://winavr.sourceforge.net/index.html> [28] Proyecto Arduino, Referencia del Lenguaje [En lnea] Artculo digital [Fecha consulta: 01-01-2012] [Acceso gratuito] <http://arduino.cc/es/Reference/HomePage> [29] Seccin de tutorials de TronixStuff, Ttulo [En lnea] Artculo digital [Fecha consulta: 01-01-2012] [Acceso gratuito] <http://tronixstuff.wordpress.com/tutorials/> [30] Manual del Starter Kit de Earthshine Electronics, Arduino Starter Kit Manual [En lnea] Artculo digital [Fecha consulta: 01-01-2012] [Acceso gratuito] <http://www.earthshineelectronics.com/files/ASKManualRev5.pdf>
116 [31] Arduino playground wiki, Libraries for Arduino [En lnea] Artculo digital [Fecha consulta: 01-01-2012] [Acceso gratuito] <http://arduino.cc/playground/Main/LibraryList> [32] Pgina web de Koolance, Flow meters [En lnea] Artculo digital [Fecha consulta: 01-12-2011] [Acceso gratuito] <http://www.koolance.com/water- cooling/product_info.php?product_id=740> [33] Tienda Tecniolid, CAUDAL LAVAVAJILLAS - Caudalimetro [En lnea] Artculo digital [Fecha consulta: 01-12-2011] [Acceso gratuito] <http://www.tiendatecniolid.com/epages/61636078.sf/es_ES/undefined/es_E S/?ViewObjectID=5056775> [34] eBay Stores, HELLFIRE TOYZ LLC [En lnea] Artculo digital [Fecha consulta: 01-12-2011] [Acceso gratuito] <http://stores.ebay.com/HELLFIRE- TOYZ-LLC> [35] Sparkfun electronics, Nokia LCD Display Driver [En lnea] Artculo digital [Fecha consulta: 01-01-2012] [Acceso gratuito] <https://docs.google.com/viewer?url=http://www.sparkfun.com/tutorial/Noki a%25206100%2520LCD%2520Display%2520Driver.pdf> [36] Richard Kaufmans blog, How to fix it: Backlight on SparkFuns Color LCD Shield not working [En lnea] Artculo digital [Fecha consulta: 01-01-2012] [Acceso gratuito] <http://richardkaufman.org/blog/how-to-fix-it-backlight- on-sparkfuns-color-lcd-shield-not-working> [37] Atmel, Main [En lnea] Artculo digital [Fecha consulta: 01-01-2012] [Acceso gratuito] <http://www.atmel.com/> [38] AVR freaks forum, GCC and the ROGMEM Attributes [En lnea] Artculo digital [Fecha consulta: 20-07-2012] [Acceso gratuito] <http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t= 38003>