[Risolto] Emulare il CAN BUS con varie ECU

Buongiorno ragazzi, spero di aver utilizzato la sezione corretta del forum. Come da titolo sto cercando di realizzare un sistema CAN BUS presente sulle auto. A questa rete simulata dovrei simulare altrettante ECU. Infine la rete deve terminare con un connettore OBD-II, ovvero quello presente nelle auto quando il meccanico fa la diagnostica. Mi sono documentato sui componenti che forse potrebbero essere utili tipo CAN-BUS Shield V2.0, CAN-BUS Grov, OBART OBD-II etc. Il mio problema è che non ho uno schema di riferimento per poter iniziare. Sono giusti i componenti scelti ? Per simulare N ECU ho bisogno di N Arduino ?
Grazie mille per il supporto.

Buongiorno,
essendo il tuo primo post, nel rispetto del regolamento della sezione Italiana del forum (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti IN QUESTO THREAD (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con molta attenzione tutto il su citato REGOLAMENTO ... Grazie. :slight_smile:

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposito thread, nessuno ti potrà rispondere, quindi ti consiglio di farla al più presto. :wink:

Ciao scusa per l'entrata a gamba tesa, mi sono subito presentato :slight_smile:

Ho letto la presentazione, per cui deduco che per la tesi ti possa tornare utile un sistema integrato sperimentale.

Chiaramente una ECU (Electronic control unit) è di per se una unita di controllo elettronico e per forza di cose è un sistema potenzialmente indipendente capace di connettersi ad un bus dati condiviso grazie al quale si viene a formare l'integrazione dei sistemi. Quindi si non c'è altro modo di simulare una ECU se non di usare almeno un arduino per ogni ECU.

Tuttavia si potrebbe pensare di usare un arduino per simulare più di una ECU, la quale alla fine invia e legge delle informazioni presenti sul bus e per fare questo basta un solo arduino, purtroppo la simulazione non risulterebbe veritiera, perché ogni ECU deve avere un suo specifico identificativo, il quale viaggia sul BUS dati.

La diagnostica tramite presa ODB ha valore solo se oltre al malfunzionamento si può stabilire l'identificativo della ECU.

Quindi riassumendo per ogni ECU un arduino board, per ogni board un transceiver CAN. Visto che la tesi verte sulla sicurezza non ti serve più di un BUS CAN. Come dire se la portiera dal punto di vista CAN è guasta non si pone il problema sicurezza. Mentre un problema al controllo di stabilità quello si che può compromettere la sicurezza. Per cui solitamente si usano almeno due BUS CAN.

Per il collegamento può fare una ricerca con google "physical layer can bus".

Ciao.

Grazie mille per il tempo dedicato, prenderò in considerazione i tuoi suggerimenti.

Come primo test d'esempio sto cercando di far comunicare due arduino attraverso due can bus shield di questo tipo(https://www.faranux.com/product/mcp2515-controller-bus-module-tja1050-receiver-spi-protocol-for-arduino/). Ho cercato di replicare le varie configurazioni presenti in rete con le varie librerie associate ma non sto ricevendo i risultati sperati, nel senso che i due arduino comunicano ma scrivono simboli strani. Dove sbaglio ?

Forse non fai alcun errore se non quello di interpretare male ciò che vedi nel serial monitor. Prova ad usare un serial monitor diverso, uno che ti permetta di vedere i codice grezzi senza interpretarli come codici ascii.

Ci sono alcuni codici ascii che se spediti da arduino non vengono stampati sul serial monitor, questo accade perché il serial monitor di arduino converte sempre il codice ricevuto in un carattere corrispondente. La corrispondenza tra codice e carattere la puoi vedere nella tabella ASCII su wikipedia.

Come serial monitor per windows so che c'è l'imbarazzo della scelta, mentre per linux io uso questo, che come vedi c'è anche la versione per windows, che tuttavia non ho provato. Su linux funziona perfettamente.

Ciao.

In QUESTA pagina si trova CoolTerm, ottimo terminale gratuito completamente multipiattaforma che fa tutto ciò che occorre :wink:

Io lo consiglio sempre ... :slight_smile:

Guglielmo

Ho risolto un mezzo problema impostando la velocità dei dati in bit al secondo per la trasmissione seriale dei dati nel riquadro del monitor ed ora sembra parlare italiano ma non vedo i risultati. Nella sezione inglese del forum si parla del clock presente sul modulo can bus di un certo crystal. Sarà quello il mio problema ?

Posta il codice di esempio con il suo output su serial monitor (sempre se stampa qualcosa).

Ciao.

Il codice d'invio è

#include <mcp_can.h>
#include <SPI.h>

MCP_CAN CAN0(10);                                      // Set CS to pin 10

void setup()
{
  Serial.begin(115200);
  // init can bus, baudrate: 500k
  if(CAN0.begin(CAN_500KBPS, MCP_8MHz) == CAN_OK) Serial.print("can init ok!!\r\n");
  else Serial.print("Can init fail!!\r\n");
}

unsigned char stmp[8] = {0, 1, 2, 3, 4, 5, 6, 7};
void loop()
{
  // send data:  id = 0x00, standrad flame, data len = 8, stmp: data buf
  CAN0.sendMsgBuf(0x00, 0, 8, stmp);  
  delay(100);                       // send data per 100ms
}

mentre il codice di ricezione è:

#include <mcp_can.h>
#include <SPI.h>

long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];

MCP_CAN CAN0(10);                               // Set CS to pin 10


void setup()
{
  Serial.begin(115200);
  CAN0.begin(CAN_500KBPS,MCP_8MHz);                       // init can bus : baudrate = 500k 
  pinMode(2, INPUT);                            // Setting pin 2 for /INT input
  Serial.println("MCP2515 Library Receive Example...");
}

void loop()
{
    if(!digitalRead(2))                         // If pin 2 is low, read receive buffer
    {
      CAN0.readMsgBuf(&len, rxBuf);              // Read data: len = data length, buf = data byte(s)
      rxId = CAN0.getCanId();                    // Get message ID
      Serial.print("ID: ");
      Serial.print(rxId, HEX);
      Serial.print("  Data: ");
      for(int i = 0; i<len; i++)                // Print each byte of the data
      {
        if(rxBuf[i] < 0x10)                     // If data byte is less than 0x10, add a leading zero
        {
          Serial.print("0");
        }
        Serial.print(rxBuf[i], HEX);
        Serial.print(" ");
      }
      Serial.println();
    }
}

Per quanto riguarda l'output del codice d'invio è (porta seriale COM3): can init ocan init ok!!
mentre per l'output del codice di ricezione è (porta seriale COM4): MCP2515 Library Receive Example...
In allegato c'è il collegamento fisico

mmmm...mi pare assurdo, no no ho riletto il codice e sicuramente non hai collegato nessun pulsante all'arduino ricevitore.

Serve collegare un pulsante al pin 2 di arduino. Modificare il codice nel setup per attivare la resistenza di pull-up interna alla MCU.

// pinMode(2, INPUT); // commentato o cancellato
pinMode(2, INPUT_PULLUP);

Ora pigiando il pulsante su arduino ricevitore si attiva questa porzione di codice:

if(!digitalRead(2))                         // If pin 2 is low, read receive buffer
    {
      CAN0.readMsgBuf(&len, rxBuf);              // Read data: len = data length, buf = data byte(s)

Ciao.

lo devo collegare anche fisicamente ?

Forse è meglio che fai pratica con gli esempio che ci sono nell'ide, perché oltre a sapere come collegare un pulsante ti serve molto altro per usare con profitto l'hardware sotto test.

Comunque si, serve portare il pin 2 a gnd per un attimo, normalmente questo si fa con un pulsante, ma se al momento non lo hai puoi fare il test con un cavetto da un lato connesso al connettore GND e l'altro capo lo colleghi e scolleghi rapidamente a mano sul pin 2.

Mi pare di capire che non hai cominciato con i tutorial, se è così inizia da qui

Ciao.

Grazie mille, problema risolto :slight_smile:

Vedo ora che non hai collegato il pin INT del modulo MCP2515 e l'esempio che hai usato dal commento si deduce che usa questo pin connesso al pin 2 di arduino.

pinMode(2, INPUT);                            // Setting pin 2 for /INT input

Il pin INT sul modulo corrisponde al piedino fisico 13 del MCP. L'uscita INT è negata, per cui è alta (in pull-up) quando non attivo. Quando attivato diventa LOW. Leggendo il datashett del MCP vedo che il comportamento di questo pin è configurabile.

Estratto dal datasheet

When the Receive Interrupt is enabled, RXnIE
(CANINTE) = 1, an interrupt will be generated on the
INT pin once a message has been successfully
received and loaded into the associated receive buffer.
This interrupt is activated immediately after receiving
the EOF field. The RXnIF bit (CANINTF) will be set to
indicate the source of the interrupt. The interrupt is
cleared by clearing the RXnIF bit.

Ciao.