c# Modbus TCP-IP Bağlantısı

osmancns

Üye
Katılım
11 Ara 2012
Mesajlar
35
Puanları
1
Yaş
31
merhaba arkadaşlar delta plc ile c# üzerinden modbus tcp ip protokolü ile haberleşmek istiyorum. plc ye ip bağlantısı ile bağlanıyorum ancak gönderdiğim paketi PLC de işlenmiyor yardımcı olabilecek arkadaşlar varmı ?

c# kodum :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;


using System.Net.Sockets;


namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{




Socket sck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);


IPEndPoint yerel = new IPEndPoint(IPAddress.Parse("192.168.1.5"), 502);




try
{


sck.Connect(yerel);
NetworkStream agAkisi = new NetworkStream(sck);
BinaryReader binaryOkuyucu = new BinaryReader(agAkisi);
BinaryWriter binaryYazici = new BinaryWriter(agAkisi);


Console.WriteLine("Sunucuya bağlandı");


Console.Write("Mesaj Yaz");

// BURADA YAZIĞIM PAKET : 00000000000601050500FF00

// Y0 ÇIKIŞINI AKTİF EDİYORUM (0500)


string mesaj = Console.ReadLine();


byte[] mesaji_ascii_yap = Encoding.ASCII.GetBytes(mesaj);


sck.Send(mesaji_ascii_yap);


Console.WriteLine("Mesaj İletildi");
string alinanMetin = binaryOkuyucu.ReadString();
Console.WriteLine(alinanMetin);


Console.Read();


sck.Close();






}


catch
{


Console.WriteLine("Bağlanamadı");


Main(args);


}





}
}
}
 
KNX Standardı, küçük bir rezidansın içerisindeki aydınlatma, perde panjur, klima kontrolünden, Dünya’nın en büyük havalimanlarındaki aydınlatma otomasyonu gibi çözümler için tercih edilen bir Dünya standardıdır.
Yazımızda endüstrinin can damarı sayılabilecek PLC’yi inceleyeceğiz.
// BURADA YAZIĞIM PAKET : 00000000000601050500FF00
böyle bir paket olmaz !
nerde lrc check kodunuz? istasyon adresiniz? durum kodunuz?
Ben bile anlamadıım ne yapmaya çalışıyorsunuz? Maksadınız ne?
Delta markalar yanlış haberleşmede yanıt vermez.
Programdan önce plc ye bak bakalım nece konuşuyor?
PDF'sini okumadan anlamadan bir şey yapmanız çok zor...
http://www.google.com/url?sa=t&rct=...=KJgEH8R5YYi_-qinWkdL1Q&bvm=bv.55980276,d.Yms
 
// BURADA YAZIĞIM PAKET : 00000000000601050500FF00
böyle bir paket olmaz !
nerde lrc check kodunuz? istasyon adresiniz? durum kodunuz?
Ben bile anlamadıım ne yapmaya çalışıyorsunuz? Maksadınız ne?
Delta markalar yanlış haberleşmede yanıt vermez.
Programdan önce plc ye bak bakalım nece konuşuyor?
PDF'sini okumadan anlamadan bir şey yapmanız çok zor...
http://www.google.com/url?sa=t&rct=...=KJgEH8R5YYi_-qinWkdL1Q&bvm=bv.55980276,d.Yms

lrc ( chechsum ) zaten modbus ascii modunda olur tcp/ip modunda olmaz..

YAZDIĞIM PAKET :

00 00 --> TRANSACTİON ID
00 00--> PROTOCOL ID
06 ---> LENGTH (BYTE)
01 ---> SLAVE ADRESS ( İSTASYON ADRESİ )
05 ---> FUNCTİON CODE ( FOR WRİTE SİNGLE COİL )
05 00 ---> Y0 HEX ADRES
FF 00 ---> COİL TURN ON

Bunların ne olduğunu araştırdım zaten . doğrusunu siz yazabilirmisiniz ozaman ????
 
