Introdução
O TISOTCPDriver fala o protocolo S7comm sobre ISO-on-TCP (RFC 1006, porta TCP 102) — o mesmo que o STEP 7, o TIA Portal e a LibNodave usam para ler e escrever memórias de um CLP Siemens. O driver é uma reescrita em Pascal do ISOTCP da LibNodave de Thomas Hergenhahn: não depende de nenhuma DLL ou biblioteca externa.
Ele conversa com:
- S7-300, S7-400, ET200S/ET200SP com CPU ou CP Ethernet;
- S7-1200 e S7-1500 — depois de liberar o acesso PUT/GET e desligar o acesso otimizado dos DBs (veja Preparando o CLP);
- S7-200 através de um CP 243-1 (
ConnectionWay = ISOTCP_VIA_CP243); - LOGO! 0BA7/0BA8 (LOGO! 7 e 8), que expõe a área V como DB1;
- qualquer simulador ou gateway compatível com S7comm (PLCSIM com NetToPLCSim, Snap7 server, etc.).
Ele não conversa com o S7-1200/1500 pelo protocolo nativo deles (S7CommPlus, que é o que o TIA Portal usa para acesso simbólico) — para isso existe o TS7CommPlusDriver. O ISOTCP continua sendo a opção mais simples para esses CLPs quando você controla o projeto no TIA e pode desligar o acesso otimizado.
Componentes necessários
- Uma
TTCP_UDPPortcomHost= IP do CLP,Port = 102(padrão) ePortType = ptTCP. Veja Portas de comunicação. - Um
TISOTCPDrivercomCommunicationPortapontando para a porta. - Os tags (
TPLCTagNumber,TPLCBlock,TPLCStruct,TPLCString) comProtocolDriverapontando para o driver.
O jeito mais rápido de chegar ao passo 3 é clicar com o botão direito no TISOTCPDriver e escolher Tag Builder (veja abaixo).
Propriedades do driver
| Propriedade | Padrão | Descrição |
|---|---|---|
CommunicationPort |
– | A porta TTCP_UDPPort usada pelo driver. |
PLCRack |
0 | Rack da CPU. |
PLCSlot |
0 | Slot da CPU. |
PLCStation |
2 | Endereço da estação. Só tem significado em redes MPI/PROFIBUS atrás de um gateway; em Ethernet deixe o padrão. |
ConnectionWay |
ISOTCP |
ISOTCP para conexão direta à CPU/CP Ethernet; ISOTCP_VIA_CP243 para S7-200 atrás de um CP 243-1. |
ISOTCPConnType |
ctOP |
Tipo de conexão que o driver se identifica ao CLP: ctPG (programadora), ctOP (painel de operação) ou ctBasic (outra). O CLP reserva recursos por tipo; se todas as conexões OP estiverem em uso, troque para ctBasic. |
ForcePDUSize |
pduAuto |
Tamanho de PDU negociado. pduAuto pede o maior que o CLP aceita; force pdu240 para CLPs antigos ou LOGO!, que não negociam corretamente. |
ReadOnly |
False |
Se True, o driver recusa qualquer escrita (ioReadOnlyProtocol). Útil para uma tela de supervisão que nunca deve alterar o processo. |
ReadSomethingAlways |
True |
Mantém a conexão viva lendo algum tag a cada ciclo mesmo que nenhum precise ser atualizado. |
Uma conexão ISOTCP fala com um único CLP. Por isso, as propriedades
PLCRack,PLCSlotePLCStationdos tags são ignoradas: o que vale é o que está configurado no driver. Para falar com dois CLPs, use duas portas e dois drivers.
Valores de rack/slot que funcionam na maioria dos casos:
| CPU | PLCRack | PLCSlot |
|---|---|---|
| S7-300 (CPU com PN integrada ou CP 343-1) | 0 | 2 |
| S7-400 | 0 | slot físico da CPU (normalmente 2 ou 3) |
| S7-1200 / S7-1500 | 0 | 0 (1 também funciona no 1200) |
| ET200S / ET200SP CPU | 0 | 2 (ET200S) / 0 (ET200SP) |
| S7-200 via CP 243-1 | 0 | 0 |
| LOGO! 7 / 8 | 0 | 0 (ver Preparando o CLP) |
Em código, UpdatePLCAddress(Rack, Slot, Station) troca os três de uma vez sem reiniciar a conexão três vezes.
Preparando o CLP
S7-300 / S7-400: nada a fazer além de ter o IP configurado. Se a CPU tiver senha de proteção contra escrita, o driver lê mas não escreve.
S7-1200 / S7-1500 (no TIA Portal):
- Nas propriedades da CPU → Protection & Security → Connection mechanisms: marque Permit access with PUT/GET communication from remote partner.
- Em cada DB que o PascalSCADA vai acessar, desmarque Optimized block access (propriedades do DB → Attributes) e recompile. Um DB otimizado não tem endereços absolutos, e o ISOTCP só endereça por byte.
- Se o nível de proteção da CPU for Full access, nada mais. Com Read access o driver só lê; com HMI access ou No access a conexão é recusada.
LOGO! 7 / 8 (no LOGO!Soft Comfort): em Tools → Ethernet connections, adicione uma conexão de servidor com TSAP local 20.00 e TSAP remoto 10.00, ou marque Allow all connections. A área V (VB/VW/VD) aparece para o PascalSCADA como DB1 (MemReadFunction = 4, MemFile_DB = 1); as memórias M como área M (MemReadFunction = 3). O exemplo examples/demo_logo8 mostra isso, com ForcePDUSize = pdu240 e PLCStation = 0.
S7-200: use ConnectionWay = ISOTCP_VIA_CP243 e configure uma conexão no CP 243-1 pelo assistente do STEP 7-Micro/WIN. A área V é MemReadFunction = 4 com MemFile_DB = 1.
Endereçando memórias
Todo endereço S7 é composto de uma área, um número de DB (só para a área DB), um endereço em bytes e o tipo da variável. No tag isso vira:
| Propriedade do tag | Preencha com |
|---|---|
MemReadFunction |
Código da área (tabela abaixo). |
MemFile_DB |
Número do DB, quando a área for 4. Ignorado nas outras. |
MemAddress |
Endereço do byte inicial (o número depois de IB, MW, DBD…). |
TagType |
Tipo da variável (tabela mais abaixo). |
MemWriteFunction, MemSubElement, PLCRack/Slot/Station |
Não usados. Deixe em zero. |
Códigos de área para MemReadFunction:
| Código | Área | CPUs | Observação |
|---|---|---|---|
| 1 | I — entradas digitais (imagem de processo) |
todas | |
| 2 | Q — saídas digitais (imagem de processo) |
todas | |
| 3 | M — memórias/flags |
todas | |
| 4 | DB — bloco de dados |
300/400/1200/1500; V no S7-200 e LOGO! | Preencha MemFile_DB. |
| 5 | C — contadores |
300/400 | TagType = pttWord. |
| 6 | T — temporizadores |
300/400 | TagType = pttWord. |
| 7 | SM — memória especial |
S7-200 | |
| 8 | AI — entradas analógicas |
S7-200 | TagType = pttWord. |
| 9 | AQ — saídas analógicas |
S7-200 | TagType = pttWord. |
| 10 | C — contadores |
S7-200 | TagType = pttWord. |
| 11 | T — temporizadores |
S7-200 | TagType = pttWord. |
| 12 | PIW — periferia de entrada |
300/400 | TagType = pttWord. Lê o valor direto do cartão, sem passar pela imagem de processo. |
Tipos de dados S7 e o TagType correspondente:
| Tipo no CLP | Bytes | TagType | SwapBytes | SwapWords | SwapDWords |
|---|---|---|---|---|---|
BOOL |
– | pttByte no tag + um TTagBit por bit |
|||
BYTE, CHAR, USINT |
1 | pttByte |
|||
SINT |
1 | pttShortInt |
|||
WORD, UINT, S5TIME, DATE |
2 | pttWord |
✔ | ||
INT |
2 | pttSmallInt |
✔ | ||
DWORD, UDINT, TIME_OF_DAY |
4 | pttDWord |
✔ | ✔ | |
DINT, TIME |
4 | pttLongInt |
✔ | ✔ | |
REAL |
4 | pttFloat |
✔ | ✔ | |
LINT, LTIME |
8 | pttInt64 |
✔ | ✔ | ✔ |
ULINT, LWORD |
8 | pttQWord |
✔ | ✔ | ✔ |
LREAL |
8 | pttDouble |
✔ | ✔ | ✔ |
STRING[n] |
n + 2 | TPLCString com StringType = stSIEMENS |
Os CLPs Siemens guardam os valores em big-endian e o PascalSCADA monta os bytes na ordem da máquina (little-endian). Por isso tudo que tem mais de um byte precisa dos Swap* marcados como na tabela — sem eles, um INT = 1 aparece como 256 e um REAL vira um número absurdo. O Tag Builder já marca os swaps corretos.
Exemplos:
| Endereço S7 | MemReadFunction | MemFile_DB | MemAddress | TagType | Swaps |
|---|---|---|---|---|---|
IB3 |
1 | 0 | 3 | pttByte |
– |
Q0.5 |
2 | 0 | 0 | pttByte + TTagBit com StartBit = EndBit = 5 |
– |
MW10 |
3 | 0 | 10 | pttWord |
B |
MD100 (como REAL) |
3 | 0 | 100 | pttFloat |
B + W |
DB5.DBW20 |
4 | 5 | 20 | pttSmallInt |
B |
DB5.DBD24 (como DINT) |
4 | 5 | 24 | pttLongInt |
B + W |
DB10.DBB0 até DBB49 |
4 | 10 | 0 | TPLCBlock pttByte, Size = 50 |
– |
DB12 STRING[30] em DBB8 |
4 | 12 | 8 | TPLCString, StringSize = 30, stSIEMENS |
– |
VW6 (LOGO!/S7-200) |
4 | 1 | 6 | pttSmallInt |
B |
T5 (S7-300) |
6 | 0 | 5 | pttWord |
B |
Bits
O ISOTCP do PascalSCADA lê e escreve por byte. Para um BOOL (uma entrada, uma saída, um bit de um DB), crie um TPLCTagNumber com TagType = pttByte apontando para o byte que contém o bit e um TTagBit para cada bit de interesse (StartBit = EndBit = número do bit). A escrita no TTagBit lê o byte atual, altera só aquele bit e grava o byte de volta.
Para muitos bits no mesmo byte, clique com o botão direito no tag e escolha Map bits: ele cria os oito TTagBit de uma vez. O exemplo examples/laz_isotcp_mapping_bits_from_other_tag faz isso com DB1.DBB0.
Blocos, estruturas e strings
- Um
TPLCBlocklêSizevariáveis consecutivas do mesmo tipo em uma requisição — um array deREALnum DB, por exemplo (TagType = pttFloat,Size= número de elementos,MemAddress= byte inicial). Os swaps valem para o bloco inteiro. - Um
TPLCStructlêSizebytes consecutivos, e cadaTPLCStructItem/TPLCStructStringinterpreta um trecho com seu próprio tipo e swap. É a forma natural de mapear um DB com campos mistos ou uma UDT — veja o exemplo em Tags. - Um
TPLCStringcomStringType = stSIEMENSlê umaSTRING[n]: os dois bytes de cabeçalho (tamanho máximo e tamanho atual) são tratados pelo driver. UsestCsó para arrays deCHARterminados em zero.
O driver junta automaticamente tags vizinhos da mesma área e do mesmo RefreshTime em uma requisição só, respeitando o tamanho da PDU negociado. Com pduAuto numa CPU moderna cabem até 1920 bytes de dados por mensagem; num S7-300 antigo ou LOGO!, 240. Se o AvgUpdateRate dos tags ficar muito acima do RefreshTime, o CLP não está dando conta — aumente o RefreshTime dos tags menos críticos ou agrupe-os em blocos.
Tag Builder
Botão direito no TISOTCPDriver → Tag Builder abre o assistente Siemens S7 Tag builder:
- Escolha a área (entradas, saídas, flags, DB, contadores, timers, áreas do S7-200…), o tipo de tag a criar (
TPLCTagNumberseparados, umTPLCBlock, ouTPLCStruct) e o tempo de varredura. - Para tags separados ou bloco: informe o tipo de dado, o endereço inicial, a quantidade e o DB. O assistente já marca
SwapBytes/SwapWordsconforme o tipo. - Para estruturas: monte a lista de itens (nome, tipo, swap, scan) na aba Items declaration; o assistente calcula os offsets e pode gerar N estruturas iguais em sequência (útil para arrays de UDT).
Os componentes criados aparecem no form/datamodule com ProtocolDriver já ligado.
Exemplo passo a passo
Ler a temperatura DB1.DBD0 (REAL) e escrever o setpoint DB1.DBW4 (INT) de um S7-1200 em 192.168.0.10:
- No TIA Portal: libere PUT/GET, desmarque Optimized block access no DB1, compile e carregue.
- Solte um
TTCP_UDPPort:Host = 192.168.0.10,Port = 102,Active = True. - Solte um
TISOTCPDriver:CommunicationPort = TCP_UDPPort1,PLCRack = 0,PLCSlot = 0. - Solte um
TPLCTagNumberchamadoTemperatura:ProtocolDriver = ISOTCPDriver1,MemReadFunction = 4,MemFile_DB = 1,MemAddress = 0,TagType = pttFloat,SwapBytes = True,SwapWords = True. - Solte outro chamado
Setpoint: idem, comMemAddress = 4,TagType = pttSmallInt,SwapBytes = True. - Ligue um
THMILabelemTemperaturae umTHMIEditemSetpoint. Rode.
O mesmo em código, para quem cria os componentes em tempo de execução:
uses tcp_udpport, ISOTCPDriver, PLCTagNumber, ProtocolTypes; var Port: TTCP_UDPPort; Drv: TISOTCPDriver; Temp: TPLCTagNumber; begin Port := TTCP_UDPPort.Create(Self); Port.Host := '192.168.0.10'; Port.Port := 102; Drv := TISOTCPDriver.Create(Self); Drv.CommunicationPort := Port; Drv.PLCRack := 0; Drv.PLCSlot := 0; Temp := TPLCTagNumber.Create(Self); Temp.MemReadFunction := 4; // DB Temp.MemFile_DB := 1; Temp.MemAddress := 0; Temp.TagType := pttFloat; Temp.SwapBytes := True; Temp.SwapWords := True; Temp.RefreshTime := 500; Temp.ProtocolDriver := Drv; // por último Port.Active := True; end;
Outros exemplos no repositório: examples/laz_isotcp_demonstration (DB com bloco, string e bits), examples/laz_isotcp_hourmeter (horímetro com escrita), examples/laz_isotcp_performance (medição de taxa de atualização) e examples/demo_logo8.
Problemas comuns
| Sintoma | Causa provável |
|---|---|
Porta abre (Active = True) mas nenhum tag atualiza; LastSyncReadStatus = ioConnectPLCFailed |
Rack/slot errados, ou S7-1200/1500 sem PUT/GET liberado, ou nível de proteção No access. |
Porta não abre (OnCommPortOpenError) |
IP errado, porta 102 bloqueada por firewall, ou o CLP já atingiu o limite de conexões (troque ISOTCPConnType). |
Tags de um DB específico dão ioIllegalMemoryAddress / ioObjectNotExists |
DB não existe, é menor que o endereço pedido, ou (1200/1500) ainda está com Optimized block access. |
Valores de 16/32 bits absurdos (1 vira 256, REAL vira 1E-40) |
Falta SwapBytes/SwapWords. |
Escritas falham com ioReadOnlyProtocol ou ioObjectAccessNotAllowed |
ReadOnly = True no driver, ou a CPU está com proteção de escrita/senha. |
| Funciona no S7-300 e não no LOGO! | Force ForcePDUSize = pdu240 e confira o TSAP da conexão de servidor no LOGO!Soft. |
| Timers/contadores lidos como zero | TagType precisa ser pttWord nessas áreas. |
Exemplos relacionados
examples/laz_isotcp_demonstration— DB comTPLCBlock, elementos,TPLCStringe bits, comTHMIEdit/THMIText(há uma versão Delphi emexamples/delphi_isotcp_demonstration).examples/laz_isotcp_hourmeter— horímetros lidos de blocos com dezenas deTTagBiteTHMIAnimation, com escrita.examples/laz_isotcp_mapping_bits_from_other_tag—DB1.DBB0com umTTagBitpor bit.examples/laz_isotcp_performance— milhares de elementos de bloco para medir a taxa de atualização e o efeito do tamanho da PDU.examples/demo_logo8— LOGO! 8: área V como DB1,ForcePDUSize = pdu240.examples/hmi_bandeja—TPLCStructsobre um DB, comTHMIBandeja.

bom dia
parabéns gostei muito, tenho uma pergunta
este protocolo tem restrição de tamanho ou quantidade de variáveis
pois tenho 6.000 variáveis e não estou conseguindo coletar todas
Qual o clp que está utilizando?