Caso práctico: Control web de garaje con ESP32

Caso práctico: Control web de garaje con ESP32 — hero

case-device-block-diagram,
.prometeo-educational-note,
.prometeo-device-postcode-section,
.prometeo-device-section-card {
margin: 2.4rem 0;
padding: 1.45rem 1.55rem;
border: 1px solid rgba(148, 163, 184, 0.30);
border-radius: 14px;
background:
linear-gradient(135deg, rgba(30, 41, 59, 0.50), rgba(15, 23, 42, 0.18)),
rgba(17, 24, 39, 0.48);
box-shadow: 0 18px 48px rgba(0, 0, 0, 0.20);
}
.case-objective > h2:first-of-type,
.case-device-block-diagram > h2:first-of-type,
.prometeo-device-postcode-section > h2:first-of-type,
.prometeo-device-section-card > h2:first-of-type {
margin-top: 0;
}
.prometeo-device-section-card > :last-child,
.case-objective > :last-child,
.case-device-block-diagram > :last-child,
.prometeo-device-postcode-section > :last-child {
margin-bottom: 0;
}
.prometeo-device-section-card.prometeo-device-section-card-code {
border-left: 4px solid rgba(56, 189, 248, 0.86);
background:
linear-gradient(135deg, rgba(8, 47, 73, 0.42), rgba(15, 23, 42, 0.18)),
rgba(15, 23, 42, 0.58);
}
.prometeo-device-section-card.prometeo-device-section-card-compact {
padding: 1.2rem 1.35rem;
}
.prometeo-device-section-card pre,
.case-objective pre,
.case-device-block-diagram pre,
.prometeo-device-postcode-section pre {
max-width: 100%;
}
.prometeo-device-postcode-section .prometeo-device-flow-item {
background:
linear-gradient(135deg, rgba(15, 23, 42, 0.50), rgba(30, 41, 59, 0.28)),
rgba(15, 23, 42, 0.28);
}
@media print {
.case-objective,
.case-device-block-diagram,
.prometeo-educational-note,
.prometeo-device-postcode-section,
.prometeo-device-section-card {
background: #fff;
color: #111827;
box-shadow: none;
break-inside: avoid;
page-break-inside: avoid;
}
}

Objetivo y caso de uso

Qué construirás: Construirás un servidor web autónomo con ESP32 que monitoriza el estado físico de una puerta de garaje utilizando un interruptor magnético de lengüeta (reed switch) y acciona de forma segura un relé para abrirla o cerrarla. Este prototipo educativo proporciona una interfaz web localizada y sin nube para el control de acceso remoto.

Por qué es importante / Casos de uso

  • Verificación remota de estado: Confirmación en tiempo real del estado físico de la puerta a través del navegador de un teléfono inteligente con una latencia inferior a 100 ms, omitiendo nubes de terceros.
  • Integración de control de acceso: Reemplaza las llaves físicas por solicitudes de red autenticadas para sistemas de entrada seguros y localizados.
  • Puente para el hogar inteligente (Smart Home): Expone hardware de garaje heredado a través de HTTP estándar para una integración perfecta en plataformas como Home Assistant.

Resultado esperado

  • Una interfaz de usuario web local y adaptable (responsive) que muestra el estado abierto/cerrado en tiempo real a través de un sondeo (polling) continuo de los GPIO.
  • Accionamiento fiable del relé utilizando un pulso de activación de ~500ms para imitar de forma segura la pulsación de un botón físico de pared.
  • Un dispositivo IoT autónomo que funciona completamente con Wi-Fi local sin dependencias de nubes externas.

Audiencia: Aficionados al IoT y desarrolladores de hogares inteligentes; Nivel: Intermedio

Arquitectura/flujo: Navegador web → HTTP GET/POST (Wi-Fi local) → Servidor web ESP32 → Lectura GPIO (Interruptor magnético) / Escritura GPIO (Relé de 5V) → Abridor de puerta de garaje

Diagrama de bloques conceptual

Vista de alto nivel: qué entra, qué procesa cada bloque y qué sale del sistema.

Arquitectura funcional

Botón local

ESP32 BLE

Paquete advertising

LED de estado

Móvil escáner