// BURADA YAZIĞIM PAKET : 00000000000601050500FF00
böyle bir paket olmaz !
nerde lrc check kodunuz? istasyon adresiniz? durum kodunuz?
Ben bile anlamadıım ne yapmaya çalışıyorsunuz? Maksadınız ne?
Delta markalar yanlış haberleşmede yanıt vermez.
Programdan önce plc ye bak bakalım nece konuşuyor?
PDF'sini okumadan anlamadan bir şey yapmanız çok zor...
http://www.google.com/url?sa=t&rct=...=KJgEH8R5YYi_-qinWkdL1Q&bvm=bv.55980276,d.Yms

bu pdf zaten modbus ascii modunu anlatıyor
 
www.digan.net/Delta.rar

Kodlarınızda hata olmasa zaten plc size yanıt verir.
Bu hatanız programda değil gönderdiğiniz sinyal ile alakalıdır.
TCP IP (zaten rs232) siz isterseniz uydudan bağlanın o yine iç haberleşmesini kullanacaktır.
modbus veya ne kullanıyorsanız her bir ayrı protokol için ayrı bir arayüz donanımı yapmış olamazlar yapsalar bile o fiyata mal edemezler.
Software Layer hep aynıdır bu firmadan firmaya değişmez. Siz bir asci modunda sinyal gönderin-alın (Station adı tanımlıyorsunuz tool portdan bağlansanız bile) o size olası hataları söyleyecektir.
Haberleşmeler hep aynıdır. Farklılıklar sadece clock ve data lengthir.
Header kaç micro saniyede tamamlanacak veri uzunluğu kaç bit olacak gibi.
Tüm haberleşmeler UART desek yalan söylemiş olmayız.
Edit:Kendi loopback inize kanca atın orada bakın sinyal geliyormu gelmiyormu ?
Bu yazdığınızla kendi kendinize chat yapıyorsanız o zaman daha rahat sorunu çözersiniz.
 
Moderatör tarafında düzenlendi:
anladım teşekkür ederim ama bir tane dahi örnek yok. yani c# ile örnek olarak şu pakedi string olarak göndericeksin diye bir bilgi hiç bir yerde bulamadım .

ascii modunda haberleşmeyi gerçekleştirdim istediğim veriyi yazıyorum. ama bu ethernet kablosuyla haberleşmede tıkandım
 
Moderatör tarafında düzenlendi:
Şöyle anlatayım
TCP veya her ne haltsa : İlk önce bir soket oluşturacaksın (Hedef ile kaynak arasındaki bağlantı) daha sonra ilk önce arabirimin anlayacağı bir sinyal oluşturman gerekiyor. (Plc nin haberleşmesini sağlayan parçaya) Daha sonra bu pakete ilave olarak PLC nin anlayacağı bir kod ilave edeceksiniz. TCP baklantılarda soket zorunludur aksi takdirde dünyadaki tüm aygıtlara sinyal göndermiş olursunuz. Yazdığınız program internet üzerinden bir sayfayı çeviriyorsa plc nizede ulaşır.
Örnek desen verecek olursak: http://192.168.1.5:1020/:0000124500016 gibi sizin paketiniz direk erişim paketidir. Sürekli bir etkileşimden bahsetmek istiyorsak kendi bağlantımızı kendimiz oluşturmak zorundayız.
Data boyu ve adresi(+port) ile feşmekan adresden gelen 1000 bitlit bir veri kabul edeceğimizi varsayalım.
#!/usr/bin/python # This is server.py file

import socket # Import socket module

s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345 # Reserve a port for your service.
s.bind((host, port)) # Bind to the port

s.listen(5) # Now wait for client connection.
while True:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
c.send('Thank you for connecting')
c.close() # Close the connection

Normalde soket ile web sunucusu bile yazılabilir(zaten öyle).
Önce kendinize bir mesaj merkezi oluşturmanız lazım ki gelen yanıtları oradan okuyun.
Bu bilgisayar işyerindeki bakayım hem server hemde sunucu içeren bir betik varmı. Bedava yazmak zorunda kalmazsın.

Edit: hiç bir tane yok yazayım bari online olursun umarım...

