2012-03-14 31 views
6

Provo a inviare comandi FINS tramite UDP da PC (C# .NET) a modulo Ethernet PLC (Omron), ma non riceve risposta dal PLC e non ho idea di dove trovo può iniziare la risoluzione dei problemi.Invia comando FINS da C# a PLC

PLC ha una logica molto semplice ladder come segue: Se DM100 ha valore di #0001, poi innescare sull'uscita 101.00. (Qui, "Trigger" è solo un nome simbolo per area di memoria D100, e "Output" è un simbolo per l'uscita 101.00) enter image description here

Poi ho scritto un pezzo di C# che esegue il comando FINS di "Memory Area Scrivi" che ha il codice di comando 01 02, seguito da indirizzo iniziale, numero di elementi da scrivere e dati. Il codice C# deve scrivere un valore di # 0001 nell'area PLC D100 per attivare ON su 101.00.

[codice cancellato che non funziona] ..

L'uscita 101.00 non ha ottenuto attivato, né io ricevuto alcuna eccezione. Mi sono assicurato il seguente:

  1. Port, nodo e l'indirizzo configurato correttamente come confermato da "Work in linea" in CX-Programmer. Ho anche pingare ogni IP per assicurarmi che i nodi siano connessi.
  2. Il codice UdpClient è valido poiché ho scritto un codice server/client molto semplice che invia e riceve correttamente i pacchetti.
  3. La logica ladder non ha alcun problema. Ho trasferito la ladder su PLC e testato da Work Online in modalità Monitor e impostando manualmente il valore D100.

Sospetto che ci sia un errore nell'array fins_cmnd, ma come visto nel mio codice, ho commentato il più possibile i dettagli su ciascun valore; Non posso assolutamente trovarmi a mancare qualcosa. Sospetto che non stia analizzando correttamente l'esadecimale, ma ancora una volta, non ho eccezioni per guidarmi.

Non ho idea di dove e come posso risolvere. Spero che qualcuno qui con programmazione FINS o esperienza PLC possa offrirmi un aiuto.

[risposta]
Grazie Porge per il collegamento - che mi ha scoperto il problema. Dopo un paio di scie finalmente lo si fa funzionare. Vedi sotto per il codice funzionante.

string SERV_IP_ADDR = "192.168.250.1"; 
const int FINS_UDP_PORT = 9600; 

byte[] sendPacket = new byte[] 
{ 
    // Full UDP packet: 80 00 02 00 00 00 00 05 00 19 01 02 82 00 64 00 00 01 00 01 

    // Header 
    0x80, //0.(ICF) Display frame information: 1000 0001 
    0x00, //1.(RSV) Reserved by system: (hex)00 
    0x02, //2.(GCT) Permissible number of gateways: (hex)02 
    0x00, //3.(DNA) Destination network address: (hex)00, local network 
    0x00, //4.(DA1) Destination node address: (hex)00, local PLC unit 
    0x00, //5.(DA2) Destination unit address: (hex)00, PLC 
    0x00, //6.(SNA) Source network address: (hex)00, local network 
    0x05, //7.(SA1) Source node address: (hex)05, PC's IP is 192.168.250.5 
    0x00, //8.(SA2) Source unit address: (hex)00, PC only has one ethernet 
    0x19, //9.(SID) Service ID: just give a random number 19 

    // Command 
    0x01, //10.(MRC) Main request code: 01, memory area write 
    0x02, //11.(SRC) Sub-request code: 02, memory area write 

    // PLC Memory Area 
    0x82, //12.Memory area code (1 byte): 82(DM) 

    // Address information 
    0x00, //13.Write start address (2 bytes): D100 
    0x64, 
    0x00, //15.Bit address (1 byte): Default 0 
    0x00, //16.No. of items (2 bytes): only one address which is D100 
    0x01, 

    // Write Data 
    0x00, //18.Data to write (2 bytes): value is 1 
    0x01, 
}; 

UdpClient client = new UdpClient(); //create a UdpClient instance 

try 
{ 
    client.Send(sendPacket, sendPacket.Length, SERV_IP_ADDR, FINS_UDP_PORT); 
} 
catch (SocketException se) 
{ 
    Console.WriteLine(se.ErrorCode + ": " + se.Message); 
} 

client.Close(); 

risposta

6

Nessuna di queste stringhe verrà analizzata come esadecimale. NumberStyles.AllowHexSpecifierconsente il prefisso esadecimale "0x" ma non analizza il numero come esadecimale a meno che non sia presente.

Quindi vuoi (char)Int16.Parse("0x64", NumberStyles.AllowHexSpecifier).

Tuttavia, i valori letterali numerici in C# possono essere esadecimali, quindi invece di fare tutto ciò che si può semplicemente scrivere 0x64.

Ho appena esaminato il protocollo this page as a reference e sarebbe anche preferibile creare il messaggio direttamente come byte anziché specificare i punti di codice Unicode e decodificarli in byte come ASCII. È inoltre possibile utilizzare la sintassi specifica array per rimuovere un sacco di confusione:

var message = new byte[] 
{ 
    // header 
    0x80, //(ICF) Display frame information: 1000 0001 
    0x00, //(RSV) Reserved by system: (hex)00 
    0x02, //(GCT) Permissible number of gateways: (hex)02 
    0x00, //(DNA) Destination network address: (hex)00, local network 
    0x00, //(DA1) Destination node address: (hex)00, local PLC unit 
    0x00, //(DA2) Destination unit address: (hex)00, PLC 
    0x00, //(SNA) Source network address: (hex)00, local network 
    0x05, //(SA1) Source node address: (hex)05, PC's IP is 192.168.250.5 
    0x00, //(SA2) Source unit address: (hex)00, PC only has one ethernet 
    0x19, //(SID) Service ID: just give a random number 19 

    // command 
    0x01, //(MRC) Main request code: 01, memory area write 
    0x02, //(SRC) Sub-request code: 02, memory area write 

    // data 
    0x82, //Memory area code, 2 bytes: 82(DM) 
    0x00, //Write start address DM100 
    0x64, 
    0x00, 
    0x00, //Word write: only one address 
    0x01, 
    0x00, //Write value of 1 to address DM100 (0000 0000 0000 0001) 
    0x01, // - this value is 0xaabbccdd -> cc dd aa bb 
    0x00, 
    0x00, 
}; 

Sembra anche che ci sono alcuni problemi con la vostra sezione di dati - secondo il documento collegato l'indirizzo di memoria dovrebbe essere di 4 byte, la scrittura lunghezza 2 byte e i valori 4 byte ciascuno. Questi non corrispondono a quello che hai, quindi ho ampliato quella sezione.

+0

La memoria è, sì, 4 byte, quindi ho due elementi di matrice uno 0x00 e 0x64 insieme a 4 byte. perché ogni "sezione" richiede solo 16 bit. – KMC

+0

@ KMC: ho ampliato la parte "dati" in base a ciò che penso debba rappresentare dalla pagina indicata. Aiuta? – porges