Ir al contenido

Capítulo 5: Control de flujo - If/Else

Parte I - Sección 2: Lógica de programación - Nivel: Principiante


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

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

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


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.


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:

  1. Se evalúa la condición voltaje > 253.0
  2. Si es true, se ejecuta el bloque entre { }
  3. Si es false, se salta el bloque y continúa después
if (condicion)
↑ ↑
| └─ Expresión booleana (true/false)
└────────── Palabra clave
{
// Bloque de código
// Puede tener múltiples líneas
}

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).");
}

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");
}

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.");
}
┌─────────────┐
│ if (cond) │
└──────┬──────┘
┌──────┴──────┐
│ │
true false
│ │
┌───▼───┐ ┌───▼───┐
│ if {} │ │else {} │
└───┬───┘ └───┬───┘
│ │
└──────┬──────┘
continúa

Solo uno de los dos bloques se ejecuta, nunca ambos.

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);
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);
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) → FIN

Solo uno de los bloques se ejecuta.


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: Voltaje
if (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");
}
}

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 directo
if (condicion1 && condicion2 && condicion3 && condicion4)
{
// Claramente se necesitan las 4 condiciones
}

O divide en funciones (lo veremos en capítulos futuros).


Para asignaciones condicionales simples, existe un atajo:

variable = condicion ? valorSiTrue : valorSiFalse;

Es equivalente a:

if (condicion)
{
variable = valorSiTrue;
}
else
{
variable = valorSiFalse;
}

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²";
}

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

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í
}
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
}
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 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);

¿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 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);
}

¿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 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;
}

¿Qué acabamos de hacer? Seleccionamos el tipo de diferencial según la carga, la sensibilidad según el ambiente, y la corriente nominal.


// ========================================
// 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 ? "" : "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);

//
// 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 ? "" : "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:

  1. Guarda el código en: X:\Scripts\v6.0\SelectorProtecciones.cs
  2. Ejecuta en EPLAN
  3. Verás un reporte completo con todas las especificaciones

Ejercicios:

  • Cambia tipoCarga a “Iluminacion” y observa cómo cambian las protecciones
  • Prueba con ambienteHumedo = true y verifica el tipo de cable
  • Aumenta longitudCable a 80m y ve la advertencia de caída de tensión

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); // OK

Para comparar una variable contra múltiples valores, switch puede ser más legible (lo veremos en el próximo capítulo):

// Con else if
if (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;
}

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)

1. Condiciones positivas son más legibles

// Menos claro
if (!(!esValido))
{
// ...
}
// Más claro
if (esValido)
{
// ...
}

2. Extrae condiciones complejas a variables

// Difícil de entender
if ((v >= 207 && v <= 253) && (i <= 16) && ((2*l*i*0.018)/s <= 6.9))
{
// ...
}
// Claro
bool 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 claro
const double VOLTAJE_MINIMO = 207.0; // 230V - 10%
const double VOLTAJE_MAXIMO = 253.0; // 230V + 10%
if (voltaje >= VOLTAJE_MINIMO && voltaje <= VOLTAJE_MAXIMO)
{
// ...
}
int voltaje = 230;
if (voltaje = 400) // ERROR: asignación, no comparación
{
// ...
}

Solución:

if (voltaje == 400) // Comparación correcta
{
// ...
}

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í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:

  1. Reciba: potencia activa, factor de potencia actual, voltaje
  2. Determine si necesita corrección (fp < 0.92)
  3. Si necesita: calcule el banco de capacitores (kVAr) para llegar a 0.95
  4. Seleccione el banco normalizado más cercano (5, 10, 15, 20, 25, 30, 40, 50 kVAr)
  5. 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.


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

Capítulo 4: Operaciones y expresiones

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.



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.

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.


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/

Todos los scripts de este capítulo están disponibles en GitHub:

📥 Ver código 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