Está en la página 1de 108

Arduino Modelling Tool

Universidad Politécnica de Madrid


Escuela Técnica Supieror de Ingenierı́a de Sistemas Informáticos

Autor: Jaime Martı́n Gutiérrez

Directora: Jenifer Pérez Benedı́

2020 - 2021
Dedicatoria

A mis dos abuelas y a mis dos abuelos.

1
Agradecimientos

Quiero agradecer a mi tutora Jenifer, que, a pesar de estar ocupada a más no poder, siempre ha
sacado tiempo para ayudarme con este proyecto. A mi padre, mi madre y a mi hermano, por el
apoyo que me han dado durante toda mi estancia en la Universidad.

2
Resumen

Internet of Things (IoT) o Internet de las Cosas representa para muchos el futuro tecnológico
a seguir por nuestra sociedad. Este concepto busca relacionar los objetos cotidianos o entidades
fı́sicas con la red digital o Internet. Esto permite construir un flujo constante de intercambio
de información entre sensores fı́sicos y la red, y, en función de las medidas recibidas, envı́ar una
serie de acciones que han de ser realizadas por unos actuadores.
Una buena forma de potenciar el desarrollo de IoT de cara al futuro, es promover su u-
so entre los estudiantes, despertando su interés para aprender a usar estas tecnologı́as. Para
este propósito, Arduino es una herramienta perfecta. Es un dispositivo IoT cuyos sensores y
actuadores son totalmente adaptables para construir sistemas de diversa complejidad.
Aunque Arduino es un sistema intuitivo, destinado para usuarios de todos los niveles, en
muchas ocasiones, puede existir una gran barrera de entrada para aquellos usuarios que no
posean conocimientos de electrónica o programación, necesarios para construir cualquier sistema
y la lógica que trata la información.
Para eliminar esa barrera, se ha desarrollado Arduino Modelling Tool, facilitando a los nuevos
usuarios la posibilidad de crear sus propios sistemas IoT, despertando ası́ interés en jóvenes
estudiantes e ingenieros en tecnologı́as IoT. Esto garantizará la continuidad en los avances para
esta corriente tecnológica, cuyos beneficios ya son visibles hoy dı́a en lo que se conoce como smart
cities o en dispositivos que utilizamos de forma cotidiana como los wearable devices.
Arduino Modelling Tool es una herramienta diseñada para construir sistemas Arduino a través
de una interfaz sencilla e intuitiva, compuesta por una barra de herramientas desde la que se
arrastran y sueltan los distintos elementos en un tapiz, formando ası́ un modelo que representa
Arduino y sus elementos.
Para construir esta herramienta, se ha seguido un desarrollo basado en Model Driven Devel-
opment (MDD) y concretamente un Modelado Especı́fico de Dominio, que permite al usuario
inexperto crear sus propios sistemas Arduino sin tener que preocuparse de errores en el código.
Además, gracias a su flexibilidad, los usuarios más avanzados podrán construir sistemas más
complejos de forma más rápida o crear sus prototipos antes de diseñarlos fı́sicamente. Esto se
consigue a través de la generación automática de código, integrado en la herramienta Arduino
Modelling Tool, capaz de generar el código que da soporte al modelo creado por el usuario de
forma instantánea y libre de errores.
Arduino Modelling Tool está basada en un Modelo Especı́fico de Dominio y su Lenguaje, el
cual es fácilmente ampliable y personalizable según las necesidades del dominio IoT. Gracias a
esto, la herramienta posee un gran potencial para expandirse a otros dispositivos, ya sean de la
familia Arduino o simplemente se encuentren dentro del ámbito IoT.
Por lo tanto, Arduino Modelling Tool se presenta como una solución que facilite la expansión
de las tecnologı́as IoT, acercándolas a usuarios poco experimentado o facilitando el prototipado
y diseño de sistemas complejos a usuarios expertos.

3
Abstract

Internet of Things (IoT) means the technological future to be followed by our society. This
concept tries to link everyday objects or physical entities with the digital network or Internet.
IoT establishes a constant information flow between sensors and actuators through the com-
munication network. Sensors collect measures, i.e. data, which are processed by controllers;
controllers determine a response, depending on the received measures and ask actuators the
response’s execution.
To encourage IoT development for the future, it is important to promote its use among
students, creating interest to learn these technologies. Arduino is a perfect candidate to deal
with this purpose. Arduino is an IoT device which allows to build different systems varying their
complexity due to the wide amount of compatible sensors and actuators it provides in order to
make multiple configurations.
However, although Arduino is an easy learning tool in general, sometimes, user without
electronics or programming knowledge, have problems to build a complete system with its pro-
gramming logic.
Arduino Modelling Tool has been developed with the objective of eliminating this barrier,
making the creation of IoT systems easier for new users. As a result, it may increase the interest
in students or future engineers in IoT technologies. This will ensure further progress for this
technological approach, which benefits are already evidenced in areas such as smart cities or IoT
use every day, such as wearables devices.
Arduino Modelling Tool has been designed to build Arduino systems through a simple and
intuitive graphical user interface that allows modelling Arduino systems by drawing and dropping
the Arduino components from a toolbar.
To build this tool, a Model Driven Development (MDD) approach has been followed, and
specifically using domain models. The model abstraction of MDD allows inexperienced users to
create their own Arduino systems without being worry about coding bugs. In addition, thanks
to its flexibility, advanced users are able to build and prototyping their complex systems more
efficiently. These advantages are achieved thanks to the automatic code generation templates,
integrated within the Arduino Modelling Tool, witch generates the code from the user model
created by the user, instantly and free of bugs.
Arduino Modelling Tool is based on a Domain Specific Model and its corresponding Language,
which are easily extensible and customisable according to the IoT domain needs. As a result,
this tool has a great potential to be extended to other devices and services, whether they belong
to the Arduino family or simply fall within the IoT scope.
As a conclusion, Arduino Modelling Tool is a solution to expend the IoT technologies, bringing
them closer to inexperienced users or facilitating the prototyping and design of complex systems
for expert users.

4
Índice

Listado de Figuras 6

1 Introducción 10
1.1 Motivación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.2 Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3 Estructura PFG . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

2 Conceptos previos 12
2.1 Internet of Things (IoT) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.2 Arduino . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.2.1 ¿Qué es Arduino? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.2.2 Arduino UNO: Componentes básicos . . . . . . . . . . . . . . . . . . . . . 13
2.2.3 Arduino IDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.2.4 Construyendo un primer proyecto . . . . . . . . . . . . . . . . . . . . . . . 19
2.3 MDD y DSL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.3.1 Modelos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.3.2 Model Driven Development (MDD) . . . . . . . . . . . . . . . . . . . . . . 23
2.3.3 Lenguaje Especı́fico de Dominio (Domain-Specific Languages DSL) . . . . 24

3 Lenguaje Especı́fico de Dominio para Arduino 32


3.1 Definición del modelo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
3.1.1 DSL-Editor y Toolbox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
3.2 Notación Gráfica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
3.3 Trazabilidad Modelo - Notación Gráfica . . . . . . . . . . . . . . . . . . . . . . . 53
3.3.1 Relaciones Embedding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

4 Arduino Modelling Tool 58


4.1 Modelado con Arduino Modelling Tool . . . . . . . . . . . . . . . . . . . . . . . . 58
4.2 Patrón de Generación automática de código para Arduino . . . . . . . . . . . . . 69
4.3 Desplegando código Arduino con Arduino Modelling Tool . . . . . . . . . . . . . 79

5 Prueba y validación del lenguaje 83


5.1 Sketch: Blink . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
5.2 Sketch: Imprimir Matriz Temperaturas . . . . . . . . . . . . . . . . . . . . . . . . 87
5.3 Sketch: Sensor de Proximidad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
5.4 Sketch: Mostrar nivel de luminosidad en un Display LCD . . . . . . . . . . . . . 96

6 Conclusiones 104
6.1 Conclusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
6.2 Trabajos futuros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
6.3 Impactos sociales y ambientales . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105

Bibliografı́a 106

5
Listado de Figuras

2.1 Arduino Starter Kit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13


2.2 Arduino UNO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.3 Protoboard Breadboard 400 points . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.4 Sensor de temperatura TMP36 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.5 Sensor de inclinación BL-XT660 . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.6 Sensor de iluminación HW5P-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.7 Pulsador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.8 Sensor Infrarrojos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.9 Potenciómetro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.10 Diodo LED Rojo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.11 Motor 6V TFK-280SA-22125 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.12 Buzzer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.13 LCD Alfanumérico JHD659 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.14 Interfaz Arduino IDE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.15 Interfaz Arduino IDE: Toolbar . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.16 Interfaz Arduino IDE: Text Editor . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.17 Esquema: Entrada a Salida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.18 Interfaz Arduino IDE: Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.19 Sketch Blink: Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.20 Sketch Blink : Montaje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.21 Sketch Blink : LED encendido . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.22 Visual Studio: Crear proyecto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.23 Visual Studio: Vista General . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.24 Visual Studio: Diagrama de Clases . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.25 Visual Studio: DSL Explorer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.26 DSL-Editor: Add New Toolbox Tab . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.27 DSL-Editor: Add Tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.28 DSL-Editor: Element Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.29 Visual Studio: Toolbox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.30 Componentes DSL: Domain Class . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.31 Componentes DSL: Embedding Relationship . . . . . . . . . . . . . . . . . . . . . 29
2.32 Componentes DSL: Reference Relationship . . . . . . . . . . . . . . . . . . . . . . 29
2.33 Componentes DSL: Image and Geometry Shape . . . . . . . . . . . . . . . . . . . 30
2.34 Componentes DSL: Connector . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.35 Image Shape: Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.36 Geometry Shape: Appearance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.37 Geometry Shape: Add Decorator . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

3.1 Elementos del lenguaje: ArduinoDevice . . . . . . . . . . . . . . . . . . . . . . . 33


3.2 Elementos del lenguaje: Inputs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.3 Elementos del lenguaje: ManualInput . . . . . . . . . . . . . . . . . . . . . . . . 34
3.4 Elementos del lenguaje: Sensor . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.5 Relaciones del lenguaje: InputHasMeasure . . . . . . . . . . . . . . . . . . . . . . 36
3.6 Relaciones del lenguaje: MeasureHasValue . . . . . . . . . . . . . . . . . . . . . . 36
3.7 Domain Enumeration: DataType and Values . . . . . . . . . . . . . . . . . . . . . 37
3.8 Elementos del lenguaje: Outputs . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.9 Elementos del lenguaje: EnvironmentalOutputs . . . . . . . . . . . . . . . . . . . 38
3.10 Elementos del lenguaje: Terminal . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.11 Elementos del lenguaje: Controller . . . . . . . . . . . . . . . . . . . . . . . . . . 39
3.12 Elementos del lenguaje: Sentence . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
3.13 Elementos del lenguaje: Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

6
3.14 Elementos del lenguaje: Condition . . . . . . . . . . . . . . . . . . . . . . . . . . 42
3.15 Domain Enumeration: Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
3.16 Relaciones del lenguaje: LoopHasSentence . . . . . . . . . . . . . . . . . . . . . . 43
3.17 Elementos del lenguaje: SimpleSentence . . . . . . . . . . . . . . . . . . . . . . . 44
3.18 Elementos del lenguaje: ManualSentence . . . . . . . . . . . . . . . . . . . . . . . 44
3.19 Elementos del lenguaje: IOSentence . . . . . . . . . . . . . . . . . . . . . . . . . 45
3.20 Elementos del lenguaje: Delay . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
3.21 DSL-Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
3.22 DSL-Editor : Compartimentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
3.23 Toolbox Icon: If . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3.24 Toolbox Icon: While . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3.25 Toolbox Icon: For . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3.26 Toolbox Icon: Condition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3.27 User Toolbox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
3.28 Main: ArduinoDevice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
3.29 Main: Measure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
3.30 Main: Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
3.31 Main: Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
3.32 Inputs: Switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
3.33 Inputs: Potentiometer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
3.34 Inputs: LightSensor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
3.35 Inputs: TemperatureSensor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
3.36 Inputs: LightSensor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
3.37 Inputs: IRSensor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
3.38 Outputs: LED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.39 Outputs: DCMotor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.40 Outputs: Terminal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.41 Outputs: Display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.42 Logical: For . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.43 Logical: While . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.44 Logical: If . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.45 Logical: Condition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.46 Logical: IOSentence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
3.47 Logical: ManualSentence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
3.48 Logical : Diagrama lógico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
3.49 Connectors: Controller-Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
3.50 Connectors: Controller-Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
3.51 Outputs - Image Shape . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
3.52 Shape Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
3.53 Shape examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
3.54 Connector Mapping: ArduinoDeviceHasOutputs . . . . . . . . . . . . . . . . . . . 55
3.55 CnctOutputs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
3.56 Parent Element Path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
3.57 Custom Parent Element Path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

4.1 Manual de Usuario: Tapiz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58


4.2 Manual de Usuario: Crear elemento . . . . . . . . . . . . . . . . . . . . . . . . . 59
4.3 Manual de Usuario: acceder a Propiedades . . . . . . . . . . . . . . . . . . . . . . 59
4.4 Manual de Usuario: modificar Propiedades . . . . . . . . . . . . . . . . . . . . . 59
4.5 Manual de Usuario: Crear Inputs . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
4.6 Manual de Usuario: Editar Inputs . . . . . . . . . . . . . . . . . . . . . . . . . . 60
4.7 Manual de Usuario: Crear Measure . . . . . . . . . . . . . . . . . . . . . . . . . . 61
4.8 Manual de Usuario: Editar Measure . . . . . . . . . . . . . . . . . . . . . . . . . 61
4.9 Manual de Usuario: Editar Value . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
4.10 Manual de Usuario: Editar Display . . . . . . . . . . . . . . . . . . . . . . . . . . 62

7
4.11 Manual de Usuario: Crear Controller . . . . . . . . . . . . . . . . . . . . . . . . . 63
4.12 Manual de Usuario: Redimensionar Controller . . . . . . . . . . . . . . . . . . . 63
4.13 Manual de Usuario: crear ManualSentence . . . . . . . . . . . . . . . . . . . . . . 64
4.14 Manual de Usuario: CnctSentence . . . . . . . . . . . . . . . . . . . . . . . . . . 64
4.15 Manual de Usuario: Ordenar Sentencias . . . . . . . . . . . . . . . . . . . . . . . 64
4.16 Manual de Usuario: Controller-Input/Output . . . . . . . . . . . . . . . . . . . . 65
4.17 Manual de Usuario: IOSentence . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
4.18 Manual de Usuario: Crear Bucles . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
4.19 Manual de Usuario: Propiedades for . . . . . . . . . . . . . . . . . . . . . . . . . 66
4.20 Manual de Usuario: Crear Condition . . . . . . . . . . . . . . . . . . . . . . . . . 67
4.21 Manual de Usuario: Propiedades Condition . . . . . . . . . . . . . . . . . . . . . 67
4.22 Manual de Usuario: Ejemplo while . . . . . . . . . . . . . . . . . . . . . . . . . . 68
4.23 Flujo de Trabajo: New Item... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
4.24 Flujo de Trabajo: Creando fichero Arduino . . . . . . . . . . . . . . . . . . . . . 80
4.25 Flujo de Trabajo: Fichero Arduino en Solution Explorer . . . . . . . . . . . . . . 80
4.26 Flujo de Trabajo: Ejemplo Modelo . . . . . . . . . . . . . . . . . . . . . . . . . . 81
4.27 Flujo de Trabajo: Plantilla1.ino . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
4.28 Flujo de Trabajo: Copiar Código en Arduino IDE . . . . . . . . . . . . . . . . . . 82

5.1 Blink : Crear Salidas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83


5.2 Blink : Propiedades LED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
5.3 Blink : Crear sentencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
5.4 Blink : Ordenar sentencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
5.5 Blink : Completar sentencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
5.6 Blink : Circuito . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
5.7 Sketch Matriz Temperaturas: Crear entradas . . . . . . . . . . . . . . . . . . . . 87
5.8 Sketch Matriz Temperaturas: Crear salidas . . . . . . . . . . . . . . . . . . . . . 87
5.9 Sketch Matriz Temperaturas: Propiedades bucle y condición . . . . . . . . . . . . 88
5.10 Sketch Matriz Temperaturas: Controlador . . . . . . . . . . . . . . . . . . . . . . 88
5.11 Sketch Matriz Temperaturas: Vista General . . . . . . . . . . . . . . . . . . . . . 89
5.12 Sketch Sensor de Proximidad: Crear Entradas . . . . . . . . . . . . . . . . . . . . 90
5.13 Sketch Sensor de Proximidad: Propiedades Salidas . . . . . . . . . . . . . . . . . 90
5.14 Sketch Sensor de Proximidad: Crear Salidas . . . . . . . . . . . . . . . . . . . . . 91
5.15 Sketch Sensor de Proximidad: Lógica general . . . . . . . . . . . . . . . . . . . . 92
5.16 Sketch Sensor de Proximidad: Condición 1 . . . . . . . . . . . . . . . . . . . . . . 92
5.17 Sketch Sensor de Proximidad: Condición 2 . . . . . . . . . . . . . . . . . . . . . . 92
5.18 Sketch Sensor de Proximidad: Diagrama General . . . . . . . . . . . . . . . . . . 93
5.19 Sketch Sensor de Proximidad: Circuito . . . . . . . . . . . . . . . . . . . . . . . . 95
5.20 Sketch Luminosidad en Display: Crear Entradas . . . . . . . . . . . . . . . . . . 96
5.21 Sketch Luminosidad en Display: Crear Salidas . . . . . . . . . . . . . . . . . . . 97
5.22 Sketch Luminosidad en Display: Crear If . . . . . . . . . . . . . . . . . . . . . . 97
5.23 Sketch Luminosidad en Display: IOSentences . . . . . . . . . . . . . . . . . . . . 98
5.24 Sketch Luminosidad en Display: Ordenar sentencias . . . . . . . . . . . . . . . . 99
5.25 Sketch Luminosidad en Display: Ejemplo Propiedades Condition . . . . . . . . . 99
5.26 Sketch Luminosidad en Display: Sentencias adicionales . . . . . . . . . . . . . . . 100
5.27 Sketch Luminosidad en Display: Display Properties . . . . . . . . . . . . . . . . . 100
5.28 Sketch Luminosidad en Display: Circuito . . . . . . . . . . . . . . . . . . . . . . 103