http://www.delta.com.tw/product/em/control/plc/download/software/DMT V2.2 Setup.zip
Örnekleri ve kütüphaneside mevcut...
 
Moderatör tarafında düzenlendi:
public abstract class ModbusBaseClientStation
{
protected string name;
protected Plugin plugin;
protected int cycleTimeout;
protected int retryTimeout;
protected int retryCount;
protected int failedCount;
protected List<ModbusChannelImp> channels = new List<ModbusChannelImp>();
protected List<ModbusBuffer> buffers = new List<ModbusBuffer>();
protected Dictionary<byte, ModbusChannelImp> failures = new Dictionary<byte, ModbusChannelImp>();
protected Queue<ModbusChannelImp> sendQueue = new Queue<ModbusChannelImp>();
protected object sendQueueSyncRoot = new object();
protected ManualResetEvent sendQueueEndWaitEvent = new ManualResetEvent(false);
protected List<ModbusChannelImp> channelsToSend = new List<ModbusChannelImp>();
protected volatile bool runThread;

public ModbusBaseClientStation(string name, Plugin plugin, int cycleTimeout, int retryTimeout, int retryCount, int failedCount)
{
this.name = name;
this.plugin = plugin;
this.cycleTimeout = Math.Max(cycleTimeout, 10);
this.retryTimeout = Math.Max(retryTimeout, 100);
this.retryCount = Math.Max(retryCount, 1);
this.failedCount = Math.Max(failedCount, 1);
this.LoggingLevel = 0;
this.StationActive = true;
}

public string Name
{
get { return name; }
set { name = value; }
}

public int CycleTimeout
{
get { return cycleTimeout; }
set { cycleTimeout = value; }
}
public int RetryTimeout
{
get { return retryTimeout; }
set { retryTimeout = value; }
}
public int RetryCount
{
get { return retryCount; }
set { retryCount = value; }
}

public int FailedCount
{
get { return failedCount; }
set { failedCount = value; }
}

public int LoggingLevel
{
get;
set;
}

public bool StationActive
{
get;
set;
}

public void AddChannel(ModbusChannelImp channel)
{
channels.Add(channel);
}

public void ClearChannels()
{
channels.Clear();
}

public void SendValueUpdateToModbusLine(ModbusChannelImp ch)
{
if (runThread)
{
lock (sendQueueSyncRoot)
{
sendQueue.Enqueue(ch);
}
sendQueueEndWaitEvent.Set();
}
}

public bool Running { get { return runThread; } }

public void Stop()
{
//MessageBox.Show("Stopping Modbus station " + name, "Info");
if (!StationActive) return;

runThread = false;
lock (sendQueueSyncRoot)
{
sendQueue.Clear();
}
}

public int Start()
{
//MessageBox.Show("Starting Modbus station " + name, "Info");
if (!StationActive) return 1;

buffers.Clear();
failures.Clear();
sendQueue.Clear();

if (channels.Count > 0)
{
//// Data Space analyse
channels.Sort(channels[0].Compare);

foreach (ModbusChannelImp ch in channels)
{
if (ch.ModbusReadWrite != ModbusReadWrite.WriteOnly && ch.ModbusDataType != ModbusDataTypeEx.DeviceFailureInfo)
{
bool found = false;
foreach (ModbusBuffer buf in buffers)
{
if (ch.SlaveId == buf.slaveId && ch.ModbusDataType == buf.ModbusDataType)
{
int mult;
if (ch.ModbusDataType == ModbusDataTypeEx.Input || ch.ModbusDataType == ModbusDataTypeEx.Coil)
mult = 16;
else
mult = 1;
if (((ch.ModbusDataAddress - buf.lastAddress) < 4 * mult) && ((buf.lastAddress - buf.startAddress + ch.DeviceDataLen) < 120 * mult))
// Optimization - "holes" in address space less than 4 words
// will be included in one read until max frame 2*120 bytes is reached
{
buf.lastAddress = (ushort)((ch.ModbusDataAddress + ch.DeviceDataLen - 1) > buf.lastAddress ? ch.ModbusDataAddress + ch.DeviceDataLen - 1 : buf.lastAddress);
buf.numInputs = (ushort)((buf.lastAddress - buf.startAddress + ch.DeviceDataLen) > buf.numInputs ? buf.lastAddress - buf.startAddress + ch.DeviceDataLen : buf.numInputs);
buf.channels.Add(ch); ch.StatusFlags = ChannelStatusFlags.Bad;
found = true;
}
}
}
if (!found)
{
// Set up a new buffer
ModbusBuffer buf = new ModbusBuffer();
buf.slaveId = ch.SlaveId;
buf.numInputs = ch.DeviceDataLen;
buf.startAddress = ch.ModbusDataAddress;
buf.lastAddress = (ushort)(ch.ModbusDataAddress + ch.DeviceDataLen - 1);
buf.ModbusDataType = ch.ModbusDataType;
buf.channels.Add(ch); ch.StatusFlags = ChannelStatusFlags.Bad;
buf.pauseCounter = 0;
buffers.Add(buf);
}
}
if (ch.ModbusDataType == ModbusDataTypeEx.DeviceFailureInfo)
{
if (failures.ContainsKey(ch.SlaveId))
{
// failure signal already defined, parameterization error
if (LoggingLevel >= ModbusLog.logErrors)
Env.Current.Logger.LogError(string.Format(StringConstants.ErrFailureTwice, this.Name, failures[ch.SlaveId].Name, ch.Name));
}
else
{
failures.Add(ch.SlaveId, ch);
ch.Value = true;
}
}
}
return 0;
}
return 1;
}

protected void ReadBuffer(ModbusBaseClientStation self, IModbusMaster master, ModbusBuffer buf)
{
try
{
ushort[] registers;
byte[] adr;
bool[] inputs;

if (buf.pauseCounter == 0)
{
ushort startAddress = buf.startAddress;
ushort numInputs = buf.numInputs;
switch (buf.ModbusDataType)
{
case ModbusDataTypeEx.InputRegister:
case ModbusDataTypeEx.HoldingRegister:
if (buf.ModbusDataType == ModbusDataTypeEx.InputRegister)
registers = master.ReadInputRegisters(buf.slaveId, startAddress, numInputs);
else
registers = master.ReadHoldingRegisters(buf.slaveId, startAddress, numInputs);
DateTime dt = DateTime.Now;
int iresult = 0;
uint uresult = 0;
double fresult = 0.0;
foreach (ModbusChannelImp ch in buf.channels)
{
switch (ch.DeviceDataType)
{
case ModbusDeviceDataType.Int:
adr = BitConverter.GetBytes(registers[ch.ModbusDataAddress - buf.startAddress]);
switch (ch.ConversionType)
{
case ModbusConversionType.SwapBytes:
byte tmp = adr[0]; adr[0] = adr[1]; adr[1] = tmp;
iresult = BitConverter.ToInt16(adr, 0);
break;
default:
iresult = BitConverter.ToInt16(adr, 0);
break;
}
if (ch.ModbusFs2InternalType == ModbusFs2InternalType.Int32)
{
ch.DoUpdate(iresult, dt, ChannelStatusFlags.Good);
}
else if (ch.ModbusFs2InternalType == ModbusFs2InternalType.Double)
{
ch.DoUpdate((double)(ch.K * iresult + ch.D), dt, ChannelStatusFlags.Good);
}
else
if (self.LoggingLevel >= ModbusLog.logWarnings)
Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrConvert,
self.Name, ch.Name, ch.DeviceDataType.ToString(), ch.ModbusFs2InternalType.ToString()));
break;
case ModbusDeviceDataType.UInt:
adr = BitConverter.GetBytes(registers[ch.ModbusDataAddress - buf.startAddress]);
switch (ch.ConversionType)
{
case ModbusConversionType.SwapBytes:
byte tmp = adr[0]; adr[0] = adr[1]; adr[1] = tmp;
uresult = BitConverter.ToUInt16(adr, 0);
break;
default:
uresult = BitConverter.ToUInt16(adr, 0);
break;
}
if (ch.ModbusFs2InternalType == ModbusFs2InternalType.UInt32)
{
ch.DoUpdate(uresult, dt, ChannelStatusFlags.Good);
}
else if (ch.ModbusFs2InternalType == ModbusFs2InternalType.Double)
{
ch.DoUpdate((double)(ch.K * uresult + ch.D), dt, ChannelStatusFlags.Good);
}
else
if (self.LoggingLevel >= ModbusLog.logWarnings)
Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrConvert,
self.Name, ch.Name, ch.DeviceDataType.ToString(), ch.ModbusFs2InternalType.ToString()));
break;
case ModbusDeviceDataType.DInt:
byte[] adr0 = BitConverter.GetBytes(registers[ch.ModbusDataAddress - buf.startAddress]);
byte[] adr1 = BitConverter.GetBytes(registers[ch.ModbusDataAddress - buf.startAddress + 1]);
byte[] res = new byte[4];
res = self.SwapBytesIn(adr0, adr1, ch.ConversionType);
iresult = BitConverter.ToInt32(res, 0);
if (ch.ModbusFs2InternalType == ModbusFs2InternalType.Int32)
{
ch.DoUpdate(iresult, dt, ChannelStatusFlags.Good);
}
else if (ch.ModbusFs2InternalType == ModbusFs2InternalType.Double)
{
ch.DoUpdate((double)(ch.K * iresult + ch.D), dt, ChannelStatusFlags.Good);
}
else
if (self.LoggingLevel >= ModbusLog.logWarnings)
Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrConvert,
self.Name, ch.Name, ch.DeviceDataType.ToString(), ch.ModbusFs2InternalType.ToString()));
break;
case ModbusDeviceDataType.DUInt:

adr0 = BitConverter.GetBytes(registers[ch.ModbusDataAddress - buf.startAddress]);
adr1 = BitConverter.GetBytes(registers[ch.ModbusDataAddress - buf.startAddress + 1]);
res = self.SwapBytesIn(adr0, adr1, ch.ConversionType);
uresult = BitConverter.ToUInt32(res, 0);
if (ch.ModbusFs2InternalType == ModbusFs2InternalType.UInt32)
{
ch.DoUpdate(uresult, dt, ChannelStatusFlags.Good);
}
else if (ch.ModbusFs2InternalType == ModbusFs2InternalType.Double)
{
ch.DoUpdate((double)(ch.K * uresult + ch.D), dt, ChannelStatusFlags.Good);
}
else
if (self.LoggingLevel >= ModbusLog.logWarnings)
Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrConvert,
self.Name, ch.Name, ch.DeviceDataType.ToString(), ch.ModbusFs2InternalType.ToString()));
break;
case ModbusDeviceDataType.Float:

