LOCODUINO

Mise en oeuvre du Bus CAN entre modules Arduino

Mise en oeuvre du Bus CAN entre modules Arduino (2)

2ème partie : la programmation

.
Par : Dominique, Jean-Luc

DIFFICULTÉ :

Dans la première partie de cet article, Mise en oeuvre du Bus CAN, nous vous avons présenté le Bus CAN comme un des meilleurs choix (je crois même que c’est le meilleur !) pour faire communiquer entre elles plusieurs cartes Arduino dans le cadre de nos projets ferroviaires.

Ce choix est d’autant plus raisonnable qu’il est facile de construire ses propres cartes CAN sur la base de la carte Can Locoduino ou à partir de cartes que l’on trouve maintenant facilement dans le commerce, pour peu que l’on fasse attention à leur compatibilité avec la carte Locoduino et le logiciel utilisé.

L’implémentation qui suit concerne uniquement les cartes Arduino à base de processeur Atmel (328, 2560), donc les Uno, Nano, Mega pour ne citer que les principaux.

Pour le Due, qui contient 2 interface CAN intégrées, c’est possible aussi mais avec une bibliothèque différente et du matériel différent mais plus simple.

Il va sans dire que le Due comme gestionnaire et quelques Mega et Nano pour s’occuper de la traction, les aiguilles, les occupations, les signaux et le décor, le tout relié sur un ou deux bus Can, constituent une informatique ferroviaire certainement haut de gamme, mais réalisable par nous autres amateurs.

Pour se fixer les idées, on va commencer par décrire les éléments logiciels qui font partie d’une carte de commande d’aiguilles, par exemple à base d’un Mega2560, sans entrer dans le détail de la façon de commander les moteurs d’aiguille (juste un petit peu), par les échanges CAN.

Ces éléments sont présentés dans l’ordre logique d’un programme Arduino. Il vous suffira de "copier-coller" les morceaux de code dans votre projet pour que les communications CAN soient immédiatement opérationnelles.

Mise en place de l’interface CAN : version "recette de cuisine"

Cette première partie dite "recette de cuisine" n’a pour but que de vous livrer les ingrédients à mettre en place dans votre programme, sans explication précise sur le bus CAN et son fonctionnement qui a été présenté dans l’article précédent. Ensuite viendront ces explications (patience !).

Aussi, si vous êtes impatient, le code important est disponible dès le début de l’article.

Le matériel se compose d’une carte Arduino (par exemple ici un Mega2560) et d’une carte CAN Locoduino. Si vous n’avez pas cette carte, mais une autre équipée d’un MCP2515 fréquencé à 16 MHz, ça doit marcher également.

On commence par relier à la carte CAN les broches du bus SPI, ainsi que le +5V et le 0V (Gnd).
Ajoutons une liaison entre la broche INT (interruption) de la carte CAN et la broche 2 (Interruption 0) de l’Arduino.l

Les branchements

Bus SPI de l’Arduino

Module CANArduino Uno/Pro Mini/Nano
SCK 13 (SCK)
SO 12 (MISO)
SI 11 (MOSI)
CS 10 (SS)
INT 2 (INT0)
Module CANArduino Mega
SCK 52 (SCK)
SO 50 (MISO)
SI 51 (MOSI)
CS 53 (SS)
INT 2 (INT0)

Alimentation

Module CANArduino
GND GND
VDD 5V

La bibliothèque

Il faut télécharger une bibliothèque qui se trouve ici : https://github.com/Seeed-Studio/CAN.... Puis il faut placer le dossier téléchargé dans le dossier des autres bibliothèques. Voir l’article Installer une bibliothèque.

Ensuite on doit placer ces 2 lignes en tête de programme pour bénéficier de la bibliothèque :

#include <SPI.h>                 // pour la bibliothèque CAN
#include "mcp_can.h"             // bibliothèque CAN

Puis il faut créer l’objet CAN comme le permet la bibliothèque :

// variables globales pour l'interface CAN
MCP_CAN CAN(53);   // Definition du CS (chip select) pin 53 (SS du bus SPI)
volatile byte Flag_Recv = 0;   // variable d'échange avec l'interruption IRQ

On voit ainsi qu’une variable globale Flag_Recv servira à faire savoir à la LOOP qu’un ou plusieurs messages sont arrivés sous interruption. Attention, quand cette interruption fait monter l’indicateur Flag_Recv, il faut bien prendre soin de vider TOUT le tampon du MCP2515 (sinon, il n’y aura plus d’autre IRQ et tout se bloque !).

Cette variable est positionnée par la routine d’interruption suivante :

/* 
 *  ISR CAN (Routine de Service d'Interruption)
 *  le flag IRQ monte quand au moins un message est reçu
 *  le flag IRQ ne retombe QUE si tous les messages sont lus
 */ 

void MCP2515_ISR()
{
     Flag_Recv = 1;
}

Après avoir placé ces lignes de code en tête de programme, dans la zone des définitions de variables, abordons le SETUP dans lequel on insère les lignes suivantes :

  /* -----------------------------------------------------
  *                       SETUP
  * -----------------------------------------------------
  */

  /////////////// INIT CAN /////////////////
  
while(true)
{
  if (CAN_OK == CAN.begin(CAN_500KBPS))      
   // initialisation du can bus : baudrate = 500k
  {
    Serial.println(F("CAN BUS init ok!"));
    break; // on sort du while.
  }
  else
  {
    Serial.println(F("CAN BUS init echec !"));
    Serial.println(F("Init CAN BUS a nouveau"));
  }
  delay(200);
}

On comprend bien ici que l’instruction CAN.begin(baudrate) démarre l’interface, avec un compte-rendu CAN_OK, sinon cela se répète car, à ce stade de l’initialisation, si le bus CAN ne démarre pas, il est inutile d’aller plus loin.

Personnellement je n’ai jamais vu d’échec sauf si la carte CAN n’est pas (ou est mal) branchée, coté Arduino.

Ensuite il faut attacher l’interruption 0 à la routine MCP2515_ISR() précédente :

attachInterrupt(0, MCP2515_ISR, FALLING); // interrupt 0 (pin 2)

Enfin on définit les filtres CAN qui limiteront les messages reçus à seulement ceux qui intéressent notre carte :

  /*
   * set mask & filter 
   */
   
  CAN.init_Mask(0, 0, 0x7F0);  // Il y a 2 masques à initialiser dans le mcp2515
  CAN.init_Mask(1, 0, 0x7F0);  // on teste tous les bits sauf les 4 de poids faible
   
  CAN.init_Filt(0, 0, 0x40);        // Reception possible : Id 40 à 4F (hex) 
  CAN.init_Filt(1, 0, 0x40);        // idem
  CAN.init_Filt(2, 0, 0x40);        // Reception possible : Id 40 à 4F (hex) 
  CAN.init_Filt(3, 0, 0x40);        // idem
  CAN.init_Filt(4, 0, 0x00);        // Reception possible : Id 00 à 0F
  CAN.init_Filt(5, 0, 0x00);        // Idem

A titre d’exemple, ces filtres sont initialisés ici pour ma carte de commande d’aiguilles.

Le setup ayant mis en place tous les acteurs, la loop peut commencer son travail répétitif !

/*-----------------------------------------------------
 *                        LOOP
 *-----------------------------------------------------                       
 */

