Parlons Arduino > Vos projets

projet de reseau etagere analogique

(1/5) > >>

palou:
Bonjour

Je suis en train de concevoir un réseau étagère. Vu le manque de place, c'est un réseau en HOe de 3,5m sur 30cm divisé en 4 modules. (3x90cm, 1x 80cm).

C'est un réseau en "Z" : La partie droite comprend une gare terminus avec une plaque tournante, la partie gauche une coulisse à tiroir. De la gauche vers la droite la diagonale du Z mène à une voie de rebroussement permettant de parcourir la partie haute à gauche qui serait une exploitation forestière. La jonction entre la voie du bas et la diagonale permet des croisements de trains (mini gare) et il y a également au milieu de la partie haute une zone de croisement (qui sera camouflée). De ce fait, malgré que le réseau soit à voie unique, entre la gare terminus, la coulisse, l'exploitation forestière (qui est aussi un mini terminus) et les deux zones de croisements, il pourrait y avoir 3 ou 4 trains qui pourraient circuler sur le réseau en même temps ...
Ca c'est la partie visible de l'iceberg ...
Pour ce qui est de la partie invisible (cad le moyen de piloter tout ça), j'ai pensé à des cartes électroniques basées sur des nanos pour gérer le PWM et la présence sur les différentes sections de voies où un train pourrait se trouver, des relais pour piloter les aiguilles et éventuellement des dételeurs pour les gares, un montage spécifique pour la table tournante, et un dernier pour gérer les animations éventuelles (leds, servos ou autres)
Pour piloter tout ça: j'ai pensé à un méga ou à un due qui serait le chef d'orchestre et commuterait la PWM sur le parcours du train. Il assurerait la sécurité, évitant que 2 trains ne se retrouvent sur la même section
La partie "IHM' serait un TCO. J'hésite à faire un TCO unique ou un TCO par module. Suivant la complexité du module, si on a un TCO par module, certains de ceux ci peuvent avoir un TCO sur un nano, d'autres seraient sur du méga.
Pour le pilotage des trains, un nano gèrerait des potentiomètres (un par locomotive possible sur le trajet) permettant d'avoir un pilotage individuel de chaque train.

Pour relier tous les arduinos, j'ai pensé à un bus CAN. J'ai commencé à tracer des schémas des certains éléments (en me basant sur les articles de locoduino et en grappillant des exemples de sketchs présentés dans les articles ou sur le forum)

