Cos’è il CAN-bus e come implementarlo su Raspberry Pi

Il CAN-bus (Controller Area Network) è uno standard seriale, un vero e proprio protocollo di rete paragonabile con le reti LAN, progettato inizialmente per l’utilizzo nel settore automotive ma successivamente diventata una tecnologia molto diffusa anche in altri settori come nella robotica, nel medicale, in ambito militare e dei trasporti. La sua rapida diffusione ha generato il bisogno di avere un protocollo standardizzato e aperto che fornisca un sistema di scambio di messaggi affidabile e sicuro. Sono così emersi diversi protocolli CAN ad alto livello come il SAE J1939, il DeviceNet e il CANopen.

In virtù della sua massiccia adozione e con l’avanzamento tecnologico, il controller CAN viene integrato direttamente nei microcontrollori evitando quindi l’utilizzo di driver esterni. In alcuni casi, come per esempio l’utilizzo del protocollo su un computer Raspberry Pi, è necessario un controller CAN. Nell’ultimo paragrafo verrà spiegato come implementare un controller CAN anche su Raspberry Pi facendo uso di un chip stand-alone esterno.

Il CAN-bus

Robert Bosch introdusse il Can-bus nel febbraio del 1986 al congresso SAE di Detroit, a metà del ’87 Intel progettò il primo chip stand-alone CAN controller identificato come Intel 82526. Successivamente anche Philips Semiconductors introdusse il suo chip 82C200.

Nel 1992 fu fondata la CAN in Automation (CiA), un’associazione internazionale di utilizzatori e produttori che sviluppano e supportano protocolli basati sul CAN. Il primo passo della CiA fu l’introduzione della specifica CAN Application Layer (CAL).

Come scritto nell’introduzione, il CAN fu originariamente progettato per le reti automobilistiche, lo scopo principale era quello di monitorare frequentemente lo stato dei sensori. Di conseguenza, il CAN gestisce piccoli frame di dati fino ad 8 byte ma è in grado di gestire al secondo una grande quantità di frame. La velocità di bit rate standard può raggiungere 1 Mbps, a questa velocità è possibile scambiare diverse migliaia di messaggi al secondo.

L’overhead per ogni messaggio trasferito include un identificatore di messaggio a 11 bit e un CRC (Cyclic Redundancy Checksum) a 15 bit. Il CAN è un protocollo molto sicuro e affidabile soprattutto perché il CRC viene confermato da tutti i nodi della rete. Se un singolo nodo dovesse segnalare un errore di CRC, tutti gli altri nodi scarterebbero il messaggio e quest’ultimo verrebbe automaticamente ritrasmesso.

Il mezzo fisico di trasmissione è una coppia di fili intrecciati e la loro lunghezza dipende molto dalla velocità bit rate desiderata. Per esempio, con un cavo di lunghezza di 40 metri è possibile raggiungere una velocità di 1Mbps. Abbassando la velocità richiesta, è possibile raggiungere distanze maggiori anche fino a mezzo chilometro.

Il CAN è una rete multi-master, quindi ogni nodo può inviare messaggi in qualsiasi momento ed i vari conflitti vengono risolti per priorità tenendo conto dell’identificatore di messaggio. In una rete CAN tutti i frame dei nodi vengono trasmessi sull’intero bus rendendola una comunicazione di tipo broadcast. Ogni singolo nodo deciderà quale particolare messaggio filtrare.

Facendo riferimento alla schematizzazione in layers definita dall’ISO con il progetto OSI (Open System Interconnection), si può ritenere che il CAN-bus implementi solo il Physical Layer ed il Data Link Layer. Ciò rende il CAN una rete di comunicazione molto flessibile.

Il Data Link Layer è a sua volta implementato attraverso altri due layers chiamati Object Layer e Trasfer Layer. Il primo si occupa del filtraggio dei messaggi ricevuti e dell’interfaccia con l’Application Layer, mentre il secondo si occupa di scartare i pacchetti non rilevanti per il nodo ricevente e definisce le modalità di trasferimento come il formato dei messaggi, l’arbitraggio, la segnalazione e correzione degli errori e l’esclusione dei nodi mal funzionanti.

L’Application Layer non è standardizzato e quindi viene lasciato interamente al progettista il compito di definire i dettagli dell’interfacciamento degli utenti verso il bus. Il Physical Layer specifica il mezzo trasmissivo e viene definito tramite un chip transceiver esterno posto tra il controller CAN e il mezzo fisico di trasmissione (coppia di fili intrecciati).

ISO 11898

Lo standard ISO 11898-2 è il layer fisico più utilizzato in applicazioni automotive e controlli industriali. Un transceiver ad alta velocità in conformità con l’ISO 11898 prende il segnale TTL proveniente dal controller CAN e lo converte in un segnale differenziali e viceversa.

Un segnale a stato logico alto sta ad indicare lo stato recessivo ed è rappresentato dal valore di tensione di 5 V (o 3,3 V per quei componenti che hanno una tensione operativa massima di 3,3 V) sulla linea TTL (TX e RX) e da una differenza di tensione uguale a 0 V tra le due linee di rete CAN (L e H). Entrambe le linee CAN presentano un livello di tensione di circa 2,5 V.

Un segnale a stato logico basso sta ad indicare lo stato dominante ed è rappresentato dal valore di tensione di 0 V sulla linea TTL e una differenza di tensione uguale a 2 V tra le due linee CAN. In una rete CAN il segnale dominante sovrascrive sempre un segnale recessivo. Finché in una rete ci sarà un solo nodo a scrivere un segnale dominante, la rete si troverà sempre nello stato dominante. Si può considerare una rete CAN come se fosse una porta logica AND cablata.