8
Código

2.1 Sketch Blink : Código Blink . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21


2.2 Sketch Blink : Código modificado . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

3.1 Código Adicional: FixUpDiagram . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

4.1 Configuración: Output Extension . . . . . . . . . . . . . . . . . . . . . . . . . . . 69


4.2 Generación: Código Previo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
4.3 Método: newInput(Inputs input) . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
4.4 Método: newMeasure(Measure measure) . . . . . . . . . . . . . . . . . . . . . . . 70
4.5 Método: newOutput(Outputs output) . . . . . . . . . . . . . . . . . . . . . . . . . 71
4.6 Generación: void setup() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
4.7 Método: setUpInput(Inputs input) . . . . . . . . . . . . . . . . . . . . . . . . . . 72
4.8 Método: setUpOutput(Outputs output) . . . . . . . . . . . . . . . . . . . . . . . . 72
4.9 Generación: void loop() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
4.10 Método: newController(Controller controller) . . . . . . . . . . . . . . . . . . . . 73
4.11 Método: newSentence(Sentence sentence) . . . . . . . . . . . . . . . . . . . . . . 74
4.12 Método: newSimpleSentence(SimpleSentence ss) . . . . . . . . . . . . . . . . . . 74
4.13 Método: newIOSentence(IOSentence ioSentence) . . . . . . . . . . . . . . . . . . 75
4.14 Método: loopInput(Inputs input) . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
4.15 Método: loopOutput(Outputs output) . . . . . . . . . . . . . . . . . . . . . . . . . 76
4.16 Método: newLoopSentence(Loop loop) . . . . . . . . . . . . . . . . . . . . . . . . 77
4.17 Método: newCondition(Loop loop) . . . . . . . . . . . . . . . . . . . . . . . . . . 77
4.18 Método: newOperator(Condition condition) . . . . . . . . . . . . . . . . . . . . . 78
4.19 Flujo de Trabajo: Modificar Código . . . . . . . . . . . . . . . . . . . . . . . . . 81

5.1 Blink : Código generado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86


5.2 Sketch Matriz Temperaturas: Código Generado . . . . . . . . . . . . . . . . . . . 89
5.3 Sketch Sensor de Proximidad: Código generado . . . . . . . . . . . . . . . . . . . 94
5.4 Sketch Sensor de Proximidad: Código Final . . . . . . . . . . . . . . . . . . . . . 94
5.5 Sketch Luminosidad en Display: Código generado . . . . . . . . . . . . . . . . . . 101
5.6 Sketch Luminosidad en Display: Código modificado . . . . . . . . . . . . . . . . . 102

9
Capı́tulo 1

Introducción

1.1 Motivación
En 2021, Internet ya se ha implantado completamente en nuestra sociedad en la mayorı́a de
lugares del planeta. Por tanto, ¿cuál es el siguiente paso? Para muchos, la respuesta es Internet
of Things (IoT) o Internet de las Cosas, una visión de futuro que busca conectar entidades
digitales con objetos fı́sicos.[1]
Esta aspiración que hace unos años parecı́a muy lejana, ya es el presente. Aunque puede
resultar a primera vista un concepto muy abstracto, en muchos casos está presente en la vida
cotidiana, en lo que se concoce como smart devices o dispositivos inteligentes. Estos disposi-
tivos son cada vez más accesibles y forman parte del dı́a a dı́a, como, por ejemplo, los relojes
inteligentes.
Desgraciadamente, un evento reciente ha mostrado el verdadero potencial de este tipo de
tecnologı́as, la pandemia del virus COVID-19 está siendo combatida en muchas ocasiones a
través de dispositivos inteligentes. Por ejemplo, ambulancias habilitadas con tecnologı́a IoT,
enviando en tiempo real el estado del paciente al hospital, que se puede preparar para recibirle
en las mejores condiciones. Pacientes que pueden ser atendidos desde sus casas ya que cuentan
con equipos que son capaces de monitorizar las constantes vitales y mandarlas través de la red
hasta sus médicos. Esta aplicación en el ámbito sanitario es denominada como Internet of Health
Thingso por su término más común e-Health. E-Health es un claro ejemplo de la importancia y
capacidad que pueden alcanzar las tecnologı́as IoT en un futuro próximo. [2]
Para poder continuar la expansión de este concepto tecnológico es necesario formar e incen-
tivar su uso y conocimiento desde edades tempranas hasta los futuros estudiantes de ingenierı́a
para que recojan el legado de lo que se ha conseguido hasta ahora y que aporten nuevas ideas que
ayuden a mejorar el estado actual de las tecnologı́as IoT. Una buena forma de despertar interés
a jóvenes y acercar este mundo IoT es a través de Arduino [3]. Un proyecto que promueve el
uso de IoT a todos los niveles y ámbitos, desde el nivel escolar hasta las empresas más punteras
en robótica o Inteligencia Artificial.[4]
Aunque Arduino es accesible desde edades tempranas, en numerosas ocasiones puede exis-
tir una gran barrera de entrada debido a que los usuarios no poseen conocimientos previos de
electrónica y, sobre todo, de programación, necesarios para crear cualquier programa en este dis-
positivo. Este proyecto nace de la necesidad de romper esa barrera y crear una herramienta capaz
de facilitar el comienzo a aquellos nuevos usuarios interesados en el aprendizaje de las tecnologı́as
IoT, que pueden ser desde jóvenes estudiantes hasta ingenieros que no poseen conocimientos de
programación y les gustarı́a crear sus propios proyectos con Arduino.

1.2 Objetivos
El objetivo de este proyecto es crear una herramienta que tenga la capacidad de potenciar
e incentivar el uso de dispositivos IoT, haciendo uso de una interfaz intuitiva y sencilla que
permita facilitar el uso y aprendizaje del sistema Arduino, tanto a usuarios sin unos conocimientos
previos sobre programación o electrónica como a aquellos usuarios más avanzados, para los cuales
supondrá una notable agilización el construir programas más complejos.
Los objetivos especı́ficos de este Trabajo de Fin de Grado son los siguientes:

ˆ Crear un Lenguaje Especı́fico de Dominio que soporte IoT y Arduino, implementando su


metamodelo y correspondiente metáfora gráfica.

10
ˆ Crear una herramienta gráfica de modelado que proporcione soporte dicho lenguaje, a
través de la cual el usuario pueda elegir distintas configuraciones para Arduino.
ˆ Crear un compilador del Modelado Especı́fico de Dominio, capaz de leer dicha configuración
introducida por el usuario y generar el código de soporte necesario de Arduino.
ˆ Diseñar un conjunto de pruebas que validan la completitud del lenguaje, construyendo
diferentes configuraciones de Arduino y generando diferentes programas.
ˆ Validar el modelo y la herramienta mediante la ejecución de las pruebas diseñadas.

1.3 Estructura PFG


Este PFG (Proyecto de Fin de Grado) consta de cinco capı́tulos:
En el segundo capı́tulo se explicarán conceptos previos y necesarios para el entendimiento del
proyecto. Está formado por los siguientes puntos:
ˆ Presentación del sistema Arduino. Utilidades y elementos que componen su entorno.
– Presentación del conjunto Arduino UNO. Explicación de los componentes que forman
el paquete de iniciazión.
– Entorno de desarrollo Arduino IDE. Explicación de sus principales funcionalidades y
uso.
– Tutorial ”Construyendo un primer proyecto”. Explicación detallada para construir
un primer proyecto utilizando Arduino UNO.
ˆ Explicación inicial sobre Internet of Things (IoT) y su relación con este proyecto.
ˆ Desarrollo Dirigido por Modelos y Lenguaje Especı́fico de Dominio. Explicación inicial
sobre estos dos conceptos.
– Presentación de los Modelos. Significado y explicación sobre su potencial.
– Model Driven Development. Introducción sobre este paradigma, sus ventajas e incove-
nientes.
– Domain-Especific Language. Explicación sobre la necesidad de definir un lenguaje
propio y sus consecuencias.
El capı́tulo tercero muestra el lenguaje y el modelo que se ha definido para este proyecto,
aplicando los conceptos que se han explicado durante el capı́tulo anterior. Está compuesto por
los siguientes puntos:
ˆ Presentación del modelo. Explicación acerca de todos los elementos que definen el modelo
y conforman el lenguaje.
ˆ Explicación de las metáforas gráficas que representarán los elementos explicados en el punto
anterior.
ˆ Trazabilidad entre el modelo y la metáfora gráfica para representar los elementos del lengua-
je.
El cuarto capı́tulo muestra el proceso de transformación del modelo generado anteriormente
a un código legible para Arduino. Lo forman los siguientes puntos:
ˆ Explicación sobre el uso de la herramienta.
ˆ Explicación de la plantilla de generación de código.
En el quinto capı́tulo se construirán distintos programas haciendo uso de la herramienta para
poder mostrar ası́ su potencial.
En el sexto y último capı́tulo se explicarán las conclusiones a las que se ha llegado gracias a
este proyecto.

11
Capı́tulo 2

Conceptos previos

2.1 Internet of Things (IoT)


Aunque el nacimiento de este concepto no es reciente, durante la última década se ha contemplado
un crecimiento exponencial del mismo, integrándose por completo en nuestra sociedad, Internet of
Things (IoT) o el Internet de las Cosas. Este nombre hace referencia a la conexión de objetos de
caracter cotidiano con Internet, lo cual conlleva a la red a sobrepasar los lı́mites que hasta ahora
impedı́an su expansión. Para conseguir esto se hace uso de sistemas integrados o embebidos,
los cuales son capaces de recopilar información y enviarla a la red, sincronizándose a su vez con
otros servicios, lo cual amplı́a las posibilidades que puede ofrecer un único dispositivo de forma
aislada [5].
Un ejemplo a gran escala de esta visión de la tecnologı́a son las conocidas como ”Smart Cities”
o Ciudades Inteligentes, las cuales integran una compleja red de dispositivos inteligentes capaces
de regular servicios como el transporte público, uso eficiente de recursos o incluso hospitales.
Otros ejemplos más tangibles pueden ser un hogar inteligente o dispositivos que se llevan en el
dı́a a dı́a, como un reloj inteligente que monitoriza el ritmo cardı́aco u otras variables.
Para conseguir este continuo intercambio de información entre el entorno y el dispositivo en
concreto, son necesarios múltiples sensores que recopilan la información necesaria y se transmite
a la red. Tras esto, la información se vuelve a transmitir al dispositivo y en caso de ser necesario,
los actuadores realizarán los ajustes necesarios para regular los parámetros controlados a los
valores que se hayan definido previamente como correctos. Este infinito bucle y el flujo de datos
constante entre sensores, la red, actuadores y múltiples dispositivos con estas caracterı́sticas
atiende al principal enfoque de Internet of Things. [6]
Un claro ejemplo de tecnologı́a IoT es Arduino. Con Arduino es posible conseguir ese flujo de
información con el entorno, gracias a la variedad de sensores y actuadores que son compatibles
con el mismo. Su intuitiva interfaz permite configurar de forma sencilla la lógica con la que
se trata la información recopilada por los sensores y transmitirla a los actuadores que se hayan
conectado. Es por esto que Arduino es una herramienta perfecta para iniciarse en las tecnologı́as
IoT.

2.2 Arduino
2.2.1 ¿Qué es Arduino?
Arduino es una plataforma open-source utilizada para la construcción de proyectos de electrónica.
Su entorno se compone de dos partes fundamentales: una placa de circuito programable y un
IDE Integrated Development Environment que se utiliza para cargar el código de un programa.
[7]
Esta placa, no deja de ser un sencillo ordenador en el que se puede cargar código y ejecutar
diversos programas. El propósito principal de Arduino no era otro que ofrecer a jóvenes estudi-
antes sin conocimientos previos en electrónica ni programación una herramienta sencilla pero con
mucho potencial con la cual iniciarse en este ámbito. Sin embargo, con el paso del tiempo y el
crecimiento de la comunidad Arduino, ha ampliado los horizontes del dispositivo hasta incluirse
en proyectos de IoT (Internet of Things), impresoras 3D o en wearable technologies, entre otros.
Existen multitud de modelos de microcontroladores Arduino, en este TFG se va a utilizar
la versión más básica, Arduino UNO, la cual es capaz de leer diversas entradas (inputs), como
la luz en un sensor o la pulsación en un botón y devolver unas salidas (outputs), por ejemplo,
encendiendo un LED o un motor.

12
2.2.2 Arduino UNO: Componentes básicos
A continuación se explican los componentes básicos de los que se compone este kit de Arduino
(ver Figura 2.1).

Figure 2.1: Arduino Starter Kit

ˆ Arduino UNO: el corazón del sistema. A partir de este microcontrolador se construyen


todos los circuitos e interfaces, además se puede inyectar el código desde un ordenador para
indicar cómo debe comportarse con el resto de componentes (ver Figura 2.2).

Figure 2.2: Arduino UNO

ˆ Protoboard: es la placa sobre la que se construyen circuitos electrónicos. Consta de una


serie de pines, conectados internamente entre sı́ siguiendo un patrón de lı́neas permitiendo
armar sobre ella prototipos de circuitos y otros sistemas (ver Figura 2.3).

13
Figure 2.3: Protoboard Breadboard 400 points

ˆ Entradas: también denominadas Inputs son los elementos encargados de recopilar infor-
mación del entorno. Existen numerosos tipos de estos elementos, dependiendo del tipo de
variable que monitoricen. A continuación, se detallan los utilizados en este PFG:
– Sensor de temperatura: Cambia su voltaje de salida en función de la temperatura del
entorno. En términos de código, producirá una salida HIGH o LOW en función de la
temperatura detectada en el entorno (ver Figura 2.4).

Figure 2.4: Sensor de temperatura TMP36

– Sensor de inclinación: Un tipo de interruptor que se abre o cierra dependiendo de su


orientación. En términos de código, producirá una salida HIGH o LOW en función
de su inclinación (ver Figura 2.5).

Figure 2.5: Sensor de inclinación BL-XT660

– Sensor de luz: resistencia fotovoltaica que permitirá el paso de corriente o no en


función de la luminosidad detectada. En términos de código, producirá una salida
HIGH o LOW en función de la iluminación detectada en el entorno(ver Figura 2.6).

Figure 2.6: Sensor de iluminación HW5P-1

14
– Pulsador: componente que permite el paso de corriente cuando es pulsado y lo impide
cuando no se encuentra pulsado. (ver Figura 2.7)

Figure 2.7: Pulsador

ˆ Sensor de infrarrojos: gracias a su rayo de infrarrojos permite detectar cuándo está cerca
de algún otro objeto, encendiendo ası́ su LED integrado y emitiendo una señal HIGH o
LOW. La distancia de detección se puede ajustar gracias a su potenciómetro (ver Figura
2.8).

Figure 2.8: Sensor Infrarrojos

ˆ Potenciómetro: resistencia variable que se puede modificar manualmente para permitir el


paso o no de corriente (ver Figura 2.9).

Figure 2.9: Potenciómetro

ˆ Salidas: también denominadas Outputs, son aquellos elementos actuadores que producen
un cambio en el entorno. El principal uso de este tipo de elemento será realizar una
determinada acción en función de la información recopilada por las entradas, siguiendo
unas reglas que haya determinado el usuario.
– Diodos emisores de luz (LEDs): un tipo de diodo que se ilumina cuando la electricidad
pasa por él. En este kit se incluyen diversos diodos LED de distintos colores (ver Figura
2.10).

15
Figure 2.10: Diodo LED Rojo

– Motor de corriente continua: convierte la energı́a eléctrica en energı́a mecánica cuando


la electricidad fluye por sus clavijas (ver Figura 2.11).

Figure 2.11: Motor 6V TFK-280SA-22125

– Zumbador: convierte la energı́a eléctrica en energı́a en una señal de sonido de frecuen-


cia variable (ver Figura 2.12).

Figure 2.12: Buzzer

– LCD alfanumérico: pantalla de cristal lı́quido capaz de mostrar hasta 16 caracteres


en cada fila, constando este modelo de 2 filas (ver Figura 2.13).

16
Figure 2.13: LCD Alfanumérico JHD659

2.2.3 Arduino IDE


Arduino IDE es el entorno de programación que se utiliza para comunicarse con el microcontro-
lador Arduino. Este IDE es de libre distribución y se puede descargar desde la página oficial de
Arduino.
Los programas codificados usando Arduino IDE se denominan sketches y se guardan con la
extensión .ino [8]. La Figura 2.14 muestra la interfaz de Arduino IDE.

Figure 2.14: Interfaz Arduino IDE

En la parte superior izquierda se pueden encontrar las principales funcionalidades. La barra

17
de herramientas permite verificar el código, subir los programas y crear, abrir o guardar los
sketches (ver Figura 2.15).

Figure 2.15: Interfaz Arduino IDE: Toolbar

Será en el editor de texto donde se deberá escribir el código de cualquier sketch (ver Figura
2.16). Al crear cualquier sketch, Arduino IDE proporciona la plantilla que incluye los dos métodos
principales.

Figure 2.16: Interfaz Arduino IDE: Text Editor

Todo sketch se compone de dos métodos:

ˆ void setup(): Este método se ejecuta una vez cuando se inicia o reinicia la placa.

ˆ void loop(): Este método es un bucle que se ejecuta de manera indefinida.