Mon principal problème actuellement est la compréhension du bus CAN. J'ai vu beaucoup d'exemples à 2 ou 3 nœuds, mais pas d'exemples ou il y aurait une multitude de nœuds. Et du coup j'ai du mal à visualiser comment positionner les masques et les filtres des différents types de modules.
Dans mon esprit, le masque représenterait le type de module (par exemple 0x78f pour les modules relais, 0x71f pour les modules pwm, ...) et le filtre représenterait l'identifiant du module ciblé (0x780 à 0x78F pour 16 modules relais maximum, 0x700 à 0x71F pour 32 modules pwm possibles). Les 8 octets de donnée serviraient à décrire la consigne à appliquer ou en retour vers le tco ou le master à renvoyer des infos (position d'aiguille, occupation, ...). Est ce que c'est la meilleure manière de procéder ?
Il y a aussi un endroit dans la trame CAN décrivant si c'est un "ordre" où une "lecture". Comment est positionné ce bits dans les librairies CAN ?
Ensuite, au point de vue faisabilité/complexité: Est ce que ça parait faisable ? J'ai du mal à concevoir la partie "master" qui doit gérer la sécurité et servir éventuellement d'interface vers un PC ou rpi pour avoir un TCO informatisé dans le futur.... (la modélisation n'est pas simple, les solutions qui sont décritent sur le site me semblent assez ardues à appréhender ...)

En PJ le plan du réseau (les couleurs indiquent les section prévues avec un PWM autonome)

Merci d'avance pour vos avis.
Pascal

palou:
Pour compléter, un exemple concret (pas testé je précise) de carte pour gérer les solénoides d'aiguilles et de dételeurs (en PJ le schéma)
Si vous voyez des erreurs n'hésitez pas ... :)
C'est basé sur un nano + une carte 8 relais + une interface CAN 2515

Le sketch est le suivant:
Tout d'abord la configuration générale (config.h):
(les adresses CAN ne sont pas fixées pour l'instant)

--- Code: ---#ifndef CONFIG_H
#define CONFIG_H

// debug
#define _dumpCan true

/* aiguille */
#define DELAI_AIGUILLE 150
#define DIRECT 0
#define DEVIE 1
#define MOVEDIRECT 2
#define MOVEDEVIE 4
#define ACTIF HIGH
#define INACTIF LOW

/* deteleur */
#define DELAI_DETELEUR 200
#define DETACTIF HIGH
#define DETINACTIF LOW

/* interface CAN */

static const uint8_t MCP2515_CS  = 10;
static const uint8_t MCP2515_INT = 2;

#define ID_MASTER 0x7a0
#define RELAI_MASK 0x7ef
#define RELAI_FILTER 0x7e1


#define CAN_ORDRE 0x10
#define CAN_LIT   0x20
#define CAN_LIT_TOUT 0x30

#endif

--- Fin du code ---

Ensuite la configuration des sorties : C'est dans un fichier séparé de manière à pouvoir le modifier facilement suivant le module qui est la cible (parametres.h)

--- Code: ---#ifndef PARAMETRES_H
#define PARAMETRES_H

#include "config.h"
#include "aiguille.h"
#include "deteleur.h"


/* 8 sorties donc 4 aiguilles possibles ou 8 dételeurs ou une combinaison des 2 */
// 2 aiguilles
aiguille aig0 = aiguille(3,4,DIRECT);
aiguille aig1 = aiguille(5,6,DIRECT);
aiguille tabAiguille[2] = {aig0,aig1};
byte nombreAiguille = 2 ;

// 3 deteleurs
deteleur det0 = deteleur(7);
deteleur det1 = deteleur(8);
deteleur det2 = deteleur(9);
deteleur tabDeteleur[3] = {det0,det1,det2};
byte nombreDeteleur = 3;



#endif

--- Fin du code ---

L'objet aiguille décrit la commutation d'une aiguille (aiguille.h). La commutation se fait en mettant la variable posAttendue à la valeur souhaitée (DIRECT ou DEVIE). La methode  "loop" qui est appelée cycliquement scanne cette valeur et la compare à la position actuelle de l'aiguille. Si les valeurs sont différentes  et qu'un déplacement n'est pas en cours, elle active le relai et positionne la limite de temps pour l'activation (en millisecondes). Si un déplacement est en cours, la méthode "loop" vérifie que le délai n'est pas dépassé. Si il est dépassé, elle désactive la sortie.

--- Code: ---#ifndef AIGUILLE_H
#define AIGUILLE_H

#include "config.h"

class aiguille {
  private:
    byte ports[2];
    byte posAiguille;
    byte posAttendue;
    boolean enCours;
    unsigned long limite;
  public:
    aiguille(byte p0, byte p1, byte posDepart);
    boolean etat();
    void positionne(byte attendu);
    byte pos_aiguille();
    void loop(); 
};

aiguille::aiguille(byte p0, byte p1, byte posDepart) {
  ports[DIRECT] = p0;
  ports[DEVIE] = p1;
  pinMode(ports[DIRECT], OUTPUT);
  pinMode(ports[DEVIE], OUTPUT);
  digitalWrite(ports[DIRECT],INACTIF);
  digitalWrite(ports[DEVIE],INACTIF);
  digitalWrite(ports[posDepart],ACTIF);
  delay(DELAI_AIGUILLE);
  digitalWrite(ports[posDepart],INACTIF);
  posAiguille = posDepart;
  posAttendue = posDepart;
  enCours = false;
  limite = 0;
}

boolean aiguille::etat() {
  return enCours;
}

byte aiguille::pos_aiguille() {
  if (enCours) {
    if (posAttendue == DIRECT) {
      return MOVEDIRECT;
    }
    else {
      return MOVEDEVIE;
    }
  }
  else {
    return posAiguille;
  }
}

void aiguille::positionne(byte attendu) {
  posAttendue = attendu;
}

void aiguille::loop() {
  if (enCours) {
    if (millis() > limite) {
      digitalWrite(ports[posAttendue],INACTIF);
      posAiguille = posAttendue;
      enCours = false;
      moveEnCours = false;
    }
  }
  else {
    if (posAttendue != posAiguille) {
      digitalWrite(ports[posAttendue],ACTIF);
      enCours = true;
      moveEnCours = true;
      limite = millis() + DELAI_AIGUILLE;
    }
  }
}

#endif

--- Fin du code ---

L'objet deteleur (deteleur.h) est plus simple (il n'y a qu'un seul relai à activer). Le principe est le même, la fonction "loop" remplit la même fonction que celle d'aiguille.h en étant plus simple.

--- Code: ---#ifndef DETELEUR_H
#define DETELEUR_H

#include "config.h"
class deteleur {
  private:
    byte port;
    boolean enCours;
    unsigned long limite;
  public:
    deteleur(byte p0);
    byte etat();
    void detelle();
    void loop(); 
};

deteleur::deteleur(byte p0) {
  port = p0;
  pinMode(port, OUTPUT);
  digitalWrite(port,DETINACTIF);
  enCours = false;
  limite = 0;
}

byte deteleur::etat() {
  return enCours?1:0;
}

void deteleur::detelle() {
  enCours = true;
  moveEnCours = true;
  digitalWrite(port,DETACTIF);
  limite = millis() + DELAI_DETELEUR;
 
}
   
void deteleur::loop() {
  if (enCours) {
    if (millis() > limite) {
      digitalWrite(port,DETINACTIF);
      enCours = false;
      moveEnCours = false;
    }
  }
}

#endif

--- Fin du code ---

Pour éviter l'activation simultanée de plusieurs solénoïdes, les demandes son stockées dans une pile et lancées lorsque il n'y a plus de sortie activée. L'objet gestAttente (gestAttente.h) remplit ce rôle. Pareil une méthode "loop" vérifie qu'aucun relai n'est actif et lance une action en attente si il y en a.


--- Code: ---#ifndef GESTATTENTE_H
#define GESTATTENTE_H

#include "config.h"
#include "aiguille.h"
#include "deteleur.h"
#include "parametres.h"

#define MAXLISTE 20

struct ordre {
  byte index;
  byte action;
};

class gestAttente {
  private:
    ordre liste[MAXLISTE];
    int indexListe;

  public:
    gestAttente();
    boolean ajouteOrdre(byte index, byte action);
    void loop();
};

gestAttente::gestAttente() {
  indexListe = -1;
}

boolean gestAttente::ajouteOrdre(byte index, byte action) {
  ordre o;
  if (indexListe < MAXLISTE -1) {
    indexListe++;
    o.index = index;
    o.action = action;
    liste[indexListe] = o;
    return true;
  }
  return false;
}

void gestAttente::loop() {
  ordre o;
  if (! moveEnCours) {
    if (indexListe > -1) {
      o = liste[indexListe];
      if (o.index < 10) {
        if (o.index < nombreAiguille) {
          tabAiguille[o.index].positionne(o.action);
        }
      }
      else {
        o.index = o.index - 10;
        if (o.index < nombreDeteleur) {
          tabDeteleur[o.index].detelle();
        }
      }
      indexListe--;
    }
  }
}


#endif

--- Fin du code ---

Enfin le sketch lui même: Il est basé sur les articles de Locoduino quand à la gestion du bus CAN
Le paquet de données de 8 octets est découpé de la façon suivante:
buf[0] = ordre (CAN_ORDRE, CAN_LIT, CAN_LIT_TOUT)
buf[1] = cible (0 -> 3 aiguille, 10 - 17 dételeur)
buf[2] = pour une aiguille, la position attendue (DIRECT/DEVIE)
En cas d'ordre CAN_LIT ou CAN_LIT_TOUT, une réponse est envoyée au demandeur

--- Code: ---#include <SPI.h>

//  Déclaration de la bubliothèque CAN pour ATmega328
#include <mcp_can.h>
boolean moveEnCours;
#include "config.h"
#include "aiguille.h"
#include "deteleur.h"
#include "parametres.h"
#include "gestAttente.h"

gestAttente gest = gestAttente();

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

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)

/*
 *  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;
}



void setup() {
  while(true) {
    if (CAN_OK == CAN.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ)) {     
    // 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);
  } 
  attachInterrupt(digitalPinToInterrupt(MCP2515_INT), MCP2515_ISR, FALLING); // interrupt 0 (pin 2)
  /*
   * set mask & filter
  */
     
  CAN.init_Mask(0, 0, RELAI_MASK); 
  CAN.init_Mask(1, 0, RELAI_MASK); 
   
  CAN.init_Filt(0, 0, RELAI_FILTER);
  CAN.init_Filt(1, 0, RELAI_FILTER);
  CAN.init_Filt(2, 0, RELAI_FILTER);
  CAN.init_Filt(3, 0, RELAI_FILTER);
  CAN.init_Filt(4, 0, RELAI_FILTER);
  CAN.init_Filt(5, 0, RELAI_FILTER);

}

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
    CAN_depile();
  }
 
  gest.loop();
  for (int i = 0; i < nombreAiguille; i++) {
    tabAiguille[i].loop();
  }
  for (int i = 0; i < nombreDeteleur; i++) {
    tabDeteleur[i].loop();
  }
}