adr0 = BitConverter.GetBytes(registers[ch.ModbusDataAddress - buf.startAddress]);
adr1 = BitConverter.GetBytes(registers[ch.ModbusDataAddress - buf.startAddress + 1]);
res = self.SwapBytesIn(adr0, adr1, ch.ConversionType);
fresult = BitConverter.ToSingle(res, 0);
if (ch.ModbusFs2InternalType == ModbusFs2InternalType.Double)
{
ch.DoUpdate((double)(ch.K * fresult + ch.D), dt, ChannelStatusFlags.Good);
}
else
if (self.LoggingLevel >= ModbusLog.logWarnings)
Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrConvert,
self.Name, ch.Name, ch.DeviceDataType.ToString(), ch.ModbusFs2InternalType.ToString()));
break;
case ModbusDeviceDataType.Bool:

bool bit = (registers[ch.ModbusDataAddress - buf.startAddress] & (0x01 << ch.BitIndex)) > 0;
if (ch.ModbusFs2InternalType == ModbusFs2InternalType.Boolean)
{
ch.DoUpdate(bit, dt, ChannelStatusFlags.Good);
}
else
if (self.LoggingLevel >= ModbusLog.logWarnings)
Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrConvert,
self.Name, ch.Name, ch.DeviceDataType.ToString(), ch.ModbusFs2InternalType.ToString()));
break;
case ModbusDeviceDataType.String:

byte[] str = new byte[2 * ch.DeviceDataLen];
Decoder ascii = (new ASCIIEncoding()).GetDecoder();
int bytesUsed = 0;
int charsUsed = 0;
bool completed = false;
int j = 0;
// Conversion strategy: FIRST NONPRINTABLE CHARACTER (ORD < 32) BREAKS CONVERSION, string consists of printables converted before
for (int i = 0; i < ch.DeviceDataLen; i++)
{
byte[] word = BitConverter.GetBytes(registers[ch.ModbusDataAddress - buf.startAddress + i]);
if (ch.ConversionType == ModbusConversionType.SwapBytes)
{
if (word[1] < 32)
break; // nonprintable character
str[j++] = word[1];
if (word[0] < 32)
break; // nonprintable character
str[j++] = word[0];
}
else
{
if (word[0] < 32)
break; // nonprintable character
str[j++] = word[0];
if (word[1] < 32)
break; // nonprintable character
str[j++] = word[1];
//Array.Copy(BitConverter.GetBytes(registers[ch.ModbusDataAddress - buf.startAddress + i]), 0, str, 2 * i, 2);
}
}
string sresult;
if (j > 0)
{
char[] chars = new char[j];
ascii.Convert(str, 0, j, chars, 0, j, true, out bytesUsed, out charsUsed, out completed);
sresult = new String(chars);
}
else
sresult = "";
if (ch.ModbusFs2InternalType == ModbusFs2InternalType.String)
{
ch.DoUpdate(sresult, dt, ChannelStatusFlags.Good);
}
else
if (self.LoggingLevel >= ModbusLog.logWarnings)
Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrConvert,
self.Name, ch.Name, ch.DeviceDataType.ToString(), ch.ModbusFs2InternalType.ToString()));
break;
}
}
break;
case ModbusDataTypeEx.Coil:
case ModbusDataTypeEx.Input:
if (buf.ModbusDataType == ModbusDataTypeEx.Coil)
inputs = master.ReadCoils(buf.slaveId, startAddress, numInputs);
else
inputs = master.ReadInputs(buf.slaveId, startAddress, numInputs);
dt = DateTime.Now;
foreach (ModbusChannelImp ch in buf.channels)
{
if (ch.ModbusFs2InternalType == ModbusFs2InternalType.UInt32)
{
uint val = (uint)(inputs[ch.ModbusDataAddress - buf.startAddress] ? 1 : 0);
ch.DoUpdate(val, dt, ChannelStatusFlags.Good);
}
else if (ch.ModbusFs2InternalType == ModbusFs2InternalType.Boolean)
{
bool val = inputs[ch.ModbusDataAddress - buf.startAddress];
ch.DoUpdate(val, dt, ChannelStatusFlags.Good);
}
else
if (self.LoggingLevel >= ModbusLog.logWarnings)
Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrConvert,
self.Name, ch.Name, ch.DeviceDataType.ToString(), ch.ModbusFs2InternalType.ToString()));
}
break;
} // Case
if (self.failures.ContainsKey(buf.slaveId))
{
// failure signal defined
self.failures[buf.slaveId].Value = false;
}
} // If
else
{
buf.pauseCounter--;
}
} // Try
catch (Modbus.SlaveException e)
{
buf.pauseCounter = self.FailedCount;
if (self.failures.ContainsKey(buf.slaveId))
{
// failure signal defined
self.failures[buf.slaveId].Value = true;
}
foreach (ModbusChannelImp ch in buf.channels)
{
ch.StatusFlags = ChannelStatusFlags.Bad;
}
if (self.LoggingLevel >= ModbusLog.logWarnings)
Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrReceive,
self.Name, buf.slaveId, buf.ModbusDataType.ToString(), buf.startAddress, buf.numInputs, e.Message));
}
catch (TimeoutException e)
{
buf.pauseCounter = self.FailedCount;
if (self.failures.ContainsKey(buf.slaveId))
{
// failure signal defined
self.failures[buf.slaveId].Value = true;
}
foreach (ModbusChannelImp ch in buf.channels)
{
ch.StatusFlags = ChannelStatusFlags.Bad;
}
if (self.LoggingLevel >= ModbusLog.logWarnings)
Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrReceive,
self.Name, buf.slaveId, buf.ModbusDataType.ToString(), buf.startAddress, buf.numInputs, e.Message));
}
}