void loop()
{

  if (Flag_Recv)  {
    Flag_Recv = 0;  // Flag MCP2515 prêt pour un nouvel IRQ
    CAN_recup();    // récupération du ou des messages CAN reçus
  }
  ...

Cette fonction CAN_recup() se charge de lire tous les messages reçus par le MCP2515 et les sauvegarder dans une mémoire tampon circulaire. Notre programme aura alors le loisir d’exploiter ces messages au rythme de son choix. Par exemple, on peut ne traiter qu’un seul message par tour de LOOP, mais j’ai constaté rapidement des pertes de messages. Il vaut mieux tout traiter d’un coup.

Tout d’abord il faut ajouter quelques variables globales :

// Variables globales pour la gestion des Messages reçus et émis
byte IdR;                       // Id pour la routine CAN_recup()
unsigned char lenR = 0;         // Longueur "    "       "
unsigned char bufR[8];          // tampon de reception      "
unsigned char bufS[8];          // tampon d'emission

// Variable globale Mémoire circulaire pour le stockage des messages reçus
unsigned char _Circule[256];    // récepteur circulaire des messages CAN sous IT
int _indexW, _indexR, _Ncan;    // index d'écriture et lecture, nb d'octets a lire
byte _CANoverflow = 0;          // flag overflow (buffer _Circule plein)

Voici la fonction CAN_recup() qui se charge du boulot :

/*
 * Routine de récupération des messages CAN dans la mémoire circulaire _Circule
 * appelée par LOOP lorsque Flag_Recv = 1;
 */
 
void CAN_recup()
{
  unsigned char len = 0;  // nombre d'octets du message
  unsigned char buf[8];   // message
  unsigned char Id;   // Id (on devrait plutôt utiliser un int car il y a 11 bits)

  while (CAN_MSGAVAIL == CAN.checkReceive())  {
    CAN.readMsgBuf(&len, buf);        // read data, len: data length, buf: data buf
    Id = CAN.getCanId();
    if ((_Ncan+len+2) < sizeof(_Circule))  { // il reste de la place dans _Circule
      _Circule[_indexW] = Id;         // enregistrement de Id
      _indexW++;
      _Ncan++;
      if (_indexW == sizeof(_Circule))  {_indexW = 0;}
      _Circule[_indexW] = len;        // enregistrement de len
      _indexW++;
      _Ncan++;
      if (_indexW == sizeof(_Circule))  {_indexW = 0;}
      for (byte z = 0; z<len; z++)  {
        _Circule[_indexW] = buf[z];    // enregistrement du message
        _indexW++;
        _Ncan++;
        if (_indexW == sizeof(_Circule))  {_indexW = 0;}
      }
    } else {
      _CANoverflow = 1;  // dépassement de la capacite de Circule
                            // le message est perdu
    }
  } 
}

A ce stade, on a juste reçu et sauvegardé les messages CAN qui viennent d’arriver.

Pour exploiter les messages, de façon indépendante de leur réception en temps réel, j’utilise le code suivant :

  byte RId;  // variables pour le traitement des messages lus dans _Circule
  byte Rlen;
  byte Rbuf[8];
  
  // traitement des messages stockés dans la mémoire circulaire _Circule
    
  while (_Ncan > 2)  {    // chaque message dans _Circule occupe au moins 3 octets
    _Ncan--;
    RId = _Circule[_indexR];        // recup Id
    _indexR++;
    if (_indexR == sizeof(_Circule))  {_indexR = 0;}
    _Ncan--;
    Rlen = _Circule[_indexR];       // recup longueur
    _indexR++;
    if (_indexR == sizeof(_Circule))  {_indexR = 0;}
    if (_dumpCan)  {     	 // _dumpCan est un boolean a déclarer en globale 
      Serial.print("CAN id ");	// si on veut conditionner l'affichage des message
      Serial.print(RId);
      Serial.print(", data ");
    }
    for (int k = 0; k < Rlen; k++)  {
      _Ncan--;
      Rbuf[k] = _Circule[_indexR];  // recup octets message
      _indexR++;
      if (_indexR == sizeof(_Circule))  {_indexR = 0;}
      if (_dumpCan)  {  
      Serial.print("0x");
      Serial.print(Rbuf[k], HEX);
      }
    }
    if (_dumpcan) Serial.println();
   // le message est maintenant dans les globales RId, Rlen et Rbuf[..]
  // ---> Votre traitement du message à ajouter ici <---
}

La suite du code est maintenant personnelle, selon la signification donnée à l’identifiant RId et aux octets de Rbuf.
On pourra avantageusement utiliser l’instruction switch pour traiter les différents cas de RId.

switch (Rid) {
  case xxx:
  // votre code
  break;
}

On pourra également utiliser les test de bits comme :

if (bitRead(Rbuf[0], 7) {
  // votre code
}

Et l’émission de messages ?

Mais c’est très simple :
J’envoie par exemple des messages ultra simples contenant un seul octet avec la fonction suivante :

void CANMessage(byte Message)
{
  unsigned char bufS[8];
  bufS[0] = Message;
  CAN.sendMsgBuf(0x30, 0, 1, bufS);  
  // Id = 30H (Aiguille), message standard avec 1 seul octet
}

Tous les éléments de base sont maintenant en place.
Voici quelques explications complémentaires.

Retour sur la fonction CAN_recup()

Pourquoi ne pas traiter directement les messages reçus par le MCP2515 dans la routine d’interruption ?
Il y a plusieurs raisons à cela :

  • il faut libérer cette routine le plus vite possible pour ne pas perdre de nouveaux messages
  • il faut éviter d’être obligé d’utiliser un grand nombre de variables globales qui seraient spécifiques aux traitements.

Le meilleur moyen de libérer le MCP2515 est de récupérer ce qui se trouve dans son tampon et le transférer en mémoire. Comme il est impossible de prévoir combien de messages arriveront, à quelle fréquence et avec quelle taille, un tableau ne convient pas du tout car il pourrait conduire au gaspillage de la mémoire.

J’utilise donc une mémoire circulaire, c’est à dire une série d’octets (un tableau unsigned char _Circule[256] précisément ici) qui est gérée comme une FIFO (1er entré, 1er sorti) : Les messages composés de leur Id (ramené à 1 octet), leur longueur len et leurs données (len octets) sont stockés à la queue leu leu au moyen d’un pointeur d’écriture _indexW qui avance d’un cran à chaque octet écrit. Lorsque ce pointeur arrive en bout de tableau, le pointeur est remis à zéro et ça continue.
Evidemment la lecture des messages se fait concurremment ailleurs dans la LOOP, à l’aide d’un pointeur de lecture _indexR répondant au même principe.

Pour savoir s’il y a des messages dans la mémoire circulaire, un compteur Ncan est incrémenté par la fonction CAN_recup() et est décrémenté par la fonction qui les traite.

Au fur et à mesure de la lecture des messages, le pointeur _indexR avance et Ncan diminue, ce qui libère de la place dans la mémoire.

Ncan = 0 signifie qu’il n’y a pas de message. Un message existe quand Ncan > 2 (un octet Id, un octet longueur, un octet de donnée).

Si Ncan = 256, cela veut dire que la mémoire circulaire est pleine, ce qui ne doit jamais arriver (il faudrait alors augmenter sa taille), ou que la fonction de traitement est en panne quelque part (c’est un bug !).

A vous de jouer !

Maintenant vous pouvez mettre du CAN dans vos projets ferroviaires !.

Yes you CAN !

79 Messages

  • communication entre deux arduino par can bus 4 janvier 2016 10:06, par alexandre

    Bonjour , est il possible d’allumer une led grâce à une impulsion sur un Bp entre deux deux arduino
    je voudrais que lorsque j’appuie sur un bp sur un arduino , une led sur un autre arduino s’allume
    les deux arduino communiquent par can bus

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 4 janvier 2016 10:50, par Dominique

    Bonjour,

    La réponse est OUI évidement et je pensais, à tort, que la réponse était dans l’article.

    Dans les sketchs de vos 2 Arduino, vous installez tout ce qui est écrit dans l’article et vous choisissez un format de message qui correspond à l’action "BP", avec un Id = votre_Id et une donnée qui peut être aussi simple que 1 bit dans le premier octet (1=true=enfoncé, 0=false=relaché, par exemple).

    Dans le sketch de l’Arduino qui gère le BP, vous testez l’état du BP (avec anti-rebond de préférence) et vous envoyez le message correspondant à son état à chaque changement, avec la routine CANMessage(byte Message) dans laquelle vous avez mis la valeur de l’Id choisie et Message = 0 ou 1 selon l’état du BP.

    En gros, la routine CANMessage() remplace l’instruction digitalWrite() qui commande la Led, si celle-ci était sur le même Arduino que le BP.

    Dans le sketch de l’Arduino qui gère a Led, vous "décodez" le message reçu comme indiqué plus haut :

    switch (RId) {
      case votre_Id:
        digitalWrite(Ledpin, Rbuf[0]);
      break;
    }

    Voilà c’est aussi simple que ça !

    Dites nous bien si ça marche !

    PS : n’oubliez pas les résistances de 120 Ohm à chaque extrémité du bus CAN

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 4 février 2016 00:31, par Stephan

    Bonjour,

    Où est-ce que je trouve les fichiers *.gerber pour fabriquer la carte CAN ?

    Merci pour les infos sur bus CAN.

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 8 mars 2016 16:05, par sierramike

    Bonjour et merci pour ces fabuleux articles !
    J’ai reçu une poignée de modules à base de 2515 qui me permettront de tester tout ça, mais après avoir lu l’article, il m’est apparu qu’il manque un détail qui a son importance : comment câbler le bus CAN ?
    Je suppose qu’il faut relier les CANH entre eux et les CANL entre eux, mais ensuite, les résistances 120 Ohms, on les met où ? Entre CANH et CANL ? Entre CANH et +5V ? Entre CANL et 0V ? Si on met une résistance entre CANH et CANL, quelle importance d’être à la "fin", on doit pouvoir la placer virtuellement n’importe où dans le bus ?
    Si on met entre CANH et 5V, et entre CANL et OV, faut-il en mettre une à chaque bout du bus ? Donc 4 resistances au total ?
    Merci d’avance pour ta réponse !

    Répondre

    • Mise en oeuvre du Bus CAN entre modules Arduino (2) 8 mars 2016 16:44, par Dominique

      Les réponses à vos questions sont :

      1) Relier les CANH ensemble et les CANL ensemble.
      2) Il faut seulement 2 résistances de 120 Ohms (pas plus, pas moins) à chaque extrémité du réseau (et pas au milieu !!!). Chaque résistance se situe entre CANH et CANL sur la carte qui se trouve à chaque extrémité.

      Ce n’est pas une résistance de tirage au Gnd ou au +5. Les alimentations ne doivent pas être reliées au bus. D’ailleurs le bus CAN permet de relier des cartes alimentées en 3,3V avec des cartes en 5V car c’est le différentiel entre CANH et CANL qui compte.

      ===>>> votre question m’étonne car toutes les cartes CAN, à ma connaissance, comportent cette résistance (un strap permet de la mettre en service ou non). Quelle carte CAN avez-vous approvisionné ?

      Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 26 avril 2016 09:40, par Plume

    Bonjour,
    Merci pour cette présentation très claire du bus CAN.

    Est-ce qu’il possible qu’une même carte Arduino UNO puisse recevoir et envoyer une trame avec le code donné ci-dessus. Cela fonctionne avec une carte MEGA mais j’ai aucune trame émise avec une UNO ?
    Le principe : la carte reçoit l’état d’occupation et du feu du canton N+1 et envoie ensuite son état (occupation, feu) au canton N-1.

    Merci d’avance pour la réponse

    Répondre

    • Mise en oeuvre du Bus CAN entre modules Arduino (2) 26 avril 2016 09:48, par Dominique

      Bonjour,

      Il n’y a aucune raison pour qu’une carte Uno, Nano, à base de 328, ne puisse envoyer ce type de trame.

      A part l’occupation mémoire ou les conflits sur l’utilisation du bus SPI ou celui des interruptions.

      Donnez nous plus de détails sur votre carte UNO, pour tenter de voir où cela coince.

      Bonne journée

      Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 26 avril 2016 10:08, par Plume

    L’instruction CAN.sendMsgBuf(0x30, 0, 1, bufS); bloque le programme avec une carte UNO.

    void loop() {
      boolean i = 1;
      if(Flag_Recv) { // check if get data
        Flag_Recv = false; // clear flag
        i = 0;
        CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf
        Serial.println("\nCAN_BUS GET DATA !");
        for(int i = 0; i<len; i++)  { Serial.print(buf[i]); Serial.print("\t"); }
      }
    
    // Code bloquant avec une carte UNO mais pas avec une MEGA
    if (buf[0] == 4 && i == 0) {CAN.sendMsgBuf(0x9, 0, 3, buf);  Serial.print("\n Envoi...");  i++; }

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 26 avril 2016 13:39, par Dominique

    À priori je ne vois rien d’anormal mais je ne suis pas dans de bonnes conditions pour réfléchir.

    Dans le 1er message vous dites que rien n’est émis. Dans le 2ème vous dites ça bloque. Mettez un Serial.print juste avant le sendMsgBuf pour voir si la condition du if se réalise.
    Quelle différence y a t-il entre le Mega et le Uno ?

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 13 mai 2016 22:36, par etudiante

    bonsoir
    je suis une étudiante ingénieur en génie électrique et je suis entrain de faire un projet fin d’étude.
    j’utilise dans mon projet des cartes arduinos qui font l’acquisition des données puis les affichent sur PC, la communication entre les cartes et le PC se fait avec le bus CAN.
    j’ai un petit problème dans la communication concernant la bibliothèque de bus CAN dans l’arduino.
    je trouve sur le net des bibliothèques qui envoient les données sur 8 octets (c’est logique puisque la taille maximale de la trame de données de bus can est de 8 octets) mais le problème que chaque donnée s’écrit seulement sur un octet (8 bits) donc si j’envoie par exemple des nombres supérieures à 2 exposant 8, la carte arduino retourne seulement le 8 premiers bits du nombre envoyé donc retourne une valeur fausse.
    y’a il quelqu’un qui a une idée ou une autre sorte de bibliothèque arduino pour un bus can qui permet l’envoie de tous nombres de taille inférieur ou égale 8 octets et n’est pas 8 bits ???
    cordialement

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 13 mai 2016 22:47, par Dominique

    Bonsoir,

    Bien que votre question ne semble pas en relation avec le modélisme ferroviaire, j’espère pouvoir vous aider quand même.
    Tout d’abord, pouvez-vous décrire votre environnement (quel Arduino, quel IDE, quelle interface et quelle bibliothèque CAN ?)

    Parce que dans les projets décrits et utilisés sur ce site, je vous garantis que le bus CAN peut utiliser de 1 à 8 octets comme prévu et cela fonctionne.

    Le fait de regarder les articles et les exemples devrait déjà répondre à votre question.

    Tenez-nous au courant de vos investigations.

    Répondre

    • Mise en oeuvre du Bus CAN entre modules Arduino (2) 13 mai 2016 23:16, par etudiante

      Merci d’abord pour votre réponse.
      j’utilise 2 arduino méga 2560 avec la bibliothèque CAN-BUS-SHEILD-MASTER, cette bibliothèque me permet d’envoyer 8 octets mais le problème quelle envoie seulement par octet donc si je veux envoyer un nombre supérieur à 255, le résultat affichée sera fausse elle prend du nombre seulement les 8 premiers bits.
      j’ai réussi à vous exprimez mon problème ou non ??

      Répondre

      • Mise en oeuvre du Bus CAN entre modules Arduino (2) 13 mai 2016 23:46, par Dominique

        J’ai bien compris votre problème : vous n’arrivez à passer qu’un seul octet !

        Ca ressemble à une erreur de programmation (indiquez-vous le nombre d’octets à transmettre ?), une utilisation erronée de la bibliothèque, peut-être un problème matériel (avez-vous les résistances de terminaison ?), est-ce l’émission qui est limitée ou la réception ?

        Faute de détails sur votre mise en œuvre, je ne peux que vous conseiller de comparer les articles et le forum de ce site avec votre réalisation : vous trouverez ainsi la solution du problème car les réalisations décrites sur Locoduino sont testée.

        Si vous ne trouvez pas, je vous conseille de vous adresser au site officiel Arduino.cc

        Bon courage

        Répondre

      • Certe ce n’est pas lié directement au ferroviaire mais la question va se poser dès que l’on veut transmettre des données qui ne sont pas des octets. Je parie là dessus :

        vous declarez votre trame CAN comme un tableau de byte ou de char :

        byte message[8];

        Ensuite, comme vous voulez envoyer des int qui sur les Arduino à base d’AVR occupe deux octets, vous écrivez :

        int a,b,c;
        
        message[0] = a;
        message[1] = b;
        message[2] = c;

        C’est à ce moment que vous perdez l’octet de poids fort de vos entiers qui nécessitent 6 octets de stockage.

        Première solution : Il faut que vous décomposiez vos données en octets pour les stocker dans les éléments du tableau message :

        message[0] = a >> 8;
        message[1] = a & 0x00FF;
        message[2] = b >> 8;
        message[3] = b & 0x00FF;
        message[4] = c >> 8;
        message[5] = c & 0x00FF;

        Mais rien n’oblige à déclarer un tableau d’octets. On peut déclarer un tableau d’entiers de 4 éléments :

        int message[4];

        Lors de l’émission, il faudra se rappeler que c’est bien le nombre d’octets que l’on indique. Le mieux est d’utiliser sizeof : si on transmet 3 entiers comme ci-dessus, la taille du message sera de 3 * sizeof(int).

        Attention toutefois. En procédant de cette manière, on se retrouve confronté au problème de l’endianess. En effet il se peut que les deux octets qui composent un entier ne soient pas stockés en memoire dans le même ordre sur le microcontroleur émetteur et le microcontroleur récepteur. Ceci dépend du matériel sur une architecture 16 ou 32 bits et du compilateur sur une architecture 8 bits. Le résultat serait l’inversion des octets de poids fort et de poids faible des entiers. Entre 2 AVR pas de problème, ce sont des microcontroleurs de la même famille. Le compilateur avr-gcc utilisé dans l’IDE Arduino manipule des entiers little endian. Pas de soucis pour faire communiquer de cette façon un Arduino AVR et un Arduino ARM car l’ARM est little endian également. Mais attention à la taille : un int occupe 2 octets sur AVR et 4 sur ARM. 

        On peut également declarer son message comme étant tout autre chose :

        typedef struct {
          word vitesse; // 2 octets
          byte feu;  // 1 octet
          bool sens; // 1 octet
        } trame_can;
        
        trame_can message;
        
        message.vitesse = 10;
        message.feu = 4;
        message.sens = true;

        La taille en octet étant donnée par sizeof(trame_can) et le pointeur passé à la fonction d’envoi étant &message

        Répondre

        • merci beaucoup pour votre réponse :)
          j’ai réussi à faire la première méthode. mais la deuxième ne marche pas j’ai cette erreur "no matching function for call to ’MCP_CAN::sendMsgBuf(int, int, int, trame_can&)’"
          maintenant pour la première méthode comment je peux récupérer la valeur décimale de l’entier envoyé pour l’afficher correctement par exemple pour l’entier 260 l’arduino affiche 1 et 4 puisque 260 =1+2^2*2^8 mais je veux que arduino affiche 260 et non 1 et 4.
          y’a il une méthode dynamique qui retourne la valeur décimale de l’entier ???
          et pour un type foat qui occupe 4 octets comment je peux le déclarer ???

          cordialement.

          Répondre

  • bonsoir :)
    j’ai réussi à avoir la valeur affichée en décimale avec la première méthode.
    maintenant il me reste la manière d’envoyer un float et pas un entier.
    merci bien pour votre aide :)

    Répondre

    • Mise en oeuvre du Bus CAN entre modules Arduino (2) 15 mai 2016 01:04, par Dominique

      Vous pourriez vous inspirer de ce code pour la conversion dans les 2 sens entre un long (Time) et 4 bytes (Page[4]) :

           Page[0] = Time;
           Page[1] = Time >> 8;
           Page[2] = Time >> 16;
           Page[3] = Time >> 24;
           
      /*   DEBUGGING PRINT OUT
           Serial.println("Page bytes: ");
           for(j = 0; j < 4;   j){
           Serial.println(Page[j], BIN);
           }
           Serial.println();
      */
           Time = 0;
           Time = Time | Page[3];
           Time = Time << 8;
           Time = Time | Page[2];
           Time = Time << 8;
           Time = Time | Page[1];
           Time = Time << 8;
           Time = Time | Page[0];

      voir ici également
      Lire et écrire dans une EEProm est dans le même cas.

      Répondre

    • Une autre façon de faire est de passer par une union :

      typedef union {
        byte octet[8];
        float flottant[2];
      } trame_can;
      
      trame_can message;

      Une union marche un peu comme une struct sauf que les membres sont alloués à la même adresse. Donc ici, message.octet[0] à message.octet[3] occupent la même zone mémoire de 4 octets que message.flottant[0]. Donc pour remplir avec des flottants :

      message.flottant[0] = 3.14158;
      message.flottant[1] = 2.71828

      Pour envoyer on passe message.octet à la fonction d’envoi.

      Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 15 mai 2016 20:40, par Dominique

    La réponse vous était donnée précédemment : il ne vous reste qu’à adaptez la fonction readfloat à votre besoin.

    byte-float

    Répondre

  • voilà mon code d’envoie et de réception, j’ai essayé comme vous m’avez dit mais toujours il y’a un problème lors de la compilation. Le code ci dessous ça marche juste dans le code de réception je veux afficher les 2 float envoyés.

    désolé si je vous dérange par mes questions ! et merci bien pour votre aide

    //*********************** sender code *******************************************
    // demo: CAN-BUS Shield, send data
    #include <mcp_can.h>
    #include <SPI.h>
    
    // the cs pin of the version after v1.1 is default to D9
    // v0.9b and v1.0 is default D10
    const int SPI_CS_PIN = 53;
    
    MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin
    
    void setup()
    {
        Serial.begin(115200);
    
        while (CAN_OK != CAN.begin(CAN_500KBPS))              // init can bus : baudrate = 500k
        {
            Serial.println("CAN BUS Shield init fail");
            Serial.println(" Init CAN BUS Shield again");
            delay(100);
        }
        Serial.println("CAN BUS Shield init ok!");
    }
    typedef union {
      byte octet[8];
      float flottant[2];
    } trame_can;
     
    trame_can message;
    
    void loop()
    {
        message.flottant[0] = 3.14158;
        message.flottant[1] = 2.71828; 
    
        CAN.sendMsgBuf(0x00, 0, 8,message.octet);
        
    }
    //**************** receiver code ****************************
    #include <SPI.h>
    #include "mcp_can.h"
    
    // the cs pin of the version after v1.1 is default to D9
    // v0.9b and v1.0 is default D10
    const int SPI_CS_PIN = 53;
    
    MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin
    
    void setup()
    {
        Serial.begin(115200);
    
        while (CAN_OK != CAN.begin(CAN_500KBPS))              // init can bus : baudrate = 500k
        {
            Serial.println("CAN BUS Shield init fail");
            Serial.println(" Init CAN BUS Shield again");
            delay(100);
        }
        Serial.println("CAN BUS Shield init ok!");
    }
    
    void loop()
    {
        unsigned char buf[8];
    
    
        if(CAN_MSGAVAIL == CAN.checkReceive())            // check if data coming
        {
            CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data 
    
            delay(100);
            
            unsigned char canId = CAN.getCanId();
            Serial.println("-----------------------------");
            
            Serial.print("Get data from ID: ");
            Serial.println(canId,HEX);
         
             for(int i = 0; i<8; i++)    // print the data
           {
               Serial.print(buf[i]);
               Serial.print("\t");
            }
            Serial.println();
      
      }
    }

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 16 mai 2016 09:11, par Jean-Luc

    Pour lire les deux float vous pourriez faire l’opération inverse de l’émission en utilisant la meme union. Votre question montre que vous ne comprenez pas vraiment ce que vous faites. Vous ne m’embêtez pas mais vous m’effrayez un peu. Pour atteindre un niveau ingénieur GEII, il va vous falloir faire de gros gros progrès en informatique bas niveau. Il y a du boulot.

    Répondre

  • bonjour :)
    c trés simple vous avez raison, mon code ça marche trés bien :) il suffit d’ajouter ce petit code si dessous. j’ai bien compris l’idée :) c vrai que j’étais un peu perturbée cette période, c pas question de compétences mais j’étais mal à l’aise à cause de grand charge de travail et du temps limité :) et je suis entrain de faire un grand projet toute seule et avec des nouvelles notions :) et comme vous avez me dit il faut travailler plus dur :) merci pour votre remarque qui m’encourage plus à avancer très vite :) voilà le reste de code :

    for(int i = 0; i<8; i++)    // print the data
    {
        message.octet[i]=buf3[i];
    }
    
    Serial.println();
    
    float y=message.flottant[1];
    float z=message.flottant[2];
    Serial.println(y); 
    Serial.println(z); 

    Répondre

  • Bonsoir :)
    j’ai une petite problème dans la réception des données,je veux envoyer 8 entiers et 16 float donc j’ai besoin d’envoyer 10 trames. les données dans la réception ne sont pas ordonnées, il y’a un conflit quelque part :( par exemples si j’envoie "10 11 13 20", dans la réception j’ai parfois "20 11 13 10". voilà les codes d’envoie et de réception ci dessous. si vous avez une idée merci de m’aider !!

    //**************** code d'envoi **************
    
    // demo: CAN-BUS Shield, send data
    #include <mcp_can.h>
    #include <SPI.h>
    
    // the cs pin of the version after v1.1 is default to D9
    // v0.9b and v1.0 is default D10
    const int SPI_CS_PIN = 53;
    
    MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin
    
    void setup()
    {
        Serial.begin(9600);
    
        while (CAN_OK != CAN.begin(CAN_500KBPS))              // init can bus : baudrate = 500k
        {
            Serial.println("CAN BUS Shield init fail");
            Serial.println(" Init CAN BUS Shield again");
            delay(100);
        }
        Serial.println("CAN BUS Shield init ok!");
    }
    
    typedef union {
      byte octet[8];
      int entier[4];
    } trame_can1;
     
    trame_can1 message1;
    trame_can1 message2;
    
    typedef union {
      byte octet[8];
      float flottant[2];
    } trame_can2;
    
    trame_can2 message3;
    trame_can2 message4;
    trame_can2 message5;
    trame_can2 message6;
    trame_can2 message7;
    trame_can2 message8;
    trame_can2 message9;
    trame_can2 message10;
    
    void loop()
    {
      message1.entier[0]=10 ;
      message1.entier[1]= 20;
      message1.entier[2]= 30;
      message1.entier[3]= 40;
    
      message2.entier[0]=50 ;
      message2.entier[1]= 60;
      message2.entier[2]= 70;
      message2.entier[3]= 80;
      
      message3.flottant[0]= 0.1;
      message3.flottant[1]= 0.2;
    
      message4.flottant[0]=0.3 ;
      message4.flottant[1]= 0.4;
    
      message5.flottant[0]=0.5 ;
      message5.flottant[1]= 0.6;
    
      message6.flottant[0]= 0.7;
      message6.flottant[1]= 0.8;
    
      message7.flottant[0]= 0.9;
      message7.flottant[1]=1.1 ;
    
      message8.flottant[0]= 1.2;
      message8.flottant[1]= 1.3;
    
      message9.flottant[0]= 1.4;
      message9.flottant[1]= 1.5;
    
      message10.flottant[0]=1.6 ;
      message10.flottant[1]=1.7 ;
      
        // send data:  id = 0x00, standrad frame, data len = 8, stmp: data buf
        CAN.sendMsgBuf(0x00, 0, 8,message1.octet);
        //delay(100);
        CAN.sendMsgBuf(0x01, 0, 8,message2.octet);
        //delay(100);
        CAN.sendMsgBuf(0x02, 0, 8,message3.octet);
        //delay(100);
        CAN.sendMsgBuf(0x03, 0, 8,message4.octet);
        //delay(100);
        CAN.sendMsgBuf(0x04, 0, 8,message5.octet);
        // delay(100);
        CAN.sendMsgBuf(0x05, 0, 8,message6.octet);
        //delay(100);
        CAN.sendMsgBuf(0x06, 0, 8,message7.octet);
        // delay(100);
        CAN.sendMsgBuf(0x07, 0, 8,message8.octet);
        //delay(100);
        CAN.sendMsgBuf(0x08, 0, 8,message9.octet);
        //delay(100);
        CAN.sendMsgBuf(0x09, 0, 8,message10.octet);
        //delay(100);
        
    }
    //************* code de réception ***************************
    
    // demo: CAN-BUS Shield, receive data with check mode
    // send data coming to fast, such as less than 10ms, you can use this way
    // loovee, 2014-6-13
    
    #include <SPI.h>
    #include "mcp_can.h"
    
    // the cs pin of the version after v1.1 is default to D9
    // v0.9b and v1.0 is default D10
    const int SPI_CS_PIN = 53;
    
    MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin
    
    typedef union {
      byte octet[8];
      int entier[4];
    } trame_can1;
     
    trame_can1 message1;
    trame_can1 message2;
    
    typedef union {
      byte octet[8];
      float flottant[2];
    } trame_can2;
    
    trame_can2 message3;
    trame_can2 message4;
    trame_can2 message5;
    trame_can2 message6;
    trame_can2 message7;
    trame_can2 message8;
    trame_can2 message9;
    trame_can2 message10;
    
    void setup()
    {
        Serial.begin(9600);
    
        while (CAN_OK != CAN.begin(CAN_500KBPS))              // init can bus : baudrate = 500k
        {
            Serial.println("CAN BUS Shield init fail");
            Serial.println(" Init CAN BUS Shield again");
            delay(100);
        }
        Serial.println("CAN BUS Shield init ok!");
    }
    
    void loop()
    {
        unsigned char len = 0;
        unsigned char buf1[8];
        unsigned char buf2[8];
        unsigned char buf3[8];
        unsigned char buf4[8];
        unsigned char buf5[8];
        unsigned char buf6[8];
        unsigned char buf7[8];
        unsigned char buf8[8];
        unsigned char buf9[8];
        unsigned char buf10[8];
    
        if(CAN_MSGAVAIL == CAN.checkReceive())            // check if data coming
        {
            CAN.readMsgBuf(&len, buf1);    // read data,  len: data length, buf: data buf
            delay(100);
            CAN.readMsgBuf(&len, buf2);  
            delay(100);  
            CAN.readMsgBuf(&len, buf3);
            delay(100);
            CAN.readMsgBuf(&len, buf4);  
            delay(100);  
            CAN.readMsgBuf(&len, buf5);  
            delay(100);
            CAN.readMsgBuf(&len, buf6);  
            delay(100);  
            CAN.readMsgBuf(&len, buf7);  
            delay(100);
            CAN.readMsgBuf(&len, buf8);  
            delay(100);  
            CAN.readMsgBuf(&len, buf9);
            delay(100);  
            CAN.readMsgBuf(&len, buf10);  
            delay(100);
                      
            //unsigned char canId = CAN.getCanId();
            //Serial.println("-----------------------------");
            
            //Serial.print("Get data from ID: ");
            //Serial.println(canId,HEX);
         
              for(int i = 0; i<8; i++)    // print the data
            {
             message1.octet[i]=buf1[i];
             message2.octet[i]=buf2[i];
             message3.octet[i]=buf3[i];
             message4.octet[i]=buf4[i];
             message5.octet[i]=buf5[i];
             message6.octet[i]=buf6[i];
             message7.octet[i]=buf7[i];
             message8.octet[i]=buf8[i];
             message9.octet[i]=buf9[i];
             message10.octet[i]=buf10[i]; 
            }
           
            
            Serial.print(message1.entier[0]);
            Serial.print(" ");
            Serial.print(message1.entier[1]);
            Serial.print(" ");
            Serial.print(message1.entier[2]);
            Serial.print(" ");
            Serial.print(message1.entier[3]);
            Serial.print(" ");
            
            Serial.print(message2.entier[0]);
            Serial.print(" ");
            Serial.print(message2.entier[1]);
            Serial.print(" ");
            Serial.print(message2.entier[2]);
            Serial.print(" ");
            Serial.print(message2.entier[3]);
            Serial.print(" ");
    
            Serial.print(message3.flottant[0]);
            Serial.print(" ");
            Serial.print(message3.flottant[1]);
            Serial.print(" ");
    
            Serial.print(message4.flottant[0]);
            Serial.print(" ");
            Serial.print(message4.flottant[1]);
            Serial.print(" ");
    
            Serial.print(message5.flottant[0]);
            Serial.print(" ");
            Serial.print(message5.flottant[1]);
            Serial.print(" ");
    
            Serial.print(message6.flottant[0]);
            Serial.print(" ");
            Serial.print(message6.flottant[1]);
            Serial.print(" ");
    
            Serial.print(message7.flottant[0]);
            Serial.print(" ");
            Serial.print(message7.flottant[1]);
            Serial.print(" ");
    
            Serial.print(message8.flottant[0]);
            Serial.print(" ");
            Serial.print(message8.flottant[1]);
            Serial.print(" ");
    
            Serial.print(message9.flottant[0]);
            Serial.print(" ");
            Serial.print(message9.flottant[1]);
            Serial.print(" ");
    
            Serial.print(message10.flottant[0]);
            Serial.print(" ");
            Serial.print(message10.flottant[1]);
            Serial.print(" ");
    
            Serial.println();
    
            delay(100);
      }
    }

    Répondre

    • Mise en oeuvre du Bus CAN entre modules Arduino (2) 21 mai 2016 08:37, par Dominique

      Vous avez posé cette question sans vous identifier (donné votre adresse email), ni précisé si elle concerne le modélisme ferroviaire.

      Une réponse sera donnée après ce préalable, sinon votre question sera supprimée.

      Néanmoins, les bons programmeurs en télécommunication savent bien qu’il faut numéroter les messages pour les remettre en ordre à l’arrivée.

      Il y a de très bons ouvrages sur le net (et dans la bibliothèque de votre école) qui décrivent comment fonctionnent les réseaux en général et le CAN ne particulier.

      C’est à vous maintenant de trouver la solution...

      Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 21 mai 2016 10:34, par etudiante

    Bonjour :)

    merci de me donner un lien,un document ou un exemple sur le net pour que je puisse avancer et comprendre mieux le fonctionnement de bus CAN.

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 21 mai 2016 10:42, par Dominique

    Ah tiens, vous ne savez pas faire une recherche sur Internet ?
    Une recherche avec "Can bus communications" donne 6 250 000 réponses : il y a de quoi faire, non ?
    Connaissez-vous Wikipedia ?
    Un document : http://www.ti.com/lit/an/sloa101a/s...

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 22 décembre 2016 12:23, par ramboman

    Bonjour
    je vois que vous regroupez les activités des Arduino par catégorie : aiguilles, feux...
    lors de mes 1ers tests j’ai plutôt prévu un Arduino par canton...
    Quel serait à votre avis l’approche la plus appropriée ?
    Excellent sujet !

    Répondre

    • Mise en oeuvre du Bus CAN entre modules Arduino (2) 22 décembre 2016 12:36, par Dominique

      Bonjour,

      C’est une excellente question d’architecture informatique de réseau : j’avoue que je n’avais pas pensé à cette architecture du type 1 Arduino par canton, qui pourrait ressembler à une architecture neuronale.

      Pour moi le gestionnaire (au sens de ce que décrit Pierre59 dans la série "Un gestionnaire en C++ pour votre réseau") doit rester quand même centralisé, ce que permet bien entendu le bus CAN non hiérarchique.

      Je vous propose de continuer cette discussion sur le Forum où il y a justement un sujet sur l’architecture et la modélisation.

      A bientôt sur ce forim
      Et bonnes fêtes
      Dominique

      Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 22 décembre 2016 14:36, par ramboman

    Si j’avais besoin d’un gestionnaire centralisé, j’aurais pu me contenter de I²C... demander au bloc suivant s’il peut recevoir mon train implique une structure "multi-master" donc CAN... mais je vais malgré tout suivre le lien... merci.

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 19 janvier 2017 07:53, par Roland

    Bonjour
    je voudrais m’assurer de ceci :
    le réseau can a deux extrémités munies chacune d’une résistance de 120 ohms
    il n’y a pas d’embranchement prévu
    donc si je branche une manette de commande il y aura forcément 4 fils...
    exact ?
    et si je débranche la manette pour suivre le train... il y aura forcément coupure du réseau can...
    exact ?
    donc il serait préférable de passer à un réseau sans fil pour les manettes...
    Puis-je avoir votre avis sur la question...
    Roland

    Répondre

    • Mise en oeuvre du Bus CAN entre modules Arduino (2) 19 janvier 2017 08:37, par Jean-Luc

      Bonjour,

      En substance, non (presque) et non.

      Tout d’abord on peut imaginer deux architectures :

      1. La manette se branche non pas sur le réseau CAN mais sur une carte connectée au réseau CAN qui fait passerelle
      2. La manette se branche sur le réseau CAN

      Pour le 1, on n’ajoute ni enlève de nœud au CAN.

      Pour le 2, le réseau est un bus, par conséquent rajouter un nœud ne se fait pas en interrompant le réseau mais en venant faire contact électrique sur la paire de fils à n’importe quel endroit où, bien sûr, on aura prévu un connecteur.

      Concernant la première question, il y aura 4 fils car il faut également que la manette soit alimentée et on prévoira un connecteur avec le CAN plus l’alimentation. Mais les deux fils d’alimentation n’ont rien à voir avec le CAN.

      Répondre

      • Mise en oeuvre du Bus CAN entre modules Arduino (2) 19 janvier 2017 09:56, par Roland

        C’est bien clair... (ou presque)...
        1. l’arduino de la manette est sur le réseau... les organes de commande sont dans un boitier passif connecté par câble (ou sans fil) à cet arduino
        2. si l’arduino de manette est au bout du fil il est nécessairement en dérivation "Y" sur le réseau... est-ce que can supporte ça ?

        Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 19 janvier 2017 13:43, par Jean-Luc

    Oui, deux camarades le font avec 4 manettes et environ 1m de câble par manette.

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 23 janvier 2017 05:47, par Roland

    Bonjour
    Avant tout "merci" pour ton fil sur le can-bus... c’est bien la première fois que je lis un texte aussi clair sur l’utilisation des masques et des filtres et sur la structure des messages.
    Avec l’arrivée de cartes à 1.65€ ça ouvre des pistes de développement inconcevables il y a peu de temps.
    Il reste un point cependant dont l’utilité m’échappe : le "circule"... le protocole "can" garantit en effet l’arrivée des paquets... pourquoi t’en charger alors une deuxième fois ?

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 23 janvier 2017 11:08, par Dominique

    Le "circule" fait, en effet, double emploi avec le tampon de la bibliothèque Can dont je ne connais pas la petite taille.
    Il a l’avantage de me permettre de choisir une taille plus grande que celle de la bibliothèque pour garantir que je ne perde aucun message.

    C’est une vieille habitude de programmation dans les télécom que j’ai gardée et que je souhaitais partager.

    En fait, ce "tampon circulaire" permet de lire immédiatement tous les messages entrants, ce qui évite de les rater et de provoquer des répétitions sur le bus (si personne ne le lit). Or sur le bus Can de mon réseau, plusieurs récepteurs sont susceptibles de lire les messages selon les filtres programmés. Donc un message peut être perdu réellement.

    C’est donc une sécurité, utile et peu coûteuse en temps processeur.

    Mais pour de petites applications, ce n’est pas toujours utile.

    Répondre

    • Mise en oeuvre du Bus CAN entre modules Arduino (2) 23 janvier 2017 15:38, par Roland

      Encore merci
      j’avais donc bien compris...
      Sans "circule" (qu’il faut se donner la peine de défricher... ce que j’ai fait), et avec tes conseils, le can-bus devient en effet d’une simplicité "biblique" à implanter.
      Je vais rester sur la notion d’un Arduino par canton... il me reste à tester une alimentation DC pur (non PWM), probablement avec un LM338 piloté pas Arduino (le schéma ad-hoc reste à trouver)

      Répondre

  • comment recuperer données du CAN MCP3202 en spi 26 janvier 2017 11:51, par Douds83

    Bonjour, je dois récupérer les données situées dans mon CAN MCO3202 et les transferer dans mon arduino avec la librairie du spi.
    Merci de m’aider.....

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 15 février 2017 15:34, par vito

    Bonjour, je voudrais communiqué entre un automate programmable, équipe d’un port CANbus modbus et un ardruino lequel communiquera avec une carte(sim800 ou autre), quelle matériel faut il pour cette configuration&

    Répondre

  • Mise en route d’un protocole CAN sur ArduinoMicro 24 avril 2017 11:28, par Robin

    Bonjour,

    Je suis un étudiant suisse entrain de mettre un place un "Block system" pour une maquette ferroviaire et j’aimerais mettre en place un protocole CAN pour communiquer entre les cantons de ma maquette.

    A ce stade,à l’aide de deux Arduino micro et des chips MCP2551/MCP2515, j’ai tenté de mettre en oeuvre une communication CAN en utilisant la libraire : https://github.com/coryjfowler/MCP_...

    A l’aide de l’oscilloscope , je vois que le Uc Arduino envoie des trâmes par le bus SPI au MCP2515 mais celui ci ne les retransmet pas au MCP2551.

    Quelqu’un aurait il déjà été confronté à ce problème ?

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 25 avril 2017 02:09, par Dominique

    Bonjour,
    Il est difficile de vous répondre en l’absence de schéma mettant en œuvre les 2515/2551.
    Vous trouverez sur ce site et sur le forum des exemples de cartes CAN qui fonctionnent parfaitement. On en trouve d’ailleurs à des prix dérisoires sur la baie.

    Répondre

  • Bonjour,
    Excellent sujet et démonstration !
    Je voulais testé le programme histoire de bien me familiariser avec le CAN pour des premiers essais, hors ce dernier se bloque en plein milieu de l’exécution, le problème arrive au niveau de la fonction CAN_recup(), elle se bloque lors de la quatrième exécution.
    J’ai utilisé le programme en identique en rajoutant une petite ligne de CAN.sendMsgBuf avec l’adresse registre et les DATA pour communiquer avec un esclave dans le réseau CAN.

    Répondre

    • Mise en oeuvre du Bus CAN entre modules Arduino (2) 26 avril 2017 03:46, par Dominique

      Bonjour,

      Quand vous écrivez que Can_recup() se bloque à la 4ème exécution, par quoi cela se manifeste ? Comment l’avez-vous détecté ?

      Est-ce que c’est l’interruption qui n’arrive plus ?

      Peut-être récupérez-vous trop ou pas assez de messages ??

      Répondre

      • Bonjour,
        Merci pour votre réponse.
        Je remarque que pour la 4ème itération la condition "if(Flag_Recv)" n’est plus satisfaite, ceci veut dire qu’il n y a pas de message reçu.
        J’ai remarqué que sur votre article vous avez précisé qu’il faut être sur de vider le tampon du MCP2515 est ce que ça pourra être la cause ?

        Répondre

        • Mise en oeuvre du Bus CAN entre modules Arduino (2) 27 avril 2017 04:22, par Dominique

          Oui c’est bien cela.
          je vous encourage à lire la datasheet du 2515 !
          Votre problème révèle qu’il ne faut pas qu’un programme se bloque, il ne faut pas perdre le contrôle. Dans votre cas, comme dans tous les cas, il faut tester tous les résultats et agir en conséquence.
          Il ne faut pas hésiter à avoir plus de lignes de code pour traiter les cas anormaux que pour les cas normaux.

          Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 8 juillet 2017 14:34, par Jacques

    Bonjour Dominique et Jean-Luc,
    Pour faire suite à ces 2 articles concernant la "Mise en oeuvre du Bus CAN entre modules Arduino", serait-il possible d’approfondir le bus CAN en utilisant la petite carte "Arduino MCP2515 CAN Bus Module TJA1050 Receiver SPI Module" peu chère et facilement accessible sur ebay ?
    Merci d’avance
    Jacques

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 13 novembre 2017 16:14, par Jean-Claude

    Bonjour
    Je découvre le monde de l’arduino. Il simplifie la vie du modéliste. J’intègre le Can-Bus dans ma maquette et le prochain travail sera le S88.
    Je vous remercie pour TOUTES les rubriques.
    Cordialement
    Jean-Claude

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 12 décembre 2017 20:56, par Jo

    Je viens de recevoir des modules MCP2515/TJA1050 et je constate que le quartz de la carte est cadencé à 8MHz alors que les cartes Arduino que j’utilise sont à 16MHz. Avant de me lancer dans les montages, pourriez vous me dire si c’est compatible ? Sinon comment faire : désouder le quartz 8MHz et souder un 16MHz ou y a t il moyen de diviser par 2 la cadence de l’Arduino ? Merci.

    Répondre

  • Cela devrait être compatible mais la vitesse sur le bus sera la moitié de celle qui sera configurée.

    Cela veut dire que cette carte ne dépassera pas les 500 kb/s en la programmant à 1Mb/s

    On peut aussi changer le quartz mais c’est difficile à dessouder !

    Dominique

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 25 janvier 2019 15:49, par SUPERN

    Bonjour,
    Je voudrai utiliser ce bus pour régler les butées d’un décodeur 8 servos avec un décodage DCC qui utilise déjà INT0.
    Peut-on utiliser INT1 (broche 3) à la place ?
    Merci de tout conseil relatif à cette cohabitation.

    Répondre

    • Mise en oeuvre du Bus CAN entre modules Arduino (2) 25 janvier 2019 16:24, par Jean-Luc

      Bonjour,
       
      Bien sûr,
      Il suffit de changer le changer le attachInterrupt(0, MCP2515_ISR, FALLING); en attachInterrupt(1, MCP2515_ISR, FALLING);. Ou mieux pour se mettre au goût du jour attachInterrupt(digitalPinToInterrupt(3), MCP2515_ISR, FALLING);.

      Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 26 décembre 2019 05:00, par Jean-Pierre Delwasse

    Bonjour,
    merci pour votre article et la contribution que vous apportez au modélisme ferroviaire. Je suis membre de l’AMFL et conçois la modernisation d’un de nos réseaux sur la base de nœuds arduino reliés par un réseau CAN. J’ai deux questions :

    • où peut-on se procurer la carte Module CAN Locoduino ?
    • est-ce que les shields qu’on peut trouver sur AliExpress à entre 4 et 8 € sont utilisables pour notre application ?
      Merci d’avance pour votre réponse.
      Jean-Pierre Delwasse

    Voir en ligne : MCP2515 Module Arduino CAN-BUS

    Répondre

    • Mise en oeuvre du Bus CAN entre modules Arduino (2) 26 décembre 2019 09:16, par Dominique

      Actuellement la tendance serait d’aller plutôt vers le MCP 2517 ( voir le forum, ici).
      Mais la petite carte que vous mentionnez semble parfaitement compatible avec la carte Locoduino. Je ne l’ai pas essayée.
      celle-ci est intéressante mais le quartz est à 8mhz donc les vitesses du Can sont divisées par 2.

      Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 29 décembre 2019 18:13, par bobyAndCo

    Petite rectification, ces cartes ont un quartz de 16 Mhz ! En fait, ce sont des copies quasi identiques des cartes SEEED. Le rapport qualité prix est excellent. J’en ai acheté 5 pour ma part. J’ai juste testé mais pas fait de tests en "charge". Didier par contre utilise ces cartes aussi et les a testées en exploitation. Vous pouvez vous mettre en rapport par MP.

    http://forum.locoduino.org/index.ph...;;u=265

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 13 février 2020 06:41, par Cedric

    Bonjour et merci pour l’excellent l’article !

    J’aurai aimé avoir votre retour d’expérience sur les câbles. Le CAN impose un câble torsadé mais j’ai vu certains montages avec des câbles plats et des connecteurs RJ11.

    Est-ce qu’un câble plat fonctionne bien finalement de l’ordre de 10m ?

    Merci d’avance

    Répondre

    • Mise en oeuvre du Bus CAN entre modules Arduino (2) 13 février 2020 09:32, par Dominique

      Bonjour,

      le bus Can n’impose rien en particulier sur de courtes distances car il utilise 2 fils en différentiel. C’est mieux en effet d’utiliser de la paire torsadée (câble téléphonique, câble ethernet. Des prises RJ11 sont très pratiques mais pas obligatoires. Il faut bien respecter la polarité.

      Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 15 février 2020 07:30, par Cédric

    Je croyais que c’était obligatoire mais je suis soulagé ! Merci Dominique.

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 5 avril 2021 17:42, par Frederic

    Bonjour, merci pour cet excellent article qui se déguste à petites doses répétées !
    Mon projet est un réseau bouclé géré par BALs autonomes (1 BAL = 1 nano), dialoguant par bus CAN. Chaque nano gère son canton incluant tout un ensemble de feux, relais, capteurs et aiguilles en interface i2c avec le nano. Est-ce que les gestions des bus CAN et i2c sont compatibles sur un même nano (bien sûr via des I/O spécifiques) ?

    pour préciser, la traction reste analogique via pwm, c’est le contrôle de circulation que je décris dans la question.

    Merci par avance pour vos réflexions !

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 5 avril 2021 19:30, par Dominique

    Bien-sûr, le bus Can utilise le SPI donc indépendamment de l’I2C.

    Nous serions interessé par la présentation de votre projet, en ouvrant un sujet sur le Forum.
    Merci d’avance.

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 3 septembre 2021 14:08, par Teindas RP

    Bonjour,

    Je suis en train de lutter afin de réaliser un CI avec 8 x MAX31855 (thermocouples) et une MEGA 2560.

    Je souhaite faire communiquer tout cela au travers d’un CAN-bus MCP2515, lui même relié à un hub can bus.
    Question : Raccordement MCP2515===>Mega pas de souci (pins 50 à 53)
    Raccordement des 8 x MAX au module MCP2515, dois-je raccorder les SO et SI des 8 MAX en// ?
    Merci de votre aide.
    Cordialement
    René-Pierre

    Répondre

    • Mise en oeuvre du Bus CAN entre modules Arduino (2) 3 septembre 2021 16:47, par msport

      Bonjour,
      votre projet ferroviaire doit certainement être un LGB pour avoir besoin de mesurer huit températures ? Pensez à le décrire sur le forum, rubrique "Vos projets".
      Consultez les spécifications : MISO=SDO=DO et SCK font partie du bus SPI et sont donc en parallèle. Vous devrez affecter une sortie du Mega à chaque CS (SPI_CHIP_SELECT) de vos MAX31855 pour les interroger un par un. Utilisez l’exemple de la bibliothèque Arduino existant pour ce composant.

      Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 3 septembre 2021 17:45, par Teindas RP

    Merci de votre réponse. Je regarde tout cela et communique la suite.

    Très cordialement.
    René-Pierre

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 6 novembre 2021 16:43, par pat95

    Bonjour
    Suite à une mise à jour de l’IDE ARDUINO j’ai mes programmes utilisant BUS CAN ne fonctionnent plus !
    J’ai chargé la nouvelle librairie.
    J’ai testé avec les exemples set_mask_filter_send et set_mask_filter_recev de la bibliothèque CAN-BUS Sield sans oublier de modifier const int SPI_CS_PIN = 10 ; mais la réception s’interrompe et est anarchique !
    Peut-on retrouver l’ancienne librairie ?
    Merci.

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 6 novembre 2021 18:17, par Dominique

    Je vous conseille fortement de changer de bibliothèque et d’utiliser ACAN 2515 (voir nos articles "La bibliothèque ACAN (1) et (2) : https://www.locoduino.org/spip.php?...)

    Et tenez nous au courant..
    Bon courage

    Répondre

  • Mise en oeuvre du Bus CAN entre modules Arduino (2) 24 novembre 2023 09:05, par Guillaume

    Bonjour,
    à moins d’être passé à côté, la norme S9.7 (LCC), destinée au Bus CAN dans le cadre du modélisme ferroviaire, n’est jamais évoquée. Comment se fait-il que celle-ci reste aussi confidentielle en Europe ? …
    Cordialement,

    Voir en ligne : LCC

    Répondre

  • Oui c’est aussi la question qu’on se pose !

    C’est peut-être trop complexe et lourd à implémenter.
    Votre avis ?

    Répondre

Réagissez à « Mise en oeuvre du Bus CAN entre modules Arduino (2) »

Qui êtes-vous ?
Votre message

Pour créer des paragraphes, laissez simplement des lignes vides.

Lien hypertexte

(Si votre message se réfère à un article publié sur le Web, ou à une page fournissant plus d’informations, vous pouvez indiquer ci-après le titre de la page et son adresse.)

Rubrique « Projets »

Les derniers articles

Les articles les plus lus