18
2.2.4 Construyendo un primer proyecto
Todo sketch de un Arduino estará compuesto por unas entradas y unas salidas, pudiendo
ser estas del entorno o fı́sicas, es decir, que involucran un componente fı́sico por el que recibir
información en caso de tratarse de una entrada, o en caso contrario, de dar información si
hablamos de una salida. Por tanto, cuando se quiera construir un nuevo sketch, se debe tener claro
cómo se quiere tratar la información proporcionada por los diferentes inputs determinando una
serie de reglas y condiciones para ası́ conseguir obtener la salida deseada. Este comportamiento
lo representa el esquema de la Figura 2.17.

Figure 2.17: Esquema: Entrada a Salida

Una vez comprendido esto, es hora de construir el primer sketch, para ello Arduino IDE
proporciona unos sencillos ejemplos ya codificados, a los que se puede acceder desde File/Ex-
amples. Aquı́ se encuentran divididos por categorı́as, para este ejemplo se accede a la categorı́a
Basics/Blink (ver Figura 2.18).

19
Figure 2.18: Interfaz Arduino IDE: Examples

Todos estos ejemplos cuentan con un comentario al inicio en el que se explica el funcionamiento
del sketch y otros detalles. Por ejemplo, el sketch Blink de los ejemplos básicos (ver Figura 2.18),
incluye un comentario donde se especifica que el código consiste en que el LED integrado en la
placa Arduino parpadee (ver Código 2.1).

20
1 /*
2 Blink
3
4 Turns an LED on for one second, then off for one second, repeatedly.
5
6 Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
7 it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
8 the correct LED pin independent of which board is used.
9 If you want to know what pin the on-board LED is connected to on your Arduino
10 model, check the Technical Specs of your board at:
11 https://www.arduino.cc/en/Main/Products
12
13 modified 8 May 2014
14 by Scott Fitzgerald
15 modified 2 Sep 2016
16 by Arturo Guadalupi
17 modified 8 Sep 2016
18 by Colby Newman
19
20 This example code is in the public domain.
21
22 http://www.arduino.cc/en/Tutorial/Blink
23 */
24
25 // the setup function runs once when you press reset or power the board
26 void setup() {
27 // initialize digital pin LED_BUILTIN as an output.
28 pinMode(LED_BUILTIN, OUTPUT);
29 }
30
31 // the loop function runs over and over again forever
32 void loop() {
33 digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
34 delay(1000); // wait for a second
35 digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
36 delay(1000); // wait for a second
37 }

Source Code 2.1: Sketch Blink : Código Blink

En el caso en el que también se quiera que parpadee el LED que se instalará en nuestra
protoboard, es necesario declarar nuestro LED de la siguiente manera: se declara led al principio
del código y se iguala al pin al que se enchufa en la placa. Cuando se llama a los métodos
pinMode y digitalWrite hay que pasar por parámetro el nuevo led en lugar del integrado (ver
Código 2.2).

1 int led = 13; //se declara el led externo


2
3 void setup() {
4
5 pinMode(led, OUTPUT);
6 }
7
8 void loop() {
9 digitalWrite(led, HIGH); // se enciende el led
10 delay(1000); // espera 1 segundo
11 digitalWrite(led, LOW); // se apaga el led
12 delay(1000); // espera un segundo
13 }

Source Code 2.2: Sketch Blink : Código modificado

Ahora hay que montar los componentes en nuestra placa, en el enlace que aparece en el
fragmento 2.1, lı́nea 22, se pueden encontrar los componentes necesarios (ver Figura 2.19).

21
Figure 2.19: Sketch Blink: Hardware

En primer lugar, es necesario conectar el cable de corriente al pin número 13 y realizar las
conexiones necesarias a la toma de tierra (GND) y a la placa protoboard, como se muestra en la
Figura 2.20.

Figure 2.20: Sketch Blink : Montaje

Después, se enchufa la placa Arduino con el cable USB al ordenador, verificar el código por si
existe algún fallo y, en caso de que todo funcione correctamente, cargarlo en la placa. Se puede
observar como el LED se enciende y se apaga con un segundo de diferencia (ver Figura 2.21). [9]

22
Figure 2.21: Sketch Blink : LED encendido

2.3 MDD y DSL


2.3.1 Modelos
Un modelo es una representación abstracta y simplificada de un componente del sistema, su
función es servir como artefacto primario para construir software de manera que se reduzcan
costes y tiempo. [10].
Los modelos se caracterizan por las siguientes propiedades:
ˆ Los modelos ayudan a comprender ideas complejas.

ˆ Pueden ser desarrollados antes de implementar un sistema fı́sico o pueden surgir de un


sistema existente como ayuda para comprender su comportamiento.
ˆ No existe un único modelo para representar un componente o sistema, en ocasiones tener
varios modelos puede dar una visión más completa. Además, existe un proceso de refi-
namiento en el que un modelo puede cambiar para adaptarse mejor a los requisitos del
cliente. [11]

2.3.2 Model Driven Development (MDD)


MDD es un paradigma de desarrollo software basado en el uso de modelos a partir de los cuales
es posible generar el código de un sistema.
Las principales caracterı́sticas del desarrollo MDD son:

23
ˆ Su principal ventaja y el objetivo por el que fue creado es incrementar la productividad a
la hora de desarrollar un sistema. Se busca reducir el tiempo de desarrollo y a la vez los
costes, generando el código a partir de los modelos.
ˆ Mantenibilidad y portabilidad: con el uso de modelos se busca obtener una arquitectura
sostenible, en la que se puedan hacer cambios rápido y de manera consistente. En caso de
que necesitemos migrarnos de tecnologı́a, los modelos son independientes de los detalles de
la implementación, por ello es más fácil realizar los cambios para efectuar la migración.
ˆ Adaptabilidad: realizar cambios en la función de un componente resulta más rápido y
directo gracias a que la inversión en automatización ya se ha realizado previamente.

ˆ Reutilización: una vez nuestro modelo ha sido completamente desarrollado y ha pasado


todas las pruebas, se puede reutilizar tantas veces como se quiera. Además, puede servir
de base para futuros desarrollos.
ˆ Comunicación más fluida con los Stakeholders: debido a que los modelos son una repre-
sentación abstracta y más simplificada del sistema, se pueden compartir con los stakeholders
para ası́ obtener retroalimentación.

A continuación, se explican las desventajas más relevantes del desarrollo MDD:

ˆ Rigidez: debido a que se parte de un modelo de mayor nivel, en ocasiones no podremos


especificar tanto como nos gustarı́a, en caso de que sea necesario deberemos dejar de aplicar
dicho modelo para completar esa componente.
ˆ Diversidad de roles en el equipo: para realizar un proyecto con un enfoque basado en
MDD se necesitará personal cualificado para construir un metamodelo, que normalmente
no es realizado por programadores, sino por un “meta-equipo”, compuesto por ingenieros
o diseñadores que sean capaces de expresar sus conocimientos en un modelo.

MDD cuenta con dos enfoques de adopción: MDA (Model Driven Architecture) y Software
Factories. MDA se asocia con un enfoque dirigido por modelos en el que el código es generado
automáticamente desde modelos abstractos, y que emplea un lenguaje estandarizado (creado por
OMG en 2001) para describir dichos modelos y las transformaciones entre ellos [12]. Su objetivo
principal es que en caso de producirse un cambio o avance tecnológico, este no afecte gravemente
a la arquitectura del sistema [11].
Sin embargo, para este PFG se ha basado en el enfoque Software Factories. Impulsado por
Microsoft, esta corriente busca la reutilización de componentes software para generar un código
de calidad. Soportado por la tecnologı́a DSL Tools utilizada en este proyecto, la cual permite
crear un Lenguaje Especı́fico de Dominio, utilizado para generar código de forma totalmente
adaptable a las necesidades del usuario [11].

2.3.3 Lenguaje Especı́fico de Dominio (Domain-Specific Languages D-


SL)
Los lenguaje especı́ficos de dominio son lenguajes cercanos al usuario que va a hacer uso de los
mismos y con una mayor nivel de abstracción que un lenguaje de programación. Estos pueden
ser gráficos o textuales, dependiendo de su identidad a la hora de utilizarse. Esto contrasta total-
mente con otros lenguajes como C o Java, los cuales están diseñados para propósitos generales.
Normalmente, un DSL será menos complejo que otros lenguajes y será desarrollado por los
ingenieros del proyecto en colaboración con los expertos del problema en concreto, para ası́
adaptarse a las necesidades que tiene que cubrir dicho lenguaje. Además, un DSL se diseña
generalmente para que alguien ajeno al mundo de la programación, pero con ciertos conceptos y
conocimientos de los elementos del DSL pueda utilizarlo sin problemas [13].
Para este PFG se ha decidido construir el lenguaje especı́fico de dominio utilizando el entorno
de desarrollo Visual Studio y su paquete para la definición de un DSL [14]. Visual Studio

24
proporciona unas plantillas sobre las que construir un lenguaje DSL, para ello tiene definido un
tipo de proyecto especı́fico (ver Figura 2.22).

Figure 2.22: Visual Studio: Crear proyecto

La interfaz de Visual Studio se divide en tres partes bien diferenciadas, que son, de izquierda
a derecha en la Figura 2.23, la Toolbox, el Diagrama de Clases y el DSL Explorer.

Figure 2.23: Visual Studio: Vista General

La parte principal y sobre la que se construye el lenguaje es el Diagrama de Clases. En este


tapiz, se crean mediante ”drag and drop”, es decir, arrastrando los elementos desde la Toolbox
y soltándolos, los distintos elementos de un DSL (ver Figura 2.24). En la parte izquierda se
encuentran las diferentes clases y las relaciones existentes entre ellas. Mientras que en la parte
derecha, están los elementos que definen las representaciones que verá el usuario final de aquellas
clases o conectores del DSL.

25
Figure 2.24: Visual Studio: Diagrama de Clases

En la parte derecha de la Figura 2.23 se encuentra el DSL Explorer, desde el que se puede
acceder de forma rápida a los elementos del lenguaje. Destacar el apartado Editor que, aunque
se explicará más adelante, permite personalizar la caja de herramientas que utilizará el usuario
final para crear su modelo (ver Figura 2.25).

Figure 2.25: Visual Studio: DSL Explorer

Al hacer botón derecho sobre Editor se pueden añadir tantos compartimentos como se nece-
siten (ver Figura 2.26).

26
Figure 2.26: DSL-Editor: Add New Toolbox Tab

Dentro de cada compartimento se pueden crear dos tipos de objetos, elementos y conectores.
Los elementos son las distintas clases que se han definido en el modelo, mientras que los conectores
son capaces de relacionar aquellas clases que tengan una relación referencial (ver Figura 2.27).
Además, en la pestaña de Propiedades, se puede personalizar el nombre del compartimento que
visualizará el usuario.

Figure 2.27: DSL-Editor: Add Tool

En las Propiedades de cada objeto que se ha creado, ya sea conector o elemento, se deben
definir distintos parámetros: la clase del modelo a la que hace referencia, el nombre que visualizará
el usuario al usar la herramienta, o el icono que representará dicho objeto en la Toolbox (ver
Figura 2.28). El resultado final de la Toolbox que verá el usuario se presentará en la siguiente
sección (ver Figura 3.27).

27
Figure 2.28: DSL-Editor: Element Properties

Por último, explicar la parte izquierda de la Figura 2.23, donde se encuentra la Toolbox desde
la que se pueden arrastrar sus elementos hasta el diagrama (ver Figura 2.29).

Figure 2.29: Visual Studio: Toolbox

Los principales elementos que se han utilizado para este proyecto se encuentran explicados a
continuación:
ˆ Domain Class (Clase de Dominio): se trata del elemento básico de nuestro lenguaje. Se
utilizará para definir los conceptos que queremos modelar. Por ejemplo, si un lenguaje
está orientado a una biblioteca multimedia, una clase de dominio podrı́a ser ”Canción”
o ”Foto”. Además podemos añadir diversas propiedades para completar la definición de

28
nuestra clase, pudiendo ser estas del tipo String, Int o DateTime entre otros, de carácter
público o privado (Figura 2.30). [15]

Figure 2.30: Componentes DSL: Domain Class

ˆ Embedding Relationship: cualquier elemento en un modelo forma parte de una relación


embedding. Esta relación permite establecer una clase como contenedor de otra (Figura
2.31). [15]

Figure 2.31: Componentes DSL: Embedding Relationship

ˆ Reference Relationship: es un tipo de relación utilizada para representar cualquier relación


entre dos clases que no sea de tipo embedding. Normalmente, en la notación gráfica se
representará como un conector que une dos clases (Figura 2.32). [15]

Figure 2.32: Componentes DSL: Reference Relationship

Los elementos explicados hasta ahora se construyen sobre la parte izquierda del diagrama
Classes and Relationships (ver Figura 2.24). Sin embargo, los tres elementos explicados a conti-
nuación tienen una naturaleza diferente, se construyen sobre la parte derecha, Diagram Elements
(ver Figura 2.24) y necesitan ser asociados a una clase o una relación.

ˆ Image Shape (Forma de Imagen): asociado a una clase, este elemento permite asignar la
imagen que representará a una clase sobre el tapiz. Un elemento similar es Geometry Shape,
que en lugar de una imagen, asociará una forma geométrica. En ambos tipos se pueden
definir Decoradores o Decorators, que permiten mostrar propiedades de la clase a la que
están asociados, por ejemplo, para mostrar un nombre (Figura 2.33).

29
Figure 2.33: Componentes DSL: Image and Geometry Shape

ˆ Connector (Conector): permite personalizar la apariencia que tendrá el conector que une
dos clases en una relación sobre el tapiz. Para el caso de las relaciones referenciales, es
obligatorio asignar un conector, sin embargo, para las relaciones embedding, es opcional
(Figura 2.34).

Figure 2.34: Componentes DSL: Connector

Como se ha explicado, para permitir posteriormente definir una metáfora gráfica, se hará
uso de dos elementos, Image Shape y Geometry Shape. La primera nos permite una asociar una
imagen determinada a la clase elegida, la segunda es algo más limitada, ya que únicamente nos
permite asociar una determinada forma geométrica, a continuación, se explica cómo hacerlo.
En las propiedades de una Image Shape, en el apartado de recursos se debe importar la imagen
que debe representar la clase en cuestión, además se puede cambiar el tamaño de la imagen con
las propiedades Initial Height e Initial Weight (Figura 2.35). En el caso de una forma geométrica
no será necesario seleccionar la imagen, sino la forma geométrica y colores deseados (Figura 2.36).

Figure 2.35: Image Shape: Resources


Figure 2.36: Geometry Shape: Appearance

Ambas formas permiten agregar decoradores o decorators, los cuales permiten mostrar pro-
piedades de la clase asociada a la shape, ya sea en forma de texto o de icono (ver Figura 2.37).

30
Figure 2.37: Geometry Shape: Add Decorator

Todas las formas que representan entradas o salidas en el modelo cuentan con un Text Decora-
tor que añade un cuadro de texto con el nombre que ha designado el usuario a dicho componente.
Esto es posible ya que las clases abstractas Inputs y Outputs (ver Figuras 3.2 y 3.8) cuentan con
una propiedad Name, heredada por las clases hijas y que ha sido enlazada a dicho Text Decorator
de las Image Shapes asociadas a cada entrada y salida.
Para conseguir este enlace entre el decorador y la propiedad en cuestión de la clase es nece-
sario relacionarlo manualmente. Accediendo a las propiedades de la relación entre la clase y la
forma asociada, en la pestaña Decorator Maps, se selecciona el Decorator a enlazar, mientras que
en el desplegable Display Property aparecerán todas las propiedades (heradadas o propias) que
posea la clase y se deberá elegir la propiedad a enlazar con el decorador.

31
Capı́tulo 3

Lenguaje Especı́fico de Dominio para


Arduino

En este capı́tulo se explica cómo se ha construido el lenguaje a partir de lo definido en la sección


2.3.3. En primera instancia, se define el modelo sobre el que se basa el DSL y se asociará una
metáfora gráfica a cada una de las clases. Además se explicará el proceso de construcción de
la barra de herramientas, la cual será imprescindible para que el usuario pueda hacer uso de la
herramienta Arduino Modelling Tool.

3.1 Definición del modelo


En esta sección se explicarán los distintos conceptos que definen el modelo creado para este
lenguaje. Un punto interesante a tener en cuenta es la posible y fácil ampliación de este modelo,
en caso de ser necesario, gracias al Desarrollo Dirigido por Modelos.
Como se indicó previamente en este documento, todo sketch de Arduino está compuesto por
unas entradas, unas salidas y una lógica que se encarga de tratar la información de dichos inputs
y transmitirlas a nuestros outputs. Por tanto, el lenguaje de dominio se compondrá a grandes
rasgos de estos tres elementos, todos unidos por un componente en común, el propio dispositivo
Arduino.

ˆ ArduinoDevice: esta clase representa el dispositivo Arduino al que irán unidos todos
los componentes, tanto fı́sicos como lógicos. Es por esto que son sumamente relevantes
las relaciones que se han definido en el lenguaje para esta clase, siendo las siguientes (ver
Figura 3.1):

– ArduinoDeviceHasInputs: esta relación permite crear las entradas de las que se


compone un sketch. La cardinalidad de esta relación es 0-*/1-1, es decir, un Ar-
duinoDevice puede tener de 0 a N Inputs, pero estos solo pertenecen a un único
ArduinoDevice.
– ArduinoDeviceHasOutputs: esta relación permite crear las salidas de las que se
compone un sketch. La cardinalidad de esta relación es 0-*/1-1, es decir, un Ar-
duinoDevice puede tener de 0 a N Outputs, pero estos solo pertenecen a un único
ArduinoDevice.
– ArduinoDeviceHasController : esta relación representa el vı́nculo entre la parte
fı́sica de nuestro Arduino y la parte lógica que se define en nuestro controlador. La
cardinalidad de esta relación es 0-*/1-1, es decir, un ArduinoDevice puede tener de 0
a N Controller, pero estos solo pertenecen a un único ArduinoDevice.

32
Figure 3.1: Elementos del lenguaje: ArduinoDevice

