750-530 is Waiting...

Kahn

Level-1
Beiträge
39
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

ich schreibe und lese eine Wago-Klemme(750), das geht wunderbar via TCP.

Nun trägt es sich zu, das alle 30 Sekunden die Klemme sich 5 Sekunden Zeit nimmt um komplett zu antworten.


1) sende ein Standard Mod Pack (immer erfolgreich)
2) warten auf 6 Bytes für den Header mit Receiv (und bleibt ab und zu mal für einige Sekunden hängen dann geht's normal weiter)
3) Man liest die Länge an Daten aus dem Header mit einem folge Recive (Wunderbar)

Danke für Hinweise falls jemand dieses Problem kennt.

Gruß
Karsten
 
Ich glaub etwas mehr wirst schon zu den Gegebenheiten sagen müssen, denn Du ließt ja sicher nicht die Klemme selbst aus, sondern das PA des (P)FC.
- An was für einem (P)FC ist die Klemme gesteckt?
- Läuft eine Applikation auf dem PFC? Wird dort auf das PA zugegriffen? Wie schaut das Tasksystem aus? Wie ist der K-Bus eingestellt?
- Was für ein System ist die Gegenstelle?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo KLM,

danke für deine Rückschrift, die Wago Klemme am TCP -Port funktiniert soweit ganz gut, jedoch muss ich nach jeder Schreibaktion
mit Write -Coil (und nur da) zweimal die Klemme mit Read -Coil Lesen, um die Kommunikation aufrecht zu erhalten.


Konfiguriert wurde diese so:

# bootptab.txt: database for bootp server
#
# Blank lines and lines beginning with '#' are ignored.
#
# Legend:
# first field -- hostname (not indented)
# bf -- bootfile
# bs -- bootfile size in 512-octet blocks
# cs -- cookie servers
# df -- dump file name
# dn -- domain name
# ds -- domain name servers
# ef -- extension file
# gw -- gateways
# ha -- hardware address
# hd -- home directory for bootfiles
# hn -- host name set for client
# ht -- hardware type
# im -- impress servers
# ip -- host IP address
# lg -- log servers
# lp -- LPR servers
# ns -- IEN-116 name servers
# ra -- reply address
# rl -- resource location protocol servers
# rp -- root path
# sa -- boot server address
# sm -- subnet mask
# sw -- swap server
# tc -- template host (points to similar host entry)
# td -- TFTP directory
# to -- time offset (seconds)
# ts -- time servers
# vm -- vendor magic number
# Tn -- generic option tag n
#
# Be careful about including backslashes where they're needed. Weird (bad)
# things can happen when a backslash is omitted where one is intended.
# Also, note that generic option data must be either a string or a
# sequence of bytes where each byte is a two-digit hex value.
#
# Example of entry with no gateway
KeinProxy:ht=1:ha=0040D301464F:ip=192.168.2.50:
# Example of entry with gateway
# The gateway address must be inserted in hexadecimal
# after the T3 parameter
#hga:ht=1:ha=0040D301464F:ip=192.168.2.50:T3=c0.a8.00.01:


Meine Funktionen für Get Coil und SetCoil Read/Write Register sehen so aus:

Code:
#include "ModBus.h"
CModBus::CModBus(void) : m_PacketID(1)
{
}
CModBus::~CModBus(void)
{
}
void CModBus::Delete(void)
{
  CMySock::Delete();
}