Flujo conceptual: configuración local, emisión BLE y lectura desde el móvil.

Ruta de validación

Código fuente

PlatformIO build

Flash

Monitor serie

Resumen conceptual de las herramientas usadas para comprobar el proyecto ESP32 publicado.

Nota educativa de validación

Antes de publicar este caso, el contenido pasó la puerta automática de validación de Prometeo con estado PASS. Para este perfil ESP32 DevKitC, el proyecto se comprobó como proyecto PlatformIO: el validador extrajo platformio.ini y src/main.cpp, creó un proyecto temporal y ejecutó pio run contra platform = espressif32, board = esp32dev y framework = arduino. También revisó la estructura del artículo, que los comandos sean copiables con guiones ASCII, y que no aparezcan stacks no soportados como ESP-IDF directo o placas ESP32 no acotadas.

Evidencia de validación publicada

  • Resultado automático: PASS.
  • Estructura parseada: 4 apartados, 3 tablas y 2 bloques de código detectados antes de publicar.
  • Código comprobado: 1 PlatformIO config + 1 ESP32 source/pio run.
  • Catálogo soportado: el texto se contrastó contra los perfiles de dispositivo validables de Prometeo y los stacks no soportados bloquean la publicación.
  • Hallazgos del informe: sin hallazgos bloqueantes.

Esta validación confirma compatibilidad sintáctica y de herramientas para el código publicado, pero no sustituye la prueba física sobre tu placa ESP32 DevKitC exacta, tu cableado, alimentación y entorno WiFi local.

Nota educativa de seguridad

Este proyecto es un prototipo educativo de baja tensión para aprender a leer el estado de una puerta y accionar una salida local, no un abridor de garaje certificado ni un sistema de control de acceso real. Prueba primero con un LED o una carga ficticia, conecta el relé solo a una entrada aislada de contacto seco y bajo voltaje del equipo de puerta, nunca a red eléctrica, motores o cableado de potencia. Mantén siempre los finales de carrera, fotocélulas y protecciones físicas originales de la puerta.

Requisitos previos

Antes de comenzar este tutorial, asegúrese de tener lo siguiente:
* Un ordenador con Windows, macOS o Linux.
* Visual Studio Code (VS Code) instalado.
* La extensión PlatformIO IDE instalada en VS Code.
* Un cable micro-USB o USB-C que soporte tanto alimentación como transferencia de datos.
* Una red Wi-Fi local de 2.4GHz (los microcontroladores ESP32 no soportan redes de 5GHz).

Materiales

Para este caso práctico, debe utilizar exactamente el siguiente modelo de dispositivo y componentes:
* Microcontrolador: ESP32 DevKitC (versión estándar de 38 o 30 pines, con el módulo ESP-WROOM-32).
* Sensor: Interruptor magnético de lengüeta (sensor estándar de puerta/ventana normalmente abierto con dos cables).
* Actuador: Módulo de relé de 5V (1 canal, con optoacoplador integrado y controlador de transistor).
* Prototipado: Placa de pruebas (breadboard) estándar sin soldadura y variedad de cables puente (jumper) macho-macho y hembra-macho.

Configuración/Conexión

La configuración del hardware requiere mapear los pines GPIO del ESP32 a los componentes respectivos. El ESP32 funciona con una lógica de 3.3V, pero la mayoría de los módulos de relé estándar de un canal requieren 5V para la bobina del relé mientras aceptan una señal lógica de 3.3V en su pin de entrada. El ESP32 DevKitC proporciona un pin de 5V (o VIN) que transmite el voltaje del USB, el cual utilizaremos para alimentar la bobina del relé.

Tabla de cableado

ComponentePin / Cable del componentePin del ESP32 DevKitCNotas
Módulo de reléVCC / DC+5V / VINAlimenta la bobina del relé (requiere alimentación por USB).
Módulo de reléGND / DC-GNDTierra común.
Módulo de reléIN / SignalGPIO 5Señal lógica de 3.3V para activar el relé.
Módulo de reléTerminales NO y COMDispositivo objetivoSe conecta a los terminales del botón de pared del abridor de garaje.
Interruptor magnéticoCable 1GPIO 18La polaridad no importa.
Interruptor magnéticoCable 2GNDUtiliza la resistencia pull-up interna del ESP32.

