Tema 4

Mantenimiento Preventivo de Sistemas ESP32

ESP32 - Monitoreo y Prevención

Duración: 20 horas | Evaluación: 2ª Evaluación

Resultados de Aprendizaje y Criterios de Evaluación

RA 4: Previene disfunciones en equipos y módulos en sistemas de radiocomunicaciones, midiendo elementos y reconociendo valores de aceptación.

Criterios de Evaluación:

Puntuación Total RA 4: 1,4 puntos

4.1 Monitoreo de Parámetros RF

4.1.1 Medición de RSSI y SNR

Monitoreo continuo de la calidad de la señal:

#include "WiFi.h" #include "esp_wifi.h" struct ParametrosRF { int32_t rssi; uint8_t snr; uint8_t canal; uint32_t frecuencia; int8_t potencia_tx; }; void medirParametrosRF() { ParametrosRF parametros; // Medir RSSI parametros.rssi = WiFi.RSSI(); // Medir SNR (Signal-to-Noise Ratio) wifi_ap_record_t ap_info; if (esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK) { parametros.snr = ap_info.rssi - ap_info.noise; } // Obtener canal y frecuencia parametros.canal = WiFi.channel(); parametros.frecuencia = 2412 + (parametros.canal - 1) * 5; // Obtener potencia de transmisión esp_wifi_get_max_tx_power(¶metros.potencia_tx); // Mostrar resultados Serial.println("=== Parámetros RF ==="); Serial.printf("RSSI: %d dBm\n", parametros.rssi); Serial.printf("SNR: %d dB\n", parametros.snr); Serial.printf("Canal: %d\n", parametros.canal); Serial.printf("Frecuencia: %d MHz\n", parametros.frecuencia); Serial.printf("Potencia TX: %d dBm\n", parametros.potencia_tx); // Evaluar calidad de señal evaluarCalidadSenal(parametros.rssi, parametros.snr); } void evaluarCalidadSenal(int32_t rssi, uint8_t snr) { Serial.println("=== Evaluación de Calidad ==="); if (rssi > -30) { Serial.println("RSSI: Excelente"); } else if (rssi > -50) { Serial.println("RSSI: Buena"); } else if (rssi > -70) { Serial.println("RSSI: Aceptable"); } else { Serial.println("RSSI: Mala"); } if (snr > 25) { Serial.println("SNR: Excelente"); } else if (snr > 15) { Serial.println("SNR: Buena"); } else if (snr > 10) { Serial.println("SNR: Aceptable"); } else { Serial.println("SNR: Mala"); } }

4.1.2 Medición de Throughput y Latencia

Evaluación del rendimiento de la red:

#include "WiFi.h" #include "HTTPClient.h" unsigned long tiempoInicio; unsigned long tiempoFin; int bytesRecibidos = 0; void medirThroughput() { Serial.println("=== Medición de Throughput ==="); tiempoInicio = millis(); bytesRecibidos = 0; HTTPClient http; http.begin("http://httpbin.org/bytes/1024"); // Descargar 1KB int httpCode = http.GET(); if (httpCode > 0) { bytesRecibidos = http.getSize(); tiempoFin = millis(); unsigned long tiempoTotal = tiempoFin - tiempoInicio; float throughput = (bytesRecibidos * 8.0) / (tiempoTotal / 1000.0); // bps Serial.printf("Bytes recibidos: %d\n", bytesRecibidos); Serial.printf("Tiempo: %lu ms\n", tiempoTotal); Serial.printf("Throughput: %.2f bps\n", throughput); Serial.printf("Throughput: %.2f Kbps\n", throughput / 1000.0); } http.end(); } void medirLatencia() { Serial.println("=== Medición de Latencia ==="); unsigned long latencias[10]; float latenciaPromedio = 0; for (int i = 0; i < 10; i++) { tiempoInicio = millis(); HTTPClient http; http.begin("http://httpbin.org/get"); http.GET(); http.end(); tiempoFin = millis(); latencias[i] = tiempoFin - tiempoInicio; latenciaPromedio += latencias[i]; Serial.printf("Ping %d: %lu ms\n", i+1, latencias[i]); delay(1000); } latenciaPromedio /= 10.0; Serial.printf("Latencia promedio: %.2f ms\n", latenciaPromedio); }

4.2 Medición de Consumo Energético

4.2.1 Monitoreo de Corrientes de Trabajo

