Gérer 2 bus CAN avec un seul bus SPI

Bonjour à tous,

Je suis actuellement en BTS et j’ai un projet de fin d’année à réalisé et l’information que je vais vous demandé est introuvable sur le net (peut-être que si…).

Mon projet concerne un CAN bus déjà existant sur lequel j’interposerais ma carte électronique permettant de filtrer les informations et de renvoyer ce qui m’intéresse.

J’utilise 2 CAN Shield sur une seule Arduino Uno.

J’ai réussi à récupérer les données mais je n’arrive pas à en avoir en sortie. Pourtant j’ai quand même réussi à créer 2 entités différentes. Mais rien à faire je n’ai pas de trames en sortie même si ma trames existe car affiché sur le port série : (Screen en Attach)

Voici mon code (si vous avez réussi à me suivre jusque là ^^) :

#include <mcp_can.h>                            //Récupération des biblihothèques CAN_BUS
#include <SPI.h>
#include "mcp_can.h"

#define CapteurLum analogRead(4)               //Récupération de la valeur de Lumière
#define EclairageInt 7

const int SPI_CS_PIN = 9;

MCP_CAN  SS1 (9);
MCP_CAN  SS2 (10);

void setup() {

  Serial.begin(250000);

  while (CAN_OK != SS1.begin(CAN_250KBPS))              // Initialisation CAN_bus entrant vitesse = 250kbit/s
  {
    Serial.println("Lancement du CAN echoue");
    Serial.println(" Redemarrage CAN bus");
    break;
  }
  while (CAN_OK != SS2.begin(CAN_250KBPS))              // Initialisation CAN_bus sortant: vitesse = 250kbit/s
  {
    Serial.println("Lancement du CAN echoue");
    Serial.println(" Redemarrage CAN bus");
    break;
  }


  Serial.println("Initialisation du CAN bus OK!");
  pinMode(7, OUTPUT);
                              //Création du filtre Id: 0xC2
}

unsigned char len = 0;
unsigned char buf[8];
unsigned char canId1 = SS1.getCanId();
unsigned char canId2 = SS2.getCanId();