void CAN_recup() {
  unsigned char len = 0;  // nombre d'octets du message
  unsigned char buf[8];   // message
  unsigned long Id;   // Id (on devrait plutôt utiliser un int car il y a 11 bits)
 
  while (CAN_MSGAVAIL == CAN.checkReceive())  {
    CAN.readMsgBuf(&Id, &len, buf);        // read data, len: data length, buf: data buf
    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
    }
  }
}

void CAN_depile() {
  byte RId;  // variables pour le traitement des messages lus dans _Circule
  byte Rlen;
  byte Rbuf[8];
  byte Ebuf[8];
  byte element;
  byte action;
  byte i;
     
  // 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[..]
    switch (Rbuf[0]) {
      case CAN_ORDRE:
        if (Rlen > 1) {
          element = Rbuf[1];
          if (element < nombreAiguille && Rlen > 2) {
            action = Rbuf[2];
            gest.ajouteOrdre(element,action);
          }
          else {
            if (element >= 10 && element < nombreDeteleur) {
              gest.ajouteOrdre(element,0);
            }
          }
        }
        break;
      case CAN_LIT:
        if (Rlen > 1) {
          element = Rbuf[1];
          if (element < nombreAiguille) {
            Ebuf[0] = CAN_LIT;
            Ebuf[1] = element;
            Ebuf[2] = tabAiguille[element].pos_aiguille();
            CAN.sendMsgBuf(RId, 0, 3, Ebuf);
          }
        }
        break;
      case CAN_LIT_TOUT:
        Ebuf[0] = CAN_LIT_TOUT;
        Ebuf[1] = 0;
        Ebuf[2] = 0;
        for(i = 0 ; i < nombreAiguille ; i++) {
          Ebuf[1] |= tabAiguille[i].pos_aiguille()<<(i*2); 
        }
        for (i = 0 ; i < nombreDeteleur ; i++) {
          Ebuf[2] |= tabDeteleur[i].etat() << i;
        }
        CAN.sendMsgBuf(RId, 0, 3, Ebuf);
        break;
      default:
        break;
    }
  }
}