protected void WriteChannel(ModbusBaseClientStation self, IModbusMaster master, ModbusChannelImp ch)
{
try
{
ushort[] registers;
byte[] adr = new byte[4];
byte[] adr0;
byte[] adr1;
bool conv_ok = true;

ushort startAddress = ch.ModbusDataAddress;
ushort numInputs = ch.DeviceDataLen;

switch (ch.ModbusDataType)
{
case ModbusDataTypeEx.HoldingRegister:
switch (ch.DeviceDataType)
{
case ModbusDeviceDataType.Int:
case ModbusDeviceDataType.UInt:
if (ch.Type == typeof(int)) // ch.ModbusFs2InternalType == ModbusFs2InternalType.Int32)
{
int v = (int)ch.Value;
adr = BitConverter.GetBytes(v);
}
else if (ch.Type == typeof(uint)) // ch.ModbusFs2InternalType == ModbusFs2InternalType.Int32)
{
uint v = (uint)ch.Value;
adr = BitConverter.GetBytes(v);
}
else if (ch.Type == typeof(double)) // ch.ModbusFs2InternalType == ModbusFs2InternalType.Double)
{
double d = (double)ch.Value;
d = (d - ch.D) / ch.K;
if (ch.DeviceDataType == ModbusDeviceDataType.Int)
{
short s = (short)d;
adr = BitConverter.GetBytes(s);
}
else
{
ushort s = (ushort)d;
adr = BitConverter.GetBytes(s);
}
}
else
{
if (self.LoggingLevel >= ModbusLog.logWarnings)
Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrConvert,
self.Name, ch.Name, ch.ModbusFs2InternalType.ToString(), ch.DeviceDataType.ToString()));
conv_ok = false;
}
if (conv_ok)
{
if (ch.ConversionType == ModbusConversionType.SwapBytes)
{
byte tmp = adr[0]; adr[0] = adr[1]; adr[1] = tmp;
}
master.WriteSingleRegister(ch.SlaveId, ch.ModbusDataAddress, BitConverter.ToUInt16(adr, 0));
}
break;
case ModbusDeviceDataType.DInt:
case ModbusDeviceDataType.DUInt:
case ModbusDeviceDataType.Float:
if (ch.Type == typeof(int)) // ch.ModbusFs2InternalType == ModbusFs2InternalType.Int32)
{
int v = (int)ch.Value;
adr = BitConverter.GetBytes(v);
}
else if (ch.Type == typeof(uint)) // ch.ModbusFs2InternalType == ModbusFs2InternalType.Int32)
{
uint v = (uint)ch.Value;
adr = BitConverter.GetBytes(v);
}
else if (ch.Type == typeof(double)) // ch.ModbusFs2InternalType == ModbusFs2InternalType.Double)
{
double d = (double)ch.Value;
d = (d - ch.D) / ch.K;
if (ch.DeviceDataType == ModbusDeviceDataType.DInt)
{
int s = (int)d;
adr = BitConverter.GetBytes(s);
}
else if (ch.DeviceDataType == ModbusDeviceDataType.DUInt)
{
uint s = (uint)d;
adr = BitConverter.GetBytes(s);
}
else
{
//float
float s = (float)d;
adr = BitConverter.GetBytes(s);
}
}
else
{
if (self.LoggingLevel >= ModbusLog.logWarnings)
Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrConvert,
self.Name, ch.Name, ch.ModbusFs2InternalType.ToString(), ch.DeviceDataType.ToString()));
conv_ok = false;
}
if (conv_ok)
{
SwapBytesOut(adr, out adr0, out adr1, ch.ConversionType);
registers = new ushort[] { BitConverter.ToUInt16(adr0, 0), BitConverter.ToUInt16(adr1, 0) };
master.WriteMultipleRegisters(ch.SlaveId, ch.ModbusDataAddress, registers);
}
break;
case ModbusDeviceDataType.String:
case ModbusDeviceDataType.Bool:
if (self.LoggingLevel >= ModbusLog.logWarnings)
Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrConvertImpl,
self.Name, ch.Name, ch.ModbusFs2InternalType.ToString(), ch.DeviceDataType.ToString()));
break;
}
break;
case ModbusDataTypeEx.Coil:
if (ch.Type == typeof(bool))
{
master.WriteSingleCoil(ch.SlaveId, ch.ModbusDataAddress, (bool)ch.Value);
}
else
{
if (self.LoggingLevel >= ModbusLog.logWarnings)
Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrConvert,
self.Name, ch.Name, ch.ModbusFs2InternalType.ToString(), ch.DeviceDataType.ToString()));
}
break;
}
}
catch (Modbus.SlaveException e)
{
if (self.LoggingLevel >= ModbusLog.logWarnings)
Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrException,
self.Name, e.Message));
}
catch (OverflowException e)
{
if (self.LoggingLevel >= ModbusLog.logWarnings)
Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrException,
self.Name, e.Message));
}
catch (TimeoutException e)
{
if (self.LoggingLevel >= ModbusLog.logWarnings)
Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrException,
self.Name, e.Message));
}
catch (InvalidCastException e)
{
if (self.LoggingLevel >= ModbusLog.logWarnings)
Env.Current.Logger.LogWarning(string.Format(StringConstants.ErrException,
self.Name, e.Message));
}
}

