Post

Sistemas combinacionais: a álgebra booleana que sustenta toda lógica digital

Sistemas combinacionais: a álgebra booleana que sustenta toda lógica digital

Quando você olha uma planta industrial moderna em operação, uma linha de montagem automotiva, uma elevatória de esgoto, uma subestação automatizada, a engenharia de controle parece invisível. Válvulas abrem, motores partem, esteiras andam, tudo no instante exato, sem ninguém apertando nada. Parece mágica.

Mas se você olha o código que faz isso acontecer, a mágica costuma acabar rápido.

Existe um vício bem espalhado no chão de fábrica: puxar linha no ensaio e erro. No calor do comissionamento, com a máquina parada e o cliente no pé, o programador vai inserindo contato em Ladder até a coisa funcionar. Sem equação, sem tabela verdade, sem a menor ideia do que separa um sistema combinacional de um sequencial. Funciona? Funciona. Até o dia em que não funciona, e aí ninguém entende por quê.

O resultado é sempre o mesmo: código frágil, bug intermitente que “só acontece às vezes”, e um programa que ninguém mais consegue dar manutenção sem medo de parar a planta.

A diferença entre esse código e um código de engenharia não é talento nem anos de estrada. É uma base matemática que cabe em um post.

Tudo começa em dois estados

Sistema digital só conhece dois valores:

  • 0: baixo, falso, desligado, 0 V ou próximo disso
  • 1: alto, verdadeiro, ligado, nível de tensão positivo

Essa dualidade é a base da álgebra booleana, formalizada por George Boole em 1854, quase um século antes de existir computador pra usar ela. Diferente de um sinal analógico, que assume infinitos valores contínuos, o sinal digital só existe em dois níveis bem definidos.

E é exatamente isso que dá robustez a ruído, uma propriedade que não é luxo em ambiente industrial. Um inversor de frequência chaveando a três metros do cabo de sinal injeta lixo elétrico em tudo. Se o sinal fosse contínuo, cada interferência viraria erro de leitura. Como ele é discreto, o ruído precisa ser grande o suficiente pra atravessar a faixa inteira entre 0 e 1 antes de causar estrago.

Níveis lógicos na prática

Domínio 0 lógico 1 lógico Onde aparece
TTL clássico 0–0,8 V 2–5 V Eletrônica digital
CMOS moderno 0–30 % Vcc 70–100 % Vcc Microcontroladores
Automação industrial 0–5 V 11–30 V Entradas de CLP (24 V)

A faixa de transição entre 0 e 1 é o nível de disparo (threshold). Em automação, entradas optoacopladas e filtros de entrada tornam essa transição ainda mais à prova de ruído, e isolam galvanicamente o campo do processador, o que já salvou muita CPU de surto.

Portas lógicas: os átomos da lógica combinacional

Uma porta lógica é um circuito que implementa uma operação booleana elementar. A saída dela depende exclusivamente das entradas naquele instante. Não existe memória, não existe passado.

Essa é a definição central de sistema combinacional:

A saída, em qualquer instante, é função apenas das entradas naquele mesmo instante.

Símbolos e tabelas verdade das portas lógicas NOT, AND, NAND, OR, NOR, XOR e XNOR As sete portas que você vai usar pelo resto da carreira. Decore as tabelas verdade, elas aparecem no Ladder, no ST, no FBD e no esquema elétrico.

As três primitivas são AND, OR e NOT. A partir delas se constrói qualquer função lógica concebível. É o que a teoria chama de completeza funcional.

Na prática, trabalhamos também com as derivadas:

  • NAND: universal, qualquer circuito pode ser feito só com NANDs
  • NOR: também universal
  • XOR: saída 1 só quando as entradas são diferentes
  • XNOR: complemento do XOR, 1 quando as entradas são iguais

Em circuito integrado, essas portas são transistores operando como chave (corte e saturação). Em CLP, elas são instruções de software executadas pelo processador. A abstração lógica é idêntica nos dois casos, e é por isso que o que você aprende em eletrônica digital vale direto no chão de fábrica.

Álgebra booleana: as regras do jogo