ˆ Inputs: esta clase de dominio representa los distintos Inputs que se emplearán en un
sketch. El marco discontinuo de la clase indica que se trata de una clase abstracta, es
decir, no se podrán instanciar objetos de esta clase, sino que se deberán crear objetos de
alguna de las clases hijas de esta, que heredarán las DomainProperties definidas en la clase
padre, Inputs (ver Figura 3.2).

33
Figure 3.2: Elementos del lenguaje: Inputs

La clase Inputs tiene dos clases hijas, ManualInput y Sensor, esta división se ha realizado
para diferenciar los dos tipos de entradas que existen. Aquellas controladas por el usuario
serán las entradas manuales, mientras que las que reciban información del entorno serán los
sensores. Además, esto facilitará la generación de código, como se explicará más adelante.

– ManualInput: esta clase (ver Figura 3.3) contiene la herencia con las clases Switch
y Potentiometer, las cuales representan un interruptor (ver Figura 2.7) y un poten-
ciómetro (Figura 2.9), respectivamente.

Figure 3.3: Elementos del lenguaje: ManualInput

34
– Sensor : esta clase (ver Figura 3.4) contiene la herencia de las clases LightSensor (sen-
sor de luz, ver Figura 2.6), TemperatureSensor (sensor de temperatura, ver Figura
2.4), IRSensor (sensor de infrarrojos, ver Figura 2.8) y TiltSensor (sensor de incli-
nación, ver Figura 2.5).

Figure 3.4: Elementos del lenguaje: Sensor

ˆ Measure: esta clase permite almacenar las medidas recopiladas por nuestros Inputs (ver
Figura 3.5). A través de las propiedades definidas se podrán establecer un nombre para
esta variable y su tipo.

– InputHasMeasure: esta relación permite asociar una medida al Input que la re-
copila. Debido a que una Measure no tiene sentido sin la existencia de un Input y
viceversa, la cardinalidad es de 1 a 1 en ambos sentidos.

35
Figure 3.5: Relaciones del lenguaje: InputHasMeasure

ˆ Value: esta clase permite traducir la medida almacenada en Measure a un valor que el
usuario pueda interpretar (ver Figura 3.6).

– MeasureHasValue: esta relación permite asociar una medida a un valor, para ası́
poder traducirlo. Una medida podrá tener o no un valor asociado, por tanto la
cardinalidad será de 0 a 1, sin embargo un valor ha de tener una y solo una medida
asociada, cardinalidad 1 a 1.

Figure 3.6: Relaciones del lenguaje: MeasureHasValue

Como se puede observar en la figura 3.6, las propiedades DataType y Type son de tipos
distintos a los habituales. Se han creado dos Enumeraciones de dominio, DataType
permite al usuario definir el tipo de variable de Measure, mientras Values representa un
tipo de medida común, por ejemplo Celsius, útil para el sensor de temperatura. Ambos
enumeradores son fácilmente ampliables en caso de ser necesario.

36
(b) Values
(a) DataType

Figure 3.7: Domain Enumeration: DataType and Values

ˆ Outputs: a partir de esta clase de dominio crean las salidas necesarias. Al igual que la
clase Inputs, es abstracta, por lo que se deberán crear las salidas instanciando alguna de
las clases hijas (Figura 3.8).

Figure 3.8: Elementos del lenguaje: Outputs

De igual manera que para las entradas, se ha realizado esta herencia ya que las clases
hijas de EnvironmentalOutputs poseen una propiedad en común, el PinNumber al que se
conectan a la placa, a diferencia de la salida Terminal.

– EnvironmentalOutputs: es la clase padre de todas las distintas salidas representadas


en el lenguaje (Figura 3.9). Cada una se corresponde con las salidas definidas en la
sección 2.2.1.

37
Figure 3.9: Elementos del lenguaje: EnvironmentalOutputs

– Terminal : esta salida representa la consola de Arduino IDE. Gracias a su propiedad


Message, se puede definir la sentencia a mostrar por la consola (ver Figura 3.10).

Figure 3.10: Elementos del lenguaje: Terminal

ˆ Controller : con esta clase se controla el tratamiento de la información proporcionada por


los Inputs y transmitirla a los Outputs. El controlador servirá de vı́nculo entre la parte
lógica y la parte fı́sica de Arduino (Figura 3.11).
La relación embebida ControllerHasSentence permite incluir las sentencias dentro del con-
trolador, formando la lógica del sketch. Un controlador podrá tener varias o ninguna
sentencia, mientras que una sentencia puede ser embebida en uno o ningún controlador,
como se explicará más adelante en los bucles.

38
Figure 3.11: Elementos del lenguaje: Controller

ˆ Sentence: una sentencia es el elemento básico que se empleará para establecer el tra-
tamiento de la información que se recopila desde los Inputs. Permitirá construir la lógica
de un programa, creando condiciones, repeticiones, operaciones, etc. En definitiva, esta
clase ofrece la posibilidad de crear un simple lenguaje de programación que le permitirá
abstraerse de la sintaxis concreta del lenguaje Arduino y de la compilación del mismo, ya
que el código asociado se generará automáticamente, libre de errores.
La relación referencial de una sentencia a otra nace de la necesidad de establecer un orden
entre las mismas, ya que, como en cualquier lenguaje de programación, es sumamente
importante el orden de ejecución de las lı́neas de código. Por tanto, esta relación representa
dicho orden entre sentencias, el usuario podrá enlazar a través de un conector las distintas
sentencias para establecer dicha ordenación (ver Figura 3.12).
La clase Sentence será abstracta, por lo que se tendrá que hacer uso de sus clases hijas,
explicadas a continuación.

39
Figure 3.12: Elementos del lenguaje: Sentence

ˆ Loop: esta clase es una de las hijas de Sentence, la cual también es abstracta, por lo que
no es posible instanciarla directamente, sino que se ha de hacer uso de sus clases hijas: If,
While y For, las cuales representan las repeticiones básicas de la programación. Destacar
que If se ha incluı́do como hija de la clase Loop ya que comparte propiedades con el resto
de bucles, y es que también posee una condición que se ha de cumplir para que se ejecuten
las sentencias que contiene en su interior, solo que, a diferencia de While y For, estas
sentencias se ejecutarán únicamente una vez.
Como propiedades de dominio adicionales, la clase For presenta cómo se actualiza la variable
que controla el número de repeticiones del bucle (Increment) y el valor de inicio de dicho
número (Initialization), para que el usuario pueda elegir el comportamiento de dicho bucle
(ver Figura 3.13).

40
Figure 3.13: Elementos del lenguaje: Loop

– LoopHasCondition: el elemento principal del que se compone un bucle es su condi-


ción de parada. Por tanto esta relación nace de la necesidad de tener una condición
asociada a los bucles de un programa. Una condición pertenece a un único bucle,
cardinalidad 1 a 1, y un bucle podrá tener una o varias condiciones, 1 a n.

ˆ Condition: esta clase permite construir las condiciones de los bucles. Una condición se
compone de dos operandos y un operador, resultando en las tres propiedades definidas para
esta clase (ver Figura 3.14).

41
Figure 3.14: Elementos del lenguaje: Condition

El operador debe incluir exclusivamente operadores aceptados. Por este motivo se ha


creado el Enumerator Operator (ver Figura 3.15), que contiene los operadores básicos
para comparar los operandos.

Figure 3.15: Domain Enumeration: Operator

Todo bucle incluye sentencias dentro de él. Para ello se debe definir en cada clase hija de
Loop la siguiente relación embebida LoopHasSentence (donde Loop corresponderá al bucle
hijo en cuestión), la cual nos permitirá ”arrastrar y soltar” sentencias de cualquier tipo
dentro de un bucle. De forma que, un bucle puede tener de 0 a n sentencias, y esta puede
pertenecer a 0 o 1 bucle (ver Figura 3.16).

42
Figure 3.16: Relaciones del lenguaje: LoopHasSentence

ˆ SimpleSentence: esta clase permite representar cualquier tipo de sentencia que no sea
compleja, es decir, que no incluya sentencias dentro, como las hijas de la clase Loop (ver
Figura 3.17). Es abstracta, por lo que no se podrá instanciar directamente, sino que se
hará uso de alguna de sus clases hijas, las cuales se explicarán a continuación.

43
Figure 3.17: Elementos del lenguaje: SimpleSentence

ˆ ManualSentence: este tipo de sentencia permite definir cualquier tipo de sentencia de


forma manual, haciendo uso de su propiedad Text, a partir de la cual se generará el cógido a
inyectar (ver Figura 3.18). Debido a su flexibilidad, esta sentencia está orientada a usuarios
expertos, que sean capaces de construir programas más complejos.

Figure 3.18: Elementos del lenguaje: ManualSentence

ˆ IOSentence: esta clase permite inyectar el código correspondiente a los principales mé-
todos de lectura y escritura que utilizan nuestras distintas entradas y salidas, los más
comunes son digitalRead(), digitalWrite(), analogRead() y analogWrite().
Sin embargo, en otras ocasiones será necesario hacer uso de otros métodos, por esta razón
será de importancia saber el tipo de Input u Output del que se está haciendo uso, de ahı́

44
la necesidad de definir dos relaciones referenciales, una para las entradas y otra para las
salidas.
Estas relaciones permitirán enlazar este tipo de sentencia con el componente del cual se
quiera crear una sentencia de lectura o escritura e inyectar el código correspondiente al
método que utiliza dicho componente, abstrayendo al usuario de la sentencia concreta que
se debe utilizar en cada caso (ver Figura 3.19).

Figure 3.19: Elementos del lenguaje: IOSentence

ˆ Delay : permite inyectar el método delay(int duration), el cual es utilizado en multitud


de programas para detener la ejecución de manera momentánea del sketch, generalmente
utilizado dentro del método void loop() (ver Figura 3.20).

Figure 3.20: Elementos del lenguaje: Delay

3.1.1 DSL-Editor y Toolbox


Una vez definido el modelo para construir el lenguaje, es necesario personalizar la interfaz, la
cual empleará el usuario para seleccionar los componentes que utilizará en su sketch. Para ello,
se debe crear una barra de herramientas o Toolbox, en la que se situarán los elementos que tengan
la posibilidad de ser creadas por el usuario, es decir, aquellas clases que no sean abstractas, como
se ha visto en la sección anterior.
A la hora de construir dicha Toolbox se hará uso de la herramienta DSL-Editor (ver Figura
3.21), presentada a continuación:

45
Figure 3.21: DSL-Editor

La Toolbox estará compuesta por distintos Toolbox Tabs, que agruparán elementos de natu-
raleza similar (ver Figura 3.22).

Figure 3.22: DSL-Editor : Compartimentos

A continuación, se explican los distintos compartimentos y los elementos que contienen cada
uno:

ˆ Connectors: los conectores se emplean para relacionar distintos elementos del modelo.
Se han definido tres tipos de conectores en nuestro lenguaje: CnctOutputSentence para

46
relacionar sentencias de entrada/salida con una salida (ver Figura 3.19, relación IOSen-
tenceReferencesOutputs), CnctIntputSentence para relacionar sentencias de entrada/salida
con una entrada (ver Figura 3.19, relación IOSentenceReferencesOutputs) y CnctSentence
para establecer el orden entre las distintas sentencias (ver Figura 3.12, relación SentenceRef-
erencesTargetSentence)

ˆ Inputs: en este apartado se encuentran las distintas entradas que se pueden utilizar en un
sketch. Los elementos incluı́dos en este compartimento hacen referencia a las clases hijas
de ManualInput (ver Figura 3.3) y Sensor (ver Figura 3.4).
ˆ Logical: este compartimento comprende aquellos elementos que se emplearán para con-
struir el apartado lógico del programa, es decir, las distintas clases hijas de la clase Sentence
(ver Figuras 3.12, 3.13 y 3.17).
ˆ Main: en el apartado Main o Principal se encuentran elementos imprescindibles para la
creación de cualquier sketch. ArduinoDevice sirve para instanciar la clase ArduinoDevice
(ver Figura 3.1), Controller instancia la clase Controller (ver Figura 3.11), mientras que
Measure y Value hacen referencia a las clases Measure y Value del modelo (ver Figura 3.6).

ˆ Outputs: en este apartado se encuentran las salidas que componen un sketch. Este Tab
hace referencia a las clases hijas de EnvironmentalOutputs (ver Figura 3.9) y a la clase
Terminal (ver Figura 3.10).

Por último, se presenta el resultado final de la Barra de Herramientas, tal y como la verı́a el
usuario (véase Figura 3.27). Comentar que los iconos empleados en el Toolbox son las mismas
imágenes que representarán a los elementos ya una vez creados sobre el tapiz. Excepcionalmente,
para representar en el Toolbox las clases If, While, For y Condition, se ha empleado un icono
personalizado para cada una, en lugar de la forma geométrica coloreada que se muestra una vez
se crean en el tapiz estas clases.

Figure 3.24: Toolbox Icon: While


Figure 3.23: Toolbox Icon: If

Figure 3.25: Toolbox Icon: For Figure 3.26: Toolbox Icon: Condition

47
Figure 3.27: User Toolbox

48
3.2 Notación Gráfica
La notación o metáfora gráfica asignada a cada elemento del lenguaje definido mediante el modelo
y la barra de herramientas, es fundamental para componer una interfaz de usuario intuitiva y
visualmente atractiva.
Como se ha explicado en el punto anterior, se ha definido una Toolbox o Caja de herramientas,
la cual esta compuesta por los elementos que se podrán utilizar para construir un sketch. Para
facilitar la comprensión al usuario, la Toolbox está dividida en distintos compartimentos, que
agrupan elementos con caracterı́sticas similares. Estos compartimentos han sido explicados en
la Figura 3.22, por tanto, ahora se agruparán de igual forma para explicar su metáfora gráfica.

ˆ Main
Para representar el dispositivo Arduino UNO, se ha decidido emplear una imagen real del
mismo, sobre el que se arrastran y sueltan el resto de elementos (ver Figura 3.28).

Figure 3.28: Main: ArduinoDevice

Una cinta de medir representará el elemento Measure (Figura 3.29), mientras que Value
será una gráfica sostenida por unas manos (Figura 3.30).

Figure 3.29: Main: Measure Figure 3.30: Main: Value

Controller es un cerebro con forma de chip con conexiones en la Toolbox (ver Figura 3.31),
mientras que sobre el tapiz será un rectángulo azul sobre el que dejar caer las distintas
sentencias con el icono mostrado en la esquina superior derecha.

49
Figure 3.31: Main: Controller

ˆ Inputs
Para representar un Switch se utiliza un dibujo de un interruptor (Figura 3.32), siendo el
caso de Potentiometer el dibujo de un potenciómetro (Figura 3.33).

Figure 3.32: Inputs: Switch Figure 3.33: Inputs: Potentiometer

El dibujo de una bombilla representa el sensor de luz (Figura 3.34) y un termómetro es la


metáfora de un sensor de temperatura (Figura 3.35).

Figure 3.34: Inputs: LightSensor Figure 3.35: Inputs: TemperatureSensor

Un nivel es la metáfora gráfica del sensor de inclinación (Figura 3.36) y la Figura 3.37
representa al sensor de infrarrojos.

Figure 3.36: Inputs: LightSensor Figure 3.37: Inputs: IRSensor

ˆ Outputs

50
El dibujo de un diodo LED y un motor eléctrico, son las metáforas gráficas de LED y
DCMotor, respectivamente (ver Figuras 3.38 y 3.39).

Figure 3.38: Outputs: LED Figure 3.39: Outputs: DCMotor

El dibujo de un monitor representa un Terminal (ver Figura 3.40), mientras que una
pantalla LCD es la salida Display (ver Figura 3.41).

Figure 3.40: Outputs: Terminal Figure 3.41: Outputs: Display

ˆ Logical
A continuación, se muestran los distintos bucles (Figuras 3.42, 3.43 y 3.44) y la metáfora
de la condición (Figura 3.45).

Figure 3.42: Logical: For Figure 3.43: Logical: While

Figure 3.44: Logical: If


Figure 3.45: Logical: Condition

Las figuras 3.46 y 3.47 representan las metáforas gráficas de la sentencia de entrada/salida
y sentencia manual respectivamente.

51
Figure 3.46: Logical: IOSentence Figure 3.47: Logical: ManualSentence

Un ejemplo más real de cómo se ven representados los distintos elementos lógicos podrı́a
ser el siguiente (Figura 3.48):

Figure 3.48: Logical : Diagrama lógico

ˆ Connectors
Estos dos conectores (ver Figuras 3.49 y 3.50 ) representan la relación referencial entre
IOSentence y una entrada o salida (ver figura 3.19). El tercer y último conector se empleará
para establecer el orden entre las distintas sentencias de un controlador. Un ejemplo de
este conector se puede observar en el ejemplo realizado en esta misma sección (ver figura
3.48), la punta en flecha indica la sentencia siguiente, mientras que el extremo opuesto
indica la sentencia previa.

52
Figure 3.49: Connectors: Controller-Input

Figure 3.50: Connectors: Controller-Output

3.3 Trazabilidad Modelo - Notación Gráfica


Una vez definido el modelo, la barra de herramientas y la metáfora gráfica que se ha elegido para
cada elemento del diagrama, es necesario asociar cada clase del modelo con su correspondiente
metáfora gráfica para que pueda ser instanciada por el usuario.
Para conseguir esto, es necesario realizar un ”mapping” entre las clases no abstractas del
modelo y sus formas. Es decir, asignar a cada clase una shape, la cual contiene la imagen que
se ha de mostrar una vez se cree dicha clase sobre el tapiz. En la imagen 3.51 se muestra un
fragmento del modelo en el que se puede apreciar la asociación entre las distintas salidas y las
formas correspondientes a cada uno de ellos.

Figure 3.51: Outputs - Image Shape

Gracias a este ”mapping”, es posible establecer una relación entre las propiedades definidas
en una clase y los decoradores de una Shape. Esto tiene como objetivo, por ejemplo en el caso
de la propiedad Name de las clases Inputs y Outputs, que se muestre el nombre especificado por
el usuario debajo de la imagen correspondiente a dicha Shape.