Medición del consumo energético en diferentes modos:

#include "esp_adc_cal.h" #include "driver/adc.h" #define ADC_PIN ADC1_CHANNEL_0 #define VOLTAGE_DIVIDER_RATIO 11.0 // R1=10k, R2=1k void configurarADC() { adc1_config_width(ADC_WIDTH_BIT_12); adc1_config_channel_atten(ADC_PIN, ADC_ATTEN_DB_11); } float medirVoltaje() { int adcValue = adc1_get_raw(ADC_PIN); float voltage = (adcValue * 3.3) / 4095.0; return voltage * VOLTAGE_DIVIDER_RATIO; } float calcularCorriente(float voltaje) { // Asumiendo resistencia de shunt de 0.1 ohm float resistenciaShunt = 0.1; return voltaje / resistenciaShunt; } void medirConsumo() { Serial.println("=== Medición de Consumo ==="); // Medir en modo activo float voltajeActivo = medirVoltaje(); float corrienteActiva = calcularCorriente(voltajeActivo); Serial.printf("Modo activo - Voltaje: %.3f V, Corriente: %.3f A\n", voltajeActivo, corrienteActiva); // Medir en modo WiFi WiFi.mode(WIFI_STA); WiFi.begin("SSID", "password"); delay(5000); float voltajeWiFi = medirVoltaje(); float corrienteWiFi = calcularCorriente(voltajeWiFi); Serial.printf("Modo WiFi - Voltaje: %.3f V, Corriente: %.3f A\n", voltajeWiFi, corrienteWiFi); // Medir en modo sleep esp_wifi_stop(); delay(1000); float voltajeSleep = medirVoltaje(); float corrienteSleep = calcularCorriente(voltajeSleep); Serial.printf("Modo sleep - Voltaje: %.3f V, Corriente: %.3f A\n", voltajeSleep, corrienteSleep); // Calcular consumo promedio float consumoPromedio = (corrienteActiva + corrienteWiFi + corrienteSleep) / 3.0; Serial.printf("Consumo promedio: %.3f A\n", consumoPromedio); }

4.2.2 Optimización de Consumo

Estrategias para reducir el consumo energético:

#include "esp_sleep.h" #include "esp_wifi.h" void optimizarConsumo() { Serial.println("=== Optimización de Consumo ==="); // Reducir frecuencia de CPU setCpuFrequencyMhz(80); Serial.println("Frecuencia CPU reducida a 80 MHz"); // Configurar WiFi para bajo consumo esp_wifi_set_ps(WIFI_PS_MIN_MODEM); Serial.println("WiFi configurado para bajo consumo"); // Desactivar Bluetooth si no se usa esp_bt_controller_disable(); Serial.println("Bluetooth desactivado"); // Configurar wake-up por timer esp_sleep_enable_timer_wakeup(30 * 1000000); // 30 segundos // Configurar wake-up por GPIO esp_sleep_enable_ext0_wakeup(GPIO_NUM_0, 0); Serial.println("Sistema configurado para bajo consumo"); } void cicloTrabajoOptimizado() { // Trabajo activo procesarDatos(); enviarTelemetria(); // Entrar en sleep Serial.println("Entrando en sleep..."); esp_light_sleep_start(); Serial.println("Despertado del sleep"); }

4.3 Verificación de Conectividad

4.3.1 Tests de Conectividad

Verificación automática de la conectividad de red:

#include "WiFi.h" #include "HTTPClient.h" #include "Ping.h" void verificarConectividad() { Serial.println("=== Verificación de Conectividad ==="); // Verificar estado WiFi if (WiFi.status() == WL_CONNECTED) { Serial.println("✓ WiFi conectado"); Serial.printf("IP: %s\n", WiFi.localIP().toString().c_str()); Serial.printf("Gateway: %s\n", WiFi.gatewayIP().toString().c_str()); Serial.printf("DNS: %s\n", WiFi.dnsIP().toString().c_str()); } else { Serial.println("✗ WiFi desconectado"); return; } // Ping al gateway if (pingGateway()) { Serial.println("✓ Ping al gateway exitoso"); } else { Serial.println("✗ Ping al gateway fallido"); } // Ping a DNS if (pingDNS()) { Serial.println("✓ Ping a DNS exitoso"); } else { Serial.println("✗ Ping a DNS fallido"); } // Test HTTP if (testHTTP()) { Serial.println("✓ Test HTTP exitoso"); } else { Serial.println("✗ Test HTTP fallido"); } } bool pingGateway() { IPAddress gateway = WiFi.gatewayIP(); return Ping.ping(gateway, 3); } bool pingDNS() { IPAddress dns = WiFi.dnsIP(); return Ping.ping(dns, 3); } bool testHTTP() { HTTPClient http; http.begin("http://httpbin.org/get"); http.setTimeout(5000); int httpCode = http.GET(); http.end(); return httpCode > 0; }

