TFG Sanz Martin 2022
TFG Sanz Martin 2022
TFG Sanz Martin 2022
2022
UNIVERSIDAD DE ALCALÁ
ESCUELA POLITÉCNICA SUPERIOR
Tribunal:
Mi ingreso en el Grado de Telecomunicaciones fue del todo inesperado y precipitado para mi entorno.
Yo, desde pequeño, disfruto de la música y tenía mi vida dedicada y encaminada a ser músico. A la
edad de dieciocho años me gradué del Conservatorio Profesional Luis de Victoria de Ávila, presentándose
una difícil decisión, pero que a día de hoy sigo considerando acertada. En la carrera, para mi sorpresa,
encontré una pasión comparable a la que siento por la música y que me ha impulsado en estos cuatro
años.
A mi familia, sobre todo a mis padres y hermana, gracias por el amor y el apoyo incondicional que
siempre me dais. Por educarme y por convertirme en la persona que soy hoy en día, ya que sin vuestra
ayuda no habría conseguido todo lo que me he propuesto. A mi pareja, que me ha acompañado durante
estos cuatro años y con la que he trabajado codo con codo. Que me quiere y me demuestra que la vida
es un poco más colorida a su lado.
También debo dar las gracias a mis compañeros y amigos las innumerables veces que me han ayudado.
Por las tardes de estudio, que acababan siendo solo de risas, y por estar ahí siempre que os he necesitado.
Por último, una mención especial merece mi tutor Óscar García Población. Gracias por ofrecerme
este proyecto tan fascinante. Por tu implicación y seguimiento constante, que ha hecho que este trabajo
tenga el detalle y el rigor que se merece.
A todos gracias.
Resumen
Palabras clave: IoT, neutrón, monitor, rayos cósmicos, ESP32, Espressif, InfluxDB, Grafana, Mos-
quitto, Google Cloud, Github Actions, Kicad 6.
Abstract
The objective of this project is to build a data acquisition system for a neutron monitor based on the
ESP32 platform and IoT technology. The system is composed of a base station and a series of sensor
nodes distributed in the area to be monitored. The sensor nodes are equipped with neutron detectors
and transmit the data collected to the base station through wireless communication technology. The
base station processes the received data and displays it in real time on a web interface. The acquisition
system designed in this document is the communication gateway between the sensor nodes and the base
station. The collected data is stored in a database, so that it can later be transferred to the scientific
community.
Keywords: IoT, neutron, monitor, cosmic rays, ESP32, Espressif, InfluxDB, Grafana, Mosquitto,
Google Cloud, Github Actions, Kicad 6.
Índice general
Resumen IX
Abstract XI
1. Introducción 1
1.1. Contexto del trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2. Presentación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3. The Neutron Monitor Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.4. Detección de rayos cósmicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.4.1. Detectores de gas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.4.2. Monitor de neutrones: Chalk-River BP28 . . . . . . . . . . . . . . . . . . . . . . . 6
1.5. Diseño del sistema . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2. Hardware de adquisición 9
2.1. Electrónica de acondicionamiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.1.1. Comparador inversor con histéresis . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.1.2. Simulación del circuito con LTSpice . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2. Dispositivo lógico programable: ESP32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.2.1. Sistemas basados en SoC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.2.2. ESP-WROOM-32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.3. Periféricos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.4. Sistema de alimentación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.5. Diseño electrónico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.5.1. Diseño del esquemático . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.5.2. Diseño del PCB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.5.3. Fabricación del PCB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.5.4. Caja estanca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
xiv ÍNDICE GENERAL
4. Software de adquisición 33
4.1. Descripción del software de adquisición . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.2. Programa principal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
4.3. Configuración Wi-Fi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
4.4. Configuración SNTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
4.5. Configuración MQTT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4.6. Sistema de clasificación y envío de mensajes . . . . . . . . . . . . . . . . . . . . . . . . . . 37
4.7. Obtención de datos meteorológicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
4.8. Tareas de detección y monitorización de rayos cósmicos . . . . . . . . . . . . . . . . . . . 38
4.8.1. Contador de pulsos: task_pcnt() . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
4.8.2. Detector de pulsos: detection_isr_handler() . . . . . . . . . . . . . . . . . . 39
4.9. Actualización mediante OTA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.10. Estructura de los módulos del programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
6. Componentes adicionales 53
6.1. Integración y distribución continua: CI/CD . . . . . . . . . . . . . . . . . . . . . . . . . . 53
6.1.1. Github Actions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
6.2. Implementación en Google Cloud . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
6.2.1. Google Compute Engine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
7. Resultados 59
7.1. Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
7.2. Software de Adquisición . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
7.2.1. Ejecución del software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
7.2.2. Ejecución de CI y actualización mediante OTA . . . . . . . . . . . . . . . . . . . . 62
7.3. Interfaz Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
9. Presupuesto 69
Bibliografía 71
Apéndice A. Esquemático 75
Introducción
Desde la pasada década se ha experimentado un rápido desarrollo del ámbito de la Física, más concre-
tamente en la investigación de la radiación ionizante de la atmósfera y su relación con los rayos cósmicos.
Por lo tanto, el propósito de este capítulo se ha centrado en estudiar su origen, composición y las inter-
acciones que producen al ingresar en la atmósfera, así como los distintos métodos que se emplean para
su detección. Finalmente, hemos definido los requisitos de nuestro sistema enumerando los bloques que
lo componen y sus interconexiones.
Este trabajo de fin de grado se ha realizado gracias a la colaboración con el grupo de investigación
espacial SRG[1] de la universidad de Alcalá, que ha puesto a mi disposición el equipo y los conocimientos
necesarios para mi formación.
Este equipo, integrado por mi tutor Óscar García Población, ha desarrollado importantes proyectos en
el área de detección de rayos cósmicos y ha ubicado un nodo de observación en Guadalajara (CaLMa[2][3,
4]) y otro en la Isla Livingston, Antártica (ORCA[5, 6]), además de otro nodo móvil (MiniCaLMa[7]).
Esta colaboración ha permitido el desarrollo de numerosos artículos[8], publicaciones, tesis doctora-
les[9], trabajos de fin de carrera y contratos de investigación. Por lo tanto estoy agradecido de que mi
trabajo pueda contribuir en el desarrollo de los proyectos existentes y futuros.
2 Capítulo 1. Introducción
1.2. Presentación
La primera década del siglo XX fue un periodo revolucionario para la ciencia, en este periodo se
realizaron grandes descubrimientos en muchas áreas. Uno de los más importantes, por su impacto en la
física de partículas, fue el descubrimiento de los rayos cósmicos en 1912 por Victor Hess.
Inicialmente existía la convicción de que la radiación presente en la atmósfera aumentaba a medida que
la distancia a la Tierra disminuía, puesto que emanaba de los elementos radioactivos naturales presentes
en la corteza terrestre. Victor Hess basó su trabajo en la medición de los niveles de radiación ionizante.
Sus experimentos resultaron ser muy reveladores ya que observó que en la atmósfera el nivel de radiación
podría ser, en realidad, más alto que en la superficie.
En consecuencia, Hess determinó que la alta radiación que penetra en la atmósfera es procedente del
espacio exterior. Años después Robert Andrews Millikan confirmó su descubrimiento nombrando a dicha
radiación como rayos cósmicos.
El origen de los rayos cósmicos[10] es aún un objeto de debate en la comunidad científica, su composi-
ción trata principalmente de protones procedentes del Sol, aunque una pequeña proporción son partículas
alfa de alta energía con un origen extragaláctico.
Estos rayos cósmicos de alta energía son particularmente interesantes para la astrofísica, ya que
pueden proporcionar información sobre objetos y fenómenos extragalácticos. Dentro de este marco, surgió
la necesidad de medir la cantidad de rayos detectados por los monitores geográficamente distribuidos,
creándose así "The Neutron Monitor Database"(NMDB).
En el mapamundi de la figura 1.A observamos que las localizaciones de los detectores varían en función
de los trópicos, siendo los más interesantes los ubicados en los círculos polares y el ecuador. Esto se debe
a que en estas zonas la densidad atmosférica permite que más o menos rayos cósmicos viajen a través de
la atmósfera sin ser absorbidos por ella como causa del campo gravitatorio terrestre.
La detección de rayos cósmicos es una técnica utilizada para estudiar los objetos más energéticos
del universo. Algunas de estas partículas pueden ser hasta millones de veces más energéticas que las
generadas en el colisionador de partículas LHC. En la Tierra, la llegada de rayos cósmicos produce
interacciones con la atmósfera, formando una lluvia de partículas que son detectables en la troposfera.
En la actualidad, se utilizan instrumentos de gran tamaño y complejidad para detectar estas par-
tículas y estudiar sus propiedades, aunque existen otros más simples y portables a efectos de reducir
sus prestaciones. Los detectores de partículas altamente energéticas, también pueden ser englobados en
dos grandes familias de acuerdo con el método utilizado para detectar la radiación: detectores pasivos y
detectores activos.
Los detectores pasivos, a diferencia de los activos, no necesitan una fuente de alimentación para
detectar los neutrones, si no que presentan desventajas que dificultan un estudio eficaz de los rayos
cósmicos. En primer lugar, la obtención de los datos se debe realizar mediante un microscopio óptico, de
manera que toma importancia la influencia del factor humano y, en consecuencia, el error producido en
sus medidas. Además, no guardan información sobre el instante de los impactos y el estudio solo se puede
realizar en periodos de tiempo reducidos, impidiendo el análisis detallado del flujo de partículas.
Por este motivo se desarrollaron los detectores activos, que son los más utilizados actualmente; re-
quieren una fuente de energía y solo registran partículas cuando están a la tensión adecuada. Una de las
mayores ventajas que debemos considerar es la rapidez de detección y la continuidad en la recopilación
de los datos
Existen dos tipos de modos básicos de operación: modo corriente y modo pulso. En el modo corriente
se realiza la media de la corriente que se genera en un periodo de tiempo determinado y el modo pulso
mide cada pulso de la señal de salida de la corriente para almacenarla. Entre los detectores activos más
empleados encontramos los detectores de gas, detectores de centelleo y detectores semiconductores.
4 Capítulo 1. Introducción
Normalmente estos detectores[12] están formados por tubos cilíndricos rellenos de un gas y un hilo
conductor para crear en su interior dos electrodos. Cuando el detector recibe partículas incidentes que
ionizan el gas a medida que lo atraviesa, se producen electrones y cargas positivas que se atraen y se
repelen, formando así una diferencia de potencial que puede ser medida. La electrónica empleada en este
proceso se observa de forma esquematizada en la figura 1.C.
Es fundamental destacar la importancia de las medidas del detector y su área de captura, ya que se ne-
cesita tener unas dimensiones lo suficientemente grandes para recolectar la mayor cantidad de ionización,
pero lo suficientemente pequeñas para no perder precisión. Además del modelo de detector menciona-
do, existen detectores esféricos que son más compactos aunque más difíciles de mantener y detectores
cuadrados o rectangulares que son más fáciles de fabricar, pero poco eficaces.
En nuestro caso, los monitores de neutrones con los que vamos a trabajar pertenecen a la familia de
los detectores de gas, utilizando BF3 como principio activo.
En la atmósfera existe una gran cantidad de radiación ionizante, por lo que si exponemos el detector
de forma directa, no seremos capaces de diferenciar la radiación producida por los rayos cósmicos. Como
podemos observar en la figura 1.D, obtenida de la Agencia para Sustancias Tóxicas y el Registro de
Enfermedades (ATSDR[13]), tan solo un 8 % de la radiación que se encuentra en la atmósfera tiene un
origen cósmico.
Radón
Otra
Productos de consumo
55 % 3%
8% Cósmica
8%
15 % 11 % Terrestre
Médica Interna
Es por esta razón que el detector de neutrones se complementa con un esqueleto compuesto por
distintos materiales que ayudan en el filtrado e incrementan la detección.
Reflector: Esta capa está formada por Polipropileno, un material que actúa como barrera para
los neutrones ambientales de baja energía. De esta forma se consigue filtrar eficazmente todas las
partículas no procedentes de los rayos cósmicos.
Productor: Formado por Plomo y como su nombre indica, es el encargado de producir en torno a
10 neutrones de energía más baja por cada neutrón de alta energía.
Moderador: Compuesto por el mismo material rico en protones que el Reflector, su función es ra-
lentizar los neutrones filtrados y generados en las dos etapas anteriores. De esta forma se incrementa
la probabilidad de detección del monitor.
Hemos incluido las especificaciones del monitor[14], las medidas y los materiales utilizados para su
armazón, como se expone en la figura 1.E, por si resultan de utilidad para el lector.
Dado este esquema general, se podrán exponer múltiples soluciones con distintos componentes en
función de las particularidades o necesidades de cada situación.
Capítulo 2
Hardware de adquisición
La conexión directa del monitor de neutrones a una de las entradas del dispositivo detector tiene una
serie de importantes problemas en cuanto a eficiencia en la detección y la existencia de falsos positivos.
Es por este motivo que surge la necesidad de diseñar un sistema capaz de filtrar el ruido y amplificar su
salida, de tal manera que los pulsos resultantes sean próximos a un pulso cuadrado TTL.
La solución propuesta modela un circuito electrónico de alta frecuencia que utiliza un amplificador
operacional comparador como se muestra en la figura 2.A:
Este circuito se basa en la utilización del integrado LM339 de la serie de comparadores de voltaje
LMx39x, capaz de trabajar con un tiempo de respuesta de 300ns, es decir, a una frecuencia de 3,3 GHz.
Para la configuración y cálculo del valor de los elementos pasivos del circuito, hemos reproducido el
modelo Inverting Comparator with Hysteresis indicado en el datasheet del componente.
Dado que el voltaje suministrado al circuito es de 3.3V y la amplitud del pulso no sobrepasa los
500mV, podemos obtener el valor aproximado de todas las resistencias del circuito. Posteriormente, se
ajustará cada valor para obtener el ciclo de histéresis adecuado que regule el área de detección. Además,
para proteger el integrado de sobretensiones se ha ubicado un diodo Schottky en cada entrada.
2.1 Electrónica de acondicionamiento 11
Hemos realizado la simulación del circuito mostrado en la figura 2.A mediante la herramienta de
simulación LTSPice.
En primer lugar, hemos simulado el comportamiento del integrado en un régimen transitorio de
100us, añadiendo ruido al pulso de entrada (verde) con la ayuda de la funcion white(). Como podemos
notar, el amplificador operacional LM339 elimina por completo dicho ruido ya que actúa como si fuera
un interruptor cuando se alcanzan los voltajes de entrada deseados. Además, como hemos configurado,
la señal de entrada se encuentra invertida respecto a la salida.
A continuación, hemos decidido representar un ciclo o curva de histéresis, que modela el compor-
tamiento de un sistema cuya salida depende de la entrada. Como resultado, el sistema puede tomar
diferentes valores incluido cuando las condiciones externas son idénticas ya que depende de su estado
previo.
En la figura 2.D, se indica como se producen las conmutaciones de 3.3V a 0V de la señal de salida
(eje y) cuando el pulso de entrada (eje x) sobrepasa los 80mV y los 320mV.
12 Capítulo 2. Hardware de adquisición
Este apartado está dedicado al análisis de los dispositivos que pueden realizar la tarea de detección
de los pulsos acondicionados. Para ello, es necesario repasar las distintas arquitecturas que existen hoy
en día a la hora de crear un dispositivo lógico programable:
INTEL Y AMD: Las arquitecturas computacionales de Intel y AMD de 32 y 64 bits (también co-
nocidas como x86 o x64, respectivamente) se caracterizan por ser una arquitectura de modelo CISC,
Complex Instruction Set Computer, ya que los procesadores tienen un conjunto de instrucciones
extenso y complejo. Estas arquitecturas son empleadas en computadores de uso personal.
ARM: Esta arquitectura, llamada Advanced RISC Machine, implementa el conjunto de instruccio-
nes reducido RISC. Su ventaja frente al resto de arquitectura es el bajo consumo de sus procesadores.
Es la arquitectura preferida en la tecnología movil y en los SoC.
Los SoC (System-on-Chip) son circuitos integrados en un único chip que incorporan múltiples com-
ponentes, formando así un sistema completo sin necesidad de otros chips de apoyo. Los SoC son un buen
candidato para nuestro proyecto debido al poco consumo de sus procesadores, la potencia de sus sistemas
y que se instalan en dispositivos económicos. Dentro de los SoC existen infinidad de dispositivos con
muchas prestaciones, pero las placas más demandadas son:
Arduino: es la marca más usada debido a su bajo coste y fácil programación. No obstante, por
estos motivos tienen funciones limitadas y poca potencia. Pero cuenta con una gran comunidad y
multitud de periféricos que ayudan a suplir dichas carencias.
Espressif : se centran en crear chips de bajo consumo y con Wi-Fi y Bluetooth integrados. Son
chips más potentes en comparación con los anteriores e implementan la mayoría de las librerías
desarrollads para Arduino.
Raspberry Pi: las tarjetas Raspberry son una buena opción en cuestión de almacenamiento de in-
formación y procesamiento de datos. Estos chips permiten utilizar sistemas operativos GNU/Linux,
pero con un coste varias veces superior a los anteriores SoC.
BeagleBoard: estas tarjetas son las más potentes, y por tanto, las menos económicas. Al igual
que para Raspberry, permiten utilizar sistemas operativos GNU/Linux, pero requieren librerías
específicas y un gran conocimiento del programador.
Por lo tanto, el dispositivo elegido ha sido un ESP32[17] de la marca Espressif, característico por
poseer tecnología Wi-Fi y Bluetooth integrado y por emplear un microprocesador Tensilica Xtensa LX6
con buenas prestaciones.
2.2 Dispositivo lógico programable: ESP32 13
2.2.2. ESP-WROOM-32
Los pines GPIO incluyen dos ADCs de 12 bits que se pueden configurar para 9, 10 y 12 bits de
resolución con una atenuación de -0dB, -6dB y -11dB. También incluyen dos DACs de 8 bits. Inicialmente
se planteó que el proceso de detección se realizara mediante esta tecnología, tomamos como referencia un
estudio publicado por Alejandro Maier en el que se utiliza el ESP-WROOM-32 para crear un prototipo
de osciloscopio inalámbrico, demostrando que el uso más óptimo de los ADCs era a 12 bits de resolución
con una atenuación de -6dB.
En otro estudio[20] realizado por Jovan Ivkovic, se comparan varios microcontroladores del mercado
realizando una serie de tests sintéticos, es decir, tests en los que se estudian componentes o operaciones
específicos sin tener en cuenta más factores. El microprocesador del ESP-WROOM-32, obtiene unos
resultados de 176 millones de operaciones de enteros por segundo y 2,805 millones de operaciones de coma
flotante por segundo. Comparando estos resultados con otros microcontroladores de la misma generación,
vemos datos bastante diversos, estando el ESP-WROOM-32 en la media.
Este microcontrolador es líder en la automatización del hogar, aplicaciones IoT de bajo consumo
con concentración de sensores y registradores de datos, y dispositivos electrónicos portables, entre otras
utilidades.
2.3. Periféricos
Aunque el proyecto cuenta con el barómetro VAISALA de altas prestaciones, hemos decidido incluir
en el circuito el módulo BMP180. Este módulo tiene la ventaja de ser fácil de aplicar en el circuito y
muy económico.
Este módulo cuenta con el protocolo de comunicación I2C (Inter-Integrated Circuit), diseñado para
transferir datos bit a bit entre dispositivos digitales. Para el correcto funcionamiento de este protocolo
es necesario un dispositivo maestro, normalmente un microcontrolador, conectado a esclavos, pueden ser
tanto sensores como monitores, que realizan las órdenes del maestro. Para este protocolo se implementan
los puertos SDA y SCL. El puerto SDA es el encargado de enviar los mensajes entre maestro y esclavo;
el puerto SCL, controlado por el maestro, transmite los pulsos de reloj.
2.4 Sistema de alimentación 15
Nuestro circuito tiene implementadas dos formas de alimentación dependiendo de las necesidades o
del material del que dispondremos cuando se realice la instalación del sistema de adquisición.
La manera principal de suministrar energía al circuito emplea uno de los conectores BNC de la placa
SRG (mostrada en la figura 2.G). De esta forma podemos, mediante el uso de una fuente de alimentación
de laboratorio, proporcionar de forma constante la potencia requerida en nuestro circuito.
En caso de no disponer de una fuente de alimentación, se ha situado otro sistema basado en los
conectores de alimentación DC jack de 2mm, utilizados en dispositivos con una tensión máxima de 30V.
Para esta configuración necesitaremos un adaptador AC/DC que proporcione 12V y 1A.
Las entradas descritas anteriormente se acoplan al módulo regulador LM2596 que regula el voltaje
de entrada de 12V a 3.3V, que es el voltaje en el que trabajan los componentes del circuito. Pero además,
obtenemos la ventaja de que mejoramos la eficiencia, traduciéndose en una mejora en el rendimiento
del circuito. También protegemos el circuito ante sobrecargas y picos de tensión. Los convertidores de
corriente continua (DC-DC), a diferencia de los transformadores tienen un tamaño y peso menor, por lo
que siempre es deseable incorporar este dispositivo si necesitamos que el circuito funcione con diferentes
niveles de tensión continua.
Kicad 6[21] es un entorno de automatización de diseño electrónico que facilita el desarrollo de esque-
mas para circuitos electrónicos. De sus herramientas principales nos centraremos en el editor de esquemas,
el editor de placas y el conversor de imágenes. Aunque la utilización del editor de símbolos y de placas
nos ayuda a diseñar nuestros propios componentes, simplificaremos el proceso descargando los diseños de
páginas gratuitas como SnapEDA[22].
Un símbolo es un figura que representa todas las conexiones físicas de un componente electrónico, en
el caso de los amplificadores operacionales se emplea un triángulo, como en la figura 2.A, aunque cuando
la figura representa varios operacionales juntos se suele ilustrar como en la figura 2.H.
Una vez hemos descargado los símbolos necesarios para nuestro proyecto creamos una librería me-
diante el explorador de librerías de símbolos, reuniendo todos los componentes en un único archivo. De
esta forma, seleccionando esta librería, de forma local o global, encontramos nuestros símbolos en el
apartado de añadir símbolo o pulsando la tecla A.
La colocación de los componentes sobre el documento se debe realizar de forma organizada, situando
las entradas del circuito separadas del resto de componentes y evitando la conexión directa de los compo-
nentes con cables. La mejor forma de señalizar e interconectar los componentes es con el uso de etiquetas
globales (Ctrl+L). Además, el patillaje que no se desee conectar, se debe indicar con un aspa pulsando
la tecla Q.
La siguiente figura representa el chip LM339N con tres operacionales conectados según la solución
diseñada en el apartado 2.1:
Figura 2.H: Conexión realizada entre el LM33N y el circuito mediante etiquetas globales
Por último, para comprobar que no existen errores de conexión en el esquema ejecutamos la herra-
mienta Control de reglas eléctricas (ERC) desde el menú Inspeccionar. EL resultado de este análisis
nos muestra una serie de mensajes catalogados según su riesgo. Siendo los mensajes etiquetados como
Error, los que debemos solucionar de forma obligatoria debido a su gravedad. Si por el contrario existe
algún aviso que se desee ignorar, se puede utilizar la herramienta de Exclusión de violaciones.
2.5 Diseño electrónico 17
Una vez que tenemos listo el esquemático, comenzamos con el diseño del PCB (Printed Circuit Board).
En primer lugar debemos asegurarnos de comprobar que todos los footprints tienen las medidas y el
patillaje correspondiente. Los footprints o huellas del PCB muestran las características físicas necesarias
de los componentes que utilizamos en la placa, así como sus conexiones. Por este motivo, es esencial
exponer con exactitud el contorno del encapsulado, la designación de pines y el patrón de tierra, entre
otros. En caso de que el símbolo no contenga la huella que necesitamos, podemos descargarla de páginas
gratuitas como SnapEDA[22].
Cuando hayamos asignado todas las huellas correspondientes con la herramienta de asignación de
huellas, en el editor de esquemas o en el gestor del proyecto, presionamos el símbolo para abrir la placa
en el editor de placas.
Para visualizar en la placa los cambios realizados en el esquema, pulsamos F8 o en su respectivo
símbolo. La primera vez que se ejecute nos coloca los componentes desordenados, una de las partes
más importantes a la hora de realizar nuestro PCB es la ubicación de los componentes. Cuanto más
optimizada esté la placa más pequeña es y, en consecuencia, será más barata de fabricar.
Ahora, es el momento de enrutar todas las conexiones del circuito. En nuestro caso, por simplificación,
hemos decidido utilizar cuatro capas de cobre, de esta forma no estaremos tan limitados a la hora de
conectar las vías.
Dos de las capas contienen únicamente zonas rellenas, una para GND y otra para VCC. En las capas
restantes se conecta el patillaje utilizando pistas de cobre. Por último, en la capa Edge.Cuts crearemos
un rectángulo con las medidas de la placa y colocaremos los orificios que necesitemos para atornillar
nuestra placa.
18 Capítulo 2. Hardware de adquisición
Kicad ofrece una herramienta para renderizar en 3D las placas que diseñemos denominada Visor 3D,
ubicada en el menú Ver o mediante el comando (Alt+3). Hemos obtenido los modelos 3D gratuitamente
de la página oficial de GrabCad[23] y los hemos asignado a cada huella. El resultado del modelo 3D se
ilustra en la siguiente figura:
La elaboración de circuitos impresos se remonta a la década de 1930, cuando el ingeniero Paul Eisler
desarrolló el primer PCB como parte de una radio. Pero no fue hasta 1940 cuando se empezó a utilizar
esta tecnología a gran escala.
Están formados por una o varias capas conductoras superpuestas entre otras aislantes. Como hemos
visto en el apartado de diseño de PCB 2.5.2, dichas capas conductoras están formadas generalmente por
pistas o superficies de cobre. De esta forma somos capaces de interconectar todos los componentes de un
circuito y al mismo tiempo sostenerlos en una base plana.
Los métodos más utilizados en la elaboración de circuitos impresos se dividen en:
Grabado ácido y alcalino: Estos métodos se divide en dos pasos, la transferencia del patrón del
circuito sobre la placa y el ataque por medio de un ácido o un fuerte agente oxidante respectiva-
mente. La transferencia del circuito a la placa se puede realizar mediante serigrafía, fotograbado
o transferencia térmica, todos se basan en la utilización de materiales que protejan el dibujo de
las pistas sobre el ataque del ácido. Los productos químicos más utilizados para el revelado de las
placas impresas son el cloruro férrico y cloruro cúprico.
Este método lo utilizamos durante la generación de las primeras versiones del código y de la placa:
(a) Transferencia térmica del circuito (b) Ataque químico con cloruro férrico
Grabado con plasma: En este proceso convierte las superficies sólidas que deseamos eliminar
directamente en gas. De forma selectiva se produce una reacción en la superficie de la placa a través
de una mezcla de gases, para después excitar sus moléculas mediante radiofrecuencias logrando
cambiar su estado a gas y produciendo finalmente la superficie grabada.
Grabado láser: Este tipo de grabado en seco emplea hardware controlado por computadora,
grabando el patrón del circuito gracias a un rayo láser de gran potencia. Comparado con los métodos
anteriores, el grabado láser reduce el número de pasos reduciendo el tiempo de producción.
20 Capítulo 2. Hardware de adquisición
Fresado: Similar al proceso anterior, pero en este caso una máquina de control numérico retira el
material conductor de la placa de cobre mediante un taladro. Este método de mecanizado suele ser
el más habitual en la industria, pero dependiendo del número de capas suele combinarse con otros
métodos.
Con el objetivo de unir y proteger los componentes electrónicos del sistema hemos decidido usar
una caja derivación IDE-EX161 con protección IP65, por lo que el sistema es hermético al polvo y
está protegido contra chorros de agua de baja potencia. Parte de esta protección se ha perdido ya que
hemos perforado la caja para exponer las entradas BNC y el conector de alimentación. Sin embargo, no
esperamos que tenga que resistir condiciones climáticas adversas.
Este capítulo esta dedicado al estudio de los bloques que componen el entorno de programación sobre
el que hemos desarrollado nuestra aplicación para el microcontrolador ESP32.
Como punto de partida encontramos las herramientas desarrolladas por Espressif para el desarrollo
de sus dispositivos, que son en gran medida, una de las principales razones por las que se concibió este
trabajo de fin de grado. Como veremos más adelante, gracias a este set de herramientas se potencian las
características mostradas en el apartado 2.2.2.
Del mismo modo, se ha realizado un estudio de los distintos sistemas operativos existentes en los
sistemas en un chip (SoC), examinando sus ventajas y desventajas para finalmente explicar que hace que
los sistemas en tiempo real (RTOS) sean tan interesantes.
A continuación, encontramos una sección dedicada al estudio del sistema operativo en tiempo real
FreeRTOS, que se presenta como un candidato idóneo dentro de los RTOS tanto su adaptación a los sis-
temas Espressif como por su eficiencia en los recursos que maneja. Adicionalmente, trataremos conceptos
y mecanismos indispensables en la programación de sistemas operativos en tiempo real particularizando
los métodos empleados.
La última sección tiene como objetivo la breve descripción de los protocolos y servicios que, por los
términos mencionados durante el desarrollo del software, resultan relevantes en este documento.
24 Capítulo 3. Entorno de Programación del ESP32
3.1.1. Menuconfig
Encontrando un listado de los distintos aspectos que podemos modificar en nuestro ESP32, de los
cuales son relevantes para nuestro proyecto Serial flasher config y Partition table.
Además de las opciones por defecto , podemos crear nuestro propio submenú gracias al fichero Kcon-
fig.projbuild1 ubicado en la carpeta main de nuestro proyecto.
Todos estos parámetros funcionan como variables globales en nuestro proyecto y son usados durante
el código mediante una abreviación. Por ejemplo, la variable que almacena la contraseña del Wi-Fi, es
referenciada por CONFIG_WIFI_PASSWORD.
De esta forma simplificamos la distribución de nuestro software, pudiéndose implementar con una
configuración distinta sin modificar ninguna línea de código.
3.1.2. Compilación
Después de configurar el dispositivo ESP32 y tras haber obtenido el fichero sdkconfig podremos eje-
cutar el comando:
$ idf.py build
CMakeLists.txt: En este archivo se establece el directorio del código del proyecto y se añaden
componentes externos, como en nuestro caso la librería "esp-idf-lib".
La ejecución del comando build generará un directorio "build" con archivos provisionales de compi-
lación, además de contener las bibliotecas y los archivos de salida binarios finales. En consecuencia, el
directorio no suele tener un control de código fuente ni se distribuye.
Tras realizar el proceso de compilación se produce el flasheo del archivo binario generado mediante el
comando:
$ idf.py flash monitor
Este proceso, como se ilustra en la figura 3.B, se realiza una conexión entre la placa y el ordenador
generalmente mediante un cable OTG. Este cable también nos servirá como puerto de comunicaciones
con el dispositivo, que al ejecutar el comando "monitor" nos despliega una terminal con sus mensajes
de log.
El sistema operativo que escogemos para un microcontrolador es otro de los aspectos más importantes
a la hora de elaborar un software. Considerando que la gran mayoría de estos dispositivos son open
source, muchos desarrolladores elaboraron distintos SO y IDEs compatibles. El objeto de este apartado
es comparar los sistemas operativos que existen para SoC y elegir el más adecuado para nuestro proyecto.
Mongoose OS: Surgió como una alternativa IoT a los sistemas. Actualmente ya no es un sistema
operativo muy utilizado, pero nos sirve como antecedente de un modelo que prioriza la conectividad
con distintas plataformas como Google Cloud, AWS o Azure.
Dado que la eficiencia de nuestro proyecto depende directamente de la capacidad que tiene el sistema
de detectar los pulsos en tiempo real, el sistema operativo más adecuado es RTOS, en concreto FreeRTOS,
ya que dispone de librerías y documentación disponible para los dispositivos de Espressif.
C++ se diseñó como una extensión de C y, por tanto, comparten características básicas como ser
lenguajes estándar y compilados. Pero también existen muchas diferencias: C++ es un lenguaje de pro-
gramación orientado a objetos y permite la creación de clases y objetos, el manejo de excepciones y el
uso de plantillas. C++ se considera, por tanto, un lenguaje híbrido ya que tiene tanto características de
la programación orientada a objetos como mejoras enfocadas a las capacidades de C.
Para este proyecto, hemos optado por emplear C, ya que aunque existe una compatibilidad entre
FreeRTOS y C++, la mayoría de la documentación estaba implementada sobre C. Además, la mayoría
de los microcontroladores normalmente se programan en este lenguaje y los compiladores utilizados en el
proceso de flasheo pueden crear conflictos en el dispositivo.
3.4. FreeRTOS
3.4.1. Tareas
Una tarea o task es un término recurrente en la multiprogramación y hace referencia a una sección
de código que se realiza de forma concurrente a otros procesos.
La multiprogramación es la técnica de multiplexación de varios procesos, hilos o tareas para
producir un paralelismo simulado ya que, por la arquitectura de un ordenador, solo un proceso puede
estar ocupando un core del CPU simultáneamente. En consecuencia, las tareas se dividen en ráfagas de
CPU y se intercalan según una lógica descrita por el planificador, por ejemplo asignando una prioridad
a cada tarea.
En FreeRTOS la creación de tareas se realiza mediante la función xTaskCreate() asignando a una
función pasada como parámetro la propiedad de concurrencia. Además, dado que el planificador del
sistema operativo funciona mediante prioridades, se puede fijar una prioridad más alta a una tarea más
importante mediante otro parámetro del tipo entero en dicha función.
En nuestro caso, además de realizar una planificación a través de prioridades hemos optado por la
implementación de la función xTaskCreatePinnedToCore() que asigna dicha tarea a un core específico,
pudiendo dividir las tareas según la carga de CPU que necesiten y otorgando más recursos a tareas más
pesadas.
3.4 FreeRTOS 29
3.4.2. Colas
En la multiprogramación a veces surge la necesidad de comunicar tareas entre sí, este problema
es muy difícil de resolver con la variables comunes de C ya que, aunque definamos una variable global
para las tareas, necesitaremos una lógica que nos indique cuando esa variable ha cambiado, además que
pueden surgir excepciones al intentar acceder a una misma variable desde varios procesos.
Una cola es un mecanismo de comunicación de procesos que se caracteriza por ser una secuencia
de elementos en la que existe operación de inserción xQueueSend() y una operación de extracción
xQueueReceive(). La extracción se puede realizar por dos métodos, si la cola es LIFO el último
elemento en entrar es el primero en salir, este modelo se suele asemejar a una pila de platos que se debe
lavar. En cambio, si la cola es del tipo FIFO el primer elemento en llegar es el primero en salir, como
por ejemplo en la cola de un establecimiento.
Ambas colas se pueden representar mediante el siguiente diagrama:
3.4.3. Semáforos
Como se ha comentado en la sección anterior, cuando dos procesos desean acceder a una misma
variable se puede producir una excepción, esto se debe a que aunque las operaciones de escritura y
lectura parezcan instantáneas realmente no lo son y su ejecución incontrolada puede corromper una
variable o un fichero. Solo las instrucciones denominadas como atómicas realizaran cambios sobre variables
globales durante la ejecución de una tarea.
Un semáforo es un mecanismo que otorga el acceso de un recurso a una tarea mediante la función
xSemaphoreTake(), impidiendo cualquier operación sobre el recurso mientras dicha tarea no haya
liberado el semáforo con xSemaphoreGive(). En consecuencia, se produce un bloqueo en el resto de
tareas que deseen acceder al mismo recurso.
Como veremos más adelante, en este proyecto utilizaremos los semáforos para bloquear el hilo principal
mientras otras secciones de código se ejecutan para desbloquearlo cuando éstas hayan alcanzado el instante
deseado, por lo que no se usarán los semáforos para acceder a recursos sensibles del código.
30 Capítulo 3. Entorno de Programación del ESP32
Para concluir este apartado hemos visto apropiado comentar los protocolos y tecnologías más im-
portantes sobre las que programaremos nuestro software. Además, servirá de referencia para algunos
conceptos mencionados durante las etapas de desarrollo y configuración de nuestro software de adquisi-
ción y de la estación base.
3.5.1. TCP/IP
La arquitectura TCP/IP fue desarrollado por el Departamento de Defensa de EE.UU, siendo actual-
mente el paquete de protocolos más utilizado. Es un conjunto de protocolos que permite la comunicación
entre dispositivos dentro de una red. Provee conectividad extremo a extremo y fiabilidad. Este sistema
es estandarizado y se puede utilizar tanto en redes privadas como en públicas.
El modelo TCP/IP se divide en distintas capas jerarquizadas (capa de aplicación, capa de transporte,
capa de red y capa física), teniendo cada una de ellas una función distinta. El objetivo es proporcionar
servicios a las capas superiores y solicitar servicios a la capa inferior.
3.5.2. Wi-Fi
El Wi-Fi[30] es una tecnología de transmisión de datos inalámbrica que se basa en el estándar 802.11.
La comunicación entre dispositivos terminales, es decir, con interfaz de red, se realiza mediante puntos
de acceso (AP) que son los que generan las redes WLAN.
El estándar Wi-Fi 802.11 registra las normas de funcionalidad de WLAN creadas por el IEEE y
define el uso de las bandas de radio industriales, científicas y médicas (ISM) para las capas tanto física
como la subcapa MAC. Entre versiones del estándar 802.11 puede haber interferencias, por esto existen
métodos para controlarlo como el espectro ensanchado por secuencia directa (DSSS) y la multiplexación
por división de frecuencia ortogonal (OFDM).
El ESP-WROOM-32 utiliza tres versiones compatibles entre sí, siendo la más actual la versión 802.11n.
El estándar 802.11n funciona en las dos bandas de frecuencia de 2,4GHz y 5GHz, llegando a velocidades
de transmisión máximas de 72,2Mbps y 150Mbps, respectivamente.
3.5 Protocolos utilizados 31
3.5.3. SNTP
Es imprescindible que los ordenadores tengan un reloj preciso y sincronizado para evitar errores a largo
plazo. Por ello, se han definido varios protocolos de tiempo. Los primeros fueron el Daytime Protocol
(RFC 867) y el Time Protocol (RFC 868). Como curiosidad, el Time Protocol sufre el problema del año
2036, también conocido como Y2K36, en el que en 2036 su contador llegará a su valor máximo. Este
problema se solucionó con el protocolo NTP (Network Time Protocol) y sus futuras versiones, una de
ellas siendo SNTP (Simple Network Time Protocol).
El protocolo SNTP[31] sincroniza el tiempo de sistema de todos los dispositivos de una misma red.
Los clientes obtienen esta información de un servidor de tiempo y se conectan utilizando el protocolo de
la capa de transporte UDP en el puerto 123. El cliente envía una solicitud SNTP cada periodo de tiempo
y ajusta el tiempo si recibe una respuesta válida del servidor.
Este protocolo es utilizado por ordenadores poco potentes ya que necesita menos memoria y recursos
CPU que NTP. SNTP no dispone de todos algoritmos que implementa NTP y, como consecuencia, SNTP
tiene valores de tiempo menos precisos que NTP.
Actualmente se utiliza el protocolo SNTPv4 que permite direccionamiento IPv4 e IPv6 y el intercambio
de información entre servidores tanto NTP y SNTP ya que existe compatibilidad entre ellos.
3.5.4. MQTT
La tecnología del Internet de las cosas o IoT se ha convertido rápidamente en un aspecto central
en la comodidad de muchas personas. En consecuencia, hemos experimentado un auge sin precedentes
en la automatización de los procesos logrando que hasta los electrodomésticos más simples, como una
tostadora, puedan estar programados y conectados a la red del hogar.
Es por este motivo, son muchos protocolos los enfocados a la tecnología IoT, siendo los más importantes
AMQP, DDS, XMPP y MQTT, entre otros.
MQTT (Message Queuing Telemetry Transport[32]) es un protocolo de comunicación que utiliza el
modelo Publicación-Suscripción para permitir la comunicación M2M (Machine to Machine). La arquitec-
tura publicación-suscripción es un diseño de patrón de mensajes en el cual el remitente envía mensajes a
un mediador (broker), es decir, no se comunica directamente con el consumidor. Los clientes se conectan
vía TCP/IP con el broker, que mantiene registro de los clientes conectados. Los mensajes se clasifican en
topics organizados jerárquicamente y los consumidores son los que se suscriben a los topics para recibir
la información deseada.
MQTT, al ser un protocolo sencillo, es ideal para dispositivos de escasa potencia. Requiere de un
ancho de banda mínimo, emplea los puertos 1883 y 8883 y dispone de un mecanismo de calidad del
servicio (QoS).
Capítulo 4
Software de adquisición
Una vez hemos creado un marco teórico y práctico sobre el que desarrollar nuestro software, es
el momento de detallar las tareas que componen el sistema de adquisición y cuales de los requisitos
mencionados hasta el momento satisfacen.
El resto de secciones del capítulo se dividen como se ha implementado cada tarea, comentando las
secciones de código más relevantes. Cabe destacar que se hacen multitud de referencias a los tasks, las
colas y los semáforos descritos en la sección 3.4, que se implementan según la lógica descrita en dicho
capítulo, también se hace referencia a conceptos relacionados con los protocolos descritos en la sección
anterior.
Clasificación y envío de mensajes: Se ha diseñado una lógica que obtiene los mensajes que cada
tarea introduce en la cola telemetry_queue y según su tipo genera el JSON correspondiente
insertando los datos de dicho mensaje.
34 Capítulo 4. Software de adquisición
La estructura del programa se ha diseñado para que exista una tarea principal encargada de la
creación e inicialización de los recursos y tareas secundarias. Adicionalmente, esta tarea sincronizará la
inicialización de dichos recursos, para que se ejecuten a medida que se produzcan los eventos a los que la
ejecución del programa debe llegar.
Para asegurarnos de que la configuración se ejecuta en orden y no se crean conflictos entre las tareas,
hemos implementado un sistema de sincronización basado en semáforos.
Los semáforos se desbloquearán cuando hayan alcanzado los siguientes eventos respectivamente:
Una vez que el microcontrolador libera el hilo principal, crea la tarea de obtención de datos meteo-
rológicos task_meteo(), la involucrada en el muestreo de los rayos task_pnct() y la encargada de
la clasificación y envío de los mensajes a la estación base mss_sender().
Como se explica en la sección 3.4, dado que nuestro microcontrolador dispone de dos CPU, vamos a
reservar el core 1 para la ejecución de la tarea task_pnct(), ya que es más susceptible ante los desalojos
que pueda realizar el planificador. El resto de tareas, por ser menos relevantes o por no requerir un tiempo
de respuesta ajustado, se delegara su ejecución en el core 0. Si nuestro microcontrolador cuenta con un
único core, es esencial establecer prioridades a las tareas, siendo las tareas con prioridad más alta las que
deben acaparar más tiempo de CPU.
Todo el código mencionado en este capítulo se encuentra también alojado en el repositorio Github del proyecto[33]
4.3 Configuración Wi-Fi 35
Cabe destacar que el manejador Wi-Fi seguirá recibiendo peticiones después de finalizar la configura-
ción, por lo que si el dispositivo se desconecta de la red Wi-Fi, por ejemplo durante una caída de conexión,
mientras realiza otra tarea, podremos reiniciar el proceso y asegurarnos de que se vuelve a conectar.
Del mismo modo, necesitaremos configurar las variables incluidas en el sdkconfig que hacen refe-
rencia al nombre de la red (CONFIG_WIFI_SSID) y su contraseña (CONFIG_WIFI_PASSWORD).
La sincronización del reloj del ESP32 se realiza de forma muy sencilla gracias a la librería
"esp_sntp.h". Mediante la función sntp_setservername()3 se especifica el servidor SNTP con
el que estableceremos la sincronización. En principio se utilizó el dominio pool.ntp.org pero después
hemos preferido instalar un servidor SNTP de forma local y utilizar la IP local del mismo.
La lógica utilizada para la configuración es similar a la mostrada en el apartado anterior, cuando se
inicializa el servidor SNTP se produce un bloqueo del hilo principal hasta que on_got_time()3 devuelva
una marca de tiempo sincronizada. La configuración de la zona horaria se realiza mediante la función
setenv() con el parámetro "CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00"
Tras comentar las implicaciones del protocolo MQTT en la sección 3.5.4 , nos centraremos en esta
sección en la preparación del microcontrolador para realizar las comunicaciones con nuestra estación base
a través de este protocolo.
En la función mqtt_setup()4 nos hemos servido de los métodos definidos en la biblioteca
"mqtt_client.h" que habilitan el registro de nuestro cliente en un servidor MQTT. Mediante la
variable esp_mqtt_client_config_t podremos definir tanto el host destino de nuestros mensajes
como el puerto al que van dirigidos, así como el usuario y la contraseña necesarios para establecer la
conexión. Estas valores se encuentran referenciados en el sdkconfig.
Finalmente, será el manejador mqtt_event_handler()4 el que procese las peticiones MQTT
según su event_id, desbloqueando el mqtt_semaphore cuando el dispositivo se haya conectado al
servidor (MQTT_EVENT_CONNECTED) y notificará en el log cuando los eventos indiquen una desconexión,
publicación, suscripción a topic, errores, etcétera.
La obtención de los datos meteorológicos a partir del módulo barómetro instalado en la placa se ha rea-
lizado gracias a la biblioteca7 "bmp180". En primer lugar, la tarea task_meteo()8 inicializa los pines
SDA y SCL asociados al módulo BMP180 y crea un telemetry_message del tipo TM_METEO. Obtiene
la temperatura en Celsius y la presión atmosférica en Pascales e identifica el mensaje mediante un times-
tamp. Por último envía el mensaje a la cola telemetry_queue mediante la función xQueueSend().
Las tareas de detección y monitorización en principio se podrían concebir como una única función, ya
que si detectamos cada pulso obtendremos el número de pulsos por minuto. Pero esto realmente presenta
varios inconvenientes.
La detección, como veremos más adelante, se realiza mediante una interrupción, por lo que es más
interesante dividir el trabajo en dos tareas, otorgando más importancia al proceso de detección e invocando
el conteo de pulsos con una tarea cada n segundos.
Esta tarea tiene como finalidad, el conteo de los rayos cósmicos detectados por unidad de tiempo.
Para desarrollar esta tarea se ha utilizado el contador hardware PCNT, capaz de registrar el número
de flancos ascendentes y/o descendentes de las señales de entrada.
Hemos creado la función pulse_counter_init()9 que, mediante el uso de la librería
"driver/pcnt.h", asigna y configura los canales PCNT definidos en el sdkconfig. Además, hemos
creado la función get_and_clear()9 encargada de leer el canal indicado como parámetro y reinicia-
lizarlo a 0. De esta forma, mediante un bucle infinito y la función vTaskDelay(), somos capaces de
obtener los valores cada n segundos. Una vez obtenidas las cuentas de cada canal, las identificamos
mediante una marca de tiempo en µs mediante la función gettimeofday().
Por último, asignamos los valores obtenidos anteriormente a un mensaje telemetry_message del
tipo TM_PULSE_COUNT y lo enviamos a la cola telemetry_queue mediante la función xQueueSend().
7 Libreríaincluida en esp-idf-lib
8 Función incluida en meteo.c
9 Función incluida en pulse_monitor.c
4.8 Tareas de detección y monitorización de rayos cósmicos 39
Cuando necesitamos obtener el instante en el que un pulso es captado por nuestro microcontrolador,
nos percatamos de que el procedimiento de polling utilizado en el apartado anterior resulta poco efectivo.
El problema surge al consultar de forma activa el estado de una entrada, ya que el tiempo entre
consultas puede ser insuficiente para registrar el pulso como en el caso a) de la figura 4.G, o que el tiempo
transcurrido desde que se produce el pulso hasta que se detecte, genere una imprecisión como en el caso
b). El único suceso válido sería el representado en el caso c).
Pero lo más importante es que en este proceso se desperdicia mucho tiempo de CPU en operaciones
prescindibles.
En estos casos, resulta más favorable el uso de la rutina de servicio de interrupción. Para explicar
como funciona este mecanismo, debemos centrarnos primero en definir los elementos que intervienen en
el proceso de una interrupción:
Interrupción: Es la acción que desencadena una suspensión temporal del sistema operativo. En
nuestro caso, la interrupción se producirá cuando se detecte un flanco de subida/bajada del pulso
procedente del monitor de neutrones.
IRQ: Es la señal que indica a la CPU que debe suspender de forma temporal la ejecución de un
proceso para pasar a ejecutar la subrutina de servicio de interrupción ISR.
Para configurar la ISR de nuestro microcontrolador, hemos definido la función init_GPIO()10 con
todas las llamadas necesarias para inicializar los pines de entrada definidos en el sdkconfig y el método
de detección mediante flanco de subida y de bajada GPIO_INTR_ANYEDGE. Además, indicamos que la
rutina de interrupción será la función detection_isr_handler()10 .
En esta función escribiremos el código para caracterizar el flanco detectado, obteniendo el nivel de
los canales mediante la llamada gpio_get_level(). A diferencia de la tarea anterior, la obtención de
la marca de tiempo se debe realizar con la función atómica xthal_get_ccount(), ya que la ejecución
de gettimeofday() dentro de una ISR produce excepciones en el sistema. Por último enviaremos el
mensaje telemetry_message del tipo TM_PULSE_DETECTION a la cola telemetry_queue.
Cuando se diseña un sistema remoto surge la necesidad de distribuir actualizaciones sobre el software
flasheado en el microcontrolador. Este proceso se realiza normalmente mediante la interfaz UART, ya
sea mediante un conversor a USB situado en la placa o mediante los puertos TX y RX. En ambos casos,
es inevitable realizar la conexión físicamente sobre la placa.
Para resolver este problema, se creó la tecnología Over-The-Air que permite la programación de un
dispositivo a través de su conexión inalámbrica. Este mecanismo es habitual en los smartphones dada la
cantidad de nuevas aplicaciones, servicios y fallos de seguridad que aparecen cada día.
En FreeRTOS, se puede realizar este proceso mediante el uso de la librería "esp_https_ota.h" que
nos permite, mediante la URL en la que se ubica nuestro nuevo binario y un certificado digital, actualizar
el microcontrolador de forma segura. El proceso de actualización se puede establecer por medio de una
conexión con el dispositivo para indicarle que existe una nueva actualización, o bien, que sea el dispositivo
el que compruebe si existe dicha actualización.
Para simplificar el código hemos desarrollado la segunda opción de forma que, para verificar si existe
un nuevo binario, primeramente, debe descargar un hash y comprobar que es distinto al de su versión.
En caso afirmativo, descarga el nuevo binario, flashea la placa y reinicia el dispositivo con el nuevo
software.
El primer flash de la placa se realiza de forma física, pero a partir de ese momento, ya podemos
actualizar nuestro software de forma remota. El hash que identifica a cada versión se genera mediante la
herramienta sha256sum, que explicaremos detalladamente en la sección 6.1.1.
Por último, para que se puedan realizar correctamente las peticiones HTTPS, es necesario el uso de
un certificado SSL que identificará la pagina web a la que nos conectamos, proporcionando además,
autenticación de los usuarios y privacidad en las comunicaciones.
Para obtener este certificado necesitamos un navegador web como Chrome o Firefox. En el dominio
en el que se ubican el hash y el binario clickamos sobre el candado de la URL, desplegando el menú con
los certificados asociados. La raíz de la ruta de certificación es el certificado más seguro, por lo que es el
que seleccionaremos para nuestro dispositivo ESP32.
En el fichero sdkconfig se encuentran las variables que hacen referencia a las URLs en las que se
encuentra el hash (CONFIG_OTA_HASH) y el binario (CONFIG_OTA_URL), así como la que hace referencia
al tiempo que transcurre entre las verificaciones de los hashes (CONFIG_OTA_TIME).
El siguiente diagrama muestra todos los archivos involucrados en el proyecto y sus dependencias entre
sí. Como podemos observar, hemos creado una librería "common.h" que contiene las declaraciones,
variables y librerías indispensables para todos los módulos. Esta librería se incluirá posteriormente
dentro de otras con preferencias más particulares, como por ejemplo en "wifi.h" que además de in-
cluir la librería común se incluye "esp_wifi.h", variables y definiciones específicas del módulo wifi.c.
La finalidad de este capítulo es la implementación de un servidor que sea capaz de manejar las
peticiones proporcionadas por el ESP32 del sistema de adquisición, almacenarlas en una base de datos y
generar una interfaz web desde la que se puedan visualizar los datos procesados en gráficas.
En la primera sección se ha dedicado a explicar la estructura de los servicios proporcionados por el
servidor y como interactúan entre sí, proporcionando un sistema completo para la obtención de los datos
y, además, para la monitorización de los recursos del servidor.
En la sección de InfluxDB se discute la elección de esta base de datos en lugar de las bases de datos
clásicas como MySQL y como el agente de servidor Telegraf se relaciona con la base de datos y obtiene
las métricas de los servicios que monitoriza. La configuración, como en el resto de apartados, se realizará
de forma guiada aportando capturas para su entendimiento.
En la sección de Mosquitto estudiaremos el funcionamiento del servidor MQTT y como procesa
los mensajes procedentes del sistema de adquisición. Realizaremos una configuración simple, aunque
comentaremos la cantidad de opciones que ofrece este servicio.
Por último, explicaremos como unir Grafana con la base de datos InfluxDB y como orquestar los
datos mediante el uso de gráficas, tablas u otros mecanismos de visualización de datos. Generaremos
un dashboard en el que mostrar las gráficas organizándolas en función del dispositivo del que proceden,
simplificando su monitorización y generando alertas para sistemas críticos.
44 Capítulo 5. Configuración estación base
5.1. Estructura
Nuestra estación base se compone de un servidor implementado sobre un MiniPC con un procesador
Intel(R) Core(TM) i7-10510U, 8 GB de memoria RAM, puerto Ethernet Gigabit y el sistema operativo
Debian 11 instalado. Este servidor, como hemos explicado anteriormente, tiene la función de recoger,
almacenar y graficar los datos transmitidos por el sistema de adquisición. Los servicios se ejecutarán
mediante el uso de Docker y Docker Compose, lo que nos garantiza una rápida implementación a la vez
que aporta escalabilidad a nuestro sistema.
La ejecución del archivo docker-compose.yml genera la siguiente estructura:
InfluxDB es un sistema de gestión de bases de datos de código abierto que, a diferencia de otras
clásicas como MySQL, almacena y analiza datos de series temporales. Una serie temporal es un conjunto
de datos obtenidos en intervalos de tiempo y ordenados cronológicamente, por lo que resultan ideales
para tareas de monitorización, almacenamiento de datos de sensores IoT y realizar análisis en tiempo
real. Cuenta con un motor de base de datos optimizado para datos de serie de tiempo, un lenguaje de
consulta simple y potente (InfluxQL), una API RESTful para acceder a los mismos desde aplicaciones
y servicios y una arquitectura de escalabilidad horizontal para permitir el crecimiento de estos y el
tráfico.
El uso de InfluxDB es sencillo gracias a que permite su instalación en cualquier sistema operativo, ser
ejecutado en una amplia variedad de plataformas y por su interfaz de la línea de comandos (CLI) que
facilita la administración de la base de datos. Como es escalable, maneja grandes cantidades de datos y
tráfico sin problemas, pudiendo añadir más servidores para manejar el crecimiento de los datos y el tráfico
gracias a que su arquitectura de escalabilidad es horizontal. Finalmente InfluxDB es una base de datos
de código abierto que puede ser usado y modificado libremente por cualquiera. Como la comunidad de
código abierto es muy activa existen una gran variedad de recursos disponibles para ayudar a los usuarios
a manejar InfluxDB.
Telegraf, desarrollado por InfluxData[34], es un agente servidor de código abierto para la moni-
torización de redes y servidores, diseñado para ser eficiente y modular. Está escrito en el lenguaje de
programación Go[35] lo que le proporciona potencia y rapidez, pudiendo ser ejecutado en Linux, MacOS
y Windows.
Lo más interesante de estos sistemas es la forma en la que son capaces de recopilar y distribuir los
datos, formando una simbiosis perfecta.
1 influxdb:
2 image: influxdb
3 container_name: influxdb
4 ports:
5 - "8086:8086"
6
7 telegraf:
8 image: telegraf
9 container_name: telegraf
10 user: telegraf:998
11 links:
12 - influxdb
13 volumes:
14 - ./telegraf.conf:/etc/telegraf/telegraf.conf:ro
15 - /var/run/docker.sock:/var/run/docker.sock
16 environment:
17 - INFLUX_TOKEN=jYPEWwAPHRMd1VtPDuIW2pfEBPxcl...
46 Capítulo 5. Configuración estación base
En la primera ejecución del docker-compose.yml el servidor descarga las imágenes de los dockers
de influxdb y telegraf directamente del repositorio oficial y configura los parámetros de los dockers con
las variables seleccionadas. El contenido y utilidad de estas variables se explicará a medida que vayamos
configurando el entorno desde la interfaz gráfica.
Una vez hemos desplegado los servicios con Docker Compose, nos dirigimos a la IP local de nuestro
servidor, accediendo a través del puerto 8086. Como podemos observar en la sección de código anterior,
en Docker se exponen los puertos de forma que asignamos un puerto del servidor al puerto interno del
docker de la siguiente forma "p-serv:p-docker".
Al acceder por primera vez al servidor de InfluxDB deberemos configurar los parámetros de nuestra
base de datos. Desde la última versión, las bases de datos se denominan buckets que son accesibles
mediante los permisos otorgados a la organización a la que pertenecen:
Desde la sección Telegraf de Load Data realizaremos la conexión entre la base de datos y el agente
de servidor telegraf. Al crear una nueva configuración seleccionaremos System y Docker como sistemas
para monitorizar, seleccionando los plugins cpu, disk, docker, mem, net, processes, swap y system. Estos
plugins obtendrán parámetros de los recursos del sistema, permitiendo controlar la carga del sistema y
de los servicios que se encuentran en ejecución.
Adicionalmente hemos seleccionado el plugin mqtt-customer[36] que nos permite obtener los datos
del servidor MQTT directamente. La forma de implementar este plugin es copiar las líneas de código
extraídas del repositorio de Github y sustituyendo las variables de servers y topics por los configurados
en la sección 4.5.
5.2 InfluxDB y Telegraf 47
Tras realizar la configuración guiada se genera un token para acceder al bucket, dicho token debe
sustituir al contenido de la variable de entorno INFLUX_TOKEN del docker-compose.
Desde el apartado Edit Telegraf Config podemos exportar el archivo de configuración con la configu-
ración por defecto de los módulos.
5.3. Mosquitto
Mosquitto[37] es un servidor de mensajería MQTT de código abierto, muy ligero y simple que
permite una implementación en diferentes dispositivos y sistemas operativos. Además, su mantenimiento
es simple, pero aun así logra manipular miles de dispositivos y miles de mensajes simultáneamente.
Mosquitto actúa de forma que un cliente MQTT se conecta al servidor broker y publica un mensaje en
un topic, cuando lo recibe el servidor Mosquitto almacena el mensaje y lo reenvía a todos los clientes que
están suscritos al topic.
1 mqtt:
2 image: eclipse-mosquitto
3 container_name: mqtt
4 links:
5 - influxdb
6 volumes:
7 - ./mosquitto.conf:/mosquitto/config/mosquitto.conf
8 ports:
9 - "9000:9000"
1 log_type all
2
3 listener 9000
4 allow_anonymous true
En esta configuración log_type se hace referencia a los tipos de mensaje que se desean registrar
como debug, error, warning, notice o all que incluye todos. Este fichero luego puede ser interpretado por
InfluxDB o Grafana para la generación de alertas, y para simplificar la configuración.
Mediante la variable listener que especifica el puerto en el que se van a escuchar las conexiones
entrantes, también podemos vincular una IP al agente mediante la opción bind address/host o
utilizar un websocket.
Si deseamos establecer una contraseña para nuestro servidor MQTT, deberemos cambiar
allow_anonymous a False y añadir el fichero donde se encuentre dicha contraseña con
password_file /etc/telegraf/pass por ejemplo. Este archivo se puede incluir también en la
sección volumes antes mencionada.
Esta resulta la configuración más básica que podemos realizar, pero gracias al manual de configuración
de Mosquitto[38] podemos establecer infinidad de características desde establecer colas con calidad de
servicio (QoS) hasta listas de usuarios permitidos (whitelist) o bloqueados (blacklist).
5.4 Grafana 49
5.4. Grafana
Grafana[39] es un servidor web con software de código abierto que visualiza y analiza datos a partir de
una base de datos. Sirve para monitorizar diferentes fuentes de datos, redes, servidores, bases de datos,
sistemas operativos, aplicaciones y para crear dashboards personalizados (tablas y gráficos que muestran
datos en tiempo real). El lenguaje de Grafana es de consulta SQL de manera que extrae datos de la base
de datos y los representa en un gráfico.
Las ventajas de Grafana frente a otras herramientas de visualización de datos son que es compatible
con una gran variedad de fuentes con datos distintos, así logra obtener múltiples datos de diferentes
fuentes y los visualiza en un único sitio, es personalizable al permitir que se puedan crear dashboards
para visualizar los datos según las preferencias o necesidades e incluso es posible incluir plugins y widgets
que mejoran la funcionalidad del dashboards creado, el interfaz de Grafana es intuitiva por lo que es fácil
y rápido configurar dashboards. Por último se pueden compartir, visualizar e interactuar los dashboards
con otros usuarios.
1 grafana:
2 image: grafana/grafana-enterprise
3 container_name: grafana
4 links:
5 - influxdb
6 ports:
7 - "3000:3000"
La configuración se realiza desde el navegador a través del puerto 3000. En primer lugar, accedemos
al servidor de Grafana mediante el usuario y contraseña admin. Tras realizar el loggin será obligatorio
cambiar la contraseña de nuestro usuario admin.
Desde la sección Data Source seleccionamos como fuente de datos InfluxDB y sustituimos los campos
de URL por la IP de nuestro servidor InfluxDB y su puerto, token por el obtenido en la figura 5.C y
organization y bucket por los elegidos en la configuración inicial de la base de datos.
Para comprobar que la configuración introducida funciona correctamente debemos obtener el tick
verde de la figura 5.E al pulsar en el botón Save & test.
En Grafana la representación de los datos se organiza con la ayuda de los dashboards, que funcionan
como una pizarra en la que puedes añadir tablas, gráficas o otras representaciones de datos.
50 Capítulo 5. Configuración estación base
Por último, para la generación de tablas usaremos el lenguaje Flux desarrollado por InfluxData,
que nos permite filtrar los datos en función del bucket, el tipo de medida y el tipo de dato. Además, la
apariencia de la gráfica se puede modificar cambiando el tipo de representación, los colores, su leyenda,
las unidades con las que trabajan los datos, etcétera. Todas estas opciones hacen de Grafana un entorno
ideal para generar nuestros gráficos.
Componentes adicionales
GitHub[40] es un servicio basado en la nube para almacenar y administrar código, así como mantener
un seguimiento y compartir proyectos. Estos proyectos se generan en repositorios y los cambios realiza-
dos se guardan con commits. Para destacar los commits más importantes podemos utilizar los tags, o
etiquetas, para determinar las nuevas versiones del proyecto. Github, además, ofrece una plataforma de
integración y despliegue continuo que permite automatizar la compilación, las prueba y el despliegue de
tu software.
Mediante un flujo de trabajo diseñado con el lenguaje YAML y ubicado en la ruta
.github/workflows de nuestro repositorio, podremos definir el entorno, las tareas y los eventos que
desencadenarán su ejecución trigger.
Hemos establecido como evento la publicación de un tag que comience con v, por ejemplo v1.1.0 o el
tag latest.
A continuación hemos seleccionado como entorno el sistema operativo Ubuntu, ejecutándose nuestras
tareas (steps) sobre el contenedor espressif/idf v4.4. La ventaja de este entorno es que no es
necesaria la instalación del set de herramientas de Espressif, por lo que simplificamos en gran medida las
tareas y delegamos la configuración del entorno al distribuidor oficial.
1 jobs:
2 builder:
3 runs-on: ubuntu-latest
4 container: espressif/idf:v4.4
5 steps:
6 - ...
54 Capítulo 6. Componentes adicionales
La lógica que hemos implementado sigue el esquema de la figura 6.A, de forma que se realizará un
checkeo del código y se compilará mediante los comandos de IDF explicados en la sección 3 del capítulo
3.1. Por último actualizará o creará un latest release con el binario generado en el bloque de compilación
y un hash asociado a esta versión.
Estas tareas se realizarán de forma segura y sin revelar datos o información sensible gracias al uso de
los secretos de Github. De esta forma, hemos configurado un token en Github para actualizar el release
y subir los nuevo ficheros y lo hemos almacenando en la variable secrets.TOKEN.
Además, dado que el menuconfig genera un archivo sdkconfig con las contraseñas del Wi-Fi y MQTT
en texto plano se ha evitado añadir este archivo al control de versiones y en su lugar hemos comprimido
dicho archivo y se ha almacenado en la variable secrets.SDKCONFIG. En el proceso de compilación
se usará esta variable descomprimida para generar los binarios configurados, pero no se mostrán nunca
estas contraseñas.
Todo el código mencionado en este capítulo se encuentra también alojado en el repositorio Github del proyecto[33]
6.2 Implementación en Google Cloud 55
Google Cloud[41] es un servicio ofrecido por Google que permite almacenar en la nube gran variedad de
herramientas sin necesidad de hardware o software adicional. Destaca por su escalabilidad y flexibilidad,
adaptando las necesidades del usuario o la empresa de manera sencilla. También se caracteriza por la
seguridad a la hora de proteger datos y su precio competitivo.
Hemos elegido esta plataforma frente a AWS (Amazon Web Services) por diversas razones. En primer
lugar, debido a la facilidad de uso e interfaz más intuitiva. En segundo lugar, Google Cloud ofrece un
mejor soporte técnico y una mayor cantidad de documentación. Por último, como hemos nombrado antes,
por su escalabilidad y precio.
Google Compute Engine (GCE) es una infraestructura de Google Cloud Platform que ofrece numerosos
servicios para lanzar máquinas virtuales según las necesidades de cada usuario. GCE permite ejecutar
gran cantidad de máquinas virtuales simultáneamente y administrar recursos de manera eficiente, para
así ahorrar tanto tiempo como dinero.
Nuestra estación base se ha configurado sobre un servidor conectado de forma local con el resto de
dispositivos, este modelo hace que la escalabilidad del sistema sea muy complicada, ya que no podremos
situar distintos sistemas de adquisición geográficamente distribuidos y conectarlos al mismo servidor.
La solución planteada es utilizar la infraestructura de Google Cloud, alojando nuestro servidor en la
nube, de forma que cada sistema de adquisición pueda conectarse de forma remota y enviar los datos
recopilados.
Cabe mencionar que la conexión de los sistemas a la nube de Google se puede filtrar mediante el
uso de su propio firewall, simplemente deberemos configurar una regla para el puerto 9000 del servidor
de Mosquitto y el puerto http/https. Hay que tener en cuenta que desde ese momento el puerto se
encontrará disponible para todo Internet, por lo que debemos securizar la conexión mediante usuario y
contraseña o el uso de claves simétricas. Adicionalmente, deberemos modificar el puerto expuesto en el
docker-compose.yml sustituyendo "3000:3000" por "80:3000", de esta forma visualizaremos la
interfaz web desde le puerto HTTP en lugar del asignado por defecto.
Este servidor debe tener instalado docker y docker-compose, de forma que, levantando el servicio
configurado en el docker-compose.yml, simplemente reproduciendo la configuración mostrada en el
capítulo 5 habremos transferido el servicio a Google.
Las especificaciones de la máquina virtual de Google se muestran en la figura 6.D, además de las
reglas firewall configuradas. La herramienta de estimación del coste de la instancia de Google nos puede
ayudar a ajustar los recursos del servidor teniendo en cuenta el gasto del servicio.
6.2 Implementación en Google Cloud 57
Resultados
En este capítulo se va a mostrar el resultado de los distintos bloques del sistema de adquisición, de
forma que sirva tanto como un reflejo del funcionamiento final del sistema como una comprobación en
caso de replicar el modelo.
En primer lugar explicaremos los pasos necesarios para realizar la compra de nuestros circuitos im-
presos en la empresa JLCPCB, generando los archivos necesarios en Kicad 6 y eligiendo los parámetros
de configuración de la página web. Una vez hayamos obtenido la placa realizaremos el montaje físico de
la placa, soldando los componentes electrónicos.
En relación con el software, primeramente comentaremos la salida obtenida al realizar un flasheo
directamente en la placa, como se ha ilustrado en la figura 3.B del capítulo 3. Después realizaremos una
actualización del firmware del dispositivo mediante OTA, visualizando además el funcionamiento de la
integración continua en Github Actions.
Por último, desde Grafana visualizaremos los datos obtenidos del monitor y de la monitorización del
servidor.
60 Capítulo 7. Resultados
7.1. Hardware
JLCPCB[42] es una empresa de manufacturación de PCB fundada en 2006 en China que fabrica
sistemas empotrados por encargo. Es conocida por sus productos de calidad y bajo coste. Fabrica PCB
de una, dos y varias capas y cada una de ellas son sometidas a un control de calidad antes de ser
enviadas. Como ya explicamos y anticipamos en el capítulo 2 la creación del circuito impreso se encargó
a esta empresa, que en pocas semanas recibimos en nuestro domicilio. En Kicad 6 generamos los archivos
necesarios en el proceso de fabricación desde el menú Archivo/Salidas de fabricación/Gerbers.
El ensamblado de la placa se realizó siguiendo el esquema del apéndice A, soldando cada componente
con la ayuda de una estación de soldadura, estaño y pasta térmica. Además, para no soldar componentes
sensibles, como el ESP32, los módulos o el LM339N, directamente a la placa se han soldado unos sockets
para insertar dichos componentes, facilitando su extracción.
La siguiente figura muestra el resultado del ensamblaje:
Las capturas mostradas en esta sección son el resultado de la ejecución del siguiente comando, que
como vimos en capítulos anteriores, flashea nuestro código a la placa.
$ idf.py flash monitor
La ejecución de nuestro programa comienza con la configuración de los protocolos Wi-Fi y SNTP,
como se puede observar en la figura 7.B, cuando nuestro microcontrolador obtiene su dirección IP local
el semáforo wifi_semaphore se desconecta. De igual modo ocurre con SNTP al obtener una fecha
sincronizada.
Después de que haya terminado la inicialización de todos los recursos el hilo principal crea las tareas
asignándoles sus cores correspondientes, como vimos en la sección 4.2. La siguiente figura muestra el re-
sultado de la ejecución de las tareas, mostrándose la obtención de la temperatura y la presión atmosférica,
los pulsos detectados en cada canal y como se publican los mensajes mediante el protocolo MQTT.
Para realizar una actualización a través de internet mediante OTA, es necesario realizar un nuevo tag
latest. El workflow de Github Actions se encarga de realizar la compilación en la nube y de generar el
binario y el nuevo hash.
Al terminar la ejecución del workflow podemos visualizar el resultado de cada step y el tiempo
que han tardado, así como los logs asociados a cada una de ellas. Como podemos intuir, el proceso de
compilación del binario es la tarea que más tiempo requiere.
Desde la sección releases de nuestro proyecto de Github se obtiene el resultado final de la integración
y distribución continua. Desde esta página descargará nuestro microcontrolador el binario y comparará
los hashes. Además, se incorpora el código asociado a este tag.
Ahora que Github tiene almacenada una versión de código superior a la implementada en el micro-
controlador, la tarea task_ota() verifica que el hash guardado es distinto y se produce la actualización
del firmware. El ESP32 descarga el nuevo binario (Reciving data), lo almacena en la memoria y reinicia
el microcontrolador con la siguiente versión.
64 Capítulo 7. Resultados
Finalmente, en esta sección visualizaremos mediante el uso de gráficas los datos obtenidos por el
sistema de adquisición de datos conectado a dos monitores de neutrones BP28 Chalk-River.
En la figura 7.H hemos representado las siguientes gráficas:
Monitor Counts Graph: Esta gráfica muestra el número de cuentas que han obtenido los moni-
tores cada 10 segundos. Los resultados revelan que el número de cuentas por minuto es del orden
de 720-840cpm, lo que es un resultado acertado en la localización geográfica en la que se encuentra
nuestro monitor. En la base Antártica, debido a la baja densidad atmosférica, las cuentas son del
orden de 10000cpm.
Monitor Counts Pie Chart: En este gráfico circuilar se ha representado la media de cuentas
por cada canal, esto es necesario para saber si existe algún problema hardware o software que
desequilibre el número de cuentas de los monitores.
Monitor Counts Bar Chart: Dado que en la primera gráfica no se visualiza de forma directa
el número de cuentas cada 10 segundos, resulta más útil generar un gráfico de barras que además
representa su proporción, siendo el rango de 140-150cpm los valores más detectados.
Las siguientes gráficas representan los parámetros capturados por el agente servidor Telegraf. Estos
datos son clave para el buen mantenimiento del servidor, ya que si detectamos que por ejemplo la CPU
está sobrecargada, tiene una temperatura crítica o falta espacio en el disco, deberemos realizar cambios
hardware en la estación base.
Del mismo modo, se ha representado la carga de cada Docker, el porcentaje de espacio que utilizan y
el tiempo que llevan ejecutándose de forma ininterrumpida. Todo esto es útil para verificar el correcto
funcionamiento del servidor y que no se hayan producido reinicios.
Lineas futuras
Para el presente Trabajo de Fin de Grado se proponen los siguientes puntos:
Incorporar el módulo de Arduino SDCH para almacenar los datos obtenidos también de forma
local. Esto puede ser útil si se producen desconexiones durante periodos muy largos de tiempo.
Establecer un mecanismo de gestión de logs con logrotate y una rutina crontab. De esta forma
realizaremos una limpieza de logs cada cierto tiempo.
Presupuesto
Concepto Importe
Componentes electrónicos 354,13 €
Material 1800 €
Personal 15000€
Total 17154,13 €
[4] E. Catalán, “Monitor de neutrones de castilla-la mancha (CaLMa).” [Online]. Available: https:
//docplayer.es/8219116-Monitor-de-neutrones-de-castilla-la-mancha-calma-edwjoe-yahoo-es.html
[8] O. G. Población, “The neutron monitor control panel,” Journal of Physics: Conference Series, no.
632, 2015. [Online]. Available: https://iopscience.iop.org/article/10.1088/1742-6596/632/1/012055/
pdf
[9] O. García, “Calma station and a new data acquisition system for neutron monitors,” Ph.D. disser-
tation, Universidad de Alcalá Departamento de Automática, 2020.
[10] V. Florio, “El origen de los rayos cósmicos : un estudio indica con mayor precisión que esas
partículas ultraenergéticas provienen del exterior de la vía láctea,” Pesquisa FAPESP, no. 260, oct
2017. [Online]. Available: https://revistapesquisa.fapesp.br/es/el-origen-de-los-rayos-cosmicos/
[12] J. Medina, Introducción al estudio de los rayos cósmicos, U. de Alcalá, Ed., 2011.
[15] “Chalk River BF3 Proportional Counter (ca. 1960s, 70s),” https://www.orau.org/
health-physics-museum/collection/proportional-counters/neutron-detectors/chalk-river-bf3.html
[último acceso 25/junio/2022].
[30] D. Stanley, “Control and provisioning of Wireless Access Points (capwap) Protocol Binding for
IEEE 802.11,” RFC 5416, mar 2009. [Online]. Available: https://www.rfc-editor.org/info/rfc5416
[31] D. Mills, “Simple network time protocol SNTP version 4 for IPv4, IPv6 and OSI,” RFC 4330, jan
2006. [Online]. Available: https://www.rfc-editor.org/info/rfc4330
[34] “Get started with IfluxDB oss 2.2,” https://docs.influxdata.com/influxdb/v2.2/ [último acceso
15/junio/2022].
[43] D. A. Zajac, “An open source iot garage real time controller (garagertc,” Jordan Journal of
Electrical Engineering, vol. 6, no. 3, pp. 179–203, 2020. [Online]. Available: https://www.academia.
edu/44811944/An_Open_Source_IoT_Garage_Real_Time_Controller_GarageRTC_
[44] R. Michon, “A fauts architecture for the ESP32 microcontroller,” in Sound and Music Computing
Conference (SMC-20). [Online]. Available: https://hal.archives-ouvertes.fr/hal-02988312/document
[46] “Página ofical The latex Project,” https://www.latex-project.org/ [último acceso 27/agosto/2022].
[55] U. ELECTRONICS, “Circuito integrado LM339 comparador de voltaje,” September 2019, https:
//grabcad.com/library/lm339n-1 [último acceso 18/agosto/2022].
[57] Singlefonts, “Pin header and jumper: Pin header, straight, 3 poles, pitch 2,54 mm with a jumper,”
April 2019, https://grabcad.com/library/pin-header-and-jumper-1 [último acceso 18/agosto2022].
[60] “Single Supply Quad Comparators LM339, LM339e, LM239, LM2901, LM2901e, LM2901v, ncv2901,
mc3302,” https://www.onsemi.com/pdf/datasheet/lm339-d.pdf [último acceso 18/agosto/2022].
[61] A. Maier, “Comparative analysis and practical implementation of the ESP32 mi-
crocontroller module for the internet of things,” in 7th International Conference on
Internet Technologies and Applications, 2017. [Online]. Available: https://www.researchgate.
net/publication/320273388_Comparative_Analysis_and_Practical_Implementation_of_the_
\uppercase{ESP}32_Microcontroller_Module_for_the_Internet_of_Things
Esquemático
Apéndice B
Esquemático PCB
Apéndice C
Herramientas y recursos
PC compatible
Universidad
de Alcalá