--- Fin du code ---

Voila

Je me pose surtout des questions coté CAN:
Est ce que ma gestion des ID est bonne ?
Est ce que l'ID reçu est celui de l'émetteur du message ou faut il envoyer la réponse à un id prédéfini ?
Est ce que la logique est bonne ?

Pascal

Dominique:
Bonjour Pascal,

Votre réseau est très intéressant car il compte pas mal de modules et quelques images, photos, plans du réseau permettrait de mieux voir le projet global.

Votre architecture de communication sur bus Can ressemble assez bien à celle de mon réseau ( https://forum.locoduino.org/index.php?topic=290.0 donc je pourrai vous aider.

Mais je sors d’un mariage dans la famille qui va me prendre encore un peu de temps avant de vous consacrer plus de temps.

Commencez par vous dire que c’est l’identifiant des messages qui est important : un identifiant par fonction, chaque module pouvant avoir plusieurs fonctions, certaines fonctions pouvant intéresser plusieurs modules.
Les masques et les filtres ne servent qu’à définir les seuls messages qui intéressent un module pour éviter de le déranger par ceux qui ne le concernent pas.

Donc il faut lister toutes les fonctions qui émettent un message, et quels modules émettent et reçoivent ces messages.

Je vous donnerai un exemple ou on regarde directement le cas de votre réseau.

Cordialement
Dominique

palou:
Bonjour Dominique

J'ai parcouru le post décrivant votre solution. Bravo pour la réalisation :)

En effet, il y a des ressemblances et aussi des différences. La principale différence est que je prévoie de rester en analogique (pas de DCC). Donc au niveau des sections,  celles ci comporteront leur propre source PWM qui sera pilotée depuis le "master" suivant le trajet des trains.

Sinon l'architecture de base est la même : Chaque module du réseau aura ses propres contrôleurs pour les aiguilles et dételeurs, les alimentations PWM, la détection de présence (que je prévoie d'intégrer aux modules gérant la PWM des sections) et les accessoires. La gare terminus aura un module spécifique pour piloter la plaque tournante (gros morceau :) ).
Pour l'instant je ne prévoie pas de signalisation sur le réseau, car le thème sera une ligne secondaire en voie étroite dans les années 50-60 (à l'époque où il y avait des trains dans nos campagnes ... :) ). Du coup si il devait y avoir une signalisation pour moi elle devrait être "mécanique" à base de sémaphores par exemple...
Les connections entre les modules comprendraient l'alimentation voie et électronique (12V), une alimentation "solénoides", le bus CAN et les raccords entre segments de voies faisant partie de sections communes.