4.3.2 Monitoreo Continuo

Sistema de monitoreo continuo de la conectividad:

unsigned long ultimaVerificacion = 0; const unsigned long INTERVALO_VERIFICACION = 30000; // 30 segundos int fallosConsecutivos = 0; const int MAX_FALLOS = 3; void monitoreoContinuo() { if (millis() - ultimaVerificacion > INTERVALO_VERIFICACION) { ultimaVerificacion = millis(); if (verificarConectividadCompleta()) { fallosConsecutivos = 0; Serial.println("Conectividad OK"); } else { fallosConsecutivos++; Serial.printf("Fallos consecutivos: %d\n", fallosConsecutivos); if (fallosConsecutivos >= MAX_FALLOS) { Serial.println("Reconectando WiFi..."); reconectarWiFi(); fallosConsecutivos = 0; } } } } bool verificarConectividadCompleta() { // Verificar WiFi if (WiFi.status() != WL_CONNECTED) { return false; } // Verificar ping if (!pingGateway()) { return false; } // Verificar HTTP if (!testHTTP()) { return false; } return true; } void reconectarWiFi() { WiFi.disconnect(); delay(1000); WiFi.begin("SSID", "password"); int intentos = 0; while (WiFi.status() != WL_CONNECTED && intentos < 10) { delay(1000); intentos++; Serial.print("."); } if (WiFi.status() == WL_CONNECTED) { Serial.println("\nWiFi reconectado"); } else { Serial.println("\nError reconectando WiFi"); } }

4.4 Análisis de Espectro

4.4.1 Herramientas de Software

Análisis de espectro usando herramientas de software:

#include "WiFi.h" #include "esp_wifi.h" void analizarEspectro() { Serial.println("=== Análisis de Espectro ==="); // Escanear redes WiFi int n = WiFi.scanNetworks(); Serial.printf("Redes encontradas: %d\n", n); for (int i = 0; i < n; i++) { Serial.printf("Red %d: %s\n", i+1, WiFi.SSID(i).c_str()); Serial.printf(" Canal: %d\n", WiFi.channel(i)); Serial.printf(" RSSI: %d dBm\n", WiFi.RSSI(i)); Serial.printf(" Encriptación: %s\n", (WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? "Abierta" : "Protegida"); Serial.printf(" Frecuencia: %d MHz\n", 2412 + (WiFi.channel(i) - 1) * 5); } // Analizar interferencias analizarInterferencias(); } void analizarInterferencias() { Serial.println("=== Análisis de Interferencias ==="); // Obtener información del canal actual uint8_t canalActual = WiFi.channel(); int32_t rssiActual = WiFi.RSSI(); Serial.printf("Canal actual: %d\n", canalActual); Serial.printf("RSSI actual: %d dBm\n", rssiActual); // Buscar interferencias en canales adyacentes for (int canal = 1; canal <= 13; canal++) { if (canal != canalActual) { int rssiCanal = medirRSSICanal(canal); if (rssiCanal > -80) { Serial.printf("Interferencia en canal %d: %d dBm\n", canal, rssiCanal); } } } } int medirRSSICanal(uint8_t canal) { // Cambiar temporalmente al canal esp_wifi_set_channel(canal, WIFI_SECOND_CHAN_NONE); delay(100); // Medir RSSI int rssi = WiFi.RSSI(); // Volver al canal original esp_wifi_set_channel(WiFi.channel(), WIFI_SECOND_CHAN_NONE); return rssi; }

4.4.2 SDR (Software Defined Radio)

Uso de SDR para análisis avanzado de espectro:

// Configuración para SDR (ejemplo conceptual) void configurarSDR() { Serial.println("=== Configuración SDR ==="); // Configurar parámetros de SDR float frecuencia_central = 2400.0; // MHz float ancho_banda = 20.0; // MHz int tasa_muestreo = 2000000; // 2 MS/s Serial.printf("Frecuencia central: %.1f MHz\n", frecuencia_central); Serial.printf("Ancho de banda: %.1f MHz\n", ancho_banda); Serial.printf("Tasa de muestreo: %d MS/s\n", tasa_muestreo / 1000000); // Configurar ventana de análisis configurarVentanaAnalisis(); } void configurarVentanaAnalisis() { Serial.println("Configurando ventana de análisis..."); // Configurar FFT int tamano_fft = 1024; float resolucion_frecuencia = 20.0 / tamano_fft; // MHz Serial.printf("Tamaño FFT: %d\n", tamano_fft); Serial.printf("Resolución de frecuencia: %.3f MHz\n", resolucion_frecuencia); // Configurar promediado int promedios = 10; Serial.printf("Promedios: %d\n", promedios); } void analizarEspectroSDR() { Serial.println("=== Análisis de Espectro SDR ==="); // Simular análisis de espectro float potencia_maxima = -100.0; float frecuencia_maxima = 0.0; for (int i = 0; i < 1024; i++) { float frecuencia = 2400.0 + (i * 20.0 / 1024.0); float potencia = simularPotencia(frecuencia); if (potencia > potencia_maxima) { potencia_maxima = potencia; frecuencia_maxima = frecuencia; } } Serial.printf("Potencia máxima: %.1f dBm\n", potencia_maxima); Serial.printf("Frecuencia máxima: %.1f MHz\n", frecuencia_maxima); } float simularPotencia(float frecuencia) { // Simular potencia de señal return -80.0 + 20.0 * sin(frecuencia / 100.0); }

4.5 Calibración de Antenas

4.5.1 Medición de ROE

Medición de la Relación de Ondas Estacionarias:

#include "WiFi.h" #include "esp_wifi.h" struct MedicionROE { float roe; float potencia_incidente; float potencia_reflejada; float impedancia; }; void medirROE() { Serial.println("=== Medición de ROE ==="); MedicionROE medicion; // Medir potencia incidente medicion.potencia_incidente = medirPotenciaIncidente(); // Medir potencia reflejada medicion.potencia_reflejada = medirPotenciaReflejada(); // Calcular ROE medicion.roe = calcularROE(medicion.potencia_incidente, medicion.potencia_reflejada); // Calcular impedancia medicion.impedancia = calcularImpedancia(medicion.roe); // Mostrar resultados Serial.printf("Potencia incidente: %.2f dBm\n", medicion.potencia_incidente); Serial.printf("Potencia reflejada: %.2f dBm\n", medicion.potencia_reflejada); Serial.printf("ROE: %.2f\n", medicion.roe); Serial.printf("Impedancia: %.2f ohm\n", medicion.impedancia); // Evaluar ROE evaluarROE(medicion.roe); } float medirPotenciaIncidente() { // Simular medición de potencia incidente return -10.0; // dBm } float medirPotenciaReflejada() { // Simular medición de potencia reflejada return -20.0; // dBm } float calcularROE(float potencia_incidente, float potencia_reflejada) { float coeficiente_reflexion = sqrt(pow(10, (potencia_reflejada - potencia_incidente) / 10.0)); return (1 + coeficiente_reflexion) / (1 - coeficiente_reflexion); } float calcularImpedancia(float roe) { // Asumiendo impedancia característica de 50 ohm float z0 = 50.0; return z0 * roe; } void evaluarROE(float roe) { Serial.println("=== Evaluación de ROE ==="); if (roe < 1.5) { Serial.println("ROE: Excelente"); } else if (roe < 2.0) { Serial.println("ROE: Buena"); } else if (roe < 3.0) { Serial.println("ROE: Aceptable"); } else { Serial.println("ROE: Mala - Requiere ajuste"); } }

4.5.2 Patrones de Radiación

Medición de patrones de radiación de antenas:

void medirPatronRadiacion() { Serial.println("=== Medición de Patrón de Radiación ==="); // Configurar parámetros de medición int angulos = 36; // 10 grados por paso float radio = 1.0; // metros Serial.printf("Angulos: %d\n", angulos); Serial.printf("Radio: %.1f metros\n", radio); // Medir en diferentes ángulos for (int i = 0; i < angulos; i++) { float angulo = i * 10.0; // grados float rssi = medirRSSIAngulo(angulo); Serial.printf("Angulo: %.0f°, RSSI: %d dBm\n", angulo, rssi); } // Analizar patrón analizarPatron(); } float medirRSSIAngulo(float angulo) { // Simular medición de RSSI en un ángulo específico // En la práctica, esto requeriría un sistema de rotación return -50.0 + 10.0 * sin(angulo * PI / 180.0); } void analizarPatron() { Serial.println("=== Análisis de Patrón ==="); // Calcular ganancia máxima float ganancia_maxima = -50.0; // dBm float angulo_maximo = 0.0; for (int i = 0; i < 36; i++) { float angulo = i * 10.0; float rssi = medirRSSIAngulo(angulo); if (rssi > ganancia_maxima) { ganancia_maxima = rssi; angulo_maximo = angulo; } } Serial.printf("Ganancia máxima: %.1f dBm\n", ganancia_maxima); Serial.printf("Angulo de máxima ganancia: %.0f°\n", angulo_maximo); // Calcular ancho de haz float ancho_haz = calcularAnchoHaz(); Serial.printf("Ancho de haz: %.1f°\n", ancho_haz); } float calcularAnchoHaz() { // Calcular ancho de haz a -3dB float ganancia_maxima = -50.0; float umbral = ganancia_maxima - 3.0; int angulos_umbral = 0; for (int i = 0; i < 36; i++) { float angulo = i * 10.0; float rssi = medirRSSIAngulo(angulo); if (rssi >= umbral) { angulos_umbral++; } } return angulos_umbral * 10.0; }

4.6 Actualizaciones de Firmware

4.6.1 Procedimientos Seguros

Actualización segura del firmware:

#include "esp_ota_ops.h" #include "esp_http_client.h" #include "esp_https_ota.h" void actualizarFirmwareSeguro() { Serial.println("=== Actualización Segura de Firmware ==="); // Verificar espacio disponible if (!verificarEspacioDisponible()) { Serial.println("Error: Espacio insuficiente"); return; } // Verificar integridad del firmware if (!verificarIntegridadFirmware()) { Serial.println("Error: Firmware corrupto"); return; } // Crear backup del firmware actual crearBackupFirmware(); // Realizar actualización if (realizarActualizacion()) { Serial.println("Actualización exitosa"); } else { Serial.println("Error en actualización, restaurando backup"); restaurarBackupFirmware(); } } bool verificarEspacioDisponible() { const esp_partition_t* update_partition = esp_ota_get_next_update_partition(NULL); if (update_partition == NULL) { return false; } size_t espacio_disponible = update_partition->size; Serial.printf("Espacio disponible: %d bytes\n", espacio_disponible); return espacio_disponible > 1024 * 1024; // 1MB mínimo } bool verificarIntegridadFirmware() { // Verificar checksum del firmware // En la práctica, esto requeriría un servidor que proporcione el checksum return true; } void crearBackupFirmware() { Serial.println("Creando backup del firmware actual..."); const esp_partition_t* running = esp_ota_get_running_partition(); Serial.printf("Partición actual: %s\n", running->label); // En la práctica, esto requeriría copiar la partición actual Serial.println("Backup creado"); } bool realizarActualizacion() { Serial.println("Realizando actualización..."); esp_http_client_config_t config = { .url = "https://servidor.com/firmware.bin", .cert_pem = NULL, }; esp_err_t ret = esp_https_ota(&config); if (ret == ESP_OK) { Serial.println("Actualización completada"); return true; } else { Serial.printf("Error en actualización: %s\n", esp_err_to_name(ret)); return false; } } void restaurarBackupFirmware() { Serial.println("Restaurando backup..."); // En la práctica, esto requeriría restaurar la partición de backup Serial.println("Backup restaurado"); }

4.7 Documentación de Mantenimiento

4.7.1 Sistema de Logs

Documentación automática del mantenimiento:

#include "esp_log.h" #include "SPIFFS.h" static const char* TAG = "MANTENIMIENTO"; void configurarLogs() { esp_log_level_set("*", ESP_LOG_INFO); esp_log_level_set("MANTENIMIENTO", ESP_LOG_DEBUG); } void generarLogMantenimiento() { ESP_LOGI(TAG, "=== Inicio de Mantenimiento ==="); // Log de parámetros RF ESP_LOGI(TAG, "RSSI: %d dBm", WiFi.RSSI()); ESP_LOGI(TAG, "Canal: %d", WiFi.channel()); ESP_LOGI(TAG, "Potencia TX: %d dBm", 20); // Log de consumo ESP_LOGI(TAG, "Memoria libre: %d bytes", ESP.getFreeHeap()); ESP_LOGI(TAG, "Tiempo de funcionamiento: %lu segundos", millis() / 1000); // Log de conectividad ESP_LOGI(TAG, "WiFi conectado: %s", WiFi.status() == WL_CONNECTED ? "Sí" : "No"); ESP_LOGI(TAG, "IP: %s", WiFi.localIP().toString().c_str()); ESP_LOGI(TAG, "=== Fin de Mantenimiento ==="); } void guardarLogEnArchivo() { if (!SPIFFS.begin(true)) { ESP_LOGE(TAG, "Error montando SPIFFS"); return; } File file = SPIFFS.open("/mantenimiento.log", "a"); if (file) { file.printf("[%lu] Mantenimiento - RSSI: %d, Canal: %d\n", millis(), WiFi.RSSI(), WiFi.channel()); file.close(); ESP_LOGI(TAG, "Log guardado en archivo"); } else { ESP_LOGE(TAG, "Error abriendo archivo de log"); } }

4.7.2 Reportes de Mantenimiento

Generación de reportes de mantenimiento:

#include "ArduinoJson.h" void generarReporteMantenimiento() { Serial.println("=== Generando Reporte de Mantenimiento ==="); DynamicJsonDocument reporte(2048); // Información del sistema reporte["sistema"]["modelo"] = "ESP32"; reporte["sistema"]["version_firmware"] = "1.0.0"; reporte["sistema"]["tiempo_funcionamiento"] = millis() / 1000; // Parámetros RF reporte["rf"]["rssi"] = WiFi.RSSI(); reporte["rf"]["canal"] = WiFi.channel(); reporte["rf"]["frecuencia"] = 2412 + (WiFi.channel() - 1) * 5; reporte["rf"]["potencia_tx"] = 20; // Estado del sistema reporte["sistema"]["memoria_libre"] = ESP.getFreeHeap(); reporte["sistema"]["wifi_conectado"] = WiFi.status() == WL_CONNECTED; reporte["sistema"]["ip"] = WiFi.localIP().toString(); // Fecha y hora reporte["fecha"] = "2025-01-01"; reporte["hora"] = "12:00:00"; // Serializar reporte String reporteJson; serializeJson(reporte, reporteJson); Serial.println("Reporte generado:"); Serial.println(reporteJson); // Guardar reporte guardarReporte(reporteJson); } void guardarReporte(String reporte) { if (!SPIFFS.begin(true)) { return; } String nombreArchivo = "/reporte_" + String(millis()) + ".json"; File file = SPIFFS.open(nombreArchivo, "w"); if (file) { file.println(reporte); file.close(); Serial.println("Reporte guardado: " + nombreArchivo); } }

Materiales Necesarios

Actividades Teóricas

Prácticas de Laboratorio

Práctica 4.1: Monitoreo de Parámetros RF

Objetivo: Implementar sistema de monitoreo continuo de parámetros RF.

Duración: 3 horas

Entregables: Sistema de monitoreo, mediciones, informe técnico

Práctica 4.2: Medición de Consumo Energético

Objetivo: Medir y optimizar el consumo energético del ESP32.

Duración: 3 horas

Entregables: Mediciones de consumo, código optimizado, análisis

Práctica 4.3: Verificación de Conectividad

Objetivo: Implementar sistema de verificación automática de conectividad.

Duración: 3 horas

Entregables: Sistema de verificación, tests automáticos, informe

Práctica 4.4: Análisis de Espectro

Objetivo: Realizar análisis de espectro usando SDR.

Duración: 4 horas

Entregables: Análisis de espectro, identificación de interferencias, informe

Práctica 4.5: Calibración de Antenas

Objetivo: Medir ROE y patrones de radiación de antenas.

Duración: 3 horas

Entregables: Mediciones de ROE, patrones de radiación, informe

Práctica 4.6: Actualización de Firmware

Objetivo: Implementar sistema seguro de actualización de firmware.

Duración: 4 horas

Entregables: Sistema OTA, procedimientos de seguridad, documentación

Criterios de Evaluación

Instrumentos de evaluación:

Entregables obligatorios:

Recursos Adicionales