bool CModBus::Create(SOCKCALLBACK pCall,void *pUsrData)
{
   return CMySock::Create(MODBUSPORT,pCall,(DWORD)pUsrData);
}
bool CModBus::Create(CString IpStr,int Port)
{
 return CMySock::Connect(IpStr.GetBuffer(0),Port,0,0);
}
CModbusPac CModBus::GetCoil(WORD Adress,WORD BitCnt)//read bits from startadress of blocktype (UNUSABLE)
{
 CModbusPac Pack(m_PacketID++,0,6,0,MBFNCWAGO::GETIOWAGO);//WORD tid,WORD pid,WORD len,BYTE uid,BYTE fnc
 Pack.m_data[0]=HIBYTE(Adress);//HiAdr
 Pack.m_data[1]=LOBYTE(Adress);//LoAdr
 Pack.m_data[2]=HIBYTE(BitCnt);//ReadSize
    Pack.m_data[3]=LOBYTE(BitCnt);//ReadSize
 if(!CMySock::Send((char *)&Pack,offsetof(CModbusPac,m_data[4])))
  return Pack;
 if(!CMySock::Receive((char *)&Pack, 8))
  return Pack;
 return Pack;
} 
CModbusPac CModBus::SetCoil(BYTE Adress,BYTE *pMem,WORD BitCnt)//write bits from startadress of blocktype (UNUSABLE)
{
 CModbusPac Pack(m_PacketID++,0,8,0,MBFNCWAGO::SETIOWAGO);//WORD tid,WORD pid,WORD len,BYTE uid,BYTE fnc
 int Cnt((BitCnt>>3));
 Pack.m_data[0]=HIBYTE(Adress);//HiAdr
 Pack.m_data[1]=LOBYTE(Adress);//LoAdr
 Pack.m_data[2]=HIBYTE(BitCnt);//ReadSize
 Pack.m_data[3]=LOBYTE(BitCnt);//ReadSize
 Pack.m_data[4]=Cnt;//Bytes
 for (register int i(0); i < Cnt; i++)
  Pack.m_data[5 + i] = *pMem++;
 if(!CMySock::Send((char *)&Pack,offsetof(CModbusPac,m_data[5])+Cnt))
  return Pack;
 int headlen = offsetof(CModbusPac, m_uid);
 if((Cnt=CMySock::Receive((char *)&Pack,headlen)) <= 0)
  return Pack;
 Pack.Rotate();
 if((Cnt=CMySock::Receive((char *)&Pack+offsetof(CModbusPac,m_uid),Pack.m_len)) < Pack.m_len)
  return Pack;
 return Pack;
}
CModbusPac CModBus::GetType(WORD Adress)
{
 CModbusPac Pack(m_PacketID++,0,6,0,MBFNCWAGO::GETTYPWAGO);//WORD tid,WORD pid,WORD len,BYTE uid,BYTE fnc
   
 int Cnt(0);
 Pack.m_data[0]=0;       //PDU
 Pack.m_data[1]=LOBYTE(Adress);  //LoAdr
 Pack.m_data[2]=HIBYTE(Adress);  //HiAdr
 Pack.m_data[3]=8;//ReadSize
 if(!CMySock::Send((char *)&Pack,offsetof(CModbusPac,m_data[4])))
  return Pack;
 if((Cnt=CMySock::Receive((char *)&Pack,offsetof(CModbusPac,m_uid))) <= 0)
  return Pack;
 Pack.Rotate();
 if((Cnt=CMySock::Receive((char *)&Pack+offsetof(CModbusPac,m_uid),Pack.m_len)) < Pack.m_len)
  return Pack;
 return Pack;
} 
CModbusPac CModBus::GetRegisters(WORD Adress,WORD CntWords/*=1*/)
{
 CModbusPac Pack(m_PacketID++,0,6,0,MBFNCWAGO::GETREGWAGO);//WORD tid,WORD pid,WORD len,BYTE uid,BYTE fnc
  
 Pack.m_data[0]=HIBYTE(Adress);  //HiAdr
 Pack.m_data[1]=LOBYTE(Adress);  //LoAdr
 Pack.m_data[2]=HIBYTE(CntWords);//ReadSize
 Pack.m_data[3]=LOBYTE(CntWords);//ReadSize
 if(!CMySock::Send((char *)&Pack,offsetof(CModbusPac,m_data[4])))
  return Pack;
 int Cnt(0);
 if((Cnt=CMySock::Receive((char *)&Pack,offsetof(CModbusPac,m_uid))) <= 0)
  return Pack;
 Pack.Rotate();
 if((Cnt=CMySock::Receive((char *)&Pack+offsetof(CModbusPac,m_uid),Pack.m_len)) < Pack.m_len)
 return Pack;
 return Pack;
} 
CModbusPac CModBus::SetRegisters(WORD adress,WORD CntWords ,WORD *pMem)
{
 CModbusPac Pack(m_PacketID++,0,9,0,MBFNCWAGO::SETREGWAGO);//WORD tid,WORD pid,WORD len,BYTE uid,BYTE fnc
 Pack.m_data[0]=HIBYTE(adress);//HiAdr
 Pack.m_data[1]=LOBYTE(adress);//LoAdr
 Pack.m_data[2]=HIBYTE(CntWords);//WordCount
 Pack.m_data[3]=LOBYTE(CntWords);//WordCount
 Pack.m_data[4]=CntWords<<1;//DataLenInBytes
 for(register BYTE n(0); n<CntWords; n++)
 {
  Pack.m_data[n+5]=HIBYTE(*pMem);//HiData
  Pack.m_data[n+6]=LOBYTE(*pMem);//LoData
  pMem++;
 }
 if(!CMySock::Send((char *)&Pack,offsetof(CModbusPac,m_data[5])+(CntWords<<1)))
 return Pack;
 int Cnt(0);
 if((Cnt=CMySock::Receive((char *)&Pack,offsetof(CModbusPac,m_uid))) <= 0)
  return Pack;
 Pack.Rotate();
 if((Cnt=CMySock::Receive((char *)&Pack+offsetof(CModbusPac,m_uid),Pack.m_len)) < Pack.m_len)
 return Pack;
 return Pack;
} 
CModbusPac CModBus::GetCounter(void)
{
 CModbusPac Pack(0,0,2,0,MBFNCWAGO::GETCNTWAGO);//WORD tid,WORD pid,WORD len,BYTE uid,BYTE fnc
  
 if(!CMySock::Send((char *)&Pack,offsetof(CModbusPac,m_data[0])))
  return Pack;
 int Cnt(0);
 if((Cnt=CMySock::Receive((char *)&Pack,offsetof(CModbusPac,m_uid))) <= 0)
  return Pack;
 Pack.Rotate();
 if((Cnt=CMySock::Receive((char *)&Pack+offsetof(CModbusPac,m_uid),Pack.m_len)) < Pack.m_len)
  return Pack;
 return Pack;
} 

CModbusPac CModBus::GetExceptStat(void)
{
 CModbusPac Pack(0,0,2,0,MBFNCWAGO::EXSTATWAGO);//WORD tid,WORD pid,WORD len,BYTE uid,BYTE fnc
  
 if(!CMySock::Send((char *)&Pack,offsetof(CModbusPac,m_data[0])))
  return Pack;
 int Cnt(0);
 if((Cnt=CMySock::Receive((char *)&Pack,offsetof(CModbusPac,m_uid))) <= 0)
  return Pack;
 Pack.Rotate();
 if((Cnt=CMySock::Receive((char *)&Pack+offsetof(CModbusPac,m_uid),Pack.m_len)) < Pack.m_len)
  return Pack;
 return Pack;
}


Die Datenstruktur mit der ich die Informationen übertrage sehen so aus:

Code:
class CModbusPac
{
public:
 CModbusPac() : m_tid(0),m_pid(0),m_len(0),m_uid(0),m_fnc(0)
 {
   memset(&m_data[0],0,sizeof(m_data));
 }
 CModbusPac(WORD tid,WORD pid,WORD len,BYTE uid,BYTE fnc):
 m_tid(tid),
 m_pid(pid),
 m_len(len),
 m_uid(uid),
 m_fnc(fnc)
 {
  Rotate();
  memset(&m_data[0],0,sizeof(m_data));
 }
 void Rotate()
 {
  __asm 
  {
       mov  ebx,this
    ror [ebx]CModbusPac.m_tid,8
    ror [ebx]CModbusPac.m_pid,8
    ror [ebx]CModbusPac.m_len,8
  }
 }
 WORD Rotate(WORD val)
 {
  __asm 
  {
   mov  ax,val;
   ror  ax,8
  }
 }
 void GetString(CString &strPack)
 {
  strPack.Format("TID(%d) PID(%d) LEN(%d) UID(%d) FUNC(%d) DATA = ",m_tid,m_pid,m_len,m_uid,m_fnc);
 
  for(register WORD n(0); n < DATLEN(); n++)
  {
   CString dat;dat.Format("0x%x|",m_data[n]);
   strPack+=dat;
  }
 }
 BYTE GetCnt(void){return DATLEN();}
 BYTE *GetDat(void){return &m_data[1];}
public:  
 WORD m_tid;
 WORD m_pid;
 WORD m_len;
 BYTE m_uid;
 BYTE m_fnc;
 BYTE m_data[MODMAXPACLEN]; 
};

Read Register Write Register Status usw. alles funktioniert.

Lediglich nach einem SetCoil wie oben muss ich dann nochmals 2 Mal GetCoil mit selber Adresse auf den Ausgangsport anrufen,
damit es zu keinem TCP Protokoll Fehler kommt und recieve sekundenlang wartet bevor es weiter ginge.

Ganz klar ist mir das nicht. jedes 53. bzw. 63.zigste write coil endet mit einem 4 Sekunden warten..

Vielen Dank für deine Interesse !
Grüße Karsten Schulz
www.FlexxVision.de
 
Zuletzt bearbeitet:
Moin Karsten,

ich stelle fest, wir reden von Modbus TCP.
Was soll mit die BootP Konfig sagen? Ein WAGO-Gerät (00:30:DE:...) konfigurierst Du damit jedenfalls nicht?!
Ist das Gerät, an dem die 530 hängt ein Controller mit Applikationsprogramm?
Welche Watchdog einstellungen hast Du gewählt?

Noch kann ich Dir nicht recht helft, sorry.
 
Zurück
Oben