Capítulo 5: Control de flujo - if/else
Capítulo 5: Control de flujo - if/else
Sección titulada «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»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); }}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: Bajo
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: Medio
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: Alta
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.
Recursos adicionales
Sección titulada «Recursos adicionales»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
Última actualización: Enero 2025
Tiempo de lectura estimado: 45-55 minutos
Código de ejemplo: code/cap-05/