Instrucciones de conexión

  1. Montar el ESP32: Coloque el ESP32 DevKitC en la placa de pruebas, asegurándose de que los pines queden a ambos lados del divisor central.
  2. Conectar el módulo de relé: Utilice cables puente hembra-macho para conectar el módulo de relé al ESP32. Conecte VCC al pin 5V del ESP32, GND al riel de tierra y el pin IN al GPIO 5.
  3. Conectar el interruptor magnético: Conecte un cable del interruptor magnético (reed switch) al GPIO 18. Conecte el otro cable al riel de tierra. Configuraremos el GPIO 18 por software para utilizar su resistencia pull-up interna. Cuando el imán está cerca del interruptor, el circuito se cierra, llevando el GPIO 18 a LOW (0V). Cuando se retira el imán, el pin pasa a HIGH (3.3V).
  4. Establecer tierra común: Asegúrese de que todos los componentes que comparten la lógica del ESP32 tengan sus conexiones de tierra unidas al pin GND del ESP32.

Código validado

El proyecto utiliza PlatformIO. Cree un nuevo proyecto y reemplace la configuración predeterminada y los archivos fuente con el código que se proporciona a continuación.

El código incluye una cadena incrustada de HTML, CSS y JavaScript. El JavaScript utiliza la moderna API fetch para consultar (poll) al ESP32 sobre el estado de la puerta cada 2 segundos, asegurando que la página web refleje la realidad física de la puerta sin requerir actualizaciones manuales del navegador.

platformio.ini

Este archivo configura el entorno de compilación, especificando la placa, el framework y la velocidad del monitor serie.

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200

src/main.cpp

Este es el archivo fuente principal que contiene la lógica Wi-Fi, el enrutamiento del servidor web y el control de hardware GPIO. Actualice las macros WIFI_SSID y WIFI_PASSWORD para que coincidan con su router de pruebas.

Vista pública parcial del archivo validado. El código completo se muestra a miembros y en PDF/Print.

#include <Arduino.h>
#include <WiFi.h>
#include <WebServer.h>

// --- Configuration ---
#define WIFI_SSID "LabNetwork"
#define WIFI_PASSWORD "LabPassword123"

// --- GPIO Pin Definitions ---
const int RELAY_PIN = 5;
const int REED_SWITCH_PIN = 18;

// --- Web Server Initialization ---
// Initialize the web server on standard HTTP port 80
WebServer server(80);