Assim como a álgebra elementar tem propriedades, a booleana tem um conjunto de leis que permitem simplificar expressão antes de ela virar código.

Lei Forma OR Forma AND
Identidade A + 0 = A A · 1 = A
Anulação A + 1 = 1 A · 0 = 0
Idempotência A + A = A A · A = A
Complemento A + Ā = 1 A · Ā = 0
Distributiva A + (B·C) = (A+B)·(A+C) A · (B+C) = A·B + A·C
De Morgan ¬(A + B) = Ā · B̄ ¬(A · B) = Ā + B̄

De Morgan é a mais útil do dia a dia e quase ninguém usa conscientemente. Ela diz que “nenhum alarme ativo” é a mesma coisa que “alarme 1 inativo E alarme 2 inativo E alarme 3 inativo”. Toda vez que você escreve uma linha de permissivo com contatos normalmente fechados em série, está aplicando De Morgan sem saber.

Linha Ladder com quatro contatos normalmente fechados de falha e defeito de encoders gerando um bit de erro crítico De Morgan na prática: quatro contatos NF em série. A saída AUX_COND[0].7 só cai quando qualquer uma das falhas aparece. Esse bit normalmente alimenta um interlock: enquanto estiver em 1, ele bloqueia a próxima etapa do processo ou dispara o alarme, até a falha de encoder ser corrigida. Lendo ao contrário: Erro = ¬(sem falha 1 · sem falha 2 · sem falha 3 · sem falha 4).

Da tabela verdade à equação: Soma de Produtos

O caminho profissional não é “ir puxando contato até acertar”. É:

  1. Escrever a tabela verdade a partir da especificação de processo
  2. Extrair a equação em Soma de Produtos (SOP) ou Produto de Somas (POS)
  3. Minimizar
  4. Só então implementar

Na SOP, você pega cada linha da tabela cuja saída é 1 e escreve o produto (AND) das entradas naquele estado, somando (OR) todos esses termos. É mecânico, não tem chute.

Pega um caso real: uma bomba de drenagem que deve ligar quando o nível está alto (A), desde que não haja falha (B), ou quando o operador força em modo manual (C), também sem falha.

# A (nível alto) B (falha) C (manual) Y (liga bomba)
0 0 0 0 0
1 0 0 1 1 ←
2 0 1 0 0
3 0 1 1 0
4 1 0 0 1 ←
5 1 0 1 1 ←
6 1 1 0 0
7 1 1 1 0

Três linhas dão saída 1. Cada uma vira um produto:

1
2
3
4
5
linha 1  →  Ā · B̄ · C
linha 4  →  A · B̄ · C̄
linha 5  →  A · B̄ · C

Y = Ā·B̄·C  +  A·B̄·C̄  +  A·B̄·C        (soma de produtos canônica)

Note que B̄ aparece nos três termos: é fator comum. Colocando em evidência:

1
2
Y = B̄ · (Ā·C + A·C̄ + A·C)
Y = B̄ · (A + C)                        ← forma mínima

De nove contatos para três. “Liga se (nível alto OU manual) E não houver falha”, que é exatamente o que o processo pedia desde o começo, mas agora você provou em vez de achar.

A mesma mecânica aparece em painel real, só que com uma SOP ainda mais direta. Numa planta de mineração, o sentido de giro de um conjunto de esteiras é redundado em dois inversores de frequência, INV1 e INV2. O bit Funcionando frente só pode subir em dois cenários: inversor 1 rodando com o sentido de giro ativo, ou inversor 2 rodando com o sentido de giro ativo. São dois produtos, somados:

1
Funcionando_Frente = (INV1.Running · INV1.DirActive) + (INV2.Running · INV2.DirActive)

Nenhuma simplificação a fazer aqui, os dois termos já são mínimos, mas é a mesma leitura mecânica de tabela verdade: cada inversor rodando no sentido certo é uma linha que dá saída 1, e a soma dos produtos vira a equação.