53
En la Figura 3.52 se muestra cómo realizar lo explicado anteriormente para la relación entre
Terminal, la cual cuenta con dos propiedades (Name y Message, ver Figura 3.8) y su Shape
asociada, ISTerminal.

Figure 3.52: Shape Mapping

Se puede observar en la imagen 3.53 cómo se asocian las imágenes explicadas en la metáfora
a las distintas salidas y se muestran los nombres gracias al resultado de este proceso.

Figure 3.53: Shape examples

En la figura 3.53 además de aparecer las formas asociadas a la clase ArduinoDevice y a los
distintos Outputs, aparece otro elemento, las lı́neas entre ambas. Para conseguir mostrar estas
lı́neas es necesario crear un Connector o conector, que irá asociado a la relación existente entre
las salidas y el dispositivo Arduino en este caso. En la Figura 3.55 se muestra el conector definido
para esta relación, mientras que en la Figura 3.54 se muestra cómo se ha enlazado dicho conector
a la relación entre ArduinoDevice y Outputs.

54
Figure 3.55: CnctOutputs
Figure 3.54: Connector Mapping: ArduinoDe-
viceHasOutputs

3.3.1 Relaciones Embedding


Una Embedding Relationship o Relación Embebida nos permite ”arrastar y soltar” un elemento
sobre otro en nuestro modelo, sin la necesidad de emplear un conector que enlace los elementos,
como si ocurre en las relaciones referenciales.
Esto es muy útil a la hora de modelar el controlador (véase figura 3.11), ya que esto convierte
a dicho elemento en un contenedor en el que podremos soltar las distintas sentencias. Esto sucede
de igual forma en la relación que existe entre Loop y Condition (véase figura 3.13) o entre los
distintos bucles y su relación con las sentencias (véase figura 3.16).

Un claro ejemplo de estos contenedores se puede observar en la figura 3.48, en el que el con-
trolador almacena todas las sentencias y los distintos bucles guardan su respectiva condición y
las distintas sentencias que se ejecutan en su interior, sin embargo, para poder lograr esto es
necesario realizar unos ajustes a cómo funciona un lenguaje DSL por defecto.

Una limitación que impone DSL es que una Clase de Dominio puede establecer una relación
”embedding” una única vez, ya sea de forma directa o transitiva. Continuando con nuestro ejem-
plo de contenedor, esto quiere decir que un elemento, solo puede ser contenido por un contenedor
a la vez. Observando de nuevo la figura 3.48 se puede apreciar que las sentencias contenidas en
los bucles if y while están a su vez contenidas en el controlador. Esto genera ambigüedad en el
lenguaje, ya que no sabe concretar quién es el contenedor de las sentencias, impidiendo ası́ su
generación.

Para solventar este problema es necesario indicar manualmente al lenguaje quién es el con-
tenedor padre del elemento, esto se hace a través de la propiedad Parent Element Path, la cual
se puede definir a través del enlace entre una Domain Class y su representación en el diagrama,
ya sea ImageShape o GeometryShape.

Figure 3.56: Parent Element Path

55
Figure 3.57: Custom Parent Element Path

La figura 3.56 muestra cómo está definida esta propiedad en la clase Buzzer, la cual no presenta
este problema ya todas las entradas y salidas de nuestro modelo únicamente son embebidas por
el propio dispositivo Arduino y por tanto, no es necesario especificar manualmente su contenedor
padre.
Por el contrario, la figura 3.57 muestra la definición de esta propiedad para la clase Manu-
alSentence, la cual, como se ha explicado previamente presenta este incoveniente de ambigüedad.
Se puede observar que está marcada la casilla ”Has custom parent element” y no se especifica la
ruta de dicho padre, significando esto que le vamos a indicar manualmente cuál es su padre.
Para establecer esta propiedad manualmente se ha creado un fichero de clase auxiliar, Fix-
UpDiagram, la cual contiene un método para cada clase del lenguaje sobre la que queremos
personalizar dicha propiedad.

1 partial class FixUpDiagram


2 {
3 private ModelElement GetParentForManualSentence(ManualSentence manualSentence)
4 {
5 if(manualSentence.If != null)
6 {
7 return manualSentence.If;
8 }
9 else if(manualSentence.For != null)
10 {
11 return manualSentence.For;
12 }
13 else if (manualSentence.While != null)
14 {
15 return manualSentence.While;
16 }
17 else
18 {
19 return manualSentence.Controller;
20 }
21
22 }
23 }

Source Code 3.1: Código Adicional: FixUpDiagram

Como se puede observar en el extracto de código 3.1 obtenido de dicha clase, se declara la
clase FixUpDiagram y uno de sus métodos, lı́nea 3. Este método es el correspondiente a la clase
ManualSentence y por ello recibe una instancia de dicha clase por parámetro. Será invocado cada
vez que se vaya a crear una sentencia manual, para ası́ saber sobre qué clase se está creando la
relación ”embedding” en tiempo de ejecución. Concretamente, lo que el código hace es comprobar
las distintas relaciones de esta sentencia, explicadas en la figura 3.16 y 3.11. devolviendo aquella
que no sea nula, es decir, aquella sobre la que se haya ”soltado” la sentencia.

56
En la clase FixUpDiagram existe un método propio para cada clase hija de Sentence, recibien-
do por parámetro una instancia de dichas clases hijas. La clase Condition también tiene definido
un método propio aunque en este caso se devuelve directamente la clase hija de Loop sobre el que
se está creando la relación. Esto permite la creación de bucles anidados sin ambigüedad sobre
qué condición pertenece a cada bucle.

57
Capı́tulo 4

Arduino Modelling Tool

4.1 Modelado con Arduino Modelling Tool


La herramienta Arduino Modelling Tool permite el modelado de placas Arduino y su lógica de
forma sencilla mediante ”drag and drop”, es decir, arrastrando y soltando los elementos. A
partir de la configuración creada por el usuario, Arduino Modelling Tool es capaz de generar
automáticamente el código para su funcionamiento.
Esta herramienta se compone de un tapiz, una barra de herramientas y un generador de
código. En la Figura 4.1 se puede observar el tapiz, que es la base sobre la que se construye el
diagrama. En la parte izquierda se encuentra la barra de herramientas desde la se arrastran los
elementos hasta el tapiz.

Figure 4.1: Manual de Usuario: Tapiz

El primer elemento que se debe crear en cualquier diagrama será el dispositivo Arduino, ya
que sin él, no se pueden instanciar el resto de elementos. Para crear cualquier elemento desde la
barra de herramientas será necesario hacer clic izquierdo en dicho elemento y arrastarlo hasta el
tapiz. En la Figura 4.2 se puede ver el resultado de esta acción. El zoom del tapiz es totalmente
regulable (Mantenga pulsada tecla CTRL + Rueda del ratón). Además todos los elementos son
reposicionables dentro del tapiz, haciendo clic izquierdo sobre el mismo y arrastrándolo hasta la
posición desesada.

58
Figure 4.2: Manual de Usuario: Crear elemento

Como se explicó durante el modelo, la mayorı́a de clases poseen propie-dades personalizables.


En este caso, Arduino Device, consta de dos propie-dades (véase Figura 3.1). Al hacer clic
derecho sobre el elemento en el tapiz, se accede a las propiedades del mismo (véase Figura 4.3).
Se abrirá una ventana en la que el usuario puede especificar sus propiedades, identificador y
nombre (véase Figura 4.4).

Figure 4.4: Manual de Usuario: modificar


Propiedades

Figure 4.3: Manual de Usuario: acceder a Propiedades

El siguiente paso será incluir las distintas entradas para el sketch, estas se encuentran en el
compartimento Inputs en la barra de herramientas. Para ello seleccionamos la entrada deseada
y la arrastramos dentro del dispositivo Arduino creado previamente.

59
Figure 4.5: Manual de Usuario: Crear Inputs

Todos los elementos del diagrama deben ser ”soltados” en una zona habilitada para ello, estas
han sido definidas gracias a las relaciones de tipo ”embedding” explicadas en la sección 3.1. En
caso de intentar soltar un elemento en una zona incorrecta, la herramienta nos imposibilitará
la acción, cambiando el icono del cursor a un sı́mbolo de ”prohibido” al pasar por una zona
incorrecta.

De igual forma que con el dispositivo Arduino, se pueden modificar las propiedades de las
entradas (véase Figura 4.6), indicando el nombre (opcional) y el número del pin al que será
enchufado (obligatorio).

Figure 4.6: Manual de Usuario: Editar Inputs

Es posible añadir tantas entradas como queramos y en caso de querer eliminar alguna, se po-
drá hacer de dos maneras: haciendo uso de la opción Delete (véase Figura 4.4) o seleccionando
el elemento a eliminar y pulsando la tecla ”Delete” o ”Supr” en el teclado.

Cada vez que se cree una entrada, es necesario asociar una Measure, para ası́ poder almacenar
el valor recopilado. Para ello, desde el apartado principal de la Toolbox se arrastra una Measure
y se deja caer sobre una entrada, ya que es el único sitio en el que la herramienta permite crearla.
De esta forma se crea la medida y un conector que relaciona la misma con la entrada a la que
está asociada (ver Figura 4.7).

60
Figure 4.7: Manual de Usuario: Crear Measure

En las propiedades de Measure se puede modificar su nombre y su Data Type o tipo de datos,
que en la mayorı́a de ocasiones se deberá seleccionar Int, para recopilar valores numéricos (ver
Figura 4.8).

Figure 4.8: Manual de Usuario: Editar Measure

En caso de necesitar traducir el valor leı́do por la entrada, al usar un sensor de temperatura
por ejemplo, será necesario asociar un Value a la medida previamente creada. En las propiedades
de Value se puede seleccionar a qué tipo de escala se desea traducir la medida recopilada (ver
Figura 4.9).

61
Figure 4.9: Manual de Usuario: Editar Value

Una vez incluı́das las entradas necesarias, se debe seguir el mismo procedimiento para las
salidas, sin embargo, para estas no es necesario asociar ninguna Measure o Value. En la figura
3.53 se puede observar un ejemplo de la creación de varias salidas. Destacar el caso del Display,
para el que se deberá especificar en sus propiedades distintos parámetros tales como el número
de filas y columnas que dispone o el mensaje a mostrar (ver Figura 4.10).

Figure 4.10: Manual de Usuario: Editar Display

El último paso será crear la lógica del programa, es decir, las reglas y condiciones por las
que pasará la información recogida por las entradas para ası́ producir unas u otras respuestas a
través de las salidas.
El elemento que almacenará todas las sentencias y bucles será el controlador, por ello será el
primer elemento a crear. Para ello se seguirán los mismos pasos que para las entradas y salidas, se
arrastrará un Controller desde la sección Main de la Toolbox y se dejará caer sobre el dispositivo
Arduino. (ver Figura 4.11)

62
Figure 4.11: Manual de Usuario: Crear Controller

El controlador puede ser reposicionado arrastrándolo por el tapiz y en la mayorı́a de ocasiones,


se deberá aumentar su tamaño para que en su interior se puedan situar todas las sentencias.
Para conseguir esto, basta con situar el puntero sobre una de sus esquinas, hacer clic izquierdo
y arrastar hasta obtener el tamaño deseado. (ver Figura 4.12)

Figure 4.12: Manual de Usuario: Redimensionar Controller

En la sección Logical de la barra de herramientas se encuentran todos los elementos que


se pueden crear dentro de un controlador. El elemento más sencillo será Manual Sentence, un
tipo de sentencia en la que el usuario puede definir completamente su función, a través de su
propiedad Text. Para crearla, se selecciona en la barra de herramientas y se arrastra hasta un
Controller. Para definir su texto, basta con acceder a sus propiedades y especificar la sentencia
(ver Figura 4.13).

63
Figure 4.13: Manual de Usuario: crear ManualSentence

Una parte de suma importancia a la hora de crear sentencias para definir la lógica del pro-
grama es establecer el orden de ejecución entre las mismas. Para ello, se deberá usar el conector
entre sentencias, CnctSentence, generado a partir de la relación SentenceReferencesTargetSen-
tence (ver Figura 3.17). Este conector se encuentra en la barra de herramienta, en la sección
Connectors (Figura 4.14).

Figure 4.14: Manual de Usuario: CnctSentence

Para hacer uso de este conector, se deberá seleccionar, haciendo clic izquierdo en la Toolbox
sobre él. Una vez seleccionado, se sitúa el cursor sobre la sentencia origen, haciendo clic sobre ella
y arrastrando el cursor hasta la sentencia destino. De esta forma se crea un enlace entre ambas,
en el que la flecha al final indica la sentencia destino, es decir, la sentencia que se ejecutará
a continuación de la que se encuentra en el extremo opuesto (ver Figura 4.15). Este conector
permite establecer el orden entre cualquier tipo de sentencia, ya sean sentencias simples o bucles
(ver Figura 3.48).

Figure 4.15: Manual de Usuario: Ordenar Sentencias

Una sentencia de entrada/salida (IOSentence) se comporta de igual forma que una sentencia
manual, sin embargo esta no tiene una propiedad Text para definir la sentencia, sino que se
deberá enlazar a una entrada o salida para que cobre significado. Para hacer esto se hará uso de
otros dos conectores: Controller-Input y Controller-Output (véase Figura 4.16).

64
Figure 4.16: Manual de Usuario: Controller-Input/Output

El uso de estos conectores es muy similar al conector entre sentencias. Una vez seleccionado el
conector, se debe situar el cursor sobre una sentencia IOSentence, hacer clic izquierdo y arrastrar
hasta un Input u Output, en función del tipo de conector seleccionado (Figura 4.17). No se podrá
usar el conector de entradas para enlazar una IOSentence con una salida ni viceversa. Tampoco
se podrá enlazar una IOSentence a más de una entrada o salida.

Figure 4.17: Manual de Usuario: IOSentence

Los bucles comparten caracterı́sticas tanto con las sentencias como con un controlador, ya
que se podrán crear sentencias en su interior y además se podrá establecer el orden de ejecución
de los bucles respecto a otras sentencias. Para crear cualquier bucle lo seleccionamos desde la
barra de herramientas y lo soltamos sobre un controlador. Además se puede modificar su tamaño
de igual forma que un controlador, para poder almacenar sentencias en él (Figura 4.18).

65
Figure 4.18: Manual de Usuario: Crear Bucles

Los bucles for tienen la peculiaridad de que poseen dos propiedades personalizables por el
usuario: la inicialización y el incremento (ver Figura 4.19). Estas propiedades permiten definir
el valor de inicio de la variable que controla el bucle y el incremento que sufre dicha variable
cada vez que se ejecuta el bucle.

Figure 4.19: Manual de Usuario: Propiedades for

Estas dos propiedades junto a una condición de parada completarı́an la definición de un bucle
for. Para establecer dicha condición que indica la finalización de la ejecución del bucle se debe
hacer uso de la clase Condition, la cual se puede crear una vez seleccionada en la barra de tareas
y arrastrando hasta soltarla sobre un bucle (Figura 4.20).

66
Figure 4.20: Manual de Usuario: Crear Condition

En las propiedades de una condición se pueden elegir los dos operandos que van a ser com-
parados y el operador que los compara, siendo Operand1 el operando a la izquierda del operador
y Operand2 el situado a la derecha (ver Figura 4.21).

Figure 4.21: Manual de Usuario: Propiedades Condition

Definiendo las propiedades tal y como se muestra en la Figura 4.21, quedarı́a una condición
de parada del bucle tal que i ¡ 10, que junto a las propiedades del bucle for definidas en la Figura
4.19, resultarı́a un bucle que comienza a ”contar” desde 0, incrementando dicha variable en 1
cada vez que se ejecuta el bucle mientras que dicha variable sea menor que 10, es decir, hasta 9.
En resumen, un bucle que ejecuta las sentencias que hay en su interior 10 veces.

Este comportamiento se podrı́a conseguir de igual forma haciendo uso de un bucle while.
Para ello, se define una sentencia manual que crea la variable ”contador” y la inicializa al valor
0. A continuación, se crea un bucle while con la misma condición que se ha explicado para el

67
bucle for previo (ver Figura 4.21), solo que esta vez en la propiedad Operand1 debemos indicar
la variable ”contador”. Importante establecer el orden correcto entre la sentencia manual y el
bucle, ya que es necesario definir primero la variable contador antes de utilizarla en el bucle.
Por último, creamos otra sentencia manual dentro del bucle, que será la que modifique el
valor de la variable contador para evitar que se produzca un bucle infinito. De nuevo, el resultado
es un bucle que ejecuta lo que hay en su interior 10 veces, en la figura 4.22 se puede observar un
posible ejemplo de ello.

Figure 4.22: Manual de Usuario: Ejemplo while

68
4.2 Patrón de Generación automática de código para Ar-
duino
El siguiente objetivo será generar un fichero con extensión .ino para ası́ cargarlo en un dispositivo
Arudino. Dicho fichero se deberá crear a partir de los elementos que se han modelado con la
herramienta en el diagrama, de tal forma que contenga el código adecuado para dar soporte a los
componentes conectados a la placa y se trate la información con las reglas definidas en la parte
lógica del sketch.
Para ello, es necesario implementar un patrón de generación de código gracias a la facilidad de
las plantillas .tt que ofrece Visual Studio. Estas plantillas .tt, que leen el diagrama creado y
producen el fichero con la extensión que indicada y el código correspondiente. La extensión del
archivo de salida se ha determinado gracias a la siguiente lı́nea de código, indicada al principio
del fichero que permite su configuración (ver Código 4.1). El campo requires indica el diagrama
sobre el que se debe basar la plantilla para generar el código.

1 <#@ output extension=".ino" #>


2 <#@ Arduino processor="ArduinoDirectiveProcessor" requires="fileName='Arduino1.Arduino'" #>

Source Code 4.1: Configuración: Output Extension