Il vantaggio principale nell’utilizzo di un segnale differenziale è la sua immunità alle interferenze elettromagnetiche (EMI). Infatti, se un segnale è influenzato da un disturbo elettromagnetico esterno, tale disturbo influirà su entrambe le linee di trasmissione, dunque il disturbo si annullerà.

Formato dei messaggi e il Data Frame

Nel protocollo CAN esistono cinque differenti strutture di messaggi denominate: Data Frame, Remote Frame, Error Frame, Overload Frame e Interframe Space.
Il Data Frame è il tipo di messaggio più diffuso e permette la trasmissione dei dati da un nodo trasmettitore a tutti gli altri che si comportano come ricevitori, dopodiché ciascun nodo deciderà se ritenere rilevanti i dati ricevuti o se scartarli. Il Remote Frame ha una struttura simile al Data Frame ma è privo del campo dati, serve a sollecitare l’invio di un determinato Data Frame da parte del nodo interrogato. L’Error Frame viene inviato da un nodo che rileva un errore e provoca la ritrasmissione del messaggio da parte del nodo trasmettitore. Poiché è sufficiente che un solo nodo segnali un errore per avere la ritrasmissione, il protocollo CAN prevede che ciascun nodo monitorizzi il proprio stato di salute, autoescludendosi in caso di tasso di errore elevato (fault confinement). L’Overload Frame viene inviato da un nodo che risulta occupato per ritardare la trasmissione del pacchetto successivo. L’Interframe Space precede ogni Data e Remote Frame e ha una funzione separatrice.

Nella figura è rappresentata la struttura di un Data Frame. Il messaggio inizia sempre con un bit di avvio dominante, ovvero uguale ad 1. Successivamente segue l’identificativo del messaggio CAN di lunghezza 11 bit, questo campo è molto importante ed è necessario che il valore sia univoco nella rete perché viene utilizzato dal processo di arbitrato per evitare conflitti tra i nodi. Procedendo verso destra abbiamo 3 bit di controllo, il DLC da 4 bit sta ad indicare la quantità di byte occupata dal data field che a sua volta contiene l’informazione da trasmettere che può essere di lunghezza massima di 8 byte (64 bit). Per concludere, il Data Frame è composto da 15 bit per il CRC e i restanti bit utilizzati come delimitatore del CRC.

Controller CAN-bus su Raspberry Pi

Purtroppo, un computer Raspberry Pi non ha un controller CAN incorporato ma è possibile implementarlo esternamente. Il controller CAN standalone più popolare e compatibile anche a livello driver Linux è il MCP2515 della Microchip. Supporta il CAN V2.0B e una velocità massima di bit-rate di 1 Mbps. Inoltre, può essere interfacciato ad un microcontrollore o una CPU tramite il bus SPI. Oltre al controller CAN bisogna abbinargli un transceiver compatibile con lo standard ISO 11898. In commercio esistono diverse schede già assemblate con controller CAN e transceiver compatibili con Raspberry Pi, consigliabili per una prima fase di prototipazione. In particolare, possiamo menzionare la scheda open-source 2-CH CAN HAT di Waveshare facilmente reperibile.

Dal seguente link è possibile visualizzare lo schematico:

https://www.waveshare.com/w/upload/1/15/2-CH-CAN-HAT-Schematic.pdf

Dallo schema elettrico si può notare che il transceivers utilizzato è un SN65HVD230 che è conforme all’ISO 11898.

Fortunatamente nel kernel di Linux è già implementato anche il driver per poter utilizzare il controller CAN MCP2515, bisogna solo abilitarlo seguendo alcuni passaggi.

Il primo passo da seguire è quello di modificare il file config.txt presente all’interno della partizione boot del sistema operativo Raspberry OS. Dunque, bisogna aggiungere al file /boot/config.txt le seguenti righe:

dtparam=spi=on
dtoverlay=mcp2515-can1,oscillator=16000000,interrupt=25
dtoverlay=mcp2515-can0,oscillator=16000000,interrupt=23

La prima riga abiliterà il bus SPI, mentre le altre due abiliteranno i due controller CAN presenti sulla scheda menzionata poco fa.

Al successivo reboot del sistema, i driver dovrebbero inizializzarsi senza problemi, è possibile fare un controllo tramite il comando da terminale:

dmesg | grep spi

Dovrebbe comparire un messaggio del tipo “MCP2515 successfully initialized”.

A questo punto se tutto è stato inizializzato correttamente, bisogna abilitare le due interfacce CAN tramite i comandi:

sudo ip link set can0 up type can bitrate 1000000
sudo ip link set can1 up type can bitrate 1000000
sudo ifconfig can0 txqueuelen 65536
sudo ifconfig can1 txqueuelen 65536

Eseguendo il comando ifconfig sarà possibile vedere le due interfacce della rete CAN (can0 e can1). Arrivati a questo punto non bisogna far altro che testare le due interfacce. Per farlo è sufficiente utilizzare l’utility candump e cansend installabili con il seguente comando:

sudo apt-get install can-utils

Dopo l’installazione, aprendo un terminale, sarà possibile monitorare il traffico dei messaggi CAN su una determinata periferica tramite candump eseguendo il comando:

candump can0

Mentre con il tool cansend è possibile inviare un messaggio sulla rete CAN.

cansend can1 000#11.22.33.44

In caso di problemi oppure per maggiori informazioni si consiglia di visitare la pagina web di riferimento alla scheda 2-CH CAN HAT al seguente link:

https://www.waveshare.com/wiki/2-CH_CAN_HAT

Giuseppe Caccavale