Duas linhas Ladder com ramos paralelos de contatos em série, implementando soma de produtos para detectar sentido de giro de motores Soma de produtos desenhada em Ladder. Cada ramo paralelo é um produto (AND de contatos em série); o paralelismo entre eles é a soma (OR). AUX_TRA[0].11 = (INV1.Running · INV1.DirActive) + (INV2.Running · INV2.DirActive).

Repare que a linha de baixo é a mesma estrutura com os contatos de direção negados. É a função complementar: Funcionando_Tras sai da mesma tabela verdade, só invertendo o sentido ativo em cada inversor, sem nenhuma adivinhação.

Minimização: K-map e o raciocínio que sobra

Para funções de até 4–6 variáveis existem os Mapas de Karnaugh: uma grade onde você distribui os 1s da tabela verdade em código Gray e agrupa células vizinhas em blocos de tamanho 1, 2, 4, 8… sempre potência de dois. Cada grupo elimina uma variável; quanto maior o grupo, menos variável sobra nele.

Isso não é curiosidade acadêmica. A maioria dos intertravamentos e permissivos de automação tem entre três e cinco variáveis relevantes, exatamente a faixa onde o K-map funciona de verdade: você pega a especificação, monta a tabela, desenha o mapa, agrupa e sai a equação mínima, pronta pra virar Ladder ou ST. É um método de trabalho real, não só um exercício de prova.

Veja a mesma função Y da bomba de drenagem, com as colunas em código Gray (00 · 01 · 11 · 10, só um bit muda por vez):

A \ BC 00 01 11 10
0 0 1 0 0
1 1 1 0 0

Os três 1s formam dois grupos de dois, ambos inteiramente dentro de B = 0:

1
2
3
4
grupo vertical   coluna BC=01  →  A muda, some  →  B̄·C
grupo horizontal linha  A=1    →  C muda, some  →  A·B̄

Y = B̄·C + A·B̄  =  B̄·(A + C)          ← mesma forma mínima

A simplificação que fiz no olho algumas seções atrás sai sozinha no mapa, sem precisar fatorar nada manualmente.

Quando o painel cresce, com intertravamentos de dez, vinte variáveis amarradas entre si, o K-map para de ser viável: a grade viraria um cubo multidimensional que ninguém desenha numa folha. É aí que entram o Quine-McCluskey e as heurísticas modernas dos sintetizadores de lógica, como o Espresso, ferramenta, não caneta. Mas o raciocínio de minimização continua valendo todo dia, com ou sem mapa desenhado. Menos contato e menos bobina significa código mais legível, scan mais rápido e menos superfície pra erro.

Quando você olha uma linha de Ladder com dezoito contatos e sente que tem algo redundante ali, é minimização que está faltando, mesmo que você resolva no olho em vez de no mapa.

A ponte: como isso vira CLP

Até aqui falamos de circuito físico. Em um CLP a execução funciona diferente, e entender isso muda como você escreve código:

  1. As entradas físicas (sensores, botoeiras, fins de curso) são lidas e congeladas numa imagem de processo de entrada (PII)
  2. O programa do usuário é executado ciclicamente, no scan cycle
  3. Toda lógica que não depende de estado anterior é, em essência, lógica combinacional
  4. Os resultados vão para a imagem de processo de saída (PIO) e só então chegam aos atuadores
1
2
3
4
5
6
7
8
9
10
11
        ┌──────────────── UM SCAN CYCLE ────────────────┐
        │                                               │
  CAMPO │   ①            ②              ③             │ CAMPO
 ───────┼──────────→  ───────────→  ───────────→ ───────┼───────
sensores│  LÊ ENTRADAS   EXECUTA O     ESCREVE        │ atuadores
 24 Vdc │   (congela      PROGRAMA     SAÍDAS         │ bobinas
        │    em PII)    lógica sobre   (da PIO)       │ válvulas
        │                 a PII                        │
        │        ▲                           │          │
        └────────┴───────────────────────────┘          │
                   repete, 1 a 50 ms típico

Essa leitura congelada no início do ciclo é o que garante que a sua lógica combinacional se comporte como combinacional de verdade: dentro de um scan, as entradas não mudam no meio do caminho.