Como se explicó en la sección de 2.2.3, todo sketch de Arduino se compone de dos métodos:
void setup() y void loop(). Antes de estos podremos inicializar, en caso de que sea necesario,
algunos compoonentes o variables, además de incluir algunas librerı́as externas, necesarias para
el correcto funcionamiento de algunos componentes. Es por esto mismo que se ha dividio la
plantilla de generación de código en tres secciones, cada una correspondiente a las tres partes de
las que consta un sketch de Arduino.

1 if(this.ArduinoDeviceModel != null)
2 {
3
4 if (this.ArduinoDeviceModel.ArduinoDevice != null)
5 {
6 if(this.ArduinoDeviceModel.ArduinoDevice.Inputs != null)
7 {
8 foreach(Inputs input in this.ArduinoDeviceModel.ArduinoDevice.Inputs)
9 {
10 newInput(input);
11 newMeasure(input.Measure);
12 }
13 }
14 if(this.ArduinoDeviceModel.ArduinoDevice.Outputs != null)
15 {
16 foreach(Outputs output in this.ArduinoDeviceModel.ArduinoDevice.Outputs)
17 {
18 newOutput(output);
19 }
20 }
21
22 }
23 }

Source Code 4.2: Generación: Código Previo

La inyección de código se produce a través del método WriteLine(), por tanto el concepto
principal de la generación de código será recorrer el modelo que se ha creado e inyectar el código
correspondiente. La primera de inicialización se muestra en el fragmento 4.2 comprobamos la
existencia de un ArduinoDevice y por cada Input y Output incluido se invocan los métodos

69
correspondientes para crear dichos elementos. Estos métodos son newInput() para las entradas
y newOutput() para las salidas.

1 <#+
2 private void newInput(Inputs input)//Method to create an input
3 {
4 if(input is ManualInput || input is Sensor)
5 {
6 WriteLine("int "+ input.Name + " = " + input.PinNumber + ";");
7 }
8 }
9 #>

Source Code 4.3: Método: newInput(Inputs input)

El método newInput() (Código 4.3) recibe por parámetro un Input, del que se leen sus
propiedades para declarar dicho elemento e indicar el pin al que lo enchufaremos fı́sicamente
en la placa Arduino. Además necesitaremos inyectar el códgio correspondiente a la Measure
asociada al Input para poder almacenar el valor recogido. Para ello, en función de la opción que
se haya seleccionado en las propiedades de dicha medida se creará un tipo de variable u otro (ver
Código 4.4).

1 <#+
2 private void newMeasure(Measure measure) //Method to create a measure
3 {
4 switch(measure.DataType.ToString())
5 {
6 case "Int":
7 WriteLine("int " + measure.Name + " = 0;");
8 break;
9 case "String":
10 WriteLine("String " + measure.Name + " = null;");
11 break;
12 case "Bool":
13 WriteLine("bool " + measure.Name + " = false;");
14 break;
15 case "Double":
16 WriteLine("double " + measure.Name + " = 0;");
17 break;
18 }
19
20 }
21 #>

Source Code 4.4: Método: newMeasure(Measure measure)

70
1 private void newOutput(Outputs output){ //Method to create an output
2 if(output is EnvironmentalOutputs)
3 {
4 if(output is LED || output is DCMotor || output is Buzzer)
5 {
6 EnvironmentalOutputs envO = (EnvironmentalOutputs) output;
7 WriteLine("int "+ envO.Name + " = " + envO.PinNumber + ";");
8 }
9 else if(output is Display)
10 {
11 WriteLine("#include <LiquidCrystal.h>");
12 WriteLine("LiquidCrystal " + output.Name + "(12, 11, 5, 4, 3, 2); //Default pins (can
,→ be changed)");
13 }
14 }
15 }

Source Code 4.5: Método: newOutput(Outputs output)

El método newOutput() es bastante similar a newInput(), comprueba el tipo de input del que
se trata e inyecta el código correspondiente. Se ha de resaltar que para el uso de un Display será
necesario importar la librerı́a que se indica en el código.
Con esta primera parte de inyección de cógido y sus métodos auxiliares ya se genera el código
previo necesario. Lo siguiente será crear el método void setup().

1 <#
2 //Generating the void setup() method
3
4 if(this.ArduinoDeviceModel != null)
5 {
6 WriteLine("void setup(){");
7 WriteLine("");
8 WriteLine("Serial.begin(9600);");
9 if (this.ArduinoDeviceModel.ArduinoDevice != null)
10 {
11 foreach(Inputs input in this.ArduinoDeviceModel.ArduinoDevice.Inputs)
12 {
13 setUpInput(input);
14 }
15 foreach(Outputs output in this.ArduinoDeviceModel.ArduinoDevice.Outputs)
16 {
17 setUpOutput(output);
18 }
19
20 }
21 WriteLine("");
22 WriteLine("}");
23 }
24
25 #>

Source Code 4.6: Generación: void setup()

La estructura de la segunda parte correspondiente al método void setup() es bastante similar


a la generación del código previo (ver Código 4.6). En primer lugar es necesario establecer la
comunicación entre el ordenador y la placa Arduino con la sentencia Serial.begin(9600); Pos-
teriormente, se ha de recorrer el diagrama en busca de Inputs y Outputs, los cuales son los
parámetros de los métodos setUpInput() (ver Código 4.7) y setUpOutput() (ver Código 4.8).

71
1 private void setUpInput(Inputs input){ //Method to set up an input
2 if(input is ManualInput)
3 {
4 WriteLine(" pinMode("+ input.Name + ", INPUT); //Optional");
5 }
6 else if(input is Sensor)
7 {
8 if(input is IRSensor)
9 {
10 WriteLine(" pinMode("+ input.Name + ", INPUT);");
11 }
12 }
13 }

Source Code 4.7: Método: setUpInput(Inputs input)

El método pinMode(pin, mode) recibe por parámetro el pin al que se ha enchufado el com-
ponente a la placa o en su defecto, el nombre asignado en el código previo y el modo en el que
se va a inicializar. Como se trata de una entrada, en este caso es INPUT, aunque en muchas
ocasiones se puede omitir.

1 private void setUpOutput(Outputs output)//Method to set up an output


2 {
3 if(output is EnvironmentalOutputs)
4 {
5 if(output is LED || output is DCMotor)
6 {
7 WriteLine(" pinMode("+ output.Name + ", OUTPUT);");
8 }
9 else if(output is Display)
10 {
11 Display display = (Display)output;
12 WriteLine(" " + display.Name +".begin("+ display.Columns +", " + display.Rows + ");");
13 }
14 }
15 }

Source Code 4.8: Método: setUpOutput(Outputs output)

Se hace lo mismo con las salidas, solo que esta vez se usa el modo OUTPUT en el método
pinMode(). Se ha de tener en cuenta que un Display tiene un tratamiento distinto ya que es
necesario indicar el número de filas y columnas del que se dispone. Tras esto solo queda generar
el código del método void loop().

72
1 <#
2 //Generating the void loop() method
3
4 if(this.ArduinoDeviceModel != null)
5 {
6 WriteLine("void loop()");
7 WriteLine("{");
8 if (this.ArduinoDeviceModel.ArduinoDevice != null)
9 {
10 if(this.ArduinoDeviceModel.ArduinoDevice != null)
11 {
12 foreach(Controller controller in this.ArduinoDeviceModel.ArduinoDevice.Controller)
13 {
14 newController(controller);
15 }
16 }
17
18 }
19 WriteLine("");
20 WriteLine("}");
21 }
22
23 #>

Source Code 4.9: Generación: void loop()

Para generar el método void loop() se buscan los controladores que se hayan creado en el
diagrama y por cada uno de ellos se llamará al método newController() (ver Código 4.10).
Este método (Fragmento de Código 4.10) crea las sentencias asignadas al controlador que recibe
por parámetro gracias al método newSentence, pudiendo generar ası́ la lógica del sketch. En
caso de que existan sentencias en el controlador (Código 4.10, lı́nea 3), se buscará la primera
sentencia según el orden que haya definido el usuario y se pasará dicha sentencia por parámetro
a newSentence() (Código 4.10, lı́nea 9).

1 private void newController(Controller controller){ //Method to create a controller


2
3 if(controller.Sentence.Count != 0)
4 {
5 foreach(Sentence sentence in controller.Sentence)//looking for the first sentence
6 {
7 if(sentence.SourceSentence == null)
8 {
9 newSentence(sentence);
10 }
11 }
12 }
13 }

Source Code 4.10: Método: newController(Controller controller)

El método para crear las sentencias es bastante sencillo, se realiza un ”casting” dependiendo
del tipo de sentencia que se trate y se invoca el método correspondiente para la creación de la
sentencia hija ya que la clase es abstracta (ver Código 4.11).

73
1 <#+
2 private void newSentence(Sentence sentence){ //Method to create a simple sentence
3 if(sentence is SimpleSentence)
4 {
5 SimpleSentence ss = (SimpleSentence) sentence;
6 newSimpleSentence(ss);
7
8 }
9 else if(sentence is Loop)
10 {
11 Loop loop = (Loop) sentence;
12 newLoopSentence(loop);
13 }
14 }
15 #>

Source Code 4.11: Método: newSentence(Sentence sentence)

El método newSimpleSentence() recibe por parámetro una sentencia de tipo simple, la cual
es abstracta, por lo que hay que comprobar de qué tipo de sentencia hija se trata y de nuevo,
realizar un ”casting” (ver Código 4.12). En caso de tratarse de una sentencia manual, el usuario
habrá definido en el parámetro Text el código a inyectar, por lo que se recupera esa información
y la generamos. Si se trata de un Delay, se inyecta el propio método delay(int duration) y se lee
la duración que el usuario haya indicado.
Por último queda la sentencia IOSentence, que al ser algo más compleja invoca a su propio
método de generación. En cualquiera de los casos, hay que comprobar la existencia de posibles
sentencias que haya a continuación de estas, de ahı́ la necesidad de la relación referencial de
Sentence a otra Sentence explicada previamente. En caso de existir sentencias siguientes, se
invoca el método de creación de sentencias para repetir todo este proceso hasta que no haya
sentencias siguientes.

1 private void newSimpleSentence(SimpleSentence ss)//Method to create a simple sentence


2 {
3 if(ss is ManualSentence)
4 {
5 ManualSentence manualSentence = (ManualSentence) ss;
6 WriteLine(" " + manualSentence.Text);
7
8 if(manualSentence.TargetSentence != null)//checking for next sentence
9 {
10 newSentence(manualSentence.TargetSentence);
11 }
12 }
13 else if(ss is Delay)
14 {
15 Delay delaySentence = (Delay) ss;
16 WriteLine(" delay(" + delaySentence.Duration + "); // Delay duration in milliseconds");
17
18 if(delaySentence.TargetSentence != null)//checking for next sentence
19 {
20 newSentence(delaySentence.TargetSentence);
21 }
22 }
23 else if(ss is IOSentence)
24 {
25 IOSentence ioSentence = (IOSentence) ss;
26 newIOSentence(ioSentence);
27 if(ioSentence.TargetSentence != null)//checking for next sentence
28 {
29 newSentence(ioSentence.TargetSentence);
30 }
31 }
32
33 }

Source Code 4.12: Método: newSimpleSentence(SimpleSentence ss)

74
Para generar una sentencia de lectura o escritura se hace uso del método newIOSentence(), el
cual recibe una sentencia de este tipo por parámetro. Esta sentencia tiene referenciado una única
entrada o salida, nunca ambas o ninguna, en cuyo caso se muestra un mensaje para indicárselo
al usuario. En caso de haber enlazado una salida, se invoca el método loopOutput, si es una
entrada se invocan los métodos correspondientes para tratar la información de una entrada.
Para almacenar en la medida el valor leı́do por la entrada, se utiliza el método setMeasure() y
en caso de que sea necesario traducir dicho valor, se llama al método setValue(), recibiendo por
parámetro dicha Measure.

1 private void newIOSentence(IOSentence ioSentence)


2 {
3 if((ioSentence.Outputs != null && ioSentence.Inputs != null)
4 || (ioSentence.Outputs == null && ioSentence.Inputs == null))
5 {
6 WriteLine("//An IOSentence must be linked either to an Input or an Output");
7 }
8 else if(ioSentence.Outputs != null)
9 {
10 loopOutput(ioSentence.Outputs);
11 }
12 else if(ioSentence.Inputs != null)
13 {
14 setMeasure(ioSentence.Inputs.Measure);
15 loopInput(ioSentence.Inputs);
16 if(ioSentence.Inputs.Measure.Value != null)
17 {
18 setValue(ioSentence.Inputs.Measure);
19 }
20 }
21 }

Source Code 4.13: Método: newIOSentence(IOSentence ioSentence)

Tanto el método loopInput() como loopOutput() (ver Código 4.14 y 4.15, respectivamente), son
invocados en newIOSentence(), ver4.13, lı́neas 10 y 15. Ambos métodos son bastantes similares,
se recibe por parámetro el elemento sobre el que se ha de crear la sentencia para leer o escribir
información. dependiendo del componente en concreto será necesario inyectar un método u
otro, por tanto, estos métodos se basan en comprobar qué tipo de componente se ha pasado
por parámetro y generar la sentencia adecuada. Por ejemplo, para recopilar información desde
cualquier tipo de sensor, será necesario el método analogRead(pin), recibiendo por parámetro el
nombre o pin al que está enchufado dicha entrada (ver Código 4.14, lı́nea 17). [16]

1 <#
2 private void loopInput(Inputs input) //Method to loop an input
3 {
4 if(input is ManualInput)
5 {
6 if(input is Switch)
7 {
8 WriteLine(" digitalRead("+ input.Name + ");");
9 }
10 else if(input is Potentiometer)
11 {
12 WriteLine(" analogRead("+ input.Name + ");");
13 }
14
15 }else if(input is Sensor)
16 {
17 WriteLine(" analogRead("+ input.Name + ");");
18 }
19 }
20 #>

Source Code 4.14: Método: loopInput(Inputs input)