// --- HTML/CSS/JS Payload ---
// Using a raw string literal to embed the frontend code cleanly
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Garage Door Web Monitor</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background-color: #f4f4f9;
            color: #333;
            text-align: center;
            padding: 50px 20px;
        }
        .container {
            background: white;
            padding: 30px;
            border-radius: 10px;
            box-shadow: 0 4px 8px rgba(0,0,0,0.1);
            max-width: 400px;
            margin: auto;
        }
        h1 { font-size: 1.5em; margin-bottom: 20px; }
        .status {
            font-size: 2em;
            font-weight: bold;
            margin: 20px 0;
            padding: 10px;
            border-radius: 5px;
        }
        .closed { background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
        .open { background-color: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
        button {
            background-color: #007bff;
            color: white;
            border: none;
            padding: 15px 30px;
            font-size: 1.2em;
            border-radius: 5px;
            cursor: pointer;
            transition: background-color 0.3s;
        }
        button:hover { background-color: #0056b3; }
        button:active { background-color: #004085; }
    </style>
</head>
<body>
    <div class="container">
        <h1>Garage Door Monitor</h1>
        <div id="door-status" class="status closed">Loading...</div>
        <button onclick="triggerRelay()">Toggle Door</button>
    </div>

    <script>
        // Function to fetch the current door status
        function fetchStatus() {
            fetch('/status')
                .then(response => response.json())
                .then(data => {
                    const statusDiv = document.getElementById('door-status');
                    if (data.state === "Closed") {
                        statusDiv.innerText = "CLOSED";
                        statusDiv.className = "status closed";
                    } else {
                        statusDiv.innerText = "OPEN";
                        statusDiv.className = "status open";
                    }
                })
                .catch(error => console.error('Error fetching status:', error));
        }

        // Function to trigger the relay via POST request
        function triggerRelay() {
            fetch('/trigger', { method: 'POST' })
                .then(response => {
                    if(response.ok) {
                        console.log("Relay triggered successfully.");
                        // Immediately fetch status to reflect potential changes
                        setTimeout(fetchStatus, 1000); 
                    }
                })
                .catch(error => console.error('Error triggering relay:', error));
        }
// ...

🔒 Este contenido es premium. Con la suscripción mensual (7 días gratis) podrás desbloquear el material didáctico completo y el pack PDF listo para imprimir.🔓 Desbloquéalo — 7 días gratis
#include <Arduino.h>
#include <WiFi.h>
#include <WebServer.h>

// --- Configuration ---
#define WIFI_SSID "LabNetwork"
#define WIFI_PASSWORD "LabPassword123"

// --- GPIO Pin Definitions ---
const int RELAY_PIN = 5;
const int REED_SWITCH_PIN = 18;

// --- Web Server Initialization ---
// Initialize the web server on standard HTTP port 80
WebServer server(80);

// --- HTML/CSS/JS Payload ---
// Using a raw string literal to embed the frontend code cleanly
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Garage Door Web Monitor</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background-color: #f4f4f9;
            color: #333;
            text-align: center;
            padding: 50px 20px;
        }
        .container {
            background: white;
            padding: 30px;
            border-radius: 10px;
            box-shadow: 0 4px 8px rgba(0,0,0,0.1);
            max-width: 400px;
            margin: auto;
        }
        h1 { font-size: 1.5em; margin-bottom: 20px; }
        .status {
            font-size: 2em;
            font-weight: bold;
            margin: 20px 0;
            padding: 10px;
            border-radius: 5px;
        }
        .closed { background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
        .open { background-color: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
        button {
            background-color: #007bff;
            color: white;
            border: none;
            padding: 15px 30px;
            font-size: 1.2em;
            border-radius: 5px;
            cursor: pointer;
            transition: background-color 0.3s;
        }
        button:hover { background-color: #0056b3; }
        button:active { background-color: #004085; }
    </style>
</head>
<body>
    <div class="container">
        <h1>Garage Door Monitor</h1>
        <div id="door-status" class="status closed">Loading...</div>
        <button onclick="triggerRelay()">Toggle Door</button>
    </div>

    <script>
        // Function to fetch the current door status
        function fetchStatus() {
            fetch('/status')
                .then(response => response.json())
                .then(data => {
                    const statusDiv = document.getElementById('door-status');
                    if (data.state === "Closed") {
                        statusDiv.innerText = "CLOSED";
                        statusDiv.className = "status closed";
                    } else {
                        statusDiv.innerText = "OPEN";
                        statusDiv.className = "status open";
                    }
                })
                .catch(error => console.error('Error fetching status:', error));
        }

        // Function to trigger the relay via POST request
        function triggerRelay() {
            fetch('/trigger', { method: 'POST' })
                .then(response => {
                    if(response.ok) {
                        console.log("Relay triggered successfully.");
                        // Immediately fetch status to reflect potential changes
                        setTimeout(fetchStatus, 1000); 
                    }
                })
                .catch(error => console.error('Error triggering relay:', error));
        }

        // Poll the ESP32 every 2 seconds for status updates
        setInterval(fetchStatus, 2000);

        // Fetch initial status on load
        window.onload = fetchStatus;
    </script>
</body>
</html>
)rawliteral";

// --- Route Handlers ---

// Serve the main HTML page
void handleRoot() {
    server.send(200, "text/html", index_html);
}

// Return the current state of the reed switch as JSON
void handleStatus() {
    // Read the reed switch. 
    // LOW means the magnet is present (door closed).
    // HIGH means the magnet is away (door open).
    int sensorValue = digitalRead(REED_SWITCH_PIN);
    String state = (sensorValue == LOW) ? "Closed" : "Open";

    String jsonResponse = "{\"state\": \"" + state + "\"}";
    server.send(200, "application/json", jsonResponse);
}

// Pulse the relay to simulate a button press
void handleTrigger() {
    if (server.method() != HTTP_POST) {
        server.send(405, "text/plain", "Method Not Allowed");
        return;
    }

    // Most relays are Active HIGH. If yours is Active LOW, invert these states.
    digitalWrite(RELAY_PIN, HIGH);
    delay(500); // Hold the relay closed for 500ms
    digitalWrite(RELAY_PIN, LOW);

    server.send(200, "text/plain", "Triggered");
}

// Handle 404 Not Found
void handleNotFound() {
    server.send(404, "text/plain", "404: Not Found");
}

// --- Main Setup and Loop ---

void setup() {
    // Initialize Serial Monitor
    Serial.begin(115200);
    delay(100);
    Serial.println("\n--- Garage Door Web Monitor ---");

    // Initialize GPIOs
    pinMode(RELAY_PIN, OUTPUT);

    // Ensure relay starts in the OFF state immediately
    digitalWrite(RELAY_PIN, LOW); 

    // Use internal pull-up for the reed switch
    pinMode(REED_SWITCH_PIN, INPUT_PULLUP);

    // Connect to WiFi
    Serial.print("Connecting to WiFi: ");
    Serial.println(WIFI_SSID);
    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

    // Wait for connection
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }

    Serial.println("\nWiFi connected successfully.");
    Serial.print("IP Address: ");
    Serial.println(WiFi.localIP());

    // Configure Web Server Routes
    server.on("/", HTTP_GET, handleRoot);
    server.on("/status", HTTP_GET, handleStatus);
    server.on("/trigger", HTTP_POST, handleTrigger);
    server.onNotFound(handleNotFound);

    // Start the server
    server.begin();
    Serial.println("HTTP server started.");
}

void loop() {
    // Listen for incoming client requests
    server.handleClient();

    // Small delay to yield to the ESP32's underlying WiFi/OS tasks
    delay(2); 
}

Comandos de Compilación/Flasheo/Ejecución

Utilice la CLI de PlatformIO Core para compilar y subir el firmware. Abra la terminal dentro de VS Code y asegúrese de estar en el directorio raíz de su proyecto.

Tabla de comandos

AcciónComando
Inicializar proyecto (si es necesario)pio project init --board esp32dev
Compilar firmwarepio run
Subir al ESP32pio run --target upload
Abrir monitor seriepio device monitor

Flujo de trabajo

  1. Cree un nuevo directorio para su proyecto y ábralo en VS Code.
  2. Inicialice el proyecto utilizando la CLI de PlatformIO.
  3. Reemplace el contenido de platformio.ini y src/main.cpp con el Código validado proporcionado anteriormente.
  4. Conecte su ESP32 DevKitC a su ordenador mediante USB.
  5. Ejecute pio run --target upload en la terminal para compilar el código y flashearlo en el microcontrolador.
  6. Ejecute pio device monitor para ver la salida serie. Anote la dirección IP que se imprime una vez que el Wi-Fi se conecte.

Validación paso a paso

Para asegurar que el prototipo funcione correcta y de forma segura, realice los siguientes puntos de control agrupados.

  1. Comprobación de inicialización de red
    • Acción: Observe la salida del Monitor Serie inmediatamente después de reiniciar la placa.
    • Observación esperada: La terminal imprime «Connecting to WiFi…», seguido de una serie de puntos, y finalmente «WiFi connected successfully» junto con una dirección IP (por ejemplo, 192.168.1.50).
    • Condición de aprobación: El ESP32 adquiere con éxito una dirección IP local.
  2. Carga de la interfaz web
    • Acción: Abra un navegador web en un ordenador o teléfono inteligente conectado a la misma red Wi-Fi e introduzca la dirección IP del ESP32 en la barra de URL.
    • Observación esperada: Se carga la página «Garage Door Monitor». La interfaz de usuario muestra un gran bloque de estado y un botón «Toggle Door».
    • Condición de aprobación: La página se renderiza correctamente sin estilos CSS faltantes ni errores de JavaScript en la consola del navegador.
  3. Monitorización del estado del sensor (Cerrado)
    • Acción: Acerque la parte magnética del interruptor a la carcasa cableada del sensor.
    • Observación esperada: En menos de 2 segundos, el bloque de estado de la interfaz web se vuelve verde y muestra «CLOSED».
    • Condición de aprobación: El ESP32 lee correctamente el estado LOW del GPIO 18 y envía el payload JSON actualizado al navegador que realiza la consulta.
  4. Monitorización del estado del sensor (Abierto)
    • Acción: Aleje el imán de la carcasa cableada del sensor.
    • Observación esperada: En menos de 2 segundos, el bloque de estado de la interfaz web se vuelve rojo y muestra «OPEN».
    • Condición de aprobación: La resistencia pull-up interna lleva con éxito el GPIO 18 a HIGH, y la interfaz web refleja el cambio automáticamente.
  5. Validación del disparo del actuador
    • Acción: Haga clic en el botón «Toggle Door» en la interfaz web.
    • Observación esperada: Debería escuchar un «clic» audible del módulo de relé, seguido de un segundo «clic» exactamente medio segundo después.
    • Condición de aprobación: El ESP32 recibe correctamente la petición HTTP POST, lleva el GPIO 5 a HIGH durante 500ms y lo devuelve a LOW, simulando la pulsación momentánea de un botón.

Solución de problemas

SíntomaCausa probableSolución
El monitor serie imprime puntos continuos; nunca se conecta.Credenciales Wi-Fi incorrectas o fuera de rango.Verifique que WIFI_SSID y WIFI_PASSWORD coincidan exactamente con su red de 2.4GHz. Asegúrese de que el ESP32 esté dentro del alcance del router.
La página web carga, pero el estado se mantiene en «Loading…».Error del fetch en JavaScript o el navegador está bloqueando las peticiones locales.Revise la consola de desarrolladores del navegador (F12) en busca de errores de red o de CORS. Asegúrese de que está accediendo mediante http://, no https://.
El relé hace clic inmediatamente al arrancar y se queda activado.El módulo de relé es de tipo «Active LOW» en lugar de «Active HIGH».Cambie digitalWrite(RELAY_PIN, LOW) a HIGH en setup(), e intercambie HIGH/LOW en la función handleTrigger().
El estado de la puerta alterna aleatoriamente entre Abierto y Cerrado.Pin flotante o cable suelto en el interruptor magnético.Asegúrese de que el interruptor esté firmemente conectado al GPIO 18 y a GND. Verifique que pinMode esté estrictamente configurado como INPUT_PULLUP.
El LED del relé se enciende, pero no hay un «clic» audible.Alimentación insuficiente para la bobina del relé.Asegúrese de que el VCC del relé esté conectado al pin 5V (VIN) del ESP32, no al pin 3.3V. Asegúrese de que el puerto USB proporcione corriente suficiente (500mA+).

Encuentra este producto y/o libros sobre este tema en Amazon

Ir a Amazon

Como afiliado de Amazon, gano con las compras que cumplan los requisitos. Si compras a través de este enlace, ayudas a mantener este proyecto.

Quiz rápido

Pregunta 1: ¿Cuál es el objetivo principal del proyecto descrito en el texto?




Pregunta 2: ¿Cuál es el objetivo principal del proyecto descrito en el texto?




Pregunta 3: ¿Cuál es el objetivo principal del proyecto descrito en el texto?




Pregunta 4: ¿Cuál es el objetivo principal del proyecto descrito en el texto?




Pregunta 5: ¿Cuál es el objetivo principal del proyecto descrito en el texto?




Pregunta 6: ¿Cuál es el objetivo principal del proyecto descrito en el texto?




Pregunta 7: ¿Cuál es el objetivo principal del proyecto descrito en el texto?




Pregunta 8: ¿Cuál es el objetivo principal del proyecto descrito en el texto?




Pregunta 9: ¿Cuál es el objetivo principal del proyecto descrito en el texto?




Pregunta 10: ¿Cuál es el objetivo principal del proyecto descrito en el texto?




Carlos Núñez Zorrilla
Carlos Núñez Zorrilla
Electronics & Computer Engineer

Ingeniero Superior en Electrónica de Telecomunicaciones e Ingeniero en Informática (titulaciones oficiales en España).

Sígueme:
Scroll al inicio