No Ladder

O Ladder é tradução quase literal de circuito de relé:

  • Contatos em série → AND
  • Contatos em paralelo → OR
  • Contato normalmente fechado → NOT
  • Bobina → atribuição da função
1
2
3
4
5
6
7
AND  (série)                 OR  (paralelo)            NOT  (contato NF)

│──┤ ├──┤ ├──( )──│          │──┬─┤ ├─┬──( )──│        │──┤/├──( )──│
    A    B    Y              │  │  A  │   Y   │            A     Y
                             │  └─┤ ├─┘       │
Y = A · B                    │     B          │        Y = Ā
                             Y = A + B

Isso não é analogia didática: o Ladder é a álgebra booleana desenhada. Quando você entende isso, parar de “puxar linha” vira consequência natural: você passa a desenhar a equação que já tinha na mão.

Veja a prensa de segurança do exemplo mais abaixo, com o ramo de manutenção em paralelo:

1
2
3
4
5
6
7
│──┤ ├──────┤ ├──────┤ ├────────┤ ├────────────────( )──│
│  Botao_Esq Botao_Dir Cortina_Luz Porta_Fechada  Solenoide
│                                              │
│──┤ ├─────────────────────────────────────────┘
│  Modo_Manut

Solenoide = (Botao_Esq · Botao_Dir · Cortina_Luz · Porta_Fechada) + Modo_Manut

O Modo_Manut em paralelo é o OR: libera o solenoide ignorando os quatro permissivos quando a prensa está em manutenção. Isso é só pra ilustrar a porta OR em Ladder, não é como se faz bypass de segurança numa prensa real: cortina de luz e porta são dispositivo de categoria de segurança, e bypass de verdade vive num relé de segurança ou CLP de segurança dedicado, com chave física, monitoramento de tempo e circuito próprio, nunca um bit de modo comum numa OR de lógica padrão. Fora desse modo, é AND puro, e é exatamente esse AND puro que aparece na captura de painel real abaixo, num intertravamento de bomba:

Linha Ladder de intertravamento com quatro permissivos em série: nível de sucção, pressão de descarga, modo automático e relé térmico, acionando o bit PermissivosOK Intertravamento combinacional puro: PermissivosOK = Nível · Pressão · ModoAuto · Térmico. Quatro contatos em série, um AND de quatro entradas. Nenhuma memória envolvida: se qualquer permissivo cai, a bomba é bloqueada no mesmo instante.

Repare no comentário de cabeçalho da linha. A equação booleana escrita ali em cima não é enfeite: é a especificação do que aquela linha faz, e é o que permite outra pessoa auditar o código sem precisar simular na cabeça.

No texto estruturado

Pra quem vem da computação tradicional, o ST (texto estruturado, IEC 61131-3, sintaxe baseada em Pascal) é a forma mais direta de expressar lógica combinacional complexa.

O erro comum é escrever a lógica direto num PROGRAM, com o endereço físico de cada entrada amarrado na própria declaração da variável. Funciona, mas prende a lógica ao hardware: trocar o módulo de slot ou reaproveitar o mesmo intertravamento numa segunda bomba do mesmo padrão exige reescrever tudo. A prática correta separa as duas coisas: a lógica mora num FUNCTION_BLOCK que só enxerga nomes, o mapeamento físico fica isolado no programa principal.

Pegando o intertravamento da Bomba 1 do Ladder acima, o FUNCTION_BLOCK fica assim:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
FUNCTION_BLOCK FB_PermissivosBomba
VAR_INPUT
    nivelSuccaoOK     : BOOL; // nível do poço de sucção dentro da faixa
    pressaoDescargaOK : BOOL; // sem sobrepressão na linha de descarga
    modoAuto          : BOOL; // seletora local em Remoto/Automático
    termicoOK         : BOOL; // relé térmico íntegro, sem trip de sobrecarga
END_VAR
VAR_OUTPUT
    permissivosOK : BOOL;
END_VAR

permissivosOK := nivelSuccaoOK AND pressaoDescargaOK AND modoAuto AND termicoOK;