75
1 <#
2 private void loopOutput(Outputs output)
3 {
4 if(output is Terminal)
5 {
6 Terminal terminal = (Terminal)output;
7 WriteLine(" Serial.print("+ terminal.Message + ");");
8 }
9 else if(output is EnvironmentalOutputs)
10 {
11 if(output is LED)
12 {
13 WriteLine(" digitalWrite("+ output.Name +", HIGH); //use LOW to turn off the LED");
14 }
15 if(output is Buzzer)
16 {
17 Buzzer buzzer = (Buzzer)output;
18 if(buzzer.Duration != 0)
19 {
20 WriteLine(" tone(" + buzzer.Name + ", " + buzzer.Frequency + ", " + buzzer.Duration +
,→ "); //duration parameter is optional and noTone(buzzer.Name) can be used instead");
21 }
22 else
23 {
24 WriteLine(" tone(" + buzzer.Name + ", " + buzzer.Frequency + "); //use
,→ noTone(buzzer.Name) to turn the buzzer off");
25 }
26 }
27 if(output is DCMotor)
28 {
29 DCMotor dcMotor = (DCMotor)output;
30 WriteLine(" analogWrite(" + dcMotor.Name + ", " + dcMotor.Speed + "); //Speed must be
,→ between 0 and 255");
31 }
32 if(output is Display)
33 {
34 Display display = (Display)output;
35 WriteLine(" " + display.Name + ".clear();");
36 WriteLine(" " + display.Name + ".setCursor(0,0);");
37 WriteLine(" " + display.Name + ".print(" + display.Message + ");");
38 }
39 }
40 }
41 #>

Source Code 4.15: Método: loopOutput(Outputs output)

Una de las partes más importantes en cualquier lenguaje de programación son los bucles y las
condiciones. Para generarlos, se hace uso del método newLoopSentence, que recibe por parámetro
una sentencia de tipo loop. Como se ha explicado previamente, la clase Loop es abstracta y es
padre de las clases While, For e If, por tanto lo primero que hace este método es comprobar de
qué tipo es el parámetro que se le ha pasado para ası́ tratarlo de una forma u otra.
En cualquiera de los casos se genera la condición de parada de dicho bucle haciendo uso del
método newCondition(). Al igual que en el método newController() (véase Fragmento de código
4.10), hay que buscar la primera sentencia siguiendo el orden que ha definido el usuario. Destacar
también que para el bucle for se registran las propiedas definidas por el usuario para inyectar el
código correspondiente a su inicialización e incremento.

76
1 private void newLoopSentence(Loop loop)//Method to create a loop
2 {
3 if(loop is If){
4 Write(" if (");
5 newCondition(loop);
6 WriteLine(")");
7 WriteLine(" {");
8 If ifLoop = (If) loop;
9 if(ifLoop.Sentence.Count != 0)//checking for sentences inside the loop
10 {
11 foreach(Sentence sentence in ifLoop.Sentence)//looking for the first sentence
12 {
13 if(sentence.SourceSentence == null)
14 {
15 newSentence(sentence);
16 }
17 }
18 }
19 WriteLine(" }");
20 if(ifLoop.TargetSentence != null)//checking for sentences after the loop
21 {
22 newSentence(ifLoop.TargetSentence);
23 }
24 }else if(loop is For){
25 For forLoop = (For)loop;
26 Write(" for (" + forLoop.Initialization + "; ");
27 newCondition(forLoop);
28 WriteLine(" ; " + forLoop.Increment + ")");
29 WriteLine(" {");
30 if(forLoop.Sentence.Count != 0)//checking for sentences inside the loop
31 {
32 foreach(Sentence sentence in forLoop.Sentence)//looking for the first sentence
33 {
34 if(sentence.SourceSentence == null)
35 {
36 newSentence(sentence);
37 }
38 }
39 }
40 WriteLine(" }");
41 if(forLoop.TargetSentence != null)//checking for sentences after the loop
42 {
43 newSentence(forLoop.TargetSentence);
44 }
45 } else if(loop is While)
46 {
47 //...
48 }
49 }

Source Code 4.16: Método: newLoopSentence(Loop loop)

Para inyectar el código correspondiente a la condición asociada a un bucle, se le pasa dicho


bucle por parámetro y se revisan las condiciones que tiene asociadas, ya que puede tratarse de
una condición múltiple. Como ya se ha visto en el apartado 3.1 Modelo, una condición está
formada por dos operandos y operador, ası́ que se accede a dichas propiedades de la clase y se
genera el código correspondiente.

1 private void newCondition(Loop loop)


2 {
3 foreach(Condition condition in loop.Condition)
4 {
5 Write(condition.Operand1 + " ");
6 newOperator(condition);
7 Write(" " + condition.Operand2);
8 }
9 }

Source Code 4.17: Método: newCondition(Loop loop)

77
1 private void newOperator(Condition condition)
2 {
3 switch(condition.Operator.ToString()){
4 case "And":
5 Write("&&");
6 break;
7 case "Equals":
8 Write("==");
9 break;
10 case "Greater":
11 Write(">");
12 break;
13 case "GreaterOrEquals":
14 Write(">=");
15 break;
16 case "Lesser":
17 Write("<");
18 break;
19 case "LesserOrEquals":
20 Write("<=");
21 break;
22 case "NotEquals":
23 Write("!=");
24 break;
25 case "Or":
26 Write("||");
27 break;
28 }
29 }

Source Code 4.18: Método: newOperator(Condition condition)

De esta forma, quedan explicados los métodos que contiene la plantilla de generación de
código empleada para generar todo el código que da soporte al diagrama creado por el usuario
en la interfaz gráfica.

78
4.3 Desplegando código Arduino con Arduino Modelling
Tool
En esta sección se va a explicar el flujo de trabajo o los distintos pasos a seguir para crear un
modelo concreto en Arduino Modelling Tool hasta desplegar el código generado automáticamente
por la herramienta (sketch) en el dispositivo Arduino.
Una vez ejecutada la herramienta, para crear un nuevo modelo desde el que generar código,
hay que dirigirse a parte derecha, Solution Explorer. Se debe hace clic derecho sobre el apartado
Debugging - Add - New Item... (ver Figura 4.23).

Figure 4.23: Flujo de Trabajo: New Item...

Se abrirá esta ventana en la que se puede crear cualquier tipo de elemento. Para crear un
tapiz sobre el que crear modelo, se debe elegir un fichero tipo Arduino, se puede buscar utilizando
el buscador de la esquina superior derecha. En la parte inferior se puede modificar el nombre del
fichero que se ofrece por defecto a uno representativo del modelo que se va a crear. Por último,
se debe pulsar el botón Add para terminar este proceso (ver Figura 4.24).

79
Figure 4.24: Flujo de Trabajo: Creando fichero Arduino

Una vez hecho esto, se habrá creado un modelo sobre el que modelar los elementos del sistema
Arduino que se desea diseñar. Este archivo se puede visualizar en el Solution Explorer (ver Figura
4.25)

Figure 4.25: Flujo de Trabajo: Fichero Arduino en Solution Explorer

Para abrir este archivo, basta con hacer doble clic sobre él en el explorador de soluciones.
Se abrirá un tapiz con la interfaz gráfica para construir un modelo. A modo ilustrativo, se ha
creado un modelo de ejemplo (ver Figura 4.26) sobre el que se generará el código.

80
Figure 4.26: Flujo de Trabajo: Ejemplo Modelo

Una vez creado el modelo, hay que abrir la plantilla de generación de código y modificar el
campo que indica el fichero Arduino sobre el que se debe generar el código (ver Código 4.1). Para
este caso, hay que indicar NewSketch.Arduino, que es el fichero sobre el que se está trabajando.
En el Código 4.19 se puede observar el resultado de esta modificación. Esto se debe de hacer
únicamente si se ha creado un nuevo modelo, la herramienta proporciona un modelo en blanco
por defecto. En caso de utilizar este modelo inicial, no es necesario modificar este parámetro en
ningún momento.

1 <#@ output extension=".ino" #>


2 <#@ Arduino processor="ArduinoDirectiveProcessor" requires="fileName='NewSketch.Arduino'" #>

Source Code 4.19: Flujo de Trabajo: Modificar Código

Al guardar los cambios realizados en la plantilla y en el modelo, se actualizará el archivo


Plantilla1.ino, que contiene el código generado (ver Figura 4.27). En caso de realizar algún
cambio en el modelo, se deberá guardar la plantilla de nuevo para que vuelva a generar código,
refrescando ası́ los cambios en el archivo .ino.

81
Figure 4.27: Flujo de Trabajo: Plantilla1.ino

Por último, se debe copiar el código generado en el IDE Arduino (ver Figura 4.28) para poder,
en última instancia, subir el código al dispositivo Arduino conectado al ordenador. Se deberá
reproducir fı́sicamente la configuración realizada en el modelo de Arduino Modelling Tool para
comprobar que el código y el diseño se comportan correctamente.

Figure 4.28: Flujo de Trabajo: Copiar Código en Arduino IDE

82
Capı́tulo 5

Prueba y validación del lenguaje

En este capı́tulo se lleva a cabo el objetivo del trabajo fin de carrera de Diseñar un conjunto
de pruebas que validan la completitud del lenguaje, construyendo diferentes configuraciones de
Arduino y generando diferentes programas.
Para ello, se han diseñado un total cuatro pruebas de modelado y generación en las que se varı́a
su complejidad y se emplean diferentes tipos de sensores, actuadores, ası́ cómo la lógica asociada,
utilizando diferentes estructuras de control de programación. En esta baterı́a de pruebas es
posible observar el flujo de información recopilado por las diferentes entradas y cómo afecta,
siguiendo la lógica del código, a las diferentes salidas empleadas.

5.1 Sketch: Blink


La primera prueba que se presenta se ha explicado en la sección 2.2.4, Blink. El objetivo de
ese programa es conseguir que un LED conectado a la placa se encienda y apague de forma
intermitente con un segundo de espera entre las acciones de encendido y apagado.
Para empezar, hay que identificar las entradas necesarias. En este caso no será necesaria
ninguna, ya que no se requiere recopilar información del entorno. El siguiente paso será crear las
salidas, que únicamente será un LED (ver Figura 5.1).

Figure 5.1: Blink : Crear Salidas

En la pestaña de propiedades se asigna el nombre del LED y el PinNumber al que estará


enchufado en la placa, que normalmente será el 13 (véase Figura 5.2).

83
Figure 5.2: Blink : Propiedades LED

Además, hay que establecer las reglas por las que se rigen las salidas definidas, crear la lógica
del Sketch. Para este primer programa, la lógica será sencilla, únicamente se necesita incluir un
retraso entre cada encendido y apagado del LED. El orden necesario es el siguiente: encender
LED, esperar un segundo, apagar LED, esperar un segundo y vuelta a empezar. Por tanto serán
necesarias dos sentencias de entrada/salida y dos sentencias de Delay, como se muestra en la
Figura 5.3.

Figure 5.3: Blink : Crear sentencias

A continuación, utilizando el conector entre sentencias, se establece el orden adecuado (Figura


5.4).

84
Figure 5.4: Blink : Ordenar sentencias

Por último, se enlazan las sentencias de entrada/salida con el LED, utilizando el conector
desde controlador a salida y se establece la duración del retraso en milisegundos (Figura 5.5).

Figure 5.5: Blink : Completar sentencias

Al actualizar la plantilla de generación, se genera el código, el resultado de dicho proceso


es el siguiente archivo .ino (ver Código 5.1), del cual se debe modificar el segundo método
digitalWrite(), indicando LOW como segundo parámetro para que se apague el LED.

85
1 int led = 13;
2
3 void setup() {
4
5 pinMode(led, OUTPUT);
6 }
7
8 void loop() {
9 digitalWrite(led, HIGH);
10 delay(1000);
11 digitalWrite(led, LOW);
12 delay(1000);
13 }

Source Code 5.1: Blink : Código generado

En la figura 5.18 se muestra la disposición fı́sica de los elementos empleados. Se debe observar
cómo el led está conectado al pin número 13, tal como se ha indicado en el código.

Figure 5.6: Blink : Circuito

El resultado del montaje del circuito, ası́ como una muestra de su ejecución se puede observar
en las figuras 2.20 y 2.21. El código utilizado para esa demostración (ver Código 2.2) es el mismo
que se ha generado en esta prueba (ver Código 5.1).

86
5.2 Sketch: Imprimir Matriz Temperaturas
En la siguiente prueba se muestra cómo se puede crear un programa en el que se recopila la
información de cualquier input, en este caso será un sensor de temperatura y se muestran por
pantallas dichos valores, formando una matriz. Además, se mostrará la posibilidad que ofrece la
herramienta de crear bucles anidados necesarios para crear la forma de matriz.
La metodologı́a a seguir será la misma que en el ejemplo anterior, primero, se identifican
las entradas, que únicamente será un sensor de temperatura, con su correspondiente Measure y
Value, para poder tratar los datos (Figura 5.7).

Figure 5.7: Sketch Matriz Temperaturas: Crear entradas

Como la salida se imprimirá por pantalla, es necesario crear una salida Terminal, que muestre
el valor almacenado en temperature (Figura 5.8).

Figure 5.8: Sketch Matriz Temperaturas: Crear salidas

Queda definir la lógica del programa, la cual consiste básicamente en dos bucles for anidados
que serán capaces de generar la matriz. Se ha decidido que la matriz sea de 10x10, por tanto,
los bucles se repetirán diez veces. En la Figura 5.9 se puede observar cómo se ha definido el
primer bucle y su condición, siendo igual para el bucle anidado salvo que para este se utilizará
otra variable.

87
Figure 5.9: Sketch Matriz Temperaturas: Propiedades bucle y condición

En la Figura 5.10 se presenta el resultado final del controlador del programa. El orden de las
secuencias es el siguiente: primero se ejecuta el bucle for que representa las filas de la matriz,
imprimiendo por pantalla un salto de lı́nea cada vez. Tras esto, se accede al bucle anidado, que
se encarga de imprimir las columnas de la matriz. Cada vez que se ejecute este bucle, el sensor
de temperatura enlazado a la primera IOSentence, recupera la temperatura actual y la traduce
a Celsius. A continuación, la siguiente sentencia enlazada a la salida Terminal, imprime por
pantalla el valor almacenado en temperature. Por último, se imprime un espacio y se espera un
minuto antes de continuar con la ejecución del bucle.

Figure 5.10: Sketch Matriz Temperaturas: Controlador

Se puede observar la vista general del tapiz en la Figura 5.11.

88
Figure 5.11: Sketch Matriz Temperaturas: Vista General

El código generado a partir del modelo realizado se puede observar en el Fragmento 5.2.

1 int tempPin = 13;


2 int temperature = 0;
3
4 void setup()
5 {
6 Serial.begin(9600);
7
8 }
9
10 void loop()
11 {
12 for (int i = 0; i < 10 ; i++)
13 {
14 Serial.println("");
15 for (int j = 0; j < 10 ; j++)
16 {
17 temperature = analogRead(tempPin);
18 temperature = temperature * 0.48828125; //convert output to readable Celsius
19 Serial.print(temperature);
20 Serial.print(" ");
21 delay(60000); // Delay duration in milliseconds
22 }
23 }
24
25 }

Source Code 5.2: Sketch Matriz Temperaturas: Código Generado

89
5.3 Sketch: Sensor de Proximidad
En este sketch, se construirá un sensor de proximidad. Para ello, se utilizará un sensor de
infrarrojos como el de la Figura 2.8. Esta será la única entrada utilizada, mientras que la salidas
serán un zumbador (ver Figura 2.12) y dos leds de distintos colores (ver Figura 2.10).
La lógica propuesta para este sketch es la siguiente: cuando el sensor de infrarrojos detecte
un objeto cercano, deberá avisar al usuario de ello. Para esto, se activará el zumbador, emitiendo
un pitido intermitente y se encenderá un led de color rojo. Mientras que no haya ningún objeto
cercano, se mantendrá encendido un led de color verde.
De nuevo, se construyen primero las entradas en Arduino Modelling Tool. Se creará una
entrada IRSensor y se asocia una Measure en la cual se almacena el valor leı́do. Se personalizan
las propiedades de estos elementos, asociando un nombre a cada una e indicando el pin en el que
se enchufará fı́sicamente el sensor, que en este caso será el pin número 3. El resultado de este
proceso se puede observar en la Figura 5.12.

Figure 5.12: Sketch Sensor de Proximidad: Crear Entradas

A continuación, se añaden las salidas. Como se ha explicado previamente, se va a utilizar


un Buzzer y dos LED que se pueden crear desde la Toolbox. De igual forma que a las entradas,
se les asigna un nombre utilizando sus propiedades y un PinNumber. Destacar las propiedades
de un Buzzer, en las que además del nombre y el PinNumber, se debe especificar la frecuencia
de sonido del pitido y la duración del mismo, siendo esta última propiedad opcional (ver Figura
5.13). El modelo quedarı́a tras añadir las salidas de la siguiente forma (ver Figura 5.14):

Figure 5.13: Sketch Sensor de Proximidad: Propiedades Salidas

90
Figure 5.14: Sketch Sensor de Proximidad: Crear Salidas

Para crear la lógica explicada, se necesitarán dos condiciones que ejecuten sentencias difer-
entes en función de la información recibida por el sensor. Cuando el sensor detecta un objeto,
emite una señal igual al valor 0, entonces el Buzzer debe emitir un pitido, se debe encender el
led rojo y apagar el led verde. Cuando la Measure del sensor sea igual a 1, significa que no hay
ningún objeto cerca y por tanto, se debe encender el led verde y apagar el rojo.
Se empieza por crear la estructura general de la lógica, para ello se hará uso de un Controller
que almacenará todas las sentencias. Se necesita una sentencia IOSentence enlazada al IRSensor
para leer la información y guardarla en la Measure. Posteriormente, se llegará a los bucles If con
sus respectivas condiciones. Por último, se añade un Delay para evitar la ejecución continua del
programa (ver Figura 5.15).

91
Figure 5.15: Sketch Sensor de Proximidad: Lógica general

En las condiciones es necesario comparar el valor guardado en sensorMeasure con un 1 o 0,


para ejecutar las acciones en las salidas explicadas anteriomente. En las Figuras 5.16 y 5.17, se
muestran las condiciones del primer y segundo If, respectivamente.

Figure 5.16: Sketch Sensor de Proximidad: Condición 1 Figure 5.17: Sketch Sensor de Proximidad: Condición 2

Si se cumple la primera condición, significa que ha detectado algún objeto cercano, por tanto,
se debe activar tanto el zumbador como el led de color rojo y apagar el verde. Por tanto, se
necesitarán tres sentencias de entrada/salida, cada una enlazada a una salida. Cuando se cumpla
la segunda condición, se debe apagar el led de color rojo y encender verde. Por ello, se necesitarán
únicamente dos sentencias IOSentence enlazadas a estas salidas.
El resultado de crear estas sentencias y enlazarlas a sus respectivas salidas y con ello, el
aspecto final del diagrama, se puede observar en la Figura 5.18.

92
Figure 5.18: Sketch Sensor de Proximidad: Diagrama General

El archivo .ino generado contiene el código mostrado en Código 5.3 del cual hay que realizar
únicamente dos modificaciones. Estas modificaciones serán en las lı́neas 23 y 28, para apagar el
led correspondiente según el valor leı́do por el sensor. Esto se consigue pasando como segundo
parámetro el valor LOW en lugar de HIGH. Se puede observar el resultado final del código en
Código 5.4.

93
1 int irSensor = 3;
2 int sensorMeasure = 0;
3 int ledVerde = 6;
4 int ledRojo = 5;
5 int buzzer = 10;
6
7 void setup()
8 {
9 Serial.begin(9600);
10 pinMode(irSensor, INPUT);
11 pinMode(ledVerde, OUTPUT);
12 pinMode(ledRojo, OUTPUT);
13
14 }
15
16 void loop()
17 {
18 sensorMeasure = digitalRead(irSensor);
19 if (sensorMeasure == 0)
20 {
21 tone(buzzer, 800, 500); //duration parameter is optional and noTone(buzzer.Name) can be used
,→ instead
22 digitalWrite(ledRojo, HIGH); //use LOW to turn off the LED
23 digitalWrite(ledVerde, HIGH); //use LOW to turn off the LED
24 }
25 if (sensorMeasure == 1)
26 {
27 digitalWrite(ledVerde, HIGH); //use LOW to turn off the LED
28 digitalWrite(ledRojo, HIGH); //use LOW to turn off the LED
29 }
30 delay(1000); // Delay duration in milliseconds
31
32 }

Source Code 5.3: Sketch Sensor de Proximidad: Código generado

1 int irSensor = 3;
2 int sensorMeasure = 0;
3 int ledVerde = 6;
4 int ledRojo = 5;
5 int buzzer = 10;
6
7 void setup()
8 {
9 Serial.begin(9600);
10 pinMode(irSensor, INPUT);
11 pinMode(ledVerde, OUTPUT);
12 pinMode(ledRojo, OUTPUT);
13
14 }
15
16 void loop()
17 {
18 sensorMeasure = digitalRead(irSensor);
19 if (sensorMeasure == 0)
20 {
21 tone(buzzer, 800, 500);
22 digitalWrite(ledRojo, HIGH);
23 digitalWrite(ledVerde, LOW);
24 }
25 if (sensorMeasure == 1)
26 {
27 digitalWrite(ledVerde, HIGH);
28 digitalWrite(ledRojo, LOW);
29 }
30 delay(1000);
31
32 }

Source Code 5.4: Sketch Sensor de Proximidad: Código Final

94
Por último, en la Figura 5.19 se muestra el circuito montado y las conexiones realizadas.
Destacar que las entradas y salidas están conectadas a los pines especificados en la propiedad
PinNumber, lo cual se refleja en el código generado (ver Código 5.4).

Figure 5.19: Sketch Sensor de Proximidad: Circuito

Se ha grabado un vı́deo a modo de demostración en el que se muestra todo el proceso de


construcción que se ha explicado previamente ası́ como la carga del sketch en un dispositivo
Arduino y la ejecución del mismo. El acceso a dicho vı́deo se puede obtener desde el siguiente
enlace: https://youtu.be/-yOZLJYTU-c

95
5.4 Sketch: Mostrar nivel de luminosidad en un Display
LCD
El objetivo de este sketch es mostrar la capacidad de la herramienta para construir un sistema
en el que la información del entorno recibida por las entradas afecte de forma directa a unos
actuadores visibles, a través de un código con distintas condiciones que se cumplirán en función
de las entradas. En este caso, se construirá un sistema en el que la entrada es un sensor de
luminosidad, que recopilará información sobre los niveles de luz del entorno. La salida en la que
se mostrarán los datos es un Display LCD, en el que aparecerá un mensaje u otro dependiendo
de la luz detectada.
Para conseguir esto, se construyen primero las entradas. En este caso se necesita únicamente
un sensor de luminosidad (ver Figura 2.6). En la Figura 5.20 se muestra el resultado de crear la
entrada y asociar una Measure, lo cual es necesario para cualquier entrada.

Figure 5.20: Sketch Luminosidad en Display: Crear Entradas

El siguiente paso es construir las salidas. Como el objetivo es que en función de las medidas
recopiladas por el sensor, aparezca un mensaje u otro en un display, se crea un Display LCD
desde la toolbox (ver Figura 5.21).

96
Figure 5.21: Sketch Luminosidad en Display: Crear Salidas

Se ha decidido definir cuatro niveles de luminosidad: ”Oscuro”, ”Normal”, ”claro”, ”muy


claro”. Según la luminosidad detectada en el ambiente, se quiere mostrar un mensaje en el display
indicando la luminosidad actual. Para ello se deben definir cuatro If y sus condiciones, cuando
se cumpla una se imprimirá en el display el mensaje correspondiente. Todas estas sentencias y
condiciones deben de ser creadas dentro de un Controller. El resultado de este proceso se puede
ver en la Figura 5.22.

Figure 5.22: Sketch Luminosidad en Display: Crear If

También se necesita una sentencia de entrada/salida a través de la cual se lea la información

97
desde el sensor de luz. Como la sentencia a ejecutar dentro de cada condición está directamente
relacionada con la salida, será necesario hacer uso de las sentencias tipo IOSentence, creando
una en cada condición. Todas estas sentencias se deben unir a sus entradas o salidas utilizando
el conector correspondiente (ver Figura 5.23).

Figure 5.23: Sketch Luminosidad en Display: IOSentences

Es importante establecer el orden correcto de ejecución entre las sentencias. La primera ha de


ser la lectura de información de la entrada, después se irán sucediendo las distintas condiciones.
Tras esto, se puede añadir una función delay() para tomar información cada cierto tiempo y no
de forma continua (ver Figura 5.24).

98
Figure 5.24: Sketch Luminosidad en Display: Ordenar sentencias

Las condiciones se encargan de establecer un rango de valores para la medida luminosidad


que se ha definido. En función del valor leı́do, entrará a una condición u otra. Utilizando las
propiedades de cada Condition (ver Figura 5.25) se ha definido el siguiente rango de valores:
ˆ Oscuro: luminosidad menor que 250.

ˆ Normal: luminosidad entre 250 y 500.

ˆ Claro: luminosidad entre 500 y 750.

ˆ Muy claro: luminosidad mayor que 750.

Figure 5.25: Sketch Luminosidad en Display: Ejemplo Propiedades Condition

De forma opcional, se puede mostar en el Display el valor exacto leı́do. Para ello se deben
añadir sentencias manuales (aunque también se podrı́a hacer uso una sentencia IOSentence),
siendo las siguientes (ver Figura 5.26):

99
ˆ Sentencia 1: display.setCursor(0,1); para situar el cursor en la segunda fila del Display.

ˆ Sentencia 2: display.print(”Valor: ”); imprime ”Valor: ”.

ˆ Sentencia 3: display.print(luminosidad); imprime el valor leı́do.

Figure 5.26: Sketch Luminosidad en Display: Sentencias adicionales

Antes de generar el código se debe definir el mensaje a mostrar por las sentencias de salidas
de las cuatro condiciones. Esto se debe hacer a través de las propiedades de Display. Se indicará
un mensaje general que luego se debe personalizar una vez generado el código (ver Figura 5.27).

Figure 5.27: Sketch Luminosidad en Display: Display Properties

A continuación se muestra el código generado (ver Código 5.5), del que se debe modificar el
mensaje mostrado en cada condición, siguiendo el rango de valores definido anteriomente. El
resultado final se puede observar en Código 5.6.

100
1 int lightPin = A0;
2 int luminosidad = 0;
3 #include <LiquidCrystal_I2C.h>
4 LiquidCrystal_I2C display(0x27,20,4); //Default pins (can be changed)
5
6 void setup()
7 {
8 Serial.begin(9600);
9 display.init();
10 display.backlight();
11
12 }
13
14 void loop()
15 {
16 luminosidad = analogRead(lightPin);
17 if (luminosidad < 250)
18 {
19 display.clear();
20 display.setCursor(0,0);
21 display.print("NIVEL: " );
22 }
23 if (luminosidad > 250)
24 {
25 display.clear();
26 display.setCursor(0,0);
27 display.print("NIVEL: " );
28 }
29 if (luminosidad > 500)
30 {
31 display.clear();
32 display.setCursor(0,0);
33 display.print("NIVEL: " );
34 }
35 if (luminosidad > 750)
36 {
37 display.clear();
38 display.setCursor(0,0);
39 display.print("NIVEL: " );
40 }
41 display.setCursor(0,1);
42 display.print("Valor: ");
43 display.print(luminosidad);
44 delay(2000); // Delay duration in milliseconds
45
46 }

Source Code 5.5: Sketch Luminosidad en Display: Código generado

101
1 int lightPin = A0;
2 int luminosidad = 0;
3 #include <LiquidCrystal_I2C.h>
4 LiquidCrystal_I2C display(0x27,20,4); //Default pins (can be changed)
5
6 void setup()
7 {
8 Serial.begin(9600);
9 display.init();
10 display.backlight();
11
12 }
13
14 void loop()
15 {
16 luminosidad = analogRead(lightPin);
17 if (luminosidad < 250)
18 {
19 display.clear();
20 display.setCursor(0,0);
21 display.print("NIVEL: Oscuro" );
22 }
23 if (luminosidad > 250)
24 {
25 display.clear();
26 display.setCursor(0,0);
27 display.print("NIVEL: Normal" );
28 }
29 if (luminosidad > 500)
30 {
31 display.clear();
32 display.setCursor(0,0);
33 display.print("NIVEL: Claro" );
34 }
35 if (luminosidad > 750)
36 {
37 display.clear();
38 display.setCursor(0,0);
39 display.print("NIVEL: MuyClaro" );
40 }
41 display.setCursor(0,1);
42 display.print("Valor: ");
43 display.print(luminosidad);
44 delay(2000); // Delay duration in milliseconds
45
46 }

Source Code 5.6: Sketch Luminosidad en Display: Código modificado

En la Figura 5.28 se muestra en detalle el circuito construido para este sketch. Destacar que
el sensor de luminosidad debe ir conectado al pin A0 de la parte ANALOG IN del dispositivo
Arduino, tal y como se ha indicado en su inicialización en el Código 5.6.

102
Figure 5.28: Sketch Luminosidad en Display: Circuito

Se ha grabado un vı́deo a modo de demostración en el que se muestra todo el proceso de


construcción que se ha explicado previamente ası́ como la carga del sketch en un dispositivo
Arduino y la ejecución del mismo. El acceso a dicho vı́deo se puede obtener desde el siguiente
enlace: https://youtu.be/TD_9zgzh9OU
Con estas pruebas queda validada la profundidad del lenguaje, ası́ como su potencial. Se
han realizado diversos ejemplos que prueban el flujo de información en un dispositivo Arduino.
Se puede apreciar cómo la información recopilada por las entradas afecta de forma directa a
las salidas creadas, siendo tratada previamente por la lógica definida por el usuario. Esta lógica
puede ser da la complejidad que el usuario decida, desde condiciones únicas hasta bucles anidados
con diversas condiciones y múltiples sentencias a ejecutar en su interior.

103
Capı́tulo 6

Conclusiones

6.1 Conclusiones
En este Proyecto de Fin de Grado se ha explicado todo el proceso de construcción de una
herramienta de modelado, Arduino Modelling Tool, la cual permite crear diversas configuraciones
para una placa Arduino UNO, a través de una interfaz intuitiva y sencilla. Además, permite
generar de forma automática el código Arduino necesario que aporta la lógica y soporte para el
correcto funcionamiento de los componentes seleccionados por el usuario.
La principal motivación de este proyecto se ha visto alcanzada al ofrecer a aquellos usuar-
ios que no poseen grandes conocimientos previos sobre programación, una herramienta que les
permita diseñar sus propios proyectos Arduino. Eliminando esa barrera, se fomenta que jóvenes
estudiantes conozcan el mundo IoT, propulsando el futuro de estas tecnologı́as.
Como Arduino Modelling Tool ha sido desarrollada siguiendo los principios definidos por
MDD, tanto su evolución como mantenimiento resultarán tareas sencillas y de bajo coste. Por
ejemplo, es fácilmente adaptable a otro modelo de placa Arduino, ya que las entradas y salidas
son ampliables y sustituibles.
En cuanto a la generación automática de código, los ficheros .ino se encuentran libre de
errores, al eliminar la posibilidad de introducir errores humanos, lo cual supone una gran ventaja
para los nuevos usuarios. Sin embargo, los usuarios más avanzados también pueden beneficiarse
de esta funcionalidad, ya que pueden empezar sus proyectos desde una base generada y seguir
programando a partir de ella, aumentando ası́ su productividad.
A nivel personal, para poder realizar este proyecto y enseñar los conceptos básicos sobre
Arduino, primero los he tenido que aprender yo. Este proceso de aprendizaje ha supuesto el
diseño y programación manual de distintos sketches Arduino a través de los cuales he adquirido
los conocimientos necesarios para más tarde ”enseñárselos” a la herramienta y poder obtener la
plantilla de generación de código. Gracias a la directora de este proyecto, he conocido más a
fondo el mundo IoT y el potencial que este alberga. También he profundizado mis conocimientos
en MDD y la creación de Lenguajes Especı́ficos de Dominio, que, aunque se estudian durante la
carrera, son tecnologı́as y enfoques en constante evolución y que ofrecen multitud de posibilidades
a los desarrolladores.

6.2 Trabajos futuros


La lista de entradas y salidas compatibles con Arduino es muy extensa. Para este PFG se han
utilizado las principales entradas y salidas que contiene el paquete Arduino Starter Kit, las cuales
son suficientes para construir el lenguaje y evaluar su viabilidad, realizando pruebas variadas.
Sin embargo, este proceso no es demasiado costoso ya que el desarrollo siguiendo un enfoque
MDD sobre el que se ha basado este proyecto agilizarı́a estos cambios. Por tanto, algunas de las
mejoras posibles respecto al lenguaje son las siguientes:
ˆ Añadir más variedad de entradas y salidas al modelo. Esto conlleva actualizar además la
barra de herramientas para que el usuario pueda hacer uso de ellas y actualizar también la
plantilla de generación de código para dar soporte a estos nuevos componentes. Algunos
de estas nuevas entradas/salidas podrı́an ser: sensor de ultrasonidos o sensor de humedad.
ˆ En cuanto a la parte lógica del modelo, se podrı́a ampliar añadiendo una clase hija más a la
clase Loops. Esta serı́a la clase Switch-Case, que permita crear este tipo de bucle complejo.
De igual forma habrı́a que dar soporte desde la Toolbox y añadir el código correspondiente
en la plantilla de generación.

104
ˆ Creación de modelos completos construidos. Integrar en la herramienta una serie de ejemp-
los de modelos sencillos ya construidos, por ejemplo, Sketch: Blink. De esta forma, aquellos
usuarios sin experiencia o nuevos en la herramienta puedan aprender a través de estos e-
jemplos, teniendo la oportunidad de personalizar pequeñas variables a modo de iniciación
en el entorno.

Otro objetivo futuro serı́a la distribución de la herramienta. A partir del proyecto de Visual
Studio original, se puede crear una plantilla del mismo como una extensión de Visual Studio,
que al ser instalada en otros equipos, permite crear proyectos a otros usuarios, es decir, utilizar
la herramienta de modelado [17] [18]. Además de esto, habrı́a que crear un manual de usuario
con los requisitos previos y pasos a seguir sobre la instalación de la herramienta.

6.3 Impactos sociales y ambientales


La Organización de las Naciones Unidas (ONU) aprobó en 2015 una Agenda sobre el Desarollo
Sostenible que contiene 17 objetivos de Desarrollo Sostenible para cumplir en el año 2030. Al-
gunos de estos objetivos son poner fin a la pobreza, conseguir la igualdad de género o alcanzar
una producción y consumo responsables. [19]
El objetivo número 4 representa una educación de calidad. Arduino presenta numerosos pro-
gramas y apoyos para instituciones de todos los niveles, desde escuelas hasta hasta universidades
[20]. Al ser un sistema asequible económicamente, estas instituciones pueden plantearse incluir
Arduino en sus programas didácticos, involucrando a sus alumnos en el estudio de tecnologı́as
IoT.
Arduino Modelling Tool puede ayudar a aquellos alumnos que no tengan conocimientos sobre
electrónica o programación a construir sus propios sistemas, gracias a la interfaz gráfica que posee,
en lugar de enfrentarse en primera instancia con el entorno de programación que proporciona
Arduino, lo cual puede resultar un poco arduo.
Las tecnologı́as IoT también están fuertemente relacionadas con el objetivo número 11, Ciu-
dades y Comunidades Sostenibles. Esto es gracias al aumento y la integración de lo que se
denomina como smart cities. Estas ciudades cuentan con dispositivos IoT que monitorizan
variables como la concentración de dióxido de carbono en el aire, concentración del tráfico o
distribución de los servicios sanitarios y de seguridad [21]. Esto contribuye al objetivo determi-
nado por la ONU, buscando optimizar los recursos disponibles y reducir la contaminación en los
núcleos urbanos.

105
Bibliografı́a

[1] D. Miorandi, S. Sicari, F. De Pellegrini, and I. Chlamtac, “Internet of things: Vision,


applications and research challenges,” Ad hoc networks, vol. 10, no. 7, pp. 1497–1516, 2012.
[2] M. Kamal, A. Aljohani, and E. Alanazi, “Iot meets covid-19: Status, challenges, and op-
portunities,” arXiv preprint arXiv:2007.12268, 2020.
[3] T. A. Team, “Arduino home,” accessed: 20-04-2021. [Online]. Available: https:
//www.arduino.cc
[4] ——, “Arduino pro,” accessed: 20-04-2021. [Online]. Available: https://www.arduino.cc/
pro
[5] H. Kopetz, Internet of Things. Boston, MA: Springer US, 2011, pp. 307–323. [Online].
Available: https://doi.org/10.1007/978-1-4419-8237-7 13
[6] F. Wortmann and K. Flüchter, “Internet of things,” Business & Information Systems En-
gineering, vol. 57, no. 3, pp. 221–224, 2015.
[7] T. A. Team, “Arduino guide,” accessed: 17-02-2021. [Online]. Available: https:
//www.arduino.cc/en/Guide/Introduction
[8] ——, “Arduino software,” accessed: 17-02-2021. [Online]. Available: https://www.arduino.
cc/en/software
[9] ——, “Blink,” accessed: 25-04-2021. [Online]. Available: https://www.arduino.cc/en/
Tutorial/BuiltInExamples/Blink
[10] M. Staron, “Adopting model driven software development in industry–a case study at t-
wo companies,” in International Conference on Model Driven Engineering Languages and
Systems. Springer, 2006, pp. 57–72.
[11] J. P. y Soledad Delgado, TEMA 3. DESARROLLO DE SOFTWARE AUTOMATIZADO.
E.T.S. de Ingenierı́a en Sistemas Informáticos, Departamento de Sistemas Informáticos.
[12] S. Beydeda, M. Book, V. Gruhn et al., Model-driven software development. Springer, 2005,
vol. 15.
[13] S. Cook, G. Jones, S. Kent, and A. C. Wills, Domain-specific development with visual studio
dsl tools. Pearson Education, 2007.
[14] github@Mgoertz Msft, “Introducción a los lenguajes especı́ficos de dominio - visual
studio.” [Online]. Available: https://docs.microsoft.com/es-es/visualstudio/modeling/
getting-started-with-domain-specific-languages?view=vs-2019
[15] Microsoft, “Understanding models, classes and relationships,” accessed: 17-
02-2021. [Online]. Available: https://docs.microsoft.com/en-us/visualstudio/modeling/
understanding-models-classes-and-relationships?view=vs-2019
[16] T. A. Team, “Language reference,” accessed: 25-04-2021. [Online]. Available:
https://www.arduino.cc/reference/en/
[17] github@Mgoertz Msft, “Implementación mediante msi y vsix de un dsl,” 2016, accessed:
27-05-2021. [Online]. Available: https://docs.microsoft.com/es-es/visualstudio/modeling/
msi-and-vsix-deployment-of-a-dsl?view=vs-2019
[18] github@leslierichardson95, “Introducción a la plantilla de proyecto de vsix,” 2019,
accessed: 27-05-2021. [Online]. Available: https://docs.microsoft.com/es-es/visualstudio/
extensibility/getting-started-with-the-vsix-project-template?view=vs-2019

106
[19] O. de las Naciones Unidas, “Desarrollo sostenible – united nations sustainable
development sites,” accessed: 14-05-2021. [Online]. Available: https://www.un.org/
sustainabledevelopment/es/
[20] T. A. Team, “Arduino education,” accessed: 14-05-2021. [Online]. Available:
https://www.arduino.cc/education

[21] F. Endesa, “Smart city: Las ciudades inteligentes en la actualidad,” accessed: 14-05-2021.
[Online]. Available: https://www.fundacionendesa.org/es/recursos/a201908-smart-city

107

También podría gustarte