Pular para o conteúdo

Jefferson Wilhelm Meyer Soares

ATV 10 — Da UART para a rede CAN

Erros no barramento

Todo nó CAN confere cada quadro, e quem encontra um erro avisa o barramento todo na hora, com seis bits dominantes seguidos que destroem o quadro. O transmissor percebe e repete o quadro sozinho, sem o programa pedir.

Para um nó com defeito não travar a rede repetindo erros para sempre, cada nó conta seus erros. O contador de erros de transmissão sobe 8 a cada quadro que falha e desce 1 a cada quadro que dá certo, e pelo valor do contador o nó muda de estado:

  • ativo, abaixo de 128: o nó funciona normalmente e avisa os erros que vê;
  • passivo, de 128 a 255: o nó continua transmitindo, mas não destrói mais os quadros dos outros;
  • bus-off, acima de 255: o nó se desliga do barramento e para de transmitir.

Um quadro que fica sem ACK também conta como erro, mas a norma não deixa esse caso, sozinho, levar o nó do passivo ao bus-off: um nó que não tem com quem falar fica esperando, sem sair da rede.

Neste firmware, o transmissor sai do bus-off sozinho: espera o barramento ficar livre por um tempo, passa por recuperando e volta a ativo com o contador zerado. Os quadros que ainda não saíram esperam numa fila de envio, que tem lugar para seis.

O gráfico simula o contador de um nó que transmite muitos quadros, uma parte deles com erro.

Ver código
import numpy as np
import matplotlib.pyplot as plt

gerador = np.random.default_rng(10)
contador, historico, saiu = 0, [], None
for k in range(int(quadros)):
    if gerador.random() < erro / 100:
        contador += 8
    else:
        contador = max(0, contador - 1)
    historico.append(contador)
    if contador > 255:
        saiu = k + 1
        break
fig, eixo = plt.subplots(figsize=(11, 4))
eixo.axhspan(0, 128, color="C2", alpha=0.12, label="ativo")
eixo.axhspan(128, 256, color="C1", alpha=0.15, label="passivo")
eixo.axhspan(256, 300, color="C3", alpha=0.15, label="bus-off")
eixo.plot(range(1, len(historico) + 1), historico, color="C0", linewidth=1.5)
eixo.set_xlim(0, quadros)
eixo.set_ylim(0, 300)
eixo.set_xlabel("quadros transmitidos")
eixo.set_ylabel("contador de erros de transmissão")
eixo.legend(loc="upper left", fontsize=9)
eixo.grid(True)
fig.tight_layout()

saldo = 8 * erro / 100 - (1 - erro / 100)
print(f"Saldo médio por quadro: {saldo:+.2f}".replace(".", ","))
print(f"Bus-off no quadro {saiu}" if saiu else f"Contador no fim: {historico[-1]}")

O monitor serial do transmissor mostra, a cada envio, o retorno de twai_transmit (transmit), os quadros na fila (na_fila, que conta também o quadro que acabou de entrar), o contador de erros de transmissão (erros_tx) e o estado do controlador (estado).

  1. No protocolo.h, volte FILTRO_ID = 0 e grave o receptor-can.
  2. Preencha a tabela pelo monitor serial do transmissor. Para desligar o receptor, tire o USB dele.
  3. Para a linha dos 250 kbit/s, faça TAXA_KBPS = 250 e grave só o receptor-can. Para a última linha, volte TAXA_KBPS = 500 e grave só o receptor-can de novo.
Questão 19 de 20 Preencha a tabela

O monitor serial do transmissor em cada situação.

transmitna_filaerros_txestado
Receptor ligado
Receptor desligado, primeiros envios
Receptor desligado há 30 s
Receptor religado há 10 s
Receptor a 250 kbit/s
Receptor de volta a 500 kbit/s há 10 s
Questão 20 de 20 Resposta escrita

Sem o receptor, o contador de erros do transmissor parou em 128 e ele não saiu da rede. Com o receptor a 250 kbit/s, o transmissor foi a bus-off. Explique a diferença entre os dois casos e compare com o que o transmissor da UART percebeu quando o receptor foi desligado.

Anexos