ATV 10 — Da UART para a rede CAN
Seções Erros no barramento
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).
- No
protocolo.h, volteFILTRO_ID = 0e grave oreceptor-can. - Preencha a tabela pelo monitor serial do transmissor. Para desligar o receptor, tire o USB dele.
- Para a linha dos 250 kbit/s, faça
TAXA_KBPS = 250e grave só oreceptor-can. Para a última linha, volteTAXA_KBPS = 500e grave só oreceptor-cande novo.