byte[] SwapBytesIn(byte[] adr0, byte[] adr1, ModbusConversionType con)
{
byte[] res = new byte[4];
switch (con)
{
case ModbusConversionType.SwapBytes:
res[0] = adr1[1];
res[1] = adr1[0];
res[2] = adr0[1];
res[3] = adr0[0];
break;
case ModbusConversionType.SwapWords:
res[0] = adr0[0];
res[1] = adr0[1];
res[2] = adr1[0];
res[3] = adr1[1];
break;
case ModbusConversionType.SwapAll:
res[0] = adr0[1];
res[1] = adr0[0];
res[2] = adr1[1];
res[3] = adr1[0];
break;
default:
res[0] = adr1[0];
res[1] = adr1[1];
res[2] = adr0[0];
res[3] = adr0[1];
break;
}
return res;
}

void SwapBytesOut(byte[] inp, out byte[] adr0, out byte[] adr1, ModbusConversionType con)
{
adr0 = new byte[2];
adr1 = new byte[2];
switch (con)
{
case ModbusConversionType.SwapBytes:
adr1[1] = inp[0];
adr1[0] = inp[1];
adr0[1] = inp[2];
adr0[0] = inp[3];
break;
case ModbusConversionType.SwapWords:
adr0[0] = inp[0];
adr0[1] = inp[1];
adr1[0] = inp[2];
adr1[1] = inp[3];
break;
case ModbusConversionType.SwapAll:
adr0[1] = inp[0];
adr0[0] = inp[1];
adr1[1] = inp[2];
adr1[0] = inp[3];
break;
default:
adr1[0] = inp[0];
adr1[1] = inp[1];
adr0[0] = inp[2];
adr0[1] = inp[3];
break;
}
}

protected class ModbusBuffer
{
public ModbusDataTypeEx ModbusDataType;
public ushort startAddress;
public ushort lastAddress;
public ushort numInputs;
public List<ModbusChannelImp> channels = new List<ModbusChannelImp>();
public byte slaveId;
public int pauseCounter;
}
}
 
hocam çok teşekkür ederim bir kütüphaneye bağlı kaldınızmı bu programda ?
 
merhabalar. c# ta easymodbus kullanarak tia portal üzerinden siemens plc için arayüz, Scada yazmam gerekiyor. acaba bunu öğrenebileceğim bir kaynak var mı ? youtube baktım ama düzgün bir ders yok. teşekkür ederim. iyi çalışmalar.
 

Forum istatistikleri

Konular
127,952
Mesajlar
913,879
Kullanıcılar
449,599
Son üye
Gksn

Yeni konular

Geri
Üst