Capítulo 5: Control de flujo - If/Else
Parte I - Sección 2: Lógica de programación - Nivel: Principiante
🎯 Objetivos de aprendizaje
Sección titulada «🎯 Objetivos de aprendizaje»Al finalizar este capítulo serás capaz de:
- Usar if/else para ejecutar código condicionalmente
- Encadenar condiciones con else if para múltiples casos
- Anidar estructuras if dentro de otras
- Aplicar el operador ternario para asignaciones condicionales simples
- Construir lógica de decisión para selección automática de componentes eléctricos
📋 Requisitos previos
Sección titulada «📋 Requisitos previos»Antes de comenzar este capítulo debes:
- ✅ Haber completado el Capítulo 4
- ✅ Entender operadores de comparación (
==,!=,>,<,>=,<=) - ✅ Entender operadores lógicos (
&&, ||, !&&, ||, !,||,!) - ✅ Saber construir expresiones booleanas
🏆 Proyecto del capítulo
Sección titulada «🏆 Proyecto del capítulo»Selector Automático de Protecciones Eléctricas
Al final de este capítulo habrás construido un script que:
- Selecciona automáticamente el interruptor magnetotérmico adecuado
- Determina la sección de cable necesaria
- Calcula el tipo de protección diferencial requerida
- Genera especificaciones técnicas completas
Tiempo estimado: 45-55 minutos
📚 Contenido
Sección titulada «📚 Contenido»1. Introducción: Tomar decisiones en el código
Sección titulada «1. Introducción: Tomar decisiones en el código»Hasta ahora, nuestros scripts ejecutaban todas las líneas secuencialmente, de arriba a abajo. Pero en la vida real, necesitamos tomar decisiones:
- “Si el voltaje es mayor a 253V, entonces mostrar una alerta”
- “Si la corriente excede 16A, entonces seleccionar un cable más grueso, si no, usar el cable estándar”
- “Si es circuito de iluminación, usar protección tipo B; si es motor, usar tipo D”
La estructura if/else te permite ejecutar diferentes bloques de código según condiciones.
2. La estructura if básica
Sección titulada «2. La estructura if básica»La sintaxis más simple:
if (condicion){ // Código que se ejecuta si la condición es true}Ejemplo práctico:
double voltaje = 260.0;
if (voltaje > 253.0){ MessageBox.Show("Advertencia: Voltaje excesivo detectado.");}Flujo de ejecución:
- Se evalúa la condición
voltaje > 253.0 - Si es
true, se ejecuta el bloque entre{ } - Si es
false, se salta el bloque y continúa después
2.1 Anatomía del if
Sección titulada «2.1 Anatomía del if»if (condicion) ↑ ↑ | └─ Expresión booleana (true/false) └────────── Palabra clave{ // Bloque de código // Puede tener múltiples líneas}2.2 Ejemplos prácticos
Sección titulada «2.2 Ejemplos prácticos»Ejemplo 1: Validar corriente
double corriente = 18.5;double corrienteMaxima = 16.0;
if (corriente > corrienteMaxima){ MessageBox.Show("La corriente excede el límite permitido.");}Ejemplo 2: Verificar proyecto abierto
bool proyectoAbierto = true;
if (proyectoAbierto){ // Procesar el proyecto MessageBox.Show("Procesando proyecto...");}Ejemplo 3: Condición compuesta
double voltaje = 195.0;double voltajeMinimo = 207.0;double voltajeMaximo = 253.0;
if (voltaje < voltajeMinimo || voltaje > voltajeMaximo){ MessageBox.Show("Voltaje fuera del rango permitido (207V - 253V).");}2.3 If de una línea (sin llaves)
Sección titulada «2.3 If de una línea (sin llaves)»Si solo hay una instrucción, puedes omitir las llaves:
if (voltaje > 253.0) MessageBox.Show("Voltaje alto");Pero no es recomendable porque:
- Es fácil agregar otra línea y olvidar las llaves
- Reduce la legibilidad
Mejor práctica: Siempre usa llaves, incluso para una línea:
if (voltaje > 253.0){ MessageBox.Show("Voltaje alto");}3. La estructura if/else
Sección titulada «3. La estructura if/else»Para ejecutar un código cuando la condición es true y otro cuando es false:
if (condicion){ // Se ejecuta si condicion es true}else{ // Se ejecuta si condicion es false}Ejemplo práctico:
double corriente = 14.5;double corrienteMaxima = 16.0;
if (corriente <= corrienteMaxima){ MessageBox.Show("Corriente dentro de límites normales.");}else{ MessageBox.Show("Corriente excede el límite. Revisar instalación.");}3.1 Flujo de ejecución
Sección titulada «3.1 Flujo de ejecución» ┌─────────────┐ │ if (cond) │ └──────┬──────┘ │ ┌──────┴──────┐ │ │ true false │ │ ┌───▼───┐ ┌───▼───┐ │ if {} │ │else {} │ └───┬───┘ └───┬───┘ │ │ └──────┬──────┘ │ continúaSolo uno de los dos bloques se ejecuta, nunca ambos.
3.2 Ejemplos prácticos
Sección titulada «3.2 Ejemplos prácticos»Ejemplo 1: Clasificar proyecto por tamaño
int numeroPaginas = 45;
if (numeroPaginas <= 20){ MessageBox.Show("Proyecto pequeño (hasta 20 páginas).");}else{ MessageBox.Show("Proyecto grande (más de 20 páginas).");}Ejemplo 2: Seleccionar tipo de cable
bool ambienteHumedo = true;
if (ambienteHumedo){ MessageBox.Show("Usar cable tipo H07RN-F (resistente a humedad).");}else{ MessageBox.Show("Usar cable tipo H07V-K (instalación estándar).");}Ejemplo 3: Determinar tipo de sistema
double voltaje = 400.0;
if (voltaje > 380.0){ MessageBox.Show("Sistema trifásico (400V).");}else{ MessageBox.Show("Sistema monofásico (230V).");}4. La estructura else if - múltiples condiciones
Sección titulada «4. La estructura else if - múltiples condiciones»Cuando tienes más de dos casos posibles:
if (condicion1){ // Se ejecuta si condicion1 es true}else if (condicion2){ // Se ejecuta si condicion1 es false y condicion2 es true}else if (condicion3){ // Se ejecuta si condicion1 y condicion2 son false, y condicion3 es true}else{ // Se ejecuta si ninguna condición anterior es true}Importante: Se evalúan en orden. El primer if o else if que sea true se ejecuta, y se salta el resto.
4.1 Ejemplo práctico: Clasificar sección de cable
Sección titulada «4.1 Ejemplo práctico: Clasificar sección de cable»double corriente = 25.0;string seccionRecomendada;
if (corriente <= 16.0){ seccionRecomendada = "2.5 mm²";}else if (corriente <= 20.0){ seccionRecomendada = "4 mm²";}else if (corriente <= 25.0){ seccionRecomendada = "6 mm²";}else if (corriente <= 32.0){ seccionRecomendada = "10 mm²";}else{ seccionRecomendada = "Requiere cálculo específico (> 32A)";}
MessageBox.Show("Sección recomendada: " + seccionRecomendada);4.2 Ejemplo: Clasificar factor de potencia
Sección titulada «4.2 Ejemplo: Clasificar factor de potencia»double factorPotencia = 0.78;string clasificacion;
if (factorPotencia >= 0.95){ clasificacion = "Excelente - No requiere corrección";}else if (factorPotencia >= 0.90){ clasificacion = "Bueno - Corrección opcional";}else if (factorPotencia >= 0.85){ clasificacion = "Aceptable - Corrección recomendada";}else{ clasificacion = "Bajo - Corrección necesaria";}
string mensaje = string.Format( "Factor de potencia: {0:F2}\nClasificación: {1}", factorPotencia, clasificacion);
MessageBox.Show(mensaje);4.3 Flujo de ejecución con else if
Sección titulada «4.3 Flujo de ejecución con else if»if (cond1)? ├─ true → ejecuta bloque 1 → FIN └─ false → else if (cond2)? ├─ true → ejecuta bloque 2 → FIN └─ false → else if (cond3)? ├─ true → ejecuta bloque 3 → FIN └─ false → else (bloque 4) → FINSolo uno de los bloques se ejecuta.
5. If anidados (nested if)
Sección titulada «5. If anidados (nested if)»Puedes colocar un if dentro de otro:
if (condicionExterna){ // Código nivel 1
if (condicionInterna) { // Código nivel 2 }}5.1 Ejemplo práctico: Validación de circuito completo
Sección titulada «5.1 Ejemplo práctico: Validación de circuito completo»double voltaje = 230.0;double corriente = 15.5;
// Verificación nivel 1: Voltajeif (voltaje >= 207.0 && voltaje <= 253.0){ MessageBox.Show("Voltaje OK");
// Verificación nivel 2: Corriente (solo si voltaje OK) if (corriente <= 16.0) { MessageBox.Show("Corriente OK\nCircuito completamente validado."); } else { MessageBox.Show("Corriente excesiva. Revisar."); }}else{ MessageBox.Show("Voltaje fuera de rango. No se verificó la corriente.");}5.2 Ejemplo: Selección de protección diferencial
Sección titulada «5.2 Ejemplo: Selección de protección diferencial»string tipoCarga = "Motor"; // Opciones: "Iluminacion", "Motor", "Informatica"double corriente = 20.0;
if (tipoCarga == "Motor"){ // Motores requieren Tipo A (sensibles a CC) if (corriente <= 25.0) { MessageBox.Show("Diferencial: Tipo A, 30mA, 25A"); } else if (corriente <= 40.0) { MessageBox.Show("Diferencial: Tipo A, 30mA, 40A"); } else { MessageBox.Show("Diferencial: Tipo A, 300mA, 63A o superior"); }}else if (tipoCarga == "Informatica"){ // Informática requiere Tipo B (sensibles a CC y alta frecuencia) MessageBox.Show("Diferencial: Tipo B, 30mA, corriente según carga");}else{ // Iluminación y otros: Tipo AC estándar if (corriente <= 25.0) { MessageBox.Show("Diferencial: Tipo AC, 30mA, 25A"); } else { MessageBox.Show("Diferencial: Tipo AC, 30mA, 40A"); }}5.3 Cuidado con la complejidad
Sección titulada «5.3 Cuidado con la complejidad»Demasiados niveles de anidación reducen la legibilidad:
// Mal: demasiado anidado (difícil de leer)if (condicion1){ if (condicion2) { if (condicion3) { if (condicion4) { // ¿Qué condiciones deben cumplirse para llegar aquí? } } }}Mejor: Usa operadores lógicos para combinar condiciones:
// Bien: claro y directoif (condicion1 && condicion2 && condicion3 && condicion4){ // Claramente se necesitan las 4 condiciones}O divide en funciones (lo veremos en capítulos futuros).
6. Operador ternario (? :)
Sección titulada «6. Operador ternario (? :)»Para asignaciones condicionales simples, existe un atajo:
variable = condicion ? valorSiTrue : valorSiFalse;Es equivalente a:
if (condicion){ variable = valorSiTrue;}else{ variable = valorSiFalse;}6.1 Ejemplos prácticos
Sección titulada «6.1 Ejemplos prácticos»Ejemplo 1: Determinar tipo de sistema
double voltaje = 400.0;string tipoSistema = (voltaje > 300) ? "Trifásico" : "Monofásico";// tipoSistema = "Trifásico"Ejemplo 2: Clasificar proyecto
int numeroPaginas = 15;string tamaño = (numeroPaginas <= 20) ? "Pequeño" : "Grande";// tamaño = "Pequeño"Ejemplo 3: Determinar estado
bool tieneErrores = false;string estado = tieneErrores ? "Con errores" : "Sin errores";// estado = "Sin errores"6.2 Ternarios anidados (usar con precaución)
Sección titulada «6.2 Ternarios anidados (usar con precaución)»Puedes anidar operadores ternarios, pero reduce la legibilidad:
double corriente = 22.0;string seccion = (corriente <= 16) ? "2.5mm²" : (corriente <= 20) ? "4mm²" : (corriente <= 25) ? "6mm²" : "10mm²";Para casos complejos, usa if/else if:
string seccion;if (corriente <= 16){ seccion = "2.5mm²";}else if (corriente <= 20){ seccion = "4mm²";}else if (corriente <= 25){ seccion = "6mm²";}else{ seccion = "10mm²";}6.3 Cuándo usar el operador ternario
Sección titulada «6.3 Cuándo usar el operador ternario»Usa ternario para:
- Asignaciones simples con dos opciones
- Casos donde mejora la concisión sin sacrificar claridad
Usa if/else para:
- Múltiples líneas de código en cada rama
- Más de dos opciones
- Cuando la legibilidad es más importante que la brevedad
7. Comparación de strings
Sección titulada «7. Comparación de strings»Comparar textos requiere cuidado especial:
7.1 Comparación exacta (sensible a mayúsculas)
Sección titulada «7.1 Comparación exacta (sensible a mayúsculas)»string tipo = "Motor";
if (tipo == "Motor"){ MessageBox.Show("Tipo Motor detectado");}// Coincide: "Motor" == "Motor"string tipo = "motor"; // Minúsculas
if (tipo == "Motor") // No coincide{ // No entra aquí}7.2 Comparación insensible a mayúsculas
Sección titulada «7.2 Comparación insensible a mayúsculas»string tipo = "motor";
if (tipo.ToLower() == "motor") // Convierte a minúsculas{ MessageBox.Show("Tipo Motor detectado"); // Ahora sí coincide}O mejor aún:
string tipo = "MOTOR";
if (tipo.Equals("motor", StringComparison.OrdinalIgnoreCase)){ MessageBox.Show("Tipo Motor detectado"); // Coincide independientemente de mayúsculas}7.3 Ejemplo práctico completo
Sección titulada «7.3 Ejemplo práctico completo»string tipoCargaInput = "motor"; // Usuario escribió en minúsculas
if (tipoCargaInput.Equals("Motor", StringComparison.OrdinalIgnoreCase)){ MessageBox.Show("Protección Tipo D (arranque de motores)");}else if (tipoCargaInput.Equals("Iluminacion", StringComparison.OrdinalIgnoreCase)){ MessageBox.Show("Protección Tipo B (iluminación)");}else if (tipoCargaInput.Equals("General", StringComparison.OrdinalIgnoreCase)){ MessageBox.Show("Protección Tipo C (uso general)");}else{ MessageBox.Show("Tipo de carga no reconocido");}💻 Manos a la obra: Construyendo el proyecto
Sección titulada «💻 Manos a la obra: Construyendo el proyecto»Vamos a crear un Selector Automático de Protecciones Eléctricas.
Paso 1: Estructura básica y entrada de datos
Sección titulada «Paso 1: Estructura básica y entrada de datos»using System;using Eplan.EplApi.Base;using Eplan.EplApi.ApplicationFramework;
public class SelectorProtecciones{ [Start] public void Ejecutar() { // ======================================== // DATOS DEL CIRCUITO // ========================================
string nombreCircuito = "Línea producción - Zona 2"; string tipoCarga = "Motor"; // Opciones: "Iluminacion", "Motor", "Tomas", "Informatica" double corrienteNominal = 18.5; // Amperios double longitudCable = 42.0; // Metros bool ambienteHumedo = false; double voltajeNominal = 230.0; // Voltios }}Paso 2: Selección de curva de disparo (magnetotérmico)
Sección titulada «Paso 2: Selección de curva de disparo (magnetotérmico)»// ========================================// PASO 1: SELECCIONAR CURVA DE DISPARO// ========================================
string curvaDisparo;string justificacionCurva;
if (tipoCarga.Equals("Motor", StringComparison.OrdinalIgnoreCase)){ curvaDisparo = "Curva D"; justificacionCurva = "Motores tienen alta corriente de arranque (6-8x In)";}else if (tipoCarga.Equals("Iluminacion", StringComparison.OrdinalIgnoreCase)){ curvaDisparo = "Curva B"; justificacionCurva = "Iluminación tiene bajo pico de arranque";}else if (tipoCarga.Equals("Informatica", StringComparison.OrdinalIgnoreCase)){ curvaDisparo = "Curva C"; justificacionCurva = "Equipos informáticos tienen pico moderado";}else{ // Tomas y uso general curvaDisparo = "Curva C"; justificacionCurva = "Uso general y tomas de corriente";}¿Qué acabamos de hacer? Seleccionamos la curva de disparo apropiada según el tipo de carga. Cada tipo requiere diferente sensibilidad para evitar disparos innecesarios.
Paso 3: Selección de corriente nominal del magnetotérmico
Sección titulada «Paso 3: Selección de corriente nominal del magnetotérmico»// ========================================// PASO 2: SELECCIONAR CORRIENTE NOMINAL// ========================================
int corrienteMagnetotermico;
if (corrienteNominal <= 10.0){ corrienteMagnetotermico = 10;}else if (corrienteNominal <= 16.0){ corrienteMagnetotermico = 16;}else if (corrienteNominal <= 20.0){ corrienteMagnetotermico = 20;}else if (corrienteNominal <= 25.0){ corrienteMagnetotermico = 25;}else if (corrienteNominal <= 32.0){ corrienteMagnetotermico = 32;}else if (corrienteNominal <= 40.0){ corrienteMagnetotermico = 40;}else{ corrienteMagnetotermico = 63;}
double margenProteccion = ((corrienteMagnetotermico - corrienteNominal) / corrienteNominal) * 100;¿Qué acabamos de hacer? Seleccionamos el valor normalizado de corriente inmediatamente superior a la corriente nominal del circuito.
Paso 4: Selección de sección de cable
Sección titulada «Paso 4: Selección de sección de cable»// ========================================// PASO 3: SELECCIONAR SECCIÓN DE CABLE// ========================================
double seccionCable;double corrienteAdmisible;
// Tabla simplificada de corrientes admisibles (instalación tipo B)if (corrienteMagnetotermico <= 10){ seccionCable = 1.5; corrienteAdmisible = 15.0;}else if (corrienteMagnetotermico <= 16){ seccionCable = 2.5; corrienteAdmisible = 21.0;}else if (corrienteMagnetotermico <= 20){ seccionCable = 4.0; corrienteAdmisible = 27.0;}else if (corrienteMagnetotermico <= 25){ seccionCable = 6.0; corrienteAdmisible = 36.0;}else if (corrienteMagnetotermico <= 32){ seccionCable = 10.0; corrienteAdmisible = 50.0;}else if (corrienteMagnetotermico <= 40){ seccionCable = 16.0; corrienteAdmisible = 68.0;}else{ seccionCable = 25.0; corrienteAdmisible = 89.0;}
// Validar que el cable soporte la corriente del magnetotérmicobool cableSuficiente = (corrienteAdmisible >= corrienteMagnetotermico);¿Qué acabamos de hacer? Seleccionamos la sección de cable que puede soportar la corriente del magnetotérmico, siguiendo tablas de corrientes admisibles.
Paso 5: Selección de tipo de cable según ambiente
Sección titulada «Paso 5: Selección de tipo de cable según ambiente»// ========================================// PASO 4: SELECCIONAR TIPO DE CABLE// ========================================
string tipoCable;string descripcionCable;
if (ambienteHumedo){ tipoCable = "H07RN-F"; descripcionCable = "Cable flexible resistente a humedad y aceites";}else{ tipoCable = "H07V-K"; descripcionCable = "Cable flexible para instalación estándar";}Paso 6: Cálculo de caída de tensión
Sección titulada «Paso 6: Cálculo de caída de tensión»// ========================================// PASO 5: CALCULAR CAÍDA DE TENSIÓN// ========================================
double resistividadCobre = 0.018; // Ω·mm²/mdouble caidaTension = (2 * longitudCable * corrienteNominal * resistividadCobre) / seccionCable;double porcentajeCaida = (caidaTension / voltajeNominal) * 100;
bool caidaAceptable = (porcentajeCaida <= 3.0);
string advertenciaCaida = "";if (!caidaAceptable){ advertenciaCaida = "\n¡ADVERTENCIA! Caída de tensión excede 3%"; // Sugerir sección superior double seccionSuperior = seccionCable; if (seccionCable == 1.5) seccionSuperior = 2.5; else if (seccionCable == 2.5) seccionSuperior = 4.0; else if (seccionCable == 4.0) seccionSuperior = 6.0; else if (seccionCable == 6.0) seccionSuperior = 10.0; else if (seccionCable == 10.0) seccionSuperior = 16.0; else if (seccionCable == 16.0) seccionSuperior = 25.0;
advertenciaCaida += string.Format("\nConsiderar sección {0}mm²", seccionSuperior);}¿Qué acabamos de hacer? Calculamos la caída de tensión y verificamos que esté bajo el 3%. Si no, sugerimos una sección superior.
Paso 7: Selección de diferencial
Sección titulada «Paso 7: Selección de diferencial»// ========================================// PASO 6: SELECCIONAR DIFERENCIAL// ========================================
string tipoDiferencial;int sensibilidadDiferencial; // mAint corrienteDiferencial;
// Tipo de diferencial según cargaif (tipoCarga.Equals("Motor", StringComparison.OrdinalIgnoreCase)){ tipoDiferencial = "Tipo A"; // Sensible a corriente alterna y continua pulsante}else if (tipoCarga.Equals("Informatica", StringComparison.OrdinalIgnoreCase)){ tipoDiferencial = "Tipo B"; // Sensible a corriente continua}else{ tipoDiferencial = "Tipo AC"; // Sensible a corriente alterna (estándar)}
// Sensibilidad según ambienteif (ambienteHumedo){ sensibilidadDiferencial = 30; // Alta sensibilidad en ambiente húmedo}else{ if (corrienteMagnetotermico > 32) { sensibilidadDiferencial = 300; // Menor sensibilidad para altas corrientes } else { sensibilidadDiferencial = 30; }}
// Corriente nominal del diferencial (debe ser >= magnetotérmico)if (corrienteMagnetotermico <= 25){ corrienteDiferencial = 25;}else if (corrienteMagnetotermico <= 40){ corrienteDiferencial = 40;}else{ corrienteDiferencial = 63;}¿Qué acabamos de hacer? Seleccionamos el tipo de diferencial según la carga, la sensibilidad según el ambiente, y la corriente nominal.
Paso 8: Construcción del reporte final
Sección titulada «Paso 8: Construcción del reporte final»// ========================================// CONSTRUCCIÓN DEL REPORTE// ========================================
string reporte = string.Format( "=== SELECTOR AUTOMÁTICO DE PROTECCIONES ===\n\n" + "DATOS DEL CIRCUITO:\n" + "- Nombre: {0}\n" + "- Tipo de carga: {1}\n" + "- Corriente nominal: {2:F1} A\n" + "- Longitud: {3:F1} m\n" + "- Ambiente húmedo: {4}\n\n" + "PROTECCIÓN MAGNETOTÉRMICA:\n" + "- {5} - {6}A\n" + "- Justificación: {7}\n" + "- Margen: {8:F1}%\n\n" + "CABLE:\n" + "- Tipo: {9}\n" + "- Sección: {10}mm²\n" + "- Descripción: {11}\n" + "- Corriente admisible: {12:F1}A\n\n" + "PROTECCIÓN DIFERENCIAL:\n" + "- {13} - {14}mA - {15}A\n\n" + "CAÍDA DE TENSIÓN:\n" + "- Calculada: {16:F2}V ({17:F2}%)\n" + "- Estado: {18}{19}", nombreCircuito, tipoCarga, corrienteNominal, longitudCable, ambienteHumedo ? "Sí" : "No", curvaDisparo, corrienteMagnetotermico, justificacionCurva, margenProteccion, tipoCable, seccionCable, descripcionCable, corrienteAdmisible, tipoDiferencial, sensibilidadDiferencial, corrienteDiferencial, caidaTension, porcentajeCaida, caidaAceptable ? "Aceptable (< 3%)" : "Excesiva (> 3%)", advertenciaCaida);
// ========================================// MOSTRAR REPORTE// ========================================
MessageBoxIcon icono = caidaAceptable ? MessageBoxIcon.Information : MessageBoxIcon.Warning;
MessageBox.Show(reporte, "Selector de Protecciones", MessageBoxButtons.OK, icono);Código completo del proyecto
Sección titulada «Código completo del proyecto»//// Proyecto: Selector Automático de Protecciones Eléctricas// Capítulo: 5// Descripción: Selecciona automáticamente protecciones y cables según parámetros// Autor: C.D. López// Fecha: Enero 2025//
using System;using Eplan.EplApi.Base;using Eplan.EplApi.ApplicationFramework;
public class SelectorProtecciones{ [Start] public void Ejecutar() { // ======================================== // DATOS DEL CIRCUITO // ========================================
string nombreCircuito = "Línea producción - Zona 2"; string tipoCarga = "Motor"; // Opciones: "Iluminacion", "Motor", "Tomas", "Informatica" double corrienteNominal = 18.5; // Amperios double longitudCable = 42.0; // Metros bool ambienteHumedo = false; double voltajeNominal = 230.0; // Voltios
// ======================================== // PASO 1: SELECCIONAR CURVA DE DISPARO // ========================================
string curvaDisparo; string justificacionCurva;
if (tipoCarga.Equals("Motor", StringComparison.OrdinalIgnoreCase)) { curvaDisparo = "Curva D"; justificacionCurva = "Motores tienen alta corriente de arranque (6-8x In)"; } else if (tipoCarga.Equals("Iluminacion", StringComparison.OrdinalIgnoreCase)) { curvaDisparo = "Curva B"; justificacionCurva = "Iluminación tiene bajo pico de arranque"; } else if (tipoCarga.Equals("Informatica", StringComparison.OrdinalIgnoreCase)) { curvaDisparo = "Curva C"; justificacionCurva = "Equipos informáticos tienen pico moderado"; } else { // Tomas y uso general curvaDisparo = "Curva C"; justificacionCurva = "Uso general y tomas de corriente"; }
// ======================================== // PASO 2: SELECCIONAR CORRIENTE NOMINAL // ========================================
int corrienteMagnetotermico;
if (corrienteNominal <= 10.0) { corrienteMagnetotermico = 10; } else if (corrienteNominal <= 16.0) { corrienteMagnetotermico = 16; } else if (corrienteNominal <= 20.0) { corrienteMagnetotermico = 20; } else if (corrienteNominal <= 25.0) { corrienteMagnetotermico = 25; } else if (corrienteNominal <= 32.0) { corrienteMagnetotermico = 32; } else if (corrienteNominal <= 40.0) { corrienteMagnetotermico = 40; } else { corrienteMagnetotermico = 63; }
double margenProteccion = ((corrienteMagnetotermico - corrienteNominal) / corrienteNominal) * 100;
// ======================================== // PASO 3: SELECCIONAR SECCIÓN DE CABLE // ========================================
double seccionCable; double corrienteAdmisible;
// Tabla simplificada de corrientes admisibles (instalación tipo B) if (corrienteMagnetotermico <= 10) { seccionCable = 1.5; corrienteAdmisible = 15.0; } else if (corrienteMagnetotermico <= 16) { seccionCable = 2.5; corrienteAdmisible = 21.0; } else if (corrienteMagnetotermico <= 20) { seccionCable = 4.0; corrienteAdmisible = 27.0; } else if (corrienteMagnetotermico <= 25) { seccionCable = 6.0; corrienteAdmisible = 36.0; } else if (corrienteMagnetotermico <= 32) { seccionCable = 10.0; corrienteAdmisible = 50.0; } else if (corrienteMagnetotermico <= 40) { seccionCable = 16.0; corrienteAdmisible = 68.0; } else { seccionCable = 25.0; corrienteAdmisible = 89.0; }
// Validar que el cable soporte la corriente del magnetotérmico bool cableSuficiente = (corrienteAdmisible >= corrienteMagnetotermico);
// ======================================== // PASO 4: SELECCIONAR TIPO DE CABLE // ========================================
string tipoCable; string descripcionCable;
if (ambienteHumedo) { tipoCable = "H07RN-F"; descripcionCable = "Cable flexible resistente a humedad y aceites"; } else { tipoCable = "H07V-K"; descripcionCable = "Cable flexible para instalación estándar"; }
// ======================================== // PASO 5: CALCULAR CAÍDA DE TENSIÓN // ========================================
double resistividadCobre = 0.018; // Ω·mm²/m double caidaTension = (2 * longitudCable * corrienteNominal * resistividadCobre) / seccionCable; double porcentajeCaida = (caidaTension / voltajeNominal) * 100;
bool caidaAceptable = (porcentajeCaida <= 3.0);
string advertenciaCaida = ""; if (!caidaAceptable) { advertenciaCaida = "\n¡ADVERTENCIA! Caída de tensión excede 3%"; // Sugerir sección superior double seccionSuperior = seccionCable; if (seccionCable == 1.5) seccionSuperior = 2.5; else if (seccionCable == 2.5) seccionSuperior = 4.0; else if (seccionCable == 4.0) seccionSuperior = 6.0; else if (seccionCable == 6.0) seccionSuperior = 10.0; else if (seccionCable == 10.0) seccionSuperior = 16.0; else if (seccionCable == 16.0) seccionSuperior = 25.0;
advertenciaCaida += string.Format("\nConsiderar sección {0}mm²", seccionSuperior); }
// ======================================== // PASO 6: SELECCIONAR DIFERENCIAL // ========================================
string tipoDiferencial; int sensibilidadDiferencial; // mA int corrienteDiferencial;
// Tipo de diferencial según carga if (tipoCarga.Equals("Motor", StringComparison.OrdinalIgnoreCase)) { tipoDiferencial = "Tipo A"; // Sensible a corriente alterna y continua pulsante } else if (tipoCarga.Equals("Informatica", StringComparison.OrdinalIgnoreCase)) { tipoDiferencial = "Tipo B"; // Sensible a corriente continua } else { tipoDiferencial = "Tipo AC"; // Sensible a corriente alterna (estándar) }
// Sensibilidad según ambiente if (ambienteHumedo) { sensibilidadDiferencial = 30; // Alta sensibilidad en ambiente húmedo } else { if (corrienteMagnetotermico > 32) { sensibilidadDiferencial = 300; // Menor sensibilidad para altas corrientes } else { sensibilidadDiferencial = 30; } }
// Corriente nominal del diferencial (debe ser >= magnetotérmico) if (corrienteMagnetotermico <= 25) { corrienteDiferencial = 25; } else if (corrienteMagnetotermico <= 40) { corrienteDiferencial = 40; } else { corrienteDiferencial = 63; }
// ======================================== // CONSTRUCCIÓN DEL REPORTE // ========================================
string reporte = string.Format( "=== SELECTOR AUTOMÁTICO DE PROTECCIONES ===\n\n" + "DATOS DEL CIRCUITO:\n" + "- Nombre: {0}\n" + "- Tipo de carga: {1}\n" + "- Corriente nominal: {2:F1} A\n" + "- Longitud: {3:F1} m\n" + "- Ambiente húmedo: {4}\n\n" + "PROTECCIÓN MAGNETOTÉRMICA:\n" + "- {5} - {6}A\n" + "- Justificación: {7}\n" + "- Margen: {8:F1}%\n\n" + "CABLE:\n" + "- Tipo: {9}\n" + "- Sección: {10}mm²\n" + "- Descripción: {11}\n" + "- Corriente admisible: {12:F1}A\n\n" + "PROTECCIÓN DIFERENCIAL:\n" + "- {13} - {14}mA - {15}A\n\n" + "CAÍDA DE TENSIÓN:\n" + "- Calculada: {16:F2}V ({17:F2}%)\n" + "- Estado: {18}{19}", nombreCircuito, tipoCarga, corrienteNominal, longitudCable, ambienteHumedo ? "Sí" : "No", curvaDisparo, corrienteMagnetotermico, justificacionCurva, margenProteccion, tipoCable, seccionCable, descripcionCable, corrienteAdmisible, tipoDiferencial, sensibilidadDiferencial, corrienteDiferencial, caidaTension, porcentajeCaida, caidaAceptable ? "Aceptable (< 3%)" : "Excesiva (> 3%)", advertenciaCaida );
// ======================================== // MOSTRAR REPORTE // ========================================
MessageBoxIcon icono = caidaAceptable ? MessageBoxIcon.Information : MessageBoxIcon.Warning;
MessageBox.Show(reporte, "Selector de Protecciones", MessageBoxButtons.OK, icono); }}Cómo probar el script:
- Guarda el código en:
X:\Scripts\v6.0\SelectorProtecciones.cs - Ejecuta en EPLAN
- Verás un reporte completo con todas las especificaciones
Ejercicios:
- Cambia
tipoCargaa “Iluminacion” y observa cómo cambian las protecciones - Prueba con
ambienteHumedo = truey verifica el tipo de cable - Aumenta
longitudCablea 80m y ve la advertencia de caída de tensión
🔍 Deep Dive: Entendiendo en profundidad
Sección titulada «🔍 Deep Dive: Entendiendo en profundidad»Alcance de variables en bloques if
Sección titulada «Alcance de variables en bloques if»Las variables declaradas dentro de un bloque if solo existen dentro de ese bloque:
if (corriente > 16.0){ string mensaje = "Corriente alta"; MessageBox.Show(mensaje); // OK}
MessageBox.Show(mensaje); // ERROR: 'mensaje' no existe aquíSolución: Declara la variable antes del if:
string mensaje;
if (corriente > 16.0){ mensaje = "Corriente alta";}else{ mensaje = "Corriente normal";}
MessageBox.Show(mensaje); // OKSwitch como alternativa a else if
Sección titulada «Switch como alternativa a else if»Para comparar una variable contra múltiples valores, switch puede ser más legible (lo veremos en el próximo capítulo):
// Con else ifif (tipoCarga == "Motor"){ curva = "D";}else if (tipoCarga == "Iluminacion"){ curva = "B";}else{ curva = "C";}
// Con switch (más limpio)switch (tipoCarga){ case "Motor": curva = "D"; break; case "Iluminacion": curva = "B"; break; default: curva = "C"; break;}Patrón Guard Clause
Sección titulada «Patrón Guard Clause»Para evitar anidación profunda, valida condiciones negativas primero y retorna/salta:
// Con anidación (difícil de leer)if (proyectoAbierto){ if (tienePermisos) { if (noHayErrores) { // Código principal } }}
// Con guard clauses (más claro)if (!proyectoAbierto){ MessageBox.Show("Proyecto no abierto"); return;}
if (!tienePermisos){ MessageBox.Show("Sin permisos"); return;}
if (hayErrores){ MessageBox.Show("Proyecto con errores"); return;}
// Código principal (sin anidación)Mejores prácticas
Sección titulada «Mejores prácticas»1. Condiciones positivas son más legibles
// Menos claroif (!(!esValido)){ // ...}
// Más claroif (esValido){ // ...}2. Extrae condiciones complejas a variables
// Difícil de entenderif ((v >= 207 && v <= 253) && (i <= 16) && ((2*l*i*0.018)/s <= 6.9)){ // ...}
// Clarobool voltajeOK = (voltaje >= 207 && voltaje <= 253);bool corrienteOK = (corriente <= 16);double caidaTension = (2 * longitud * corriente * 0.018) / seccion;bool caidaOK = (caidaTension <= 6.9);
if (voltajeOK && corrienteOK && caidaOK){ // ...}3. Usa constantes para valores mágicos
// Mal: ¿qué significan estos números?if (voltaje >= 207 && voltaje <= 253){ // ...}
// Bien: significado claroconst double VOLTAJE_MINIMO = 207.0; // 230V - 10%const double VOLTAJE_MAXIMO = 253.0; // 230V + 10%
if (voltaje >= VOLTAJE_MINIMO && voltaje <= VOLTAJE_MAXIMO){ // ...}Errores comunes
Sección titulada «Errores comunes»Error 1: Usar = en lugar de ==
Sección titulada «Error 1: Usar = en lugar de ==»int voltaje = 230;
if (voltaje = 400) // ERROR: asignación, no comparación{ // ...}Solución:
if (voltaje == 400) // Comparación correcta{ // ...}Error 2: Olvidar el break en switch
Sección titulada «Error 2: Olvidar el break en switch»Lo veremos en detalle en el próximo capítulo, pero es un error muy común.
Error 3: Comparar strings con == sin considerar mayúsculas
Sección titulada «Error 3: Comparar strings con == sin considerar mayúsculas»string tipo = "motor";
if (tipo == "Motor") // No coincide{ // No entra}Solución:
if (tipo.Equals("Motor", StringComparison.OrdinalIgnoreCase)){ // Ahora sí coincide}⚡ Desafíos (Opcional)
Sección titulada «⚡ Desafíos (Opcional)»Desafío 1: Clasificador de eficiencia energética
Sección titulada «Desafío 1: Clasificador de eficiencia energética»Dificultad: ⭐☆☆
Crea un script que clasifique motores según su eficiencia:
- IE4 (Super Premium): η ≥ 95%
- IE3 (Premium): 93% ≤ η < 95%
- IE2 (High Efficiency): 90% ≤ η < 93%
- IE1 (Standard): η < 90%
Muestra la clasificación y una recomendación.
Pista
Usa else if para cada rango de eficiencia, de mayor a menor.
Desafío 2: Selector de tipo de arranque para motores
Sección titulada «Desafío 2: Selector de tipo de arranque para motores»Dificultad: ⭐⭐☆
Crea un script que seleccione el tipo de arranque según:
- Potencia del motor (kW)
- Tipo de carga (liviana, media, pesada)
- Limitación de corriente de arranque (sí/no)
Opciones: Directo, Estrella-Triángulo, Arrancador suave, Variador de frecuencia
Pista
Usa if anidados: primero verifica la potencia, luego el tipo de carga, finalmente la limitación de corriente.
Desafío 3: Calculadora de compensación reactiva completa
Sección titulada «Desafío 3: Calculadora de compensación reactiva completa»Dificultad: ⭐⭐⭐
Crea un script que:
- Reciba: potencia activa, factor de potencia actual, voltaje
- Determine si necesita corrección (fp < 0.92)
- Si necesita: calcule el banco de capacitores (kVAr) para llegar a 0.95
- Seleccione el banco normalizado más cercano (5, 10, 15, 20, 25, 30, 40, 50 kVAr)
- Calcule el ahorro económico estimado (penalización evitada)
Pista
Usa if para verificar si necesita corrección, luego calcula el kVAr necesario, luego usa else if para seleccionar el banco normalizado.
📝 Resumen
Sección titulada «📝 Resumen»En este capítulo aprendiste:
- ✅ Estructura if: Ejecutar código solo si una condición es verdadera
- ✅ Estructura if/else: Ejecutar diferentes códigos según una condición
- ✅ Estructura else if: Evaluar múltiples condiciones en secuencia
- ✅ If anidados: Colocar estructuras if dentro de otras
- ✅ Operador ternario: Atajo para asignaciones condicionales simples
- ✅ Comparación de strings: Cómo comparar textos correctamente
- ✅ Proyecto construido: Selector automático de protecciones eléctricas completo
Conceptos clave:
- Las condiciones se evalúan en orden y solo se ejecuta el primer bloque que sea verdadero
- Usa else if para múltiples opciones mutuamente excluyentes
- Usa operadores lógicos (&&, ||) para combinar condiciones
- Siempre usa llaves aunque sea una sola línea
- Extrae condiciones complejas a variables con nombres descriptivos
🔗 Conexiones
Sección titulada «🔗 Conexiones»⬅️ Capítulo anterior
Sección titulada «⬅️ Capítulo anterior»Capítulo 4: Operaciones y expresiones
➡️ Próximo capítulo
Sección titulada «➡️ Próximo capítulo»Capítulo 6: Control de flujo - switch
En el próximo capítulo aprenderás la estructura switch, una alternativa más limpia a múltiples else if cuando comparas una variable contra muchos valores específicos. Construirás un configurador de componentes eléctricos con decenas de opciones.
📚 Recursos adicionales
Sección titulada «📚 Recursos adicionales»- 📖 Documentación de C# - if/else
- 💻 [Código completo]:
code/cap-05/
❓ Preguntas frecuentes
Sección titulada «❓ Preguntas frecuentes»P: ¿Cuándo usar else if y cuándo usar if separados?
Sección titulada «P: ¿Cuándo usar else if y cuándo usar if separados?»R: Usa else if cuando las opciones son mutuamente excluyentes (solo una puede ser verdadera). Usa if separados cuando las condiciones son independientes y pueden ser verdaderas simultáneamente.
P: ¿El operador ternario es más eficiente que if/else?
Sección titulada «P: ¿El operador ternario es más eficiente que if/else?»R: No hay diferencia significativa de rendimiento. Usa ternario para asignaciones simples y legibles, usa if/else para lógica más compleja.
P: ¿Puedo poner un if dentro de un else?
Sección titulada «P: ¿Puedo poner un if dentro de un else?»R: Sí, pero generalmente es más claro usar else if en su lugar.
P: ¿Cuántos niveles de anidación son aceptables?
Sección titulada «P: ¿Cuántos niveles de anidación son aceptables?»R: Como regla general, evita más de 2-3 niveles. Si necesitas más, considera refactorizar usando funciones o combinar condiciones con operadores lógicos.
P: ¿Importa el orden de las condiciones en else if?
Sección titulada «P: ¿Importa el orden de las condiciones en else if?»R: Sí, mucho. Se evalúan en orden y se ejecuta el primer bloque verdadero. Pon las condiciones más específicas primero.
📋 Checklist de completitud
Sección titulada «📋 Checklist de completitud»Antes de pasar al siguiente capítulo, asegúrate de:
- Entender cómo funciona la estructura if básica
- Poder usar if/else para dos opciones
- Saber encadenar múltiples opciones con else if
- Comprender cuándo usar if anidados vs operadores lógicos
- Saber usar el operador ternario para asignaciones simples
- Poder comparar strings correctamente (sensible e insensible a mayúsculas)
- Haber ejecutado exitosamente el selector de protecciones
- Poder modificar los parámetros y ver cómo cambian las selecciones
- (Opcional) Haber intentado al menos un desafío
¿Listo para aprender la estructura switch? Vamos al Capítulo 6! 🚀
Última actualización: Enero 2025
Tiempo de lectura estimado: 45-55 minutos
Código de ejemplo: code/cap-05/
📂 Código del Capítulo
Sección titulada «📂 Código del Capítulo»Todos los scripts de este capítulo están disponibles en GitHub:
Los scripts son 100% funcionales y usan únicamente APIs gratuitas de EPLAN.
🔓 Desbloquea el Contenido Completo
¿Te gustó este capítulo? Hay 25 capítulos más esperándote con:
- ✅ Scripts profesionales completos
- ✅ Casos de estudio reales
- ✅ Suite de automatización integrada
- ✅ Ahorra 80-95% de tiempo en tareas repetitivas