void loop() {
if (CAN_MSGAVAIL == SS1.checkReceive())
  {
  if (CAN_MSGAVAIL == SS1.checkReceive())           // Check réception de données
  {
    SS1.readMsgBuf(&len, buf);                       // Lecture données,  len: Taille de la données, buf: Buffer données
    canId1 = SS1.getCanId();
    
      if (canId1 == 0xC2)
      {
        buf [0] = 0x54;
      }

    SS2.sendMsgBuf(canId1, 0, len, buf);            // Renvoie sur CAN 2 des données
    
    Serial.println("-----------------------------");
    Serial.println("SS2 Données envoyées avec Id: 0x");
    Serial.println(SS2.getCanId(), HEX);

    for (int i = 0; i < len; i++) // Ecriture de la données
    {
      Serial.print(buf[i]);
      Serial.print("\t");
    }
    Serial.println();
  }
}

Merci d’avance pour tout aide

Cordialement,
Un jeune électronicien :slight_smile:

###############

EDIT

###############
J’adorerais présenté ce projet sur ce forum, il existe peu de projet de ce type sur le net (surtout en français cela pourrais aider beaucoup de gens)

Salut
tu veux pirater une voiture ? :slight_smile:

qu'entends tu par "j'interposerais ma carte électronique ?"

En fait je compte utiliser ma carte comme filtre CAN, sachant que je ne peux rien reprogrammer sur le véhicule ( c'est un bus, une voiture en plus gros :)).

Je pense que le problème vient du CS sur mon bus spi, mais je ne sais pas comment le régler.

Merci d'avance pour vos réponses.

Bon,

Après quelque recherche sur le bus SPI, il semblerait que le ChipSelect puisse se faire sur n’importe quelle sortie digital (ce qui me paraît franchement bizarre, car dans les datasheet du CAN-Shield, nous pouvons choisir la pin du ChipSelect soit 9 soit 10.

J’ai adapté mon programme et je verrais demain si cela marche mais vraiment pas facile de trouver ses infos j’ai l’impression que peu de gens utilise des CAN-Shield (le CAN fait peut-être peur ^^)

#include <mcp_can.h>                            //Récupération des biblihothèques CAN_BUS
#include <SPI.h>
#include "mcp_can.h"

#define CapteurLum analogRead(4)               //Récupération de la valeur de Lumière
#define EclairageInt 7
//
//const int SPI_CS_PIN = 9;

MCP_CAN  SS1 (9);
MCP_CAN  SS2 (10);

void setup() {

  Serial.begin(250000);

  while (CAN_OK != SS1.begin(CAN_250KBPS))              // Initialisation CAN_bus entrant vitesse = 250kbit/s
  {
    Serial.println("Lancement du CAN echoue");
    Serial.println(" Redemarrage CAN bus");
    break;
  }
  while (CAN_OK != SS2.begin(CAN_250KBPS))              // Initialisation CAN_bus sortant: vitesse = 250kbit/s
  {
    Serial.println("Lancement du CAN echoue");
    Serial.println(" Redemarrage CAN bus");
    break;
  }


  Serial.println("Initialisation du CAN bus OK!");
  pinMode(7, OUTPUT);
                              
}

unsigned char len = 0;
unsigned char buf[8];
unsigned char canId1 = SS1.getCanId();
unsigned char canId2 = SS2.getCanId();





void loop() {
  
if (CAN_MSGAVAIL == SS1.checkReceive())               // Check réception de données
  {
    digitalWrite(10,HIGH);                            //Sélection de l'esclave SPI 
    digitalWrite(9, LOW);                             //Sélection de l'esclave SPI 
    SS1.readMsgBuf(&len, buf);                       // Lecture données,  len: Taille de la données, buf: Buffer données
    canId1 = SS1.getCanId();
    
      if (canId1 == 0xC2)
      {
        buf [0] = 0x54;
      }
      
    digitalWrite(9, HIGH);                         //Sélection de l'esclave SPI 
    digitalWrite(10, LOW);                         //Sélection de l'esclave SPI 
    
    SS2.sendMsgBuf(canId1, 0, len, buf);            // Renvoie sur CAN 2 des données
    
    Serial.println("-----------------------------");
    Serial.println("SS2 Données envoyées avec Id: 0x");
    Serial.println(SS2.getCanId(), HEX);
    
    digitalWrite(10,HIGH);                         //Sélection de l'esclave SPI 

    
    for (int i = 0; i < len; i++) // Ecriture de la données
    {
      Serial.print(buf[i]);
      Serial.print("\t");
    }
    Serial.println();
    
  }

Si des personnes bien aimable on d’autre infos sur le CS ou SS sur une Arduino Uno :slight_smile:

Je tiendrais au courant de l’avancé du projet.
Bonne soirée

Cordialement,
Un jeune électronicien

Bonsoir

Après quelque recherche sur le bus SPI, il semblerait que le ChipSelect puisse se faire sur n'importe quelle sortie digital

Exact

ce qui me paraît franchement bizarre, car dans les datasheet du CAN-Shield, nous pouvons choisir la pin du ChipSelect soit 9 soit 10.

L'alternative 9 ou 10 pour SS est certainement une limitation propre au shield , une restriction par rapport à l'ensemble des connections théoriquement possibles. Les créateurs du shield on choix d'offrir un choix limité , c'est mieux que pas de choix.....

L'alternative 9 ou 10 pour SS est certainement une limitation propre au shield , une restriction par rapport à l'ensemble des connections théoriquement possibles

Donc selon toi mon code est bon ? En déclarant ainsi mes pinoches avant le setup puis en le mettant à l'état haut et l'état bas cela marcherait ? Mes 2 shields sauraient quand ils sont sélectionné ?

Merci pour ton aide.

les shields sauront quand ils sont sélectionnés … si sur ceux ci les connections correspondantes 9 ou 10 ont bien été établies (piste à couper, point de soudure, cavalier à placer…selon les diverses cartes.)
Sur la carte CAN Shield V2 de SeedStudio c’est bien expliqué

D'accord, merci pour ton aide je testerais ça demain au travail.

Je viendrais faire mon rapport :slight_smile:

Bonne soirée

Avancement du projet :

En ayant fait le changement sur mon premier shield comme ceci : (Attach 1)

Mon montage est comme ceci : (Attach 2)

J’ai donc changé mon code et mon SPI_CS_PIN est donc maintenant égal à 10. Voici le code changé:

#include <mcp_can.h>                            //Récupération des biblihothèques CAN_BUS
#include <SPI.h>
#include "mcp_can.h"

#define CapteurLum analogRead(4)               //Récupération de la valeur de Lumière
#define EclairageInt 7

 const int SPI_CS_PIN = 10;

MCP_CAN  SS1 (10);
MCP_CAN  SS2 (9);

void setup() {

  Serial.begin(250000);

  while (CAN_OK != SS1.begin(CAN_250KBPS))              // Initialisation CAN_bus entrant vitesse = 250kbit/s
  {
    Serial.println("Lancement du CAN echoue");
    Serial.println(" Redemarrage CAN bus");
    break;
  }
  while (CAN_OK != SS2.begin(CAN_250KBPS))              // Initialisation CAN_bus sortant: vitesse = 250kbit/s
  {
    Serial.println("Lancement du CAN echoue");
    Serial.println(" Redemarrage CAN bus");
    break;
  }


  Serial.println("Initialisation du CAN bus OK!");
  pinMode(7, OUTPUT);
                              
}

unsigned char len = 0;
unsigned char buf[8];
unsigned char canId1 = SS1.getCanId();
unsigned char canId2 = SS2.getCanId();





void loop() {
  
if (CAN_MSGAVAIL == SS1.checkReceive())               // Check réception de données
  {
    SS1.readMsgBuf(&len, buf);                       // Lecture données,  len: Taille de la données, buf: Buffer données
    canId1 = SS1.getCanId();
    
      if (canId1 == 0xC2)
      {
        buf [0] = 0x54;
      }

    
    SS2.sendMsgBuf(canId1, 0, len, buf);            // Renvoie sur CAN 2 des données
    
    Serial.println("-----------------------------");
    Serial.println("SS2 Données envoyées avec Id: 0x");
    Serial.println(SS2.getCanId(), HEX);
    
    for (int i = 0; i < len; i++) // Ecriture de la données
    {
      Serial.print(buf[i]);
      Serial.print("\t");
    }
    Serial.println();
    
  }
}

Et le résultat est simplement que le CAN ne s’initialise même plus, je ne récupère plus aucune trame : (Attach 3)

Merci d’avance pour votre aide je ne vois plus quoi faire.

Démarrage can impossible.PNG

Bonjour

Au vu de la photo "CS en pin 10" il n'est pas évident que la piste assurant à l'origine la liaison avec pin 9 ait été coupée

Bonjour,

Elle n'avait pas été coupé (en testant la continuité), j'ai donc dessoudé et mis en pin 10 sur l'autre shield (beaucoup plus simple car pré-perçage), et coupé la pin 9 du CS, je vais aller tester en revenir par ici pour donner des nouvelles.

La commande "int SPI_CS_PIN = 9;" défini-t-elle bien la pin sur laquelle je choisis mon esclave ?

Je vais aller tester avant votre réponse :smiley:

Merci encore

Je ne connais pas la librairie utilisée mais il semble que les deux lignes suivantes servent à déclarer les positionnement des SS de chacune des deux cartes CAN

MCP_CAN  SS1 (9);
MCP_CAN  SS2 (10);

Il n'est pas certain que la ligne suivante soit utilisée (seule une étude de la librairie CAN permettrait de conclure)
Elle parait faire double emploi avec les deux lignes citées ci dessus avec en plus l'inconvénient d'uen déclaration pour une seule carte......

const int SPI_CS_PIN = 10;

Donc selon toi je ne devrais pas utilisé cette commande?

J'ai trouvé un topic sur ton lien mais ils n'ont pas fini la conversation Dual can bus · Issue #70 · Seeed-Studio/Seeed_Arduino_CAN · GitHub

Selon eux juste besoin de déclarer les SS de la même manière que je l'ai fais sans la Déclaration de l'entier...