END_FUNCTION_BLOCK
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
PROGRAM Main
VAR
    iNivelSuccaoOK     AT %I0.0 : BOOL;
    iPressaoDescargaOK AT %I0.1 : BOOL;
    iModoAuto          AT %I0.2 : BOOL;
    iTermicoOK         AT %I0.3 : BOOL;
    qPermissivosOK     AT %Q0.0 : BOOL;

    bomba1 : FB_PermissivosBomba;
END_VAR

bomba1(
    nivelSuccaoOK     := iNivelSuccaoOK,
    pressaoDescargaOK := iPressaoDescargaOK,
    modoAuto          := iModoAuto,
    termicoOK         := iTermicoOK
);

qPermissivosOK := bomba1.permissivosOK;

END_PROGRAM

A equação booleana continua exatamente a mesma do Ladder, só que agora vive isolada do endereço físico. O FB_PermissivosBomba pode ser instanciado em qualquer bomba com o mesmo padrão de intertravamento (bomba2, bomba3, cada um com seu próprio mapeamento de entradas), testado em simulação sem CLP nenhum ligado, e versionado como uma unidade só. Em intertravamentos com dezenas de variáveis, comuns em painéis de grande porte, essa separação é o que mantém o projeto auditável conforme ele cresce.

Exemplos reais de lógica combinacional pura

  • Comando bimanual de segurança: duas botoeiras pressionadas simultaneamente. A base é um AND (a janela de tempo entra depois, e aí já é sequencial)
  • Seleção de modo de operação: chave de três posições (Manual / Automático / Manutenção) com decodificação combinacional e intertravamento mútuo
  • Permissivos de partida de motor: nível OK · pressão OK · sem falha térmica · seccionadora fechada
  • Prioridade de comandos: emergência tem prioridade absoluta sobre automático, que tem sobre manual
  • Alarmes combinacionais: nível baixo · bomba ligada

Um controle de nível com dois sensores é o exemplo mais limpo: nível alto desliga a bomba, nível baixo liga. Não importa o que a bomba estava fazendo antes. Não há etapa, não há sequência, é resposta direta e imediata. Combinacional.

No momento em que você adiciona histerese ou um tempo mínimo entre partidas, o sistema deixa de ser combinacional e vira sequencial. E tudo bem, só precisa estar claro na sua cabeça em que lado da linha você está.

Cuidados de engenharia que o ensaio e erro não cobre

  1. Glitches e hazards. Atrasos de propagação e ruído eletromagnético geram variações espúrias nas entradas. Filtros de entrada digital configuráveis no hardware do CLP mitigam falsos disparos, e é exatamente isso que causa aquele bug que “só acontece de madrugada quando o compressor liga”.

  2. Fail-safe. Em lógica de segurança, a falha de um sensor (um cabo rompido mandando 0) tem que levar a máquina para o estado seguro, nunca para operação perigosa. Por isso permissivo de segurança usa contato normalmente fechado no campo: cabo partido = permissivo ausente = máquina parada.

  3. Tempo de propagação. No mundo físico, a saída muda alguns nanossegundos depois da entrada. Em automação industrial isso é irrelevante frente à dinâmica do processo, mas vira problema em alta frequência.

Onde o combinacional acaba

Um sistema puramente combinacional não tem memória. Ele não consegue lembrar que o botão de partida foi pressionado e solto. Por isso ele não:

  • Implementa sequências (passo 1 → passo 2 → passo 3)
  • Conta eventos
  • Temporiza sozinho
  • Implementa máquinas de estado

No instante em que você escreve Motor := (Partida OR Motor) AND NOT Parada, aquele Motor do lado direito é realimentação. É memória. Você acabou de sair do mundo combinacional e entrou no sequencial, assunto pra outro post.


Nada disso exige mestrado. Exige escrever a tabela verdade antes de abrir o software de programação. É literalmente a diferença entre “funcionou” e “está correto”, e o pessoal da manutenção que vai pegar a sua planta daqui a três anos sabe muito bem qual dos dois você entregou.

Esta postagem está licenciada sob CC BY 4.0 pelo autor.