Sei sulla pagina 1di 116

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);

delay(1000);
digitalWrite(13, LOW);

delay(1000);
}
void setup() {
pinMode(13, OUTPUT);
Serial.begin(9600);
}

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 */
}

rutina_servicio_interrupcio(){
contadorPulsos++;
}

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)

DIVISOR NUM_CUENTAS
1 7999999
8 999999
64 124999
256 31249
1024 7811,5

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)

DIVISOR NUM_CUENTAS
1 7999999
8 999999
64 124999
256 31249
1024 7811,5

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

Program: 7380 bytes (22.5% Full)
(.text + .data + .bootloader)

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

Program: 10390 bytes (31.7% Full)
(.text + .data + .bootloader)

Data: 1269 bytes (62.0% Full)
(.data + .bss + .noinit)


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

85

Ilustracin 58: Modificacin del fichero ColorLCDShield.cpp. 2da parte
En el fichero ColorLCDShield.h se ha definido el nuevo tipo de fuente:
const unsigned char FONT8x8[97][8] = {
{0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00}, // columns, rows,
num_bytes_per_char
{0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00}, // columns, rows,
num_bytes_per_char
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space 0x20
{0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00}, // !
{0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00}, // "
{0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00}, // #
{0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00}, // $
{0x00,0x63,0x66,0x0C,0x18,0x33,0x63,0x00}, // %
{0x1C,0x36,0x1C,0x3B,0x6E,0x66,0x3B,0x00}, // &
{0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00}, // '
{0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00}, // (
{0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00}, // )
{0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00}, // *
{0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00}, // +
{0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30}, // ,
{0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00}, // -
{0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00}, // .
{0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00}, // / (forward slash)
{0x3E,0x63,0x63,0x6B,0x63,0x63,0x3E,0x00}, // 0 0x30
{0x18,0x38,0x58,0x18,0x18,0x18,0x7E,0x00}, // 1
{0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00}, // 2
{0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00}, // 3
{0x0E,0x1E,0x36,0x66,0x7F,0x06,0x0F,0x00}, // 4
{0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00}, // 5
{0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00}, // 6
{0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00}, // 7
{0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00}, // 8
{0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00}, // 9
{0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00}, // :
{0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30}, // ;
{0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00}, // <
{0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00}, // =
{0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00}, // >
{0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00}, // ?
{0x3E,0x63,0x6F,0x69,0x6F,0x60,0x3E,0x00}, // @ 0x40
{0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00}, // A
{0x7E,0x33,0x33,0x3E,0x33,0x33,0x7E,0x00}, // B
{0x1E,0x33,0x60,0x60,0x60,0x33,0x1E,0x00}, // C
{0x7C,0x36,0x33,0x33,0x33,0x36,0x7C,0x00}, // D

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 las interrupciones
*/
const byte caudalInt = 0; // 0 = pin 2; 1 = pin 3
const byte caudalPin = 2;
const byte caudalGNDPin = 6;

/*
* 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;
}
}

/*
* Pantalla principal a mostrar
*/
void pantalla_principal()
{
lcd.setStr("Tiempo total", 3, 3, BLACK, WHITE);
lcd.setStr(" segundos", 19, 3, BLACK, WHITE);
itoa(contadorSegundos,lcdStr,10);
lcd.setStr(lcdStr, 19, 11, BLACK, WHITE);

lcd.setStr("Consumo actual", 35, 3, BLACK, WHITE);
lcd.setStr(" l x min", 48, 3, BLACK, WHITE);
dtostrf(litrosMinuto, 4, 2, lcdStr);
lcd.setStr(lcdStr, 48, 11, BLACK, WHITE);

lcd.setStr("Litros totales ", 64, 3, BLACK, WHITE);
lcd.setStr(" ", 80, 3, BLACK, WHITE);
dtostrf(litrosTotales, 6, 2, lcdStr);
lcd.setStr(lcdStr, 80, 19, BLACK, WHITE);

lcd.setStr("Cont.1 Cont.2 ", 96, 3, BLACK, WHITE);
lcd.setStr(" ", 112, 3, BLACK, WHITE);
dtostrf(litrosParcial_1, 4, 2, lcdStr);
lcd.setStr(lcdStr, 112, 3, BLACK, WHITE);
dtostrf(litrosParcial_2, 4, 2, lcdStr);
lcd.setStr(lcdStr, 112, 75, BLACK, WHITE);
}

/*
* Pantalla contadores parciales 1
*/
void pantalla_parcial_1()
{
lcd.setStr("Tiempo parcial 1", 0, 3, BLACK, WHITE);
lcd.setStr(" segundos ", 16, 3, BLACK, WHITE);
itoa(contadorSegundosParcial_1,lcdStr,10);
lcd.setStr(lcdStr, 16, 11, BLACK, WHITE);

lcd.setStr("Consumo actual ", 32, 3, BLACK, WHITE);
lcd.setStr(" l x min", 48, 3, BLACK, WHITE);
dtostrf(litrosMinuto, 4, 2, lcdStr);
lcd.setStr(lcdStr, 48, 11, BLACK, WHITE);

lcd.setStr("Litros parcial 1", 64, 3, BLACK, WHITE);
lcd.setStr(" ", 80, 3, BLACK, WHITE);
dtostrf(litrosParcial_1, 4, 2, lcdStr);
lcd.setStr(lcdStr, 80, 19, BLACK, WHITE);

lcd.setStr(" Totales ", 96, 3, BLACK, WHITE);
lcd.setStr(" ", 112, 3, BLACK, WHITE);
dtostrf(litrosTotales, 6, 2, lcdStr);
lcd.setStr(lcdStr, 112, 59, BLACK, WHITE);
}

/*

91
* Pantalla contadores parciales 2
*/
void pantalla_parcial_2()
{
lcd.setStr("Tiempo parcial 2", 0, 3, BLACK, WHITE);
lcd.setStr(" segundos ", 16, 3, BLACK, WHITE);
itoa(contadorSegundosParcial_2,lcdStr,10);
lcd.setStr(lcdStr, 16, 11, BLACK, WHITE);

lcd.setStr("Consumo actual ", 32, 3, BLACK, WHITE);
lcd.setStr(" l x min", 48, 3, BLACK, WHITE);
dtostrf(litrosMinuto, 4, 2, lcdStr);
lcd.setStr(lcdStr, 48, 11, BLACK, WHITE);

lcd.setStr("Litros parcial 2", 64, 3, BLACK, WHITE);
lcd.setStr(" ", 80, 3, BLACK, WHITE);
dtostrf(litrosParcial_2, 4, 2, lcdStr);
lcd.setStr(lcdStr, 80, 19, BLACK, WHITE);

lcd.setStr(" Totales ", 96, 3, BLACK, WHITE);
lcd.setStr(" ", 112, 3, BLACK, WHITE);
dtostrf(litrosTotales, 6, 2, lcdStr);
lcd.setStr(lcdStr, 112, 59, BLACK, WHITE);
}

/*
* 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)

self.value = initval

box = wx.StaticBox(self, -1, label)
sizer = wx.StaticBoxSizer(box, wx.VERTICAL)

self.radio_auto = wx.RadioButton(self, -1,
label="Auto", style=wx.RB_GROUP)
self.radio_manual = wx.RadioButton(self, -1,
label="Manual")
self.manual_text = wx.TextCtrl(self, -1,
size=(35,-1),
value=str(initval),

93
style=wx.TE_PROCESS_ENTER)

self.Bind(wx.EVT_UPDATE_UI, self.on_update_manual_text,
self.manual_text)
self.Bind(wx.EVT_TEXT_ENTER, self.on_text_enter, self.manual_text)

manual_box = wx.BoxSizer(wx.HORIZONTAL)
manual_box.Add(self.radio_manual, flag=wx.ALIGN_CENTER_VERTICAL)
manual_box.Add(self.manual_text, flag=wx.ALIGN_CENTER_VERTICAL)

sizer.Add(self.radio_auto, 0, wx.ALL, 10)
sizer.Add(manual_box, 0, wx.ALL, 10)

self.SetSizer(sizer)
sizer.Fit(self)

def on_update_manual_text(self, event):
self.manual_text.Enable(self.radio_manual.GetValue())

def on_text_enter(self, event):
self.value = self.manual_text.GetValue()

def is_auto(self):
return self.radio_auto.GetValue()

def manual_value(self):
return self.value


class GraphFrame(wx.Frame):
""" The main frame of the application
"""
title = 'Demo: dynamic matplotlib graph'

def __init__(self):
wx.Frame.__init__(self, None, -1, self.title)

self.dataget = DataGet()
self.data = [self.dataget.next()]
self.paused = False

self.create_menu()
self.create_status_bar()
self.create_main_panel()

self.redraw_timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.on_redraw_timer, self.redraw_timer)
self.redraw_timer.Start(100)

def create_menu(self):
self.menubar = wx.MenuBar()

menu_file = wx.Menu()
m_expt = menu_file.Append(-1, "&Save plot\tCtrl-S", "Save plot to
file")
self.Bind(wx.EVT_MENU, self.on_save_plot, m_expt)
menu_file.AppendSeparator()

94
m_exit = menu_file.Append(-1, "E&xit\tCtrl-X", "Exit")
self.Bind(wx.EVT_MENU, self.on_exit, m_exit)

self.menubar.Append(menu_file, "&File")
self.SetMenuBar(self.menubar)

def create_main_panel(self):
self.panel = wx.Panel(self)

self.init_plot()
self.canvas = FigCanvas(self.panel, -1, self.fig)

self.xmin_control = BoundControlBox(self.panel, -1, "X min", 0)
self.xmax_control = BoundControlBox(self.panel, -1, "X max", 50)
self.ymin_control = BoundControlBox(self.panel, -1, "Y min", 0)
self.ymax_control = BoundControlBox(self.panel, -1, "Y max", 100)

self.pause_button = wx.Button(self.panel, -1, "Pause")
self.Bind(wx.EVT_BUTTON, self.on_pause_button, self.pause_button)
self.Bind(wx.EVT_UPDATE_UI, self.on_update_pause_button,
self.pause_button)

self.cb_grid = wx.CheckBox(self.panel, -1,
"Show Grid",
style=wx.ALIGN_RIGHT)
self.Bind(wx.EVT_CHECKBOX, self.on_cb_grid, self.cb_grid)
self.cb_grid.SetValue(True)

self.cb_xlab = wx.CheckBox(self.panel, -1,
"Show X labels",
style=wx.ALIGN_RIGHT)
self.Bind(wx.EVT_CHECKBOX, self.on_cb_xlab, self.cb_xlab)
self.cb_xlab.SetValue(True)

self.hbox1 = wx.BoxSizer(wx.HORIZONTAL)
self.hbox1.Add(self.pause_button, border=5, flag=wx.ALL |
wx.ALIGN_CENTER_VERTICAL)
self.hbox1.AddSpacer(20)
self.hbox1.Add(self.cb_grid, border=5, flag=wx.ALL |
wx.ALIGN_CENTER_VERTICAL)
self.hbox1.AddSpacer(10)
self.hbox1.Add(self.cb_xlab, border=5, flag=wx.ALL |
wx.ALIGN_CENTER_VERTICAL)

self.hbox2 = wx.BoxSizer(wx.HORIZONTAL)
self.hbox2.Add(self.xmin_control, border=5, flag=wx.ALL)
self.hbox2.Add(self.xmax_control, border=5, flag=wx.ALL)
self.hbox2.AddSpacer(24)
self.hbox2.Add(self.ymin_control, border=5, flag=wx.ALL)
self.hbox2.Add(self.ymax_control, border=5, flag=wx.ALL)

self.vbox = wx.BoxSizer(wx.VERTICAL)
self.vbox.Add(self.canvas, 1, flag=wx.LEFT | wx.TOP | wx.GROW)
self.vbox.Add(self.hbox1, 0, flag=wx.ALIGN_LEFT | wx.TOP)
self.vbox.Add(self.hbox2, 0, flag=wx.ALIGN_LEFT | wx.TOP)

self.panel.SetSizer(self.vbox)

95
self.vbox.Fit(self)

def create_status_bar(self):
self.statusbar = self.CreateStatusBar()

def init_plot(self):
self.dpi = 100
self.fig = Figure((3.0, 3.0), dpi=self.dpi)

self.axes = self.fig.add_subplot(111)
self.axes.set_axis_bgcolor('black')
self.axes.set_title('Liters per minute', size=12)

pylab.setp(self.axes.get_xticklabels(), fontsize=8)
pylab.setp(self.axes.get_yticklabels(), fontsize=8)

# 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())

if self.xmin_control.is_auto():
xmin = xmax - 50
else:
xmin = int(self.xmin_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

96
else:
ymax = int(self.ymax_control.manual_value())

self.axes.set_xbound(lower=xmin, upper=xmax)
self.axes.set_ybound(lower=ymin, upper=ymax)

# 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())

self.plot_data.set_xdata(np.arange(len(self.data)))
self.plot_data.set_ydata(np.array(self.data))

self.canvas.draw()

def on_pause_button(self, event):
self.paused = not self.paused

def on_update_pause_button(self, event):
label = "Resume" if self.paused else "Pause"
self.pause_button.SetLabel(label)

def on_cb_grid(self, event):
self.draw_plot()

def on_cb_xlab(self, event):
self.draw_plot()

def on_save_plot(self, event):
file_choices = "PNG (*.png)|*.png"

dlg = wx.FileDialog(
self,
message="Save plot as...",
defaultDir=os.getcwd(),
defaultFile="plot.png",
wildcard=file_choices,
style=wx.SAVE)

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())

self.draw_plot()

def on_exit(self, event):
self.Destroy()

def flash_status_message(self, msg, flash_len_ms=1500):
self.statusbar.SetStatusText(msg)
self.timeroff = wx.Timer(self)
self.Bind(
wx.EVT_TIMER,
self.on_flash_status_off,
self.timeroff)
self.timeroff.Start(flash_len_ms, oneShot=True)

def on_flash_status_off(self, event):
self.statusbar.SetStatusText('')


if __name__ == '__main__':
app = wx.PySimpleApp()
app.frame = GraphFrame()
app.frame.Show()
app.MainLoop()

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

:Execute
avrdude -F -V -c arduino -p %micro% -P %port% -b 115200 -D -U
flash:w:"%file%"

: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
*/

#define SERIAL_BAUDRATE (9600U)
#define F_CPU (16000000UL)

/* 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 */

#include "Arduino_SERIAL_Api.h"

#define BAUD_RATE_REGISTER ((F_CPU / (SERIAL_BAUDRATE * 16ul)) - 1u) /*
Datasheet. Tabla 20-1. Equations for Calculating Baud Rate Register Setting
*/

/* 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>

#define SERIAL_BAUDRATE (9600U)
#define F_CPU (16000000UL)

/* 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 */

#include "Arduino_SERIAL_INTRx_Api.h"

#define BAUD_RATE_REGISTER ((F_CPU / (SERIAL_BAUDRATE * 16ul)) - 1u) /*
Datasheet. Tabla 20-1. Equations for Calculating Baud Rate Register Setting
*/

/* 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 prototipos
*/
void inicializacion(void);
void lecturaPulsadorLCD(void);
void task_1000ms(void);
void pantalla_principal(void);
void pantalla_parcial_1(void);
void pantalla_parcial_2(void);

/*
* 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:

109
break;
}
}

/*
* Pantalla principal a mostrar
*/
void pantalla_principal(void)
{
lcd.setStr("Tiempo total", 3, 3, BLACK, WHITE);
lcd.setStr(" segundos", 19, 3, BLACK, WHITE);
itoa(contadorSegundos,lcdStr,10);
lcd.setStr(lcdStr, 19, 11, BLACK, WHITE);

lcd.setStr("Consumo actual", 35, 3, BLACK, WHITE);
lcd.setStr(" l x min", 48, 3, BLACK, WHITE);
dtostrf(litrosMinuto, 4, 2, lcdStr);
lcd.setStr(lcdStr, 48, 11, BLACK, WHITE);

lcd.setStr("Litros totales ", 64, 3, BLACK, WHITE);
lcd.setStr(" ", 80, 3, BLACK, WHITE);
dtostrf(litrosTotales, 6, 2, lcdStr);
lcd.setStr(lcdStr, 80, 19, BLACK, WHITE);

lcd.setStr("Cont.1 Cont.2 ", 96, 3, BLACK, WHITE);
lcd.setStr(" ", 112, 3, BLACK, WHITE);
dtostrf(litrosParcial_1, 4, 2, lcdStr);
lcd.setStr(lcdStr, 112, 3, BLACK, WHITE);
dtostrf(litrosParcial_2, 4, 2, lcdStr);
lcd.setStr(lcdStr, 112, 75, BLACK, WHITE);
}

/*
* Pantalla contadores parciales 1
*/
void pantalla_parcial_1(void)
{
lcd.setStr("Tiempo parcial 1", 0, 3, BLACK, WHITE);
lcd.setStr(" segundos ", 16, 3, BLACK, WHITE);
itoa(contadorSegundosParcial_1,lcdStr,10);
lcd.setStr(lcdStr, 16, 11, BLACK, WHITE);

lcd.setStr("Consumo actual ", 32, 3, BLACK, WHITE);
lcd.setStr(" l x min", 48, 3, BLACK, WHITE);
dtostrf(litrosMinuto, 4, 2, lcdStr);
lcd.setStr(lcdStr, 48, 11, BLACK, WHITE);

lcd.setStr("Litros parcial 1", 64, 3, BLACK, WHITE);
lcd.setStr(" ", 80, 3, BLACK, WHITE);
dtostrf(litrosParcial_1, 4, 2, lcdStr);
lcd.setStr(lcdStr, 80, 19, BLACK, WHITE);

lcd.setStr(" Totales ", 96, 3, BLACK, WHITE);
lcd.setStr(" ", 112, 3, BLACK, WHITE);
dtostrf(litrosTotales, 6, 2, lcdStr);
lcd.setStr(lcdStr, 112, 59, BLACK, WHITE);
}

/*
* Pantalla contadores parciales 2
*/
void pantalla_parcial_2(void)
{
lcd.setStr("Tiempo parcial 2", 0, 3, BLACK, WHITE);
lcd.setStr(" segundos ", 16, 3, BLACK, WHITE);
itoa(contadorSegundosParcial_2,lcdStr,10);
lcd.setStr(lcdStr, 16, 11, BLACK, WHITE);

110

lcd.setStr("Consumo actual ", 32, 3, BLACK, WHITE);
lcd.setStr(" l x min", 48, 3, BLACK, WHITE);
dtostrf(litrosMinuto, 4, 2, lcdStr);
lcd.setStr(lcdStr, 48, 11, BLACK, WHITE);

lcd.setStr("Litros parcial 2", 64, 3, BLACK, WHITE);
lcd.setStr(" ", 80, 3, BLACK, WHITE);
dtostrf(litrosParcial_2, 4, 2, lcdStr);
lcd.setStr(lcdStr, 80, 19, BLACK, WHITE);

lcd.setStr(" Totales ", 96, 3, BLACK, WHITE);
lcd.setStr(" ", 112, 3, BLACK, WHITE);
dtostrf(litrosTotales, 6, 2, lcdStr);
lcd.setStr(lcdStr, 112, 59, BLACK, WHITE);
}

/*
* 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>

Potrebbero piacerti anche