{"id":10357,"date":"2026-05-08T09:00:00","date_gmt":"2026-05-08T07:00:00","guid":{"rendered":"https:\/\/blogs.etsii.urjc.es\/dseytr\/?p=10357"},"modified":"2026-05-08T00:24:04","modified_gmt":"2026-05-07T22:24:04","slug":"cloudia","status":"publish","type":"post","link":"https:\/\/blogs.etsii.urjc.es\/dseytr\/cloudia\/","title":{"rendered":"CloudIA"},"content":{"rendered":"\n<p id=\"cloudia\"><strong>Autor:<\/strong> David R\u00edsquez G\u00f3mez<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"-1-introducci-n\">\ud83d\ude80 1. Introducci\u00f3n<\/h2>\n\n\n\n<p><strong>CloudIA<\/strong> es un ente rob\u00f3tico dise\u00f1ado para fusionar la Inteligencia Artificial en la nube con la presencia e interacci\u00f3n f\u00edsica. Formalmente, el objetivo de este proyecto es crear un asistente de voz basado en modelos de Inteligencia Artificial modernos que, a su vez, funciona como un altavoz inteligente.<\/p>\n\n\n\n<p>Todo el sistema es impulsado por un microcontrolador ESP32, capaz de conectarse a APIs complejas, soportar flujos de streaming de datos, ejecutar protocolos de WiFi y Bluetooth y coordinar hardware interactivo en tiempo real sin comprometer la memoria ni la experiencia de usuario.<\/p>\n\n\n\n<p>A diferencia de un altavoz comercial est\u00e1ndar, CloudIA se ha dise\u00f1ado prestando especial atenci\u00f3n a la expresividad visual f\u00edsica, lo que permite interpretar su estado de \u00e1nimo y respuestas. Adem\u00e1s, se han integrado todos los componentes sobre un cuerpo en homenaje a Eva de la pel\u00edcula <em>Wall-E<\/em>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"-2-arquitectura-hardware\">\u2699\ufe0f 2. Arquitectura Hardware<\/h2>\n\n\n\n<p>El cerebro del sistema es una placa <strong>ESP32-WROOM-D<\/strong>, seleccionada por su arquitectura Dual-Core, imprescindible para manejar en paralelo el procesamiento de red (WiFi\/Bluetooth), la lectura de audio y las animaciones visuales. La placa se ha conectado a una base de expansi\u00f3n para facilitar el cableado.<\/p>\n\n\n\n<p>Los \u00absentidos\u00bb de CloudIA se dividen en los siguientes componentes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\ud83d\udd79\ufe0f <strong>Input de control:<\/strong> Pulsador moment\u00e1neo con aro RGB integrado. Configurado en el pin 19 utilizando la resistencia interna <code>INPUT_PULLDOWN<\/code> del ESP32 para evitar el uso de resistencias externas.<\/li>\n\n\n\n<li>\ud83c\udfa4 <strong>O\u00eddo (Micr\u00f3fono):<\/strong> M\u00f3dulo omnidireccional INMP441, conectado mediante el bus I2S para aprovechar el acceso directo a memoria (DMA) y no bloquear el procesador.<\/li>\n\n\n\n<li>\ud83d\udd0a <strong>Voz (Altavoz):<\/strong> Amplificador MAX98357A (tambi\u00e9n por bus I2S), conectado a un peque\u00f1o altavoz para la salida de texto a voz y la reproducci\u00f3n de m\u00fasica.<\/li>\n\n\n\n<li>\ud83d\udcfa <strong>Expresi\u00f3n Facial:<\/strong> Pantalla TFT GC9A01 redonda controlada por bus SPI.<\/li>\n\n\n\n<li>\ud83e\udd16 <strong>Expresi\u00f3n Gestual:<\/strong> Servomotor SG90 (controlado por PWM) que permite rotar la cabeza del robot de un lado a otro.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"586\" src=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/circuit-1024x586.png\" alt=\"\" class=\"wp-image-10364\" srcset=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/circuit-1024x586.png 1024w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/circuit-300x172.png 300w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/circuit-768x439.png 768w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/circuit-1536x879.png 1536w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/circuit-2048x1172.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Esquema de la circuiter\u00eda de CloudIA<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"-3-arquitectura-software-rtos-y-documentaci-n-de-clases\">\ud83d\udcbb 3. Arquitectura Software: RTOS y Documentaci\u00f3n de Clases<\/h2>\n\n\n\n<p>En beneficio de la entendibilidad, modularidad y desacoplamiento, la arquitectura software ha sido dise\u00f1ado aprovechando los beneficios de la Orientaci\u00f3n a Objetos proporcionada por C++. As\u00ed, en lugar de desarrollar el proyecto en un \u00fanico archivo principal monol\u00edtico, se ha seguido un patr\u00f3n basado en managers. De esta forma, cada componente interact\u00faa exclusivamente con el manager encargado de su comportamiento y, desde el punto de vista del software, la utilizaci\u00f3n de componentes queda completamente encapsulada.<\/p>\n\n\n\n<p>El sistema est\u00e1 gobernado por <strong>FreeRTOS<\/strong>, dividiendo el trabajo en tres tareas paralelas ancladas al n\u00facleo 1, dejando el n\u00facleo 0 libre para la conexi\u00f3n WiFi. Adem\u00e1s, se le asign\u00f3 a cada tarea la memoria RAM y prioridad en funci\u00f3n de su importancia de cara al funcionamiento del sistema.<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-center\" data-align=\"center\">Tarea<\/th><th class=\"has-text-align-center\" data-align=\"center\">Prioridad (FreeRTOS)<\/th><th class=\"has-text-align-center\" data-align=\"center\">Memoria Asignada<\/th><th class=\"has-text-align-left\" data-align=\"left\">Descripci\u00f3n<\/th><\/tr><\/thead><tbody><tr><td class=\"has-text-align-center\" data-align=\"center\"><strong><code>taskControl<\/code><\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\">Alta (3)<\/td><td class=\"has-text-align-center\" data-align=\"center\">8 KB<\/td><td class=\"has-text-align-left\" data-align=\"left\">Dirige el flujo de ejecuci\u00f3n, efect\u00faa los cambios de estado y toma las decisiones cognitivas. Orquesta los diferentes managers para conseguir el funcionamiento del sistema.<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\"><strong><code>taskWiFi<\/code><\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\">Media (Solo en Modo IA &#8211; 2)<\/td><td class=\"has-text-align-center\" data-align=\"center\">8 KB<\/td><td class=\"has-text-align-left\" data-align=\"left\">Asegura la conexi\u00f3n WiFi permanente mediante una evaluaci\u00f3n del estado de la conexi\u00f3n cada segundo.<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\"><strong><code>aestheticTask<\/code><\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\">Alta (2)<\/td><td class=\"has-text-align-center\" data-align=\"center\">4 KB<\/td><td class=\"has-text-align-left\" data-align=\"left\">Actualiza la pantalla y mueve el servo en consonancia con el estado de \u00e1nimo (Modo IA) o de reproducci\u00f3n (Modo Bluetooth) de forma fluida.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"-documentaci-n-de-clases-principales-managers-\">\ud83d\udcc2 Documentaci\u00f3n de Clases Principales (Managers)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\ud83d\udd18 <strong><code>InputManager<\/code><\/strong>: Encapsula la lectura de la entrada a trav\u00e9s del pulsador. Utiliza la librer\u00eda <em>OneButton<\/em> para registrar clicks simples, dobles, triples y pulsaciones largas sin bloquear el c\u00f3digo. Traduce las acciones del usuario en peticiones de cambio de estado que ser\u00e1n tomadas por el bucle de control principal.<\/li>\n\n\n\n<li>\ud83c\udfad <strong><code>VisualOutputs<\/code><\/strong>: Es el \u00abalma\u00bb gr\u00e1fica y f\u00edsica del robot. Gestiona la pantalla TFT, los colores del bot\u00f3n RGB y los PWM del servomotor. Posee la funci\u00f3n vital <code>generateMoodPose()<\/code>, que recibe una emoci\u00f3n y la traduce en variables f\u00edsicas (nivel de apertura del p\u00e1rpado, posici\u00f3n de las pupilas, velocidad de parpadeo y movimiento del cuello) en funci\u00f3n del estado y mood.<\/li>\n\n\n\n<li>\ud83c\udfa7 <strong><code>AudioManager<\/code><\/strong>: Encapsula la configuraci\u00f3n a bajo nivel de los buses I2S. Lee el b\u00fafer de audio del micr\u00f3fono INMP441 mediante descriptores DMA (funci\u00f3n <code>readMic()<\/code>) y contiene la l\u00f3gica para decodificar un flujo MP3 (stream) en tiempo real para el amplificador MAX98357A (funci\u00f3n <code>playMP3Stream()<\/code>).<\/li>\n\n\n\n<li>\ud83d\udce1 <strong><code>NetworkManager<\/code><\/strong>: Abstrae la configuraci\u00f3n de la conexi\u00f3n WiFi. Despliega un portal cautivo personalizado (HTML\/CSS) en caso de no encontrar redes conocidas, permitiendo al usuario introducir credenciales desde su m\u00f3vil. Establece que se produzca conexi\u00f3n a redes conocidas en caso de encontrarse en su alcance.<\/li>\n\n\n\n<li>\u2601\ufe0f <strong><code>DeepgramClient<\/code><\/strong>: Cliente dedicado a los servicios de audio en la nube. Posee dos funciones principales: <code>listen()<\/code> (abre un WebSocket bidireccional enviando audio en <em>streaming<\/em> directo) y <code>speak()<\/code> (realiza una petici\u00f3n HTTPS para recibir audio TTS en streaming).<\/li>\n\n\n\n<li>\ud83e\udde0 <strong><code>LLMClient<\/code><\/strong>: Gestiona la l\u00f3gica cognitiva mediante la interacci\u00f3n con la API de Groq (modelo LLM Llama-3.1). Env\u00eda el mensaje escuchado precedido de un <em>Prompt<\/em>, obligando a la IA a devolver un objeto <strong>JSON<\/strong> con una respuesta y una etiqueta de emoci\u00f3n (ej. FELIZ, ENFADADO, TRISTE).<\/li>\n\n\n\n<li>\ud83d\udcf6 <strong><code>BluetoothManager<\/code><\/strong>: Emplea la librer\u00eda <em>BluetoothA2DPSink<\/em> para transformar a CloudIA en un reproductor de audio comercial. Detecta eventos as\u00edncronos mediante <em>callbacks<\/em> (reproducci\u00f3n iniciada o pausada) para avisar al sistema visual de que debe activar o detener el ecualizador gr\u00e1fico en pantalla.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"498\" src=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/class_diagram-1024x498.png\" alt=\"\" class=\"wp-image-10366\" srcset=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/class_diagram-1024x498.png 1024w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/class_diagram-300x146.png 300w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/class_diagram-768x373.png 768w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/class_diagram-1536x746.png 1536w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/class_diagram-2048x995.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Diagrama de Clases de CloudIA<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"-4-casos-de-uso-y-m-quina-de-estados\">\ud83d\udd04 4. Casos de Uso y M\u00e1quina de Estados<\/h2>\n\n\n\n<p>Desde el punto de vista global, CloudIA funciona como una M\u00e1quina de Estados Finita. Esto permite al sistema reaccionar a interacciones exitosas y poseer un protocolo determinista ante errores y fallos de conexi\u00f3n. El sistema transiciona entre tres modos gen\u00e9ricos: <code>STANDBY<\/code>, <code>MODO IA<\/code> y <code>MODO BLUETOOTH<\/code><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"-4-1-modo-standby\">\ud83d\udca4 4.1. Modo STANDBY<\/h3>\n\n\n\n<p>Estado de bajo consumo en el que se desactivan la m\u00e1xima cantidad posible de componentes. La pantalla dibuja los ojos cerrados en un color tenue, se apaga el bot\u00f3n y se paraliza el servomotor. Adem\u00e1s, se desactivan los protocolos de red o audio, dedicando los recursos \u00fanicamente a detectar una orden de encendido (pulsaci\u00f3n de m\u00e1s de 1 segundo).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"-4-2-modo-ia\">\ud83e\udd16 4.2. Modo IA<\/h3>\n\n\n\n<p>Estado de interacci\u00f3n principal donde el sistema requiere de conexi\u00f3n WiFi para el uso de APIs externas. En este modo, CloudIA queda en estado <code>READY<\/code> hasta la detecci\u00f3n de alg\u00fan tipo de pulsaci\u00f3n sobre el bot\u00f3n. Al detectar una pulsaci\u00f3n larga, transiciona a la fase de conexi\u00f3n de audio (<code>CONNECTING_STT<\/code>), reflejada visualmente con ojos naranjas. Cuando la conexi\u00f3n se ha producido y est\u00e1 lista para escuchar, pasa al estado <code>LISTENING<\/code>, indic\u00e1ndolo con ojos verdes y barras de ecualizaci\u00f3n en pantalla. Al soltar el bot\u00f3n, se procesa el texto (<code>PROCESSING<\/code>) bajo un aspecto de color morado y se responde <code>SPEAKING<\/code>, de acuerdo a la emoci\u00f3n detectada.<\/p>\n\n\n\n<p>En este proceso, pueden producirse distintos errores que podr\u00edan llevar al sistema a un bloqueo. As\u00ed, se ha modelado un estado de <code>ERROR<\/code>, al que se transiciona en caso de que se produzcan alguno de los siguientes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\ud83c\udf10 <strong>Ausencia de red conocida (Portal Cautivo):<\/strong> Si al arrancar este modo el sistema no encuentra una red WiFi guardada, se evita que el sistema permanezca buscando una red mediante la creaci\u00f3n de un punto de acceso propio (<code>CAPTIVE_PORTAL<\/code>). La pantalla informa al usuario para que se conecte a la red del robot e introduzca las nuevas credenciales desde su tel\u00e9fono m\u00f3vil.<\/li>\n\n\n\n<li>\u26a0\ufe0f <strong>Fallo de transcripci\u00f3n o silencios:<\/strong> Si durante el proceso de escucha el usuario mantiene pulsado el bot\u00f3n pero no habla, o si ocurre un corte en la red que corrompe el WebSocket con Deepgram, el proceso de <em>Speech-to-Text<\/em> devuelve una cadena de texto vac\u00eda, informando por pantalla del error.<\/li>\n\n\n\n<li>\ud83d\ude91 <strong>Recuperaci\u00f3n desde <code>ERROR<\/code>:<\/strong> Si se detecta una transcripci\u00f3n vac\u00eda o una desconexi\u00f3n cr\u00edtica, se transiciona al estado <code>ERROR<\/code>. En ese momento, la pantalla muestra unos ojos en forma de equis y el anillo LED se ilumina en color rojo. Tras tres segundos, para que el usuario tenga tiempo suficiente de observar el error, el sistema vuelve al estado <code>READY<\/code>, listo para un nuevo intento.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"562\" src=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/captive_portal-1024x562.png\" alt=\"\" class=\"wp-image-10369\" srcset=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/captive_portal-1024x562.png 1024w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/captive_portal-300x165.png 300w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/captive_portal-768x421.png 768w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/captive_portal-1536x843.png 1536w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/captive_portal-2048x1124.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Portal Cautivo de CloudIA<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"-4-3-modo-bluetooth\">\ud83c\udfb5 4.3. Modo BLUETOOTH<\/h3>\n\n\n\n<p>CloudIA espera en fase de emparejamiento (<code>BT_PAIRING<\/code>) hasta vincularse con un dispositivo, pasando entonces al estado <code>BT_CONNECTED<\/code>. Cuando el dispositivo reproduce alg\u00fan sonido, se transiciona al estado activo (<code>BT_PLAYING<\/code>).<\/p>\n\n\n\n<p>Al igual que en el <code>MODO IA<\/code>, este modo cuenta con un proceso de vigilancia en segundo plano. Si el usuario pausa la m\u00fasica, el sistema retrocede al estado <code>BT_CONNECTED<\/code>. Adem\u00e1s, si se produce una desconexi\u00f3n Bluetooth, la tarea de control hace transicionar al sistema a la fase de emparejamiento, asegurando que CloudIA vuelva a ser visible en la red Bluetooth para nuevos enlaces.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"-diagrama-de-estados-uml-\">\ud83d\uddfa\ufe0f Diagrama de Estados (UML)<\/h3>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"910\" height=\"723\" src=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/use_case.png\" alt=\"\" class=\"wp-image-10370\" srcset=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/use_case.png 910w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/use_case-300x238.png 300w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/use_case-768x610.png 768w\" sizes=\"auto, (max-width: 910px) 100vw, 910px\" \/><figcaption class=\"wp-element-caption\">Diagrama de Estados y Modos de CloudIA<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"-5-modo-ia-pipeline-cognitivo-y-gesti-n-emocional\">\ud83e\udde0 5. Modo IA: Pipeline Cognitivo y Gesti\u00f3n Emocional<\/h2>\n\n\n\n<p>Este modo recoge el comportamiento principal de CloudIA. El proceso de escucha, razonamiento y respuesta queda completamente encapsulado en un <em>pipeline<\/em> de comunicaci\u00f3n en la nube, que recoge una sucesi\u00f3n ordenada de protocolos para conseguir dichas funcionalidades. Este proceso se divide en tres fases.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"455\" src=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/pipeline-1024x455.png\" alt=\"\" class=\"wp-image-10371\" srcset=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/pipeline-1024x455.png 1024w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/pipeline-300x133.png 300w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/pipeline-768x341.png 768w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/pipeline-1536x683.png 1536w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/pipeline-2048x910.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Pipeline del Modo IA<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"-5-1-fase-de-captura-y-transcripci-n\">\ud83c\udf99\ufe0f 5.1. Fase de Captura y Transcripci\u00f3n<\/h3>\n\n\n\n<p>Al mantener presionado el bot\u00f3n principal, el <code>InputManager<\/code> detecta una pulsaci\u00f3n larga y cambia el estado del sistema a <code>CONNECTING_STT<\/code>. En este momento, el bucle principal utiliza la clase <code>DeepgramClient<\/code> para abrir un t\u00fanel <strong>WebSocket<\/strong> (Streaming) con Deepgram.<\/p>\n\n\n\n<p>Una vez establecida la conexi\u00f3n WebSocket bidireccional, el sistema pasa al estado <code>LISTENING<\/code>, en el que se mantendr\u00e1 mientras que el bot\u00f3n siga pulsado.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>El <code>AudioManager<\/code> entra en un bucle donde lee los datos del micr\u00f3fono INMP441 mediante el bus I2S.<\/li>\n\n\n\n<li>Los fragmentos de audio se van almacenando en un buffer circular y se van enviando en streaming a Deepgram empleando el modelo <em>Nova-2<\/em>.<\/li>\n\n\n\n<li>Al soltar el bot\u00f3n, se env\u00eda un mensaje de control JSON (<code>{\"type\": \"CloseStream\"}<\/code>) para cerrar el flujo de audio.<\/li>\n\n\n\n<li>Se van recibiendo las transcripciones parciales mediante una funci\u00f3n <em>callback<\/em> as\u00edncrona, y se construye el <em>String<\/em> definitivo con la petici\u00f3n.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"-5-2-fase-cognitiva-y-detecci-n-de-emociones\">\ud83e\udd14 5.2. Fase Cognitiva y Detecci\u00f3n de Emociones<\/h3>\n\n\n\n<p>Una vez marcada como definitiva la transcripci\u00f3n, el sistema pasa al estado <code>PROCESSING<\/code> y se transfiere la responsabilidad a la clase <code>LLMClient<\/code>. Esta clase realiza una petici\u00f3n HTTPS POST a la API de Groq, uno de los motores de inferencia con menor latencia del mercado, usando el modelo <strong>Llama-3.1-8b-instant<\/strong>.<\/p>\n\n\n\n<p>Con el objetivo de dotar a CloudIA de consciencia de su existencia y de personalidad, la petici\u00f3n inyecta una cabecera en el <em>Prompt<\/em> que le indica a la IA su nombre, creador y contexto. Adem\u00e1s, impone que la respuesta ha de ser devuelta en el siguiente formato JSON: <code>{\"respuesta\": \"texto\", \"emocion\": \"ETIQUETA\"}<\/code>.<\/p>\n\n\n\n<p>Al recibir la respuesta de Groq, se extrae por un lado el texto de respuesta y por otro el valor de la emoci\u00f3n. La respuesta es devuelta por <code>LLMClient<\/code> para ser usada en la siguiente fase, mientras que se actualiza la variable global <code>volatile mood_t current_mood<\/code> con la emoci\u00f3n reconocida. Las emociones mapeadas en el sistema son ocho: <code>NEUTRO, FELIZ, TRISTE, PENSATIVO, NEGACION, ENFADADO, SORPRENDIDO y NERVIOSO<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"-5-3-fase-de-s-ntesis-y-reacci-n-f-sica\">\ud83c\udfad 5.3. Fase de S\u00edntesis y Reacci\u00f3n F\u00edsica<\/h3>\n\n\n\n<p>La respuesta proporcionada por <code>LLMClient<\/code> es enviada a trav\u00e9s de la API <em>Text-to-sound<\/em> (TTS) de Deepgram (modelo <em>Aura<\/em>) solicitando una codificaci\u00f3n MP3. Para evitar retrasos, no se espera a descargar el archivo al completo, sino que se utiliza una clase <em>wrapper<\/em> (<code>AudioFileSourceWiFiStream<\/code>) que recoge los fragmentos de audio y se los entrega directamente a la librer\u00eda decodificadora MP3 (<code>AudioGeneratorMP3<\/code>). Esto permite que el altavoz empiece a sonar en el instante en el que llega el primer paquete de audio, reduciendo los tiempos de espera.<\/p>\n\n\n\n<p>En el momento el que tiene lugar la primera expulsi\u00f3n de audio por el altavoz, se transiciona al estado <code>SPEAKING<\/code> (mediante <em>callback<\/em>), de manera que la tarea <code>aestheticTask<\/code> muestra a CloudIA hablando en el momento exacto en el que empieza a haber sonido. Paralelamente, al haberse establecido el <em>mood<\/em> actual del robot, la respuesta vendr\u00e1 acompa\u00f1ada de diferentes reacciones en funci\u00f3n de su valor. De este modo, los distintos estados de \u00e1nimo tienen asociados valores particulares para los par\u00e1metros citados a continuaci\u00f3n, que regulan la forma en la que <code>aestheticTask<\/code> ejecuta la respuesta est\u00e9tica del robot:<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">Par\u00e1metro Din\u00e1mico<\/th><th class=\"has-text-align-left\" data-align=\"left\">Funci\u00f3n(es) a la que aplica<\/th><th class=\"has-text-align-left\" data-align=\"left\">Ejemplo de Comportamiento<\/th><\/tr><\/thead><tbody><tr><td class=\"has-text-align-left\" data-align=\"left\">\ud83d\udc44 <strong>Apertura de la Boca<\/strong> (<code>mouth_opening<\/code>)<\/td><td class=\"has-text-align-left\" data-align=\"left\"><code>speakingActions()<\/code><\/td><td class=\"has-text-align-left\" data-align=\"left\">M\u00e1s cerrada para la emoci\u00f3n <code>TRISTE<\/code> y m\u00e1s abierta de forma aleatoria para el resto.<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">\ud83d\udd04 <strong>\u00c1ngulo del Cuello<\/strong> (<code>target_servo_angle<\/code>)<\/td><td class=\"has-text-align-left\" data-align=\"left\"><code>generateMoodPose()<\/code>, <code>speakingActions()<\/code><\/td><td class=\"has-text-align-left\" data-align=\"left\">Posici\u00f3n a 135\u00ba (mirando a la lejan\u00eda) para <code>PENSATIVO<\/code>, u oscilaciones matem\u00e1ticas para gesticular la <code>NEGACION<\/code>.<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">\ud83d\udc40 <strong>Direcci\u00f3n de Pupilas<\/strong> (<code>eye_offsetX<\/code>, <code>eye_offsetY<\/code>)<\/td><td class=\"has-text-align-left\" data-align=\"left\"><code>generateMoodPose()<\/code>, <code>drawEyes()<\/code><\/td><td class=\"has-text-align-left\" data-align=\"left\">Cambios aleatorios y r\u00e1pidos en <code>NERVIOSO<\/code> o desplazamiento fijo que apunta hacia el cuello en <code>TRISTE<\/code>.<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">\ud83d\ude11 <strong>Apertura de P\u00e1rpados<\/strong> (<code>lidTop<\/code>)<\/td><td class=\"has-text-align-left\" data-align=\"left\"><code>generateMoodPose()<\/code>, <code>drawEyes()<\/code><\/td><td class=\"has-text-align-left\" data-align=\"left\">Cerrados (ce\u00f1o fruncido) en <code>ENFADADO<\/code> y completamente abiertos en <code>SORPRENDIDO<\/code>.<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">\u26a1 <strong>Velocidad de Gesticulaci\u00f3n<\/strong> (<code>speakingSpeed<\/code>)<\/td><td class=\"has-text-align-left\" data-align=\"left\"><code>generateMoodPose()<\/code>, <code>speakingActions()<\/code><\/td><td class=\"has-text-align-left\" data-align=\"left\">Movimiento lento (cada 400 ms) en <code>TRISTE<\/code> o movimientos r\u00e1pidos (cada 50 ms) para <code>NERVIOSO<\/code>.<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">\u2b55 <strong>Color del Aura<\/strong> (<code>aura_color<\/code>)<\/td><td class=\"has-text-align-left\" data-align=\"left\"><code>setAura()<\/code><\/td><td class=\"has-text-align-left\" data-align=\"left\">Dibujo de una circunferencia en la TFT, para remarcar el estado de \u00e1nimo con un color.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"578\" src=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/moods-1024x578.png\" alt=\"\" class=\"wp-image-10372\" srcset=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/moods-1024x578.png 1024w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/moods-300x169.png 300w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/moods-768x434.png 768w, https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/moods.png 1410w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Paleta de Estados incorporados en CloudIA<\/figcaption><\/figure>\n\n\n\n<p>El resultado es una ilusi\u00f3n de que CloudIA cuenta con consciencia realista, siendo capaz responder a conversaciones humanas con gesticulaci\u00f3n, voz y cambios de humor en tiempo real.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"-6-modo-bluetooth-altavoz-\">\ud83d\udcf1 6. Modo Bluetooth (Altavoz)<\/h2>\n\n\n\n<p>El Modo Bluetooth transforma a CloudIA en un altavoz inal\u00e1mbrico. Aunque el protocolo se delega a la librer\u00eda externa <em>BluetoothA2DPSink<\/em>, la monitorizaci\u00f3n constante del estado de reproducci\u00f3n permiti\u00f3 ofrecer retroalimentaci\u00f3n visual en tiempo real.<\/p>\n\n\n\n<p>Cuando el sistema arranca en este modo, la clase <code>BluetoothManager<\/code> configura el receptor A2DP (Advanced Audio Distribution Profile). Cabe destacar que este manager enruta el flujo de audio hacia el Puerto I2S 1, evitando colisionar con el micr\u00f3fono, que reside en el Puerto 0. Tras la configuraci\u00f3n, el dispositivo se anuncia en la red Bluetooth como \u00abClaudIA Speaker\u00bb.<\/p>\n\n\n\n<p>Cuando la m\u00e1quina se encuentra en alguno de los estados correspondientes al modo Bluetooth, la tarea principal <code>taskControl<\/code> verifica el estado de la conexi\u00f3n utilizando los m\u00e9todos <code>isConnected()<\/code> y <code>isPlaying()<\/code> del manager. As\u00ed, es capaz de transitar entre los distintos estados avalados en este modo:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong><code>BT_PAIRING<\/code>:<\/strong> Ning\u00fan dispositivo conectado. El sistema queda a la espera de emparejamiento.<\/li>\n\n\n\n<li><strong><code>BT_CONNECTED<\/code>:<\/strong> Un dispositivo se ha enlazado con \u00e9xito, pero no est\u00e1 emitiendo sonido.<\/li>\n\n\n\n<li><strong><code>BT_PLAYING<\/code>:<\/strong> Un dispositivo est\u00e1 enlazado con \u00e9xito y se est\u00e1 reproduciendo sonido.<\/li>\n<\/ol>\n\n\n\n<p>El comportamiento visual de CloudIA se modifica en funci\u00f3n de los anteriores estados gracias a la <code>aestheticTask<\/code>, que hace uso del manager <code>VisualOutputs<\/code>.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>BT_PAIRING<\/code>:<\/strong> Ojos azules en modo b\u00fasqueda, acompa\u00f1ados de un logotipo de Bluetooth parpadeante y r\u00e1fagas azules en el bot\u00f3n RGB.<\/li>\n\n\n\n<li><strong><code>BT_CONNECTED<\/code>:<\/strong> Logotipo fijo de color azul, mirada de frente y el anillo LED en azul fijo.<\/li>\n\n\n\n<li><strong><code>BT_PLAYING<\/code>:<\/strong> Reproduce un ecualizador gr\u00e1fico compuesto por seis barras verticales para simular los picos de las frecuencias de audio y movimientos aleatorios de cabeza variando entre 80\u00ba y 100\u00ba.<\/li>\n<\/ul>\n\n\n\n<p>Cuando el dispositivo deja de emitir sonido, la m\u00e1quina retrocede a <code>BT_CONNECTED<\/code>, deteniendo el servo y devolviendo el rostro a la pantalla en cuesti\u00f3n de un par de segundos.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"7-problemas-encontrados-y-soluciones\">7. Problemas Encontrados y Soluciones<\/h2>\n\n\n\n<p>El desarrollo de un sistema embebido con recursos tan limitados para ejecutar tareas de gran carga supuso varios retos. A continuaci\u00f3n, se exponen los obst\u00e1culos m\u00e1s cr\u00edticos y las soluciones aplicadas para sortearlos:<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">Problema<\/th><th class=\"has-text-align-left\" data-align=\"left\">Impacto en el Sistema<\/th><th class=\"has-text-align-left\" data-align=\"left\">Soluci\u00f3n Implementada<\/th><\/tr><\/thead><tbody><tr><td class=\"has-text-align-left\" data-align=\"left\">\ud83d\udca5 <strong>L\u00edmite de RAM por Modos Incompatibles<\/strong><\/td><td class=\"has-text-align-left\" data-align=\"left\">La decodificaci\u00f3n Bluetooth A2DP (~150KB) y los certificados WiFi SSL (~100KB) exced\u00edan la RAM de la placa, causando <em>Kernel Panics<\/em> al activarse simult\u00e1neamente.<\/td><td class=\"has-text-align-left\" data-align=\"left\"><strong>Reinicio Limpio Invisible:<\/strong> Se guarda el estado en la memoria Flash (<code>Preferences<\/code>) y se reinicia la placa al cambiar de modo, arrancando con los m\u00f3dulos requeridos para el modo solicitado y el 100% de la RAM disponible.<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">\ud83d\udd00 <strong>Colisi\u00f3n de Puertos I2S<\/strong><\/td><td class=\"has-text-align-left\" data-align=\"left\">Tanto el micr\u00f3fono, el amplificador y el la librer\u00eda Bluetooth intentaban apoderarse del Puerto I2S 0, bloqueando el audio.<\/td><td class=\"has-text-align-left\" data-align=\"left\"><strong>Reasignaci\u00f3n de Puertos:<\/strong> Se forz\u00f3 al micr\u00f3fono a operar en el I2S-0 y el resto de salidas de audio (MP3\/Bluetooth) al I2S-1.<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">\u23f3 <strong>Colapso por Archivos de Audio (TTS)<\/strong><\/td><td class=\"has-text-align-left\" data-align=\"left\">El MP3 de respuesta completo saturaba la memoria y generaba altas latencias de respuesta.<\/td><td class=\"has-text-align-left\" data-align=\"left\"><strong>Audio en Streaming:<\/strong> Creaci\u00f3n de la clase <code>AudioFileSourceWiFiStream<\/code> para interceptar la red y pasar peque\u00f1os fragmentos directamente al decodificador hardware.<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">\ud83d\udcc9 <strong>Ruido en Transcripci\u00f3n (TTS)<\/strong><\/td><td class=\"has-text-align-left\" data-align=\"left\">El DMA del I2S reten\u00eda ruido previo a la pulsaci\u00f3n del bot\u00f3n, ensuciando la escucha del modelo STT.<\/td><td class=\"has-text-align-left\" data-align=\"left\"><strong>Limpieza de B\u00fafer:<\/strong> Implementaci\u00f3n de <code>clearMicBuffer()<\/code> para leer y descartar la basura justo antes de abrir la conexi\u00f3n WebSocket.<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">\ud83e\uddca <strong>Congelaci\u00f3n de Animaciones Visuales<\/strong><\/td><td class=\"has-text-align-left\" data-align=\"left\">Las esperas bloqueantes por peticiones web o <em>Timeouts<\/em> congelaban el movimiento del servo y el parpadeo de los ojos.<\/td><td class=\"has-text-align-left\" data-align=\"left\"><strong>Extracci\u00f3n a Tarea Independiente:<\/strong> Aislamiento de la l\u00f3gica gr\u00e1fica en la tarea <code>aestheticTask<\/code>, comunicada v\u00eda variables vol\u00e1tiles independientes.<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">\ud83d\udce1 <strong>Inestabilidad de STT y TTS por conexi\u00f3n WiFi<\/strong><\/td><td class=\"has-text-align-left\" data-align=\"left\">La conexi\u00f3n WiFi es determinante para el funcionamiento del <em>streaming<\/em> del micr\u00f3fono hacia y desde Deepgram, provocando bloqueos.<\/td><td class=\"has-text-align-left\" data-align=\"left\"><strong>Aislamiento de Cores:<\/strong> Ejecuci\u00f3n del <code>NetworkManager<\/code> en el n\u00facleo 0 del procesador y reducci\u00f3n de fragmentaci\u00f3n de memoria ajustando b\u00faferes a 8KB.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Aunque este \u00faltimo problema se ve mitigado por la soluci\u00f3n adoptada, las limitaciones de hardware del ESP32 impiden garantizar la estabilidad del streaming de audio ante micro-cortes de red superiores a los 400-500 milisegundos.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"-8-v-deo-demostrativo\">\ud83c\udfa5 8. V\u00eddeo Demostrativo<\/h2>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<div class=\"video-container\"><iframe loading=\"lazy\" title=\"CloudIA  - David R\u00edsquez G\u00f3mez  -  Sistemas Empotrados y de Tiempo Real - URJC\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/vz4JjznC-dE?feature=oembed&#038;wmode=opaque\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/div>\n<\/div><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"-9-componentes-del-proyecto-bom-\">\ud83d\udd0c 9. Componentes del Proyecto (BOM)<\/h2>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table class=\"has-fixed-layout\"><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">Componente<\/th><th class=\"has-text-align-left\" data-align=\"left\">Descripci\u00f3n<\/th><th class=\"has-text-align-left\" data-align=\"left\">Coste Estimado (\u20ac)<\/th><\/tr><\/thead><tbody><tr><td class=\"has-text-align-left\" data-align=\"left\"><strong>ESP32-WROOM-D + Placa de Expansi\u00f3n<\/strong><\/td><td class=\"has-text-align-left\" data-align=\"left\">Placa de desarrollo Dual-Core con WiFi\/BT<\/td><td class=\"has-text-align-left\" data-align=\"left\">5,37 \u20ac<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\"><strong>GC9A01<\/strong><\/td><td class=\"has-text-align-left\" data-align=\"left\">Pantalla TFT circular de 1.28&#8243; (SPI)<\/td><td class=\"has-text-align-left\" data-align=\"left\">2,36\u20ac<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\"><strong>INMP441<\/strong><\/td><td class=\"has-text-align-left\" data-align=\"left\">Micr\u00f3fono I2S omnidireccional<\/td><td class=\"has-text-align-left\" data-align=\"left\">1,46 \u20ac<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\"><strong>MAX98357A<\/strong><\/td><td class=\"has-text-align-left\" data-align=\"left\">M\u00f3dulo Amplificador de audio I2S<\/td><td class=\"has-text-align-left\" data-align=\"left\">1,16 \u20ac<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\"><strong>Altavoz Magn\u00e9tico 3W<\/strong><\/td><td class=\"has-text-align-left\" data-align=\"left\">Altavoz gen\u00e9rico de 4 ohmios<\/td><td class=\"has-text-align-left\" data-align=\"left\">2,71 \u20ac<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\"><strong>Servo SG90<\/strong><\/td><td class=\"has-text-align-left\" data-align=\"left\">Micro servomotor de 180\u00ba<\/td><td class=\"has-text-align-left\" data-align=\"left\">1,86 \u20ac<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\"><strong>Bot\u00f3n LED RGB<\/strong><\/td><td class=\"has-text-align-left\" data-align=\"left\">Pulsador moment\u00e1neo con retroiluminaci\u00f3n RGB<\/td><td class=\"has-text-align-left\" data-align=\"left\">2,01 \u20ac<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\"><strong>Material 3D (PLA)<\/strong><\/td><td class=\"has-text-align-left\" data-align=\"left\">~50 metros de filamento PLA gris<\/td><td class=\"has-text-align-left\" data-align=\"left\">~3,00 \u20ac<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\"><strong>Varios<\/strong><\/td><td class=\"has-text-align-left\" data-align=\"left\">Cables, mini-protoboard<\/td><td class=\"has-text-align-left\" data-align=\"left\">estimado 1,00 \u20ac<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\"><strong>TOTAL<\/strong><\/td><td class=\"has-text-align-left\" data-align=\"left\"><\/td><td class=\"has-text-align-left\" data-align=\"left\"><strong>~ 20,93 \u20ac<\/strong><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udce6 Repositorio del Proyecto<\/h3>\n\n\n\n<p>Todo el c\u00f3digo fuente, la arquitectura de carpetas, los esquemas y la documentaci\u00f3n t\u00e9cnica de <strong>CloudIA<\/strong> est\u00e1n alojados de forma p\u00fablica y open-source.<\/p>\n\n\n\n<p>\ud83d\udc49 <strong><a href=\"https:\/\/github.com\/davidrisqgom\/CloudIA\" target=\"_blank\" rel=\"noreferrer noopener\">Acceder al repositorio en GitHub<\/a><\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>CloudIA es un ente rob\u00f3tico dise\u00f1ado para fusionar la Inteligencia Artificial en la nube con la presencia e interacci\u00f3n f\u00edsica.<\/p>\n","protected":false},"author":346,"featured_media":10378,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-10357","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-proyectos"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>CloudIA - Proyectos con Arduino.<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/cloudia\/\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"CloudIA - Proyectos con Arduino.\" \/>\n<meta property=\"og:description\" content=\"CloudIA es un ente rob\u00f3tico dise\u00f1ado para fusionar la Inteligencia Artificial en la nube con la presencia e interacci\u00f3n f\u00edsica.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/cloudia\/\" \/>\n<meta property=\"og:site_name\" content=\"Proyectos con Arduino.\" \/>\n<meta property=\"article:published_time\" content=\"2026-05-08T07:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/main_picture-1-e1778085280550-1024x1024.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"1024\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"seytrmo2526g151\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Escrito por\" \/>\n\t<meta name=\"twitter:data1\" content=\"seytrmo2526g151\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tiempo de lectura\" \/>\n\t<meta name=\"twitter:data2\" content=\"16 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/cloudia\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/cloudia\\\/\"},\"author\":{\"name\":\"seytrmo2526g151\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#\\\/schema\\\/person\\\/553c9bcd55f8c24aa347491060aede19\"},\"headline\":\"CloudIA\",\"datePublished\":\"2026-05-08T07:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/cloudia\\\/\"},\"wordCount\":3025,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/cloudia\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/wp-content\\\/uploads\\\/sites\\\/8\\\/2026\\\/05\\\/main_picture-1-e1778085280550.png\",\"articleSection\":[\"Proyectos\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/cloudia\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/cloudia\\\/\",\"url\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/cloudia\\\/\",\"name\":\"CloudIA - Proyectos con Arduino.\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/cloudia\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/cloudia\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/wp-content\\\/uploads\\\/sites\\\/8\\\/2026\\\/05\\\/main_picture-1-e1778085280550.png\",\"datePublished\":\"2026-05-08T07:00:00+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/cloudia\\\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/cloudia\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/cloudia\\\/#primaryimage\",\"url\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/wp-content\\\/uploads\\\/sites\\\/8\\\/2026\\\/05\\\/main_picture-1-e1778085280550.png\",\"contentUrl\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/wp-content\\\/uploads\\\/sites\\\/8\\\/2026\\\/05\\\/main_picture-1-e1778085280550.png\",\"width\":1620,\"height\":1620},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/cloudia\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Portada\",\"item\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"CloudIA\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#website\",\"url\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/\",\"name\":\"Proyectos con Arduino.\",\"description\":\"Blog de proyectos de Arduino de alumnos de la URJC\",\"publisher\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#organization\",\"name\":\"Universidad Rey Juan Carlos\",\"url\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/wp-content\\\/uploads\\\/sites\\\/8\\\/2022\\\/05\\\/logourjc-1.jpg\",\"contentUrl\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/wp-content\\\/uploads\\\/sites\\\/8\\\/2022\\\/05\\\/logourjc-1.jpg\",\"width\":745,\"height\":288,\"caption\":\"Universidad Rey Juan Carlos\"},\"image\":{\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/#\\\/schema\\\/person\\\/553c9bcd55f8c24aa347491060aede19\",\"name\":\"seytrmo2526g151\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5d3c56b0fc9556044ff912b0f25c5e9e7e96aed83d299c2e80ece36ac47b80e1?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5d3c56b0fc9556044ff912b0f25c5e9e7e96aed83d299c2e80ece36ac47b80e1?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5d3c56b0fc9556044ff912b0f25c5e9e7e96aed83d299c2e80ece36ac47b80e1?s=96&d=mm&r=g\",\"caption\":\"seytrmo2526g151\"},\"url\":\"https:\\\/\\\/blogs.etsii.urjc.es\\\/dseytr\\\/author\\\/seytrmo2526g151\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"CloudIA - Proyectos con Arduino.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blogs.etsii.urjc.es\/dseytr\/cloudia\/","og_locale":"es_ES","og_type":"article","og_title":"CloudIA - Proyectos con Arduino.","og_description":"CloudIA es un ente rob\u00f3tico dise\u00f1ado para fusionar la Inteligencia Artificial en la nube con la presencia e interacci\u00f3n f\u00edsica.","og_url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/cloudia\/","og_site_name":"Proyectos con Arduino.","article_published_time":"2026-05-08T07:00:00+00:00","og_image":[{"width":1024,"height":1024,"url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/main_picture-1-e1778085280550-1024x1024.png","type":"image\/png"}],"author":"seytrmo2526g151","twitter_card":"summary_large_image","twitter_misc":{"Escrito por":"seytrmo2526g151","Tiempo de lectura":"16 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/cloudia\/#article","isPartOf":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/cloudia\/"},"author":{"name":"seytrmo2526g151","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#\/schema\/person\/553c9bcd55f8c24aa347491060aede19"},"headline":"CloudIA","datePublished":"2026-05-08T07:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/cloudia\/"},"wordCount":3025,"commentCount":0,"publisher":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#organization"},"image":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/cloudia\/#primaryimage"},"thumbnailUrl":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/main_picture-1-e1778085280550.png","articleSection":["Proyectos"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/blogs.etsii.urjc.es\/dseytr\/cloudia\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/cloudia\/","url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/cloudia\/","name":"CloudIA - Proyectos con Arduino.","isPartOf":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/cloudia\/#primaryimage"},"image":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/cloudia\/#primaryimage"},"thumbnailUrl":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/main_picture-1-e1778085280550.png","datePublished":"2026-05-08T07:00:00+00:00","breadcrumb":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/cloudia\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blogs.etsii.urjc.es\/dseytr\/cloudia\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/cloudia\/#primaryimage","url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/main_picture-1-e1778085280550.png","contentUrl":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2026\/05\/main_picture-1-e1778085280550.png","width":1620,"height":1620},{"@type":"BreadcrumbList","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/cloudia\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Portada","item":"https:\/\/blogs.etsii.urjc.es\/dseytr\/"},{"@type":"ListItem","position":2,"name":"CloudIA"}]},{"@type":"WebSite","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#website","url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/","name":"Proyectos con Arduino.","description":"Blog de proyectos de Arduino de alumnos de la URJC","publisher":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blogs.etsii.urjc.es\/dseytr\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#organization","name":"Universidad Rey Juan Carlos","url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#\/schema\/logo\/image\/","url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2022\/05\/logourjc-1.jpg","contentUrl":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-content\/uploads\/sites\/8\/2022\/05\/logourjc-1.jpg","width":745,"height":288,"caption":"Universidad Rey Juan Carlos"},"image":{"@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/blogs.etsii.urjc.es\/dseytr\/#\/schema\/person\/553c9bcd55f8c24aa347491060aede19","name":"seytrmo2526g151","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/secure.gravatar.com\/avatar\/5d3c56b0fc9556044ff912b0f25c5e9e7e96aed83d299c2e80ece36ac47b80e1?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/5d3c56b0fc9556044ff912b0f25c5e9e7e96aed83d299c2e80ece36ac47b80e1?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/5d3c56b0fc9556044ff912b0f25c5e9e7e96aed83d299c2e80ece36ac47b80e1?s=96&d=mm&r=g","caption":"seytrmo2526g151"},"url":"https:\/\/blogs.etsii.urjc.es\/dseytr\/author\/seytrmo2526g151\/"}]}},"_links":{"self":[{"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/posts\/10357","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/users\/346"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/comments?post=10357"}],"version-history":[{"count":16,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/posts\/10357\/revisions"}],"predecessor-version":[{"id":10449,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/posts\/10357\/revisions\/10449"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/media\/10378"}],"wp:attachment":[{"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/media?parent=10357"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/categories?post=10357"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.etsii.urjc.es\/dseytr\/wp-json\/wp\/v2\/tags?post=10357"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}