310 lines
11 KiB
Markdown
310 lines
11 KiB
Markdown
# LibS7Adv - Librería de Comunicación PLC con Soporte Dual
|
|
|
|
Esta librería proporciona c### Ejemplo de Uso Futuro (Con Tabla de Mapeo)
|
|
```csharp
|
|
// Una vez implementada la tabla de mapeo:
|
|
bool motorRunning = plc.LeerBool("MotorRunning"); // → "DB1.DBX0.0"
|
|
plc.EscribirBool("OutputAlarm", true); // → "Q0.1"
|
|
string temperature = plc.LeerNumber("Temperature"); // → "DB1.DBW2"
|
|
|
|
// Combinado con normalización automática:
|
|
bool sensor = plc.LeerBool("SensorInput"); // → "E0.0" → "I0.0"
|
|
plc.EscribirBool("MotorOutput", true); // → "A0.1" → "Q0.1"
|
|
```ción con PLCs Siemens usando dos drivers diferentes:
|
|
- **AdvCoSimulator**: API oficial de Siemens (Siemens.Simatic.Simulation.Runtime.Api.x64.dll)
|
|
- **Sharp7**: Librería C# administrada para comunicación S7 (sin dependencias DLL nativas)
|
|
|
|
## Características
|
|
|
|
### Funcionalidades Comunes (Ambos Drivers)
|
|
- Lectura/escritura de booleanos por dirección directa (ej: %M0.0, %DB1.DBX0.0)
|
|
- Lectura/escritura de números (Byte, Word, DWord)
|
|
- Acceso directo a áreas de memoria (Input, Output, Marker, DataBlocks)
|
|
- Interfaz unificada independiente del driver
|
|
- **NUEVO**: Mapeo automático de tags a direcciones absolutas
|
|
|
|
### Funcionalidades Exclusivas de AdvCoSimulator
|
|
- Lectura/escritura usando nombres simbólicos de tags
|
|
- Métodos específicos para tags: `LeerTag()`, `EscribirTag()`, `LeerTagBool()`, etc.
|
|
- Sincronización automática con cambios de configuración del PLC
|
|
|
|
### Funcionalidades de Sharp7
|
|
- **Comunicación directa con PLCs reales**: No requiere simulador
|
|
- **Solo acceso directo**: Direcciones absolutas (ej: DB1.DBX0.0, M0.0, Q0.1)
|
|
- **Sin dependencias DLL nativas**: Librería C# completamente administrada
|
|
- **Mapeo automático**: Todos los métodos usan MapTagToAddress() internamente
|
|
|
|
## ⚡ Nueva Funcionalidad: Mapeo de Tags a Direcciones Absolutas
|
|
|
|
Todas las funciones de la biblioteca ahora utilizan un sistema de mapeo interno que:
|
|
|
|
1. **Actualmente**: Normaliza diferentes notaciones de direcciones PLC y las convierte al formato Sharp7
|
|
2. **Futuro**: Permitirá mapear tags simbólicos a direcciones absolutas mediante una tabla
|
|
|
|
### 🔄 **Sistema de Normalización de Direcciones**
|
|
|
|
La biblioteca ahora soporta **múltiples notaciones** de direcciones PLC y las normaliza automáticamente:
|
|
|
|
#### **Notaciones Soportadas:**
|
|
- **🇩🇪 Alemán**: E (Eingang/Input), A (Ausgang/Output)
|
|
- **🇺🇸 Americano**: I (Input), O (Output)
|
|
- **📍 Con/Sin P**: PEW/EW, PIW/IW, PAW/AW, POW/QW
|
|
|
|
#### **Ejemplos de Normalización Automática:**
|
|
```csharp
|
|
// Todas estas direcciones se normalizan automáticamente:
|
|
|
|
// INPUTS (todas → formato americano IW/IB/ID/I0.0)
|
|
"PEW0" → "IW0" // Alemán con P
|
|
"EW0" → "IW0" // Alemán sin P
|
|
"PIW0" → "IW0" // Americano con P
|
|
"IW0" → "IW0" // Ya correcto
|
|
|
|
"PE0.0" → "I0.0" // Bits alemán con P
|
|
"E0.0" → "I0.0" // Bits alemán sin P
|
|
"PI0.0" → "I0.0" // Bits americano con P
|
|
|
|
// OUTPUTS (todas → formato americano QW/QB/QD/Q0.0)
|
|
"PAW0" → "QW0" // Alemán con P
|
|
"AW0" → "QW0" // Alemán sin P
|
|
"POW0" → "QW0" // Americano con P
|
|
"QW0" → "QW0" // Ya correcto
|
|
|
|
"PA0.0" → "Q0.0" // Bits alemán con P
|
|
"A0.0" → "Q0.0" // Bits alemán sin P
|
|
"PO0.0" → "Q0.0" // Bits americano con P
|
|
```
|
|
|
|
### Ejemplo de Uso Actual
|
|
```csharp
|
|
// ¡Ahora puedes usar cualquier notación!
|
|
// Todas funcionan con ambos drivers (Sharp7 y AdvCoSimulator)
|
|
|
|
// Notación alemana
|
|
bool sensor = plc.LeerBool("E0.0"); // → I0.0
|
|
string temp = plc.LeerNumber("EW2"); // → IW2
|
|
plc.EscribirBool("A0.1", true); // → Q0.1
|
|
plc.EscribirNumber("AW4", 1234); // → QW4
|
|
|
|
// Notación alemana con P
|
|
bool motor = plc.LeerBool("PE0.2"); // → I0.2
|
|
int speed = plc.LeerTagInt16("PEW6"); // → IW6
|
|
plc.EscribirTagBool("PA0.3", false); // → Q0.3
|
|
plc.EscribirTagInt16("PAW8", 5678); // → QW8
|
|
|
|
// Notación americana (ya compatible)
|
|
bool status = plc.LeerBool("I0.0"); // Sin cambios
|
|
plc.EscribirBool("Q0.1", true); // Sin cambios
|
|
```
|
|
|
|
### Ejemplo de Uso Futuro (Con Tabla de Mapeo)
|
|
```csharp
|
|
// Una vez implementada la tabla de mapeo:
|
|
bool motorRunning = plc.LeerBool("MotorRunning"); // -> "DB1.DBX0.0"
|
|
plc.EscribirBool("OutputAlarm", true); // -> "Q0.1"
|
|
string temperature = plc.LeerNumber("Temperature"); // -> "DB1.DBW2"
|
|
```
|
|
|
|
## Configuración
|
|
|
|
### 1. Selección del Driver
|
|
En el control, use el PropertyGrid para configurar:
|
|
- **ConnectionType**: Seleccionar entre `AdvCoSimulator` o `Sharp7`
|
|
- **IP**: Dirección IP del PLC
|
|
- **Name**: Nombre de la instancia (para AdvCoSimulator) o nombre descriptivo (para Sharp7)
|
|
|
|
### 2. Instalación de Dependencias
|
|
|
|
#### Para AdvCoSimulator:
|
|
- Instalar PLCSim Advanced
|
|
- Verificar la ruta de la DLL en el proyecto: `C:\Program Files (x86)\Common Files\Siemens\PLCSIMADV\API\6.0\`
|
|
|
|
#### Para Sharp7:
|
|
- ✅ **Sin dependencias externas**: Es una librería C# completamente administrada
|
|
- ✅ **Sin archivos DLL adicionales requeridos**
|
|
|
|
## Uso de la API
|
|
|
|
### Métodos Principales
|
|
|
|
```csharp
|
|
// Conexión
|
|
void Connect()
|
|
void Disconnect()
|
|
|
|
// Lectura/Escritura por Dirección Directa (Ambos drivers) - CON MAPEO AUTOMÁTICO
|
|
bool? LeerBool(string tag) // ej: "M0.0", "DB1.DBX0.0"
|
|
bool? EscribirBool(string tag, bool valor)
|
|
string LeerNumber(string tag, bool signed = false) // ej: "MW0", "DB1.DBW0"
|
|
bool EscribirNumber(string tag, object valor) // NUEVO: Escritura de números
|
|
|
|
// Acceso por Byte/Bit (Ambos drivers)
|
|
bool LeerSalidaBool(byte pByte, int pBit)
|
|
void EscribirInputBool(byte pByte, int pBit, bool valor)
|
|
|
|
// Métodos de Tag (Solo AdvCoSimulator) - CON MAPEO AUTOMÁTICO
|
|
SDataValue LeerTag(string tag)
|
|
void EscribirTag(string tag, SDataValue valor)
|
|
bool LeerTagBool(string tag)
|
|
void EscribirTagBool(string tag, bool valor)
|
|
int? LeerTagInt16(string tag)
|
|
void EscribirTagInt16(string tag, int valor)
|
|
int? LeerTagDInt(string tag)
|
|
void EscribirTagDInt(string tag, int valor)
|
|
```
|
|
|
|
### Formatos de Dirección Válidos
|
|
|
|
#### Para Sharp7 (Direcciones Absolutas + Normalización):
|
|
```csharp
|
|
// Bits (BOOL) - Soporta múltiples notaciones
|
|
"I0.0", "I0.1", "I0.7" // Entradas (formato destino)
|
|
"E0.0", "PE0.0", "PI0.0" // → Normalizadas a I0.0
|
|
"Q0.0", "Q0.1", "Q0.7" // Salidas (formato destino)
|
|
"A0.0", "PA0.0", "PO0.0" // → Normalizadas a Q0.0
|
|
"M0.0", "M0.1", "M0.7" // Marcas (sin cambios)
|
|
"DB1.DBX0.0", "DB1.DBX0.1" // Data Block bits (sin cambios)
|
|
|
|
// Números (WORD, DWORD) - Soporta múltiples notaciones
|
|
"IW0", "IW2", "IW4" // Input Words (formato destino)
|
|
"EW0", "PEW0", "PIW0" // → Normalizadas a IW0
|
|
"QW0", "QW2", "QW4" // Output Words (formato destino)
|
|
"AW0", "PAW0", "POW0" // → Normalizadas a QW0
|
|
"MW0", "MW2", "MW4" // Memory Words (sin cambios)
|
|
"DB1.DBW0", "DB1.DBW2" // Data Block Words (sin cambios)
|
|
"DB1.DBD0", "DB1.DBD4" // Data Block DWords (sin cambios)
|
|
|
|
// Ejemplos de bytes y dwords también normalizados:
|
|
"IB0", "EB0", "PEB0", "PIB0" // → IB0
|
|
"ID0", "ED0", "PED0", "PID0" // → ID0
|
|
"QB0", "AB0", "PAB0", "POB0" // → QB0
|
|
"QD0", "AD0", "PAD0", "POD0" // → QD0
|
|
```
|
|
|
|
#### Para AdvCoSimulator:
|
|
```csharp
|
|
// Puede usar tanto direcciones absolutas como tags simbólicos
|
|
// Las direcciones se normalizan automáticamente y luego se pasan al driver
|
|
// Los tags se mapean automáticamente a través de MapTagToAddress()
|
|
|
|
// Ejemplos con normalización:
|
|
"E0.0" → "I0.0" // Alemán → Americano
|
|
"PEW2" → "IW2" // Alemán con P → Americano
|
|
"AW4" → "QW4" // Alemán → Americano
|
|
```
|
|
|
|
### Ejemplos de Uso
|
|
|
|
#### Ejemplo básico (Ambos drivers con normalización)
|
|
```csharp
|
|
var plc = new PLCViewModel();
|
|
|
|
// Configurar para Sharp7
|
|
plc.PlcData.ConnectionType = ConnectionType.Sharp7;
|
|
plc.PlcData.IP = "192.168.1.100";
|
|
plc.Connect();
|
|
|
|
if (plc.IsConnected)
|
|
{
|
|
// ¡Ahora puedes usar cualquier notación de direcciones!
|
|
|
|
// Notación alemana (se normaliza automáticamente)
|
|
bool sensor = plc.LeerBool("E0.0"); // → "I0.0"
|
|
plc.EscribirBool("A0.1", true); // → "Q0.1"
|
|
|
|
// Notación alemana con P
|
|
string temp = plc.LeerNumber("PEW2"); // → "IW2"
|
|
plc.EscribirNumber("PAW4", 1234); // → "QW4"
|
|
|
|
// Notación americana (sin cambios)
|
|
bool status = plc.LeerBool("I0.2"); // Sin cambios
|
|
plc.EscribirNumber("QW6", 5678); // Sin cambios
|
|
|
|
// Data Blocks (sin cambios)
|
|
bool dbBit = plc.LeerBool("DB1.DBX0.0"); // Sin cambios
|
|
plc.EscribirNumber("DB1.DBW2", 9999); // Sin cambios
|
|
|
|
// ¡Funciones Tag también usan normalización!
|
|
int value = plc.LeerTagInt16("EW8") ?? 0; // → "IW8"
|
|
plc.EscribirTagInt16("AW10", 4321); // → "QW10"
|
|
}
|
|
|
|
plc.Disconnect();
|
|
```
|
|
|
|
#### Ejemplo con tabla de mapeo (Implementación futura)
|
|
```csharp
|
|
// Una vez implementada la tabla de mapeo en MapTagToAddress():
|
|
bool motorStatus = plc.LeerBool("MotorRunning"); // -> "DB1.DBX0.0"
|
|
plc.EscribirBool("AlarmOutput", true); // -> "Q0.1"
|
|
string temp = plc.LeerNumber("TemperatureSensor"); // -> "DB1.DBW2"
|
|
plc.EscribirNumber("SetPoint", 1234); // -> "DB1.DBW4"
|
|
```
|
|
"%M0.0" // Bit 0 del byte 0 de Markers
|
|
"%MB5" // Byte 5 de Markers
|
|
"%MW10" // Word en offset 10 de Markers
|
|
|
|
// Inputs
|
|
"%E0.0" // Bit 0 del byte 0 de Inputs
|
|
"%EB2" // Byte 2 de Inputs
|
|
"%EW4" // Word en offset 4 de Inputs
|
|
|
|
// Outputs
|
|
"%A0.0" // Bit 0 del byte 0 de Outputs
|
|
"%AB1" // Byte 1 de Outputs
|
|
"%AW6" // Word en offset 6 de Outputs
|
|
|
|
// Data Blocks
|
|
"%DB1.DBX0.0" // Bit 0 del byte 0 del DB1
|
|
"%DB1.DBB2" // Byte 2 del DB1
|
|
"%DB1.DBW4" // Word en offset 4 del DB1
|
|
"%DB1.DBD8" // DWord en offset 8 del DB1
|
|
```
|
|
|
|
## Ejemplo de Uso
|
|
|
|
```csharp
|
|
// Crear instancia del control
|
|
var plcControl = new PLCControl();
|
|
var viewModel = plcControl.DataContext as PLCViewModel;
|
|
|
|
// Configurar para usar Snap7
|
|
viewModel.PlcData.ConnectionType = ConnectionType.Sharp7;
|
|
viewModel.PlcData.IP = "192.168.1.100";
|
|
|
|
// Conectar
|
|
viewModel.Connect();
|
|
|
|
// Leer/Escribir datos (funciona con ambos drivers)
|
|
bool valor = viewModel.LeerBool("%M0.0") ?? false;
|
|
viewModel.EscribirBool("%M0.1", true);
|
|
string numero = viewModel.LeerNumber("%MW10");
|
|
|
|
// Usar tags (solo con AdvCoSimulator)
|
|
if (viewModel.PlcData.ConnectionType == ConnectionType.AdvCoSimulator)
|
|
{
|
|
bool tagValue = viewModel.LeerTagBool("MiTag");
|
|
viewModel.EscribirTagBool("MiTag", true);
|
|
}
|
|
```
|
|
|
|
## Manejo de Errores
|
|
|
|
- Los errores se reportan en `PlcData.LastError`
|
|
- Para Snap7: Mensajes específicos de errores de comunicación TCP/IP y S7
|
|
- Para AdvCoSimulator: Manejo automático de estados "NotUpToDate" con reintentos
|
|
|
|
## Migración y Compatibilidad
|
|
|
|
El API hacia afuera permanece igual, facilitando la migración entre drivers:
|
|
1. Cambiar `ConnectionType` en la configuración
|
|
2. Para código que usa Tags: Verificar el tipo de conexión antes de llamar métodos de Tag
|
|
3. Usar direcciones directas para máxima compatibilidad entre drivers
|
|
|
|
## Notas Técnicas
|
|
|
|
- Snap7 usa comunicación TCP/IP directa al PLC (puerto 102)
|
|
- AdvCoSimulator requiere PLCSim Advanced en ejecución
|
|
- Los enums `EArea` y `EDataType` son compartidos entre ambos drivers
|
|
- La clase `TagAddress` parseará direcciones en formato Siemens estándar
|