Comme je ne suis pas riche ( :-[ ) je prévoie de construire module par module en étalant dans le temps la réalisation. La déco peut être faite en parallèle une fois les bases posées pour un module  (  cad définition des volumes et rampes + pose de la voie + l'électronique minimale du module (aiguilles/pwm/détection))

Donc je prévoie de commencer par le module de droite (la gare terminus) qui devrait d'après mes prévision nécessiter 2aiguilles, 3 dételeurs, 6 sections PWM et maximum 12 détecteurs de présence type "barrière infrarouge ou réfléchissants" (extrémités de sections) et 6 détecteurs de présence par conso de courant (1/ section PWM). Cela devrait faire 1 contrôleur aiguille et 3 contrôleurs PWM + éventuellement 2 ou 3 contrôleurs "présence" (si je n'arrive pas à les fusionner avec les contrôleurs PWM).
Ensuite j'avancerai vers la gauche module par module...

Le gros morceau au niveau électronique et logique pour ce module est la plaque tournante: Le contrôleur devra piloter un moteur pas à pas (rotation), six contacts "rupteurs" (six positions possibles), une sortie PWM (alimentation voie) et deux barrieres infrarouges d'extrémité (histoire de ne pas faire tourner la plaque si une locomotive est à cheval sur l'entrée). Avec un nano, impossible de rajouter une détection par conso de courant, il ne reste pas assez d'E/S.

Sinon globalement ce qu'il me reste à faire:

* Prévoir un plan d'adressage des modules pour le CAN.
* Mettre au point des modules génériques (solénoides, PWM, présence) et faire un banc test pour vérifier que ça marche
* Mettre au point la plaque tournante (au niveau mécanique c'est pas évident, au niveau logique encore moins ... :) )
* Le module "master" au niveau électronique est assez simple : 1 Méga ou Due avec un CAN + éventuellement une carte wifi pour dialoguer avec un pc ou autre et un écran pour voir ce qui se passe. Par contre, la partie logique est elle assez ardue ... (là je dois avouer que je tatonne beaucoup)
* Le module TCO sera basé sur un méga pour gérer les différents boutons poussoirs ou inverseurs  + leds + les potentiomètres de pilotage des locos.
Au niveau logique, les points qui restent à déterminer sont (en dehors de la plaque tournante qui est un mini projet à elle seule):

* Comment gérer la sécurité entre les sections. Est ce que le master s'en charge (il a une vue globale du réseau) ou est ce que ce sera décentralisé ? Dans ce cas les modules PWM devront demander à leurs voisins (en fonction des positions d'aiguille) si ils peuvent avancer ou non
* J'ai vu en parcourant les forums des interrogations sur les "sauts de PWM" entre sections qui peuvent entrainer des comportements erratiques des locos lors du passage d'une section à l'autre. Vu l'architecture, il faut que je mette en place aussi une synchro entre les PWM...EDIT: J'ai trouvé la librairie syncPWM en parcourant les forums. Par contre du coup il faut aussi prévoir une base de temps pour générer le signal de synchro. A ce sujet: Quelle est la meilleure frequence de PWM pour animer une locomotive en analogique ?
* Un truc trivial sans lequel cela ne marche pas: Le positionnement des trains et l'affectation des potentiomètres au train.
* Prévoir un système d'itinéraires avec une gestion autonome du réseau ?
* Au vue des points précédents, le script du "master"
* Tous les trucs auquel je n'ai pas pensé pour l'instant ... :)    

Enfin voilà l'état de mes réflexions...
En PJ une vue agrandie de la gare terminus (tracé des rails) (la voie en haut à gauche surplombe la gare et est en fait l'extrémité haute du "Z")
Et le synoptique de la carte de commande du pont tournant

Cordialement
Pascal
 

Dominique:
Il est évident que ton réseau analogique est très différent de mon réseau digital mais, du point de vue Can, nous mettons en œuvre un ensemble de sous-systemes interconnectés via Can et c’est là qu’il y a similitude.

En ce qui concerne la synchronisation des PWM, l’expert Locoduino est Jean-Luc.
Tu trouveras ici http://modelleisenbahn.triskell.org/ son site perso.

Navigation

[0] Index des messages

[#] Page suivante

Utiliser la version classique