# Siemens S7

> Conecte CLPs Siemens S7 por endereço, pelo S7comm, ou por nome da variável, pelo S7CommPlus: o campo Acesso, rack e slot, áreas de memória, endereçamento tipado por byte e bit, nomes de variáveis, as definições de HMI e os tipos de dado nativos.

O driver **Siemens S7** conversa com CLPs Siemens S7 por S7comm, o protocolo
clássico do Step 7 transportado sobre ISO-on-TCP. Ele usa endereçamento absoluto (área
de memória, número do bloco de dados, byte e bit), então funciona sem nenhuma exportação
de símbolos do projeto de engenharia. Adicione um dispositivo sob o driver Siemens S7 no
[Connector](connector) e preencha os campos abaixo; o painel mostra só os
campos que este protocolo usa.

Isso vale para o acesso **Por endereço**. Cada dispositivo escolhe o seu
**Acesso**: **Por endereço**, como descrito acima, ou **Por nome**, pelo
S7CommPlus, o protocolo que o TIA Portal e as HMIs da Siemens usam, em que cada
tag indica a sua variável como o TIA Portal a escreve e a CPU diz o tipo dela.

## Acesso {#access}

| Aspecto | Por endereço | Por nome |
| --- | --- | --- |
| Protocolo | S7comm sobre ISO-on-TCP, porta 102 | S7CommPlus sobre TLS 1.3 em ISO-on-TCP, porta 102 |
| CPUs | S7-300, S7-400, S7-1200, S7-1500 | S7-1500 com firmware V2.9 ou mais novo, S7-1200 com firmware V4.5 ou mais novo, configurados no TIA Portal V17 ou mais novo |
| Campos do dispositivo | Host ou IP, Bastidor / Slot | Host ou IP, Usuário e Senha, os dois opcionais |
| O que uma tag indica | Área, número do DB, byte e bit, e o tipo de dado | O nome da variável, por exemplo `GanterOpt.Real_`; a CPU diz o tipo |
| Na CPU | PUT/GET liberado e blocos de dados sem acesso otimizado ([Preparar a CPU](#prepare-the-cpu)) | Nada a mudar: blocos de dados otimizados são lidos e o PUT/GET não é necessário |
| Descobrir | Nenhum | As variáveis da CPU ([Descoberta](#discovery)) |

Um dispositivo criado agora nasce **Por nome**. Um dispositivo salvo antes de a
escolha existir continua lendo **Por endereço**, como sempre leu. Trocar o
acesso mantém tanto os endereços tipados das tags quanto os nomes das
variáveis, então voltar encontra tudo onde estava. Por nome, o cabeçalho do
dispositivo mostra o endpoint sem rack e slot, por exemplo
`s7://192.168.0.2?access=name`. Uma CPU que não responde ao acesso por nome diz
isso na página do dispositivo ([Uma CPU sem o acesso por nome](#a-cpu-without-the-access-by-name)).

## Conexão {#connection}

| Campo | Significado | Padrão |
| --- | --- | --- |
| **Host ou IP** | Endereço IP ou nome de host da CPU (ou do módulo CP que fica na frente dela). | vazio |
| **Acesso** | **Por endereço** ou **Por nome** ([Acesso](#access)). | Por nome |
| **Bastidor / Slot** | Só por endereço. Os números de rack e slot da CPU, como configurados no layout de hardware da Siemens. Duas caixas numéricas numa linha: rack primeiro, slot depois. | 0 / 0 |
| **Usuário / Senha** | Só por nome, os dois opcionais: a senha da proteção da CPU, quando o nível de acesso dela pede uma, e um nome de usuário só para uma CPU que mantém usuários. Guardados protegidos neste computador. | vazio |
| **Intervalo de leitura (ms)** | Período de leitura de todo o dispositivo, para as tags que não o sobrepõem. | 1.000 |

A porta TCP é fixa em 102 (ISO-on-TCP), então não há campo de porta. O
cabeçalho do dispositivo mostra o endpoint montado, por exemplo `s7://192.168.0.2:0:1`
(host, rack, slot).

Rack e slot precisam bater com o hardware: CPUs S7-1200 e S7-1500 respondem no
rack 0, slot 0 ou 1; uma CPU S7-300 típica fica no rack 0, slot 2; os racks do S7-400
variam com o layout. Um slot errado faz a conexão falhar, em vez de ler
dados errados.

Cada tag pode definir o próprio **Intervalo de leitura (ms)**; um valor 0 na tag recai no
intervalo do dispositivo.

## Ler por nome {#read-by-name}

Uma tag de um dispositivo lido por nome indica a sua variável na caixa **Nome da
variável** do cartão Origem, como o TIA Portal a escreve: o bloco de dados e a
variável, um ponto antes de um membro, um elemento de vetor entre colchetes. As
aspas duplas do TIA Portal podem ser digitadas (`"GanterOpt".Real_`) e são
descartadas.

| Variável no TIA Portal | Nome da variável |
| --- | --- |
| `Real_` no bloco de dados `GanterOpt` | `GanterOpt.Real_` |
| `Valor` da instância de UDT `Udt_` | `GanterOpt.Udt_.Valor` |
| Elemento 0 do vetor `Vetor` | `GanterOpt.Vetor[0]` |
| O DTL `DataHora` | `GanterOpt.DataHora`: uma tag só, uma data e hora |

Não há área, número de bloco de dados nem byte a digitar: a CPU diz onde a
variável está e o tipo dela, e o driver a lê no tipo de dado da tag:

| Tipo na CPU | Tipo de dado | Nota |
| --- | --- | --- |
| Bool | Boolean | |
| Byte, USInt; SInt | Byte; SByte | Sem sinal; com sinal |
| Word, UInt; Int | UInt16; Int16 | Sem sinal; com sinal |
| DWord, UDInt; DInt | UInt32; Int32 | Sem sinal; com sinal |
| LWord, ULInt; LInt | UInt64; Int64 | Os 64 bits, exatos |
| Real; LReal | Float; Double | |
| Char, String | String | Windows-1252, como por endereço |
| WChar, WString | String | UTF-16, qualquer escrita |
| Time, S5Time | Int32 | Milissegundos |
| LTime | Int64 | Nanossegundos |
| Time_Of_Day | UInt32 | Milissegundos desde a meia-noite, abaixo de 24 h |
| Date, Date_And_Time, DTL, LDT | DateTime | Só a data; data e hora |

O Descobrir dá a cada tag o tipo de dado e a unidade (ms, ns) da variável dela.
Uma tag digitada à mão fica com o tipo de dado que você escolher, e o valor da
CPU é convertido para ele.

Uma String ou uma WString é escrita inteira, com o tamanho com que está
declarada no bloco, que o driver lê da variável antes da primeira escrita: um
texto mais longo é recusado com os dois tamanhos e nada é enviado, e uma String
recusa um caractere fora do Windows-1252. Um DTL é lido e escrito inteiro, como
uma data e hora; os oito campos dele nunca são oferecidos sozinhos, porque um
campo escrito sozinho aceita qualquer valor (mês 90 inclusive). Um valor fora
da faixa do tipo (um Time_Of_Day de 24 h ou mais, 40000 num Int) é recusado com
a faixa, e nada é enviado. Um nome que a CPU não tem é o erro da tag, dizendo
isso; um campo de um DTL indicado sozinho é orientado a indicar o DTL.

### As definições de HMI {#the-hmi-settings}

O TIA Portal guarda três definições para cada variável de um bloco de dados,
nas colunas do bloco. A estação as respeita como a HMI e o servidor OPC UA da
própria Siemens, seja o que for que a CPU deixe passar:

| Definição no TIA Portal | Quando está desmarcada |
| --- | --- |
| **Accessible from HMI/OPC UA/Web API** | A variável não é lida nem escrita: o erro da tag nomeia a definição, e o Descobrir a deixa de fora. |
| **Visible in HMI engineering** | O Descobrir deixa a variável de fora; uma tag que a indica à mão a lê normalmente. |
| **Writable from HMI/OPC UA/Web API** | A variável é somente leitura: uma escrita é recusada nomeando a definição, o **Acesso** da tag oferece Somente leitura e diz por quê, e o Descobrir a oferece como Somente leitura. |

### Uma CPU sem o acesso por nome {#a-cpu-without-the-access-by-name}

Uma CPU que aceita a conexão e não responde ao acesso por nome (um S7-1500 antes
do firmware V2.9, um S7-1200 antes do V4.5, um projeto configurado num TIA
Portal anterior ao V17, ou uma CPU que só fala S7comm) deixa o dispositivo
offline. A página do dispositivo diz isso num aviso no lugar do erro: o que a
CPU precisa, onde o TIA Portal mostra o firmware (o firmware que a CPU roda em
**Online & diagnostics**, a versão que o projeto indica nas propriedades da CPU
em **General > Catalog information**) e as três saídas:

1. Atualizar o firmware da CPU, colocar a mesma versão na CPU do projeto do TIA
   Portal e fazer o download da configuração de hardware. Atualizar só o
   firmware não basta.
2. Mudar o **Acesso** para **Por endereço**, com o PUT/GET liberado e blocos de
   dados sem acesso otimizado ([Preparar a CPU](#prepare-the-cpu)).
3. Ler a CPU pelo servidor OPC UA dela mesma (um S7-1500, ou um S7-1200 a partir
   do firmware V4.4) com o driver [OPC UA](driver-opc-ua).

Cada tag do dispositivo traz o mesmo aviso na própria página, e o aviso some
sozinho assim que a CPU responde por nome. O diário e o agente leem os mesmos
passos no erro do dispositivo.

## Preparar a CPU {#prepare-the-cpu}

Esta seção vale para o acesso por endereço; um dispositivo lido por nome não
precisa de nenhuma destas definições.

Um S7-1200 ou S7-1500 só atende o endereçamento absoluto do S7comm com duas definições dele mesmo, as duas feitas no TIA Portal e baixadas para a CPU. Um S7-300 ou S7-400 não precisa de nenhuma.

| Definição | Onde no TIA Portal | Sem ela |
| --- | --- | --- |
| **Permit access with PUT/GET communication from remote partner**, marcada | Abra a configuração de dispositivos da CPU, selecione a CPU e então **Properties > General > Protection & Security > Connection mechanisms**. Baixe a configuração de hardware (**Download to device > Hardware configuration**): um download só do programa não a leva. | A CPU aceita a conexão e recusa toda leitura e escrita. O dispositivo segue conectado e as tags dele leem qualidade ruim. |
| **Optimized block access**, desmarcada, em todo bloco de dados que a estação lê | Na árvore do projeto, em **Program blocks**, clique com o botão direito no bloco de dados e então **Properties > General > Attributes**. Compile o bloco e baixe-o. A coluna **Offset** do bloco passa a mostrar onde cada variável começa, que é o que o **Byte inicial** de uma tag recebe. | A CPU não entrega nenhum byte do bloco por endereço. As tags dele leem qualidade ruim, e as outras tags do dispositivo seguem lendo. |

Mudar **Optimized block access** reinicializa o bloco de dados no download: as variáveis voltam aos valores iniciais. A memória de marcadores (M), as entradas (I) e as saídas (Q) sempre são endereçáveis e não precisam de mudança. Um bloco de dados que precisa continuar otimizado pode ser lido de outro jeito: o programa do CLP copia os valores que a estação lê para um bloco de dados sem acesso otimizado, ou para a memória de marcadores, e as tags apontam para lá; ou a estação lê o CLP pelo servidor OPC UA dele mesmo (S7-1500; S7-1200 a partir do firmware 4.4) com o driver [OPC UA](driver-opc-ua).

Quando a CPU recusa por causa de uma das duas definições, a página do dispositivo diz qual, com estes passos, num aviso que some sozinho assim que a CPU aceita. Para um bloco de dados, ele nomeia o bloco e as tags que ficam sem leitura. O diário e o agente leem os mesmos passos. Um bloco de dados que a CPU não tem, e um endereço além do fim de um bloco de dados, são ditos como o que são na tag que os nomeia.

## Endereçamento {#addressing}

Esta seção e as duas seguintes (tipos de dado, escritas) valem para o acesso
por endereço; o acesso por nome está em [Ler por nome](#read-by-name).

Uma tag S7 é endereçada por campos tipados, não por uma cadeia de texto livre. O painel
os mostra no cartão Origem da tag:

| Campo | Significado | Valores aceitos | Padrão |
| --- | --- | --- | --- |
| **Área** | A área de memória a ler. | `DataBlock`, `Merker`, `ProcessInput`, `ProcessOutput`, `Timer`, `Counter` | `DataBlock` |
| **Número do DB** | Qual bloco de dados, mostrado só quando a Área é `DataBlock`. | 0 ou mais | 1 |
| **Byte inicial** | Deslocamento de byte dentro da área em que o valor começa. Nas áreas `Timer` e `Counter` a caixa é rotulada **Número do temporizador** ou **Número do contador** e pede o número do timer ou do contador em vez do byte. | 0 ou mais | 0 |
| **Bit (0 a 7)** | Posição do bit dentro do byte inicial. Mostrado só em tags booleanas. | 0–7 | 0 |
| **Comprimento máximo (vazio = 254)** | Máximo declarado de um STRING ou WSTRING do S7, em caracteres. Mostrado só em tags String fora das áreas `Timer` e `Counter`. | 1–254 num STRING, 1–16382 num WSTRING, em branco | em branco |
| **Tipo do texto no CLP** | O tipo com que o texto é declarado no bloco, ao lado do comprimento: `STRING` (um byte por caractere, Windows-1252) ou `WSTRING` (dois bytes por caractere, UTF-16, qualquer escrita). Mostrado onde o Comprimento máximo aparece. | `STRING`, `WSTRING` | `STRING` |

As áreas correspondem à notação Siemens de sempre: `Merker` é a memória de marcadores (M),
`ProcessInput` são as entradas da imagem de processo (I/E), `ProcessOutput` são as
saídas da imagem de processo (Q/A), e `Timer`/`Counter` são as áreas de timer e contador
das CPUs S7-300 e S7-400. Timers e contadores são endereçados por número, não por byte: `Timer` com
o número 5 lê T5, e `Counter` com o número 3 lê C3. Traduzindo
endereços absolutos clássicos:

| Endereço clássico | Tipo de dado | Campos a preencher |
| --- | --- | --- |
| `DB5.DBD12` guardando um REAL | Float | Área `DataBlock`, Número do DB 5, Byte inicial 12 |
| `DB1.DBX3.4` | Boolean | Área `DataBlock`, Número do DB 1, Byte inicial 3, Bit 4 |
| `DB2.DBW20` guardando um INT | Int16 | Área `DataBlock`, Número do DB 2, Byte inicial 20 |
| `MW10` | Int16 | Área `Merker`, Byte inicial 10 |
| `M10.3` | Boolean | Área `Merker`, Byte inicial 10, Bit 3 |
| `IB2` | Byte | Área `ProcessInput`, Byte inicial 2 |
| `Q4.1` | Boolean | Área `ProcessOutput`, Byte inicial 4, Bit 1 |
| `T5` | Int16 | Área `Timer`, Número do timer 5 |
| `C3` | Int16 | Área `Counter`, Número do counter 3 |

Uma tag booleana lê e escreve exatamente um bit no barramento; ela nunca reescreve
o byte ao redor. Todo outro tipo é endereçado por byte, no byte inicial, com
a largura exata do seu tipo de dado. A linha somente leitura **Endereço de origem
(barramento)** do cartão Origem mostra o endereço montado enquanto você edita.

## Tipos de dado {#data-types}

O **Tipo de dado** da tag decide o tipo nativo do S7 no barramento. As treze
larguras nativas do S7 estão disponíveis:

| Tipo de dado | Tipo S7 | Tamanho no barramento |
| --- | --- | --- |
| Boolean | BOOL | 1 bit |
| SByte | SINT | 1 byte |
| Byte | USINT | 1 byte |
| Int16 | INT | 2 bytes |
| UInt16 | UINT | 2 bytes |
| Int32 | DINT | 4 bytes |
| UInt32 | UDINT | 4 bytes |
| Int64 | LINT | 8 bytes |
| UInt64 | ULINT | 8 bytes |
| Float | REAL | 4 bytes |
| Double | LREAL | 8 bytes |
| String | STRING ou WSTRING | comprimento máximo + 2 bytes (STRING), comprimento máximo × 2 + 4 bytes (WSTRING) |
| DateTime | DTL | 12 bytes |

Valores de vários bytes usam automaticamente a ordem big-endian nativa do S7; não
existe opção de ordem de bytes porque nenhuma é necessária.

Uma tag String lê o layout STRING padrão do S7: um byte com o máximo
declarado, um byte com o comprimento atual e então os caracteres, um byte cada um em
Windows-1252, a página de código em que o TIA Portal e as IHMs Siemens mostram um STRING. O que
a estação escreve é o que o TIA Portal e a IHM mostram ("Peça 12" continua "Peça 12"), e a
estação lê de volta igual. O **Comprimento máximo** conta caracteres e
precisa bater com a declaração do STRING no bloco (em branco significa o máximo do S7, de
254); o driver transfere comprimento máximo + 2 bytes por leitura. Uma tag DateTime corresponde
à estrutura DTL da família S7-1200/1500 (do ano até os nanossegundos);
o DATE_AND_TIME antigo, de 8 bytes, não é oferecido.

Uma tag String cujo **Tipo do texto no CLP** é `WSTRING` lê no lugar dele o layout WSTRING do S7: uma palavra com o máximo declarado, uma palavra com o comprimento atual e então os caracteres, dois bytes cada um em UTF-16, então comporta qualquer escrita ("中" é escrito e lido de volta como "中"). O **Comprimento máximo** continua contando caracteres, de 1 a 16382, e precisa bater com a declaração WString no bloco (em branco significa 254, o comprimento que o TIA Portal dá a um WString declarado sem nenhum); o driver transfere comprimento máximo × 2 + 4 bytes por leitura. O S7comm não lê o tipo na CPU, então ele precisa bater com a variável: uma tag deixada em `STRING` diante de uma variável WString lê e escreve no layout errado. Toda tag salva antes de o campo existir é `STRING`.

## Escritas {#writes}

Tags cujo **Acesso** é Leitura e escrita ou Somente escrita podem ser escritas. As escritas
endereçam a mesma área, o mesmo byte e o mesmo bit das leituras: uma escrita booleana liga o
bit dela sozinho, e todo o resto escreve os bytes exatos do tipo. Uma tag nova nasce como
Somente leitura.

Uma escrita String que ocupa mais bytes que o **Comprimento máximo** é recusada e nada é
enviado, nunca cortada no tamanho: o diário e o agente leem, por exemplo, "The DB1 byte
44 write was not sent: the text takes 21 bytes, and the STRING holds 20." Um texto com
exatamente o **Comprimento máximo** é escrito inteiro.

Uma escrita String com um caractere fora do Windows-1252 (um caractere chinês, por exemplo)
é recusada do mesmo jeito, nunca escrita com um ponto de interrogação no lugar dele: o diário
e o agente leem, por exemplo, "The DB1 byte 44 write was not sent: the STRING holds
Windows-1252 characters only, and '中' (U+4E2D) is not one of them; it fits once the tag's text type in the PLC and the PLC variable are both WSTRING." O painel da tag diz o mesmo motivo no idioma da estação.

Para escrever um texto assim, declare a variável como WString no bloco e escolha `WSTRING` no **Tipo do texto no CLP** da tag. Um WSTRING conta dois bytes por caractere, então um texto mais longo que o **Comprimento máximo** dele é recusado do mesmo jeito, sem nada enviado: "The DB1 byte 94 write was not sent: the text takes 42 bytes, and the WSTRING holds 40 (20 characters of two bytes)."

## Descoberta {#discovery}

Uma CPU lida por nome lista as suas variáveis; o S7comm não lista nenhuma, e
nenhuma difusão encontra uma CPU. Na página do driver, **CPU a varrer** no
cartão **Escopo da varredura** diz qual CPU: um dispositivo Siemens do driver
que lê a sua CPU por nome, varrido no host desse dispositivo e entrando com a
senha dele (o jeito de uma CPU protegida por senha listar as suas variáveis),
ou **Um endereço digitado aqui**, com o endereço da CPU em **Endereço da CPU**.

**Descobrir** oferece a CPU como um dispositivo com as variáveis como tags: as
que a CPU marca como acessíveis e visíveis pela HMI, todas marcadas, com o tipo
que a CPU diz, e Somente leitura onde a CPU as marca como não graváveis pela
HMI. A lista é uma árvore pelo caminho de cada nome: o bloco de dados, depois
cada struct ou instância de UDT e cada array, depois as variáveis, cada uma
nomeada pelo menor final do nome que nenhuma outra variável divide (`Real_`,
`Valor`, `Vetor[0]`). Marcar um ramo marca ou desmarca tudo o que está abaixo
dele, e o ramo diz quantas das suas variáveis estão marcadas; um DTL é uma
variável só. **Acrescentar dispositivo** cria um dispositivo lido por nome com
as tags marcadas.

Uma CPU que um dispositivo Siemens desta estação já lê por nome é esse
dispositivo, como quer que a varredura a tenha nomeado: a varredura entra com a
senha desse dispositivo, e **Acrescentar tags** acrescenta as variáveis para as
quais ele ainda não tem tag. Na página de um dispositivo lido por nome, o
**Descobrir tags** do cartão Tags faz o mesmo só para ele, com a mesma árvore
(veja [Descoberta](connector-discovery#discovering-a-devices-tags)). Um
dispositivo lido por endereço não oferece Descobrir tags: acrescente as tags à
mão.

## Bom saber {#good-to-know}

- As áreas Timer e Counter só existem nas CPUs S7-300 e S7-400. O S7-1200 não tem
  essas áreas, e o S7-1500 as recusa pelo S7comm com "Address out of range" mesmo
  com o PUT/GET permitido; nesse caso, copie o valor do timer ou do contador para um
  bloco de dados ou para a memória de marcadores no programa do CLP e leia de lá. Onde
  as áreas existem, elas são endereçadas por número, não por deslocamento de byte:
  a caixa pede o próprio timer ou contador (T0, T1, T2 e C0, C1, C2).
  Cada valor é uma palavra de 16 bits, então combine-o com Int16; um
  tipo de dado mais largo ou mais estreito é recusado, com a tag nomeada no diário, e as
  outras tags do dispositivo seguem lendo.
- Um CLP inalcançável não custa nada na inicialização: o dispositivo segue tentando em
  segundo plano e as tags dele leem qualidade ruim até a conexão acontecer.
- Um cabo puxado depois de o dispositivo estar online é percebido na próxima leitura: o
  dispositivo fica offline, as tags dele viram qualidade ruim, e ele reconecta sozinho
  assim que a rede volta. Um endereço que a CPU recusa não faz isso, então uma
  tag digitada errada nunca derruba o resto do dispositivo junto. A tag cuja leitura encontrou o enlace caído diz que a conexão com o dispositivo foi perdida, na língua da estação, e a página Eventos guarda as palavras do Sharp7.
