Auteur Sujet: DCC++ BaseStation  (Lu 104681 fois)

Thierry

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 740
    • Voir le profil
DCC++ BaseStation
« le: mars 03, 2016, 02:31:09 pm »
Denis nous a signalé il y a peu de temps l'existence d'une bibliothèque très intéressante pour créer un module de pilotage DCC à partir d'un Arduino: https://github.com/DccPlusPlus/BaseStation . Il faut que tout le monde en profite, alors je porte la discussion sur le Forum.

Ce projet couvre plusieurs domaines:

un générateur de signaux DCC comme le cmdrArduino largement utilisé ici, mais maison, qui traite aussi bien les locos que les accessoires.
un module de commande série permettant d'envoyer des commandes de pilotage via la console série
une extension de tout ça pour gérer aussi des aiguillages en conservant les dernières positions, et des capteurs de toutes sortes.

A noter les vidéos (https://www.youtube.com/channel/UCJmvQx-fe0OMAIH-_g-_rZw) très bien faites (si on comprend l'anglais) sur le DCC en général, et le projet en particulier.

Vu la qualité du discours et des commentaires sur les videos, c'est dommage que le gars soit anglo-saxon, sinon on aurait fait le forcing pour le fairer venir sur Locoduino !

DDEFF

  • Hero Member
  • *****
  • Messages: 730
    • Voir le profil
Re : DCC++ BaseStation
« Réponse #1 le: mars 03, 2016, 10:32:46 pm »
C'est vrai que j'ai eu un choc en voyant ça pour la première fois.
Et je n'avais pas tout vu, juste la partie github...(du 10/01/2016)

Je pense vraiment qu'on a intérêt à creuser, ça paraît prometteur.  ;D
« Modifié: mars 10, 2016, 02:25:40 pm par DDEFF »
"Ce n'est pas le puits qui est trop profond, c'est ta corde qui est trop courte" (proverbe chinois)

DDEFF

  • Hero Member
  • *****
  • Messages: 730
    • Voir le profil
Re : DCC++ BaseStation
« Réponse #2 le: mars 04, 2016, 11:39:18 am »
Je viens de regarder les premières vidéos (je conseille fortement de les regarder dans l'ordre).
Elles sont extrêmement bien faites (pour qui comprend l'américain, malheureusement).

Disons qu'on se rapproche vraiment de productions commerciales ("gold", pour ne pas citer de marque) :

La première vidéo est assez impressionnante : conduite aléatoire de 6 trains qui ne font donc pas toujours la même chose, ni dans le même ordre.
Et, pour autant, un vrai décor, typiquement américain.
Décor qui fait souvent cruellement défaut à ceux qui s'intéressent à la technique et qui le feront "plus tard"  ;D ;D ;D

1°) On a besoin d'un ordi, souris, clavier pour commander les trains

2°) Suit le programme en processing, assez costaud, pour commander le réseau, les CV sur la voie de programmation, les aiguilles, les circuits pré-enregistrés, ...
C'est bien fait.
Je ne l'ai pas implémenté complètement car il faut implanter d'abord certaines autres bibliothèques java avant. Mais je le ferai, maintenant que je commence à tâter de processing  ;)
Il y a aussi un certain ordre à suivre pour les ouvrir.

3°) Des bibliothèques Arduino pour gérer le DCC. Là, je ne connais pas. Mais tout y est (28 (!) fonctions par loco, 128 crans, ...) et assez costaud pour 6 trains simultanés.

On a même une fonction que je n'avais jamais vu (mais je ne suis pas spécialiste) : affichage, avec graphique historique (!) du courant consommé  :-*

Vraiment un sacré projet, complet. Chapeau l'artiste !
« Modifié: mars 05, 2016, 04:46:15 pm par DDEFF »
"Ce n'est pas le puits qui est trop profond, c'est ta corde qui est trop courte" (proverbe chinois)

DDEFF

  • Hero Member
  • *****
  • Messages: 730
    • Voir le profil
Re : DCC++ BaseStation
« Réponse #3 le: mars 05, 2016, 11:48:41 am »
J'ai vu toutes les vidéos.
Encore une fonction vraiment pas courante : à l'écran, on choisit la couleur de l'éclairage du réseau, sur un cercle coloré (16 millions de couleurs !)
Et donc, faire le jour, la nuit, les éclairs, l'orage, etc,... n'est qu'un jeu d'enfant.

Il a vraiment pensé à tout !  :-*
"Ce n'est pas le puits qui est trop profond, c'est ta corde qui est trop courte" (proverbe chinois)

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2870
  • 100% Arduino et N
    • Voir le profil
Re : DCC++ BaseStation
« Réponse #4 le: mars 08, 2016, 10:32:04 pm »
En fait ce n'est pas une bibliothèque, c'est carrément un système de pilotage de trains et accessoires en DCC.

Le premier document d'introduction (en anglais) est ici ->https://sites.google.com/site/dccppsite/

Sur le plan matériel, on a deux sous-ensemble :
  • une station DCC composée d'un Arduino UNO ou MEGA sur laquelle on insère une carte moteur double (Motor Shield)
  • un ordinateur dans lequel on lance une application Processing qui s'occupe de l'interface utilisateur. L'ordinateur et l'Arduino sont reliés ensemble, soit en liaison série (cable USB) soit en TCP/IP si on ajoute une carte ethernet ou WiFi.

On a donc 2 programmes :
  • Un programme Arduino : DCCpp_UNO pour l'Arduino avec son extension 2 moteurs
  • Un programme Processing : DCCpp_Controller pour le PC

Les liens de téléchargement sont là :

J'avoue que j'ai tout de suite installé le programme DCCpp_UNO sur un MEGA (oui le nom du programme est plutôt mal choisi!!), compilé (il y a juste quelques Warnings sur lesquels on reviendra plus tard), le téléversement se passe bien et un message s'affiche sur le moniteur :

<iDCC++ BASE STATION FOR ARDUINO MEGA / ARDUINO MOTOR SHIELD: V-1.2.1+ / Mar  8 2016 21:43:55><N0: SERIAL>

D'après la documentation très complète qui est intégrée au programme, je vois que c'est la pin 12 du MEGA qui délivre le signal DCC. Je branche mon petit oscillo de poche et je vois ce signal immédiatement, avec des créneaux de 50 et 100 microsecondes environ (mon oscillo n'est pas très précis, mais cela suffit).

Donc ça marche !

A suivre...
Cordialement,
Dominique

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2870
  • 100% Arduino et N
    • Voir le profil
Re : DCC++ BaseStation
« Réponse #5 le: mars 08, 2016, 10:44:24 pm »
L'architecture a de quoi intéresser pas mal de monde :

  • une station de base qui génère du DCC sur 2 voies (principales et programmation avec retour des acquittements), qui peut gérer des capteurs et des actionneurs, en bref un système presque complet sur un Mega, + une interface série (async, internet, ...) avec un protocole du type de celui de JMRI
  • une plateforme de commande interactive basée sur Processing qui utilise ce protocole.


Le code est assez difficile à lire, il faut du temps. Le développeur doit être un expert. Il y a des tonnes de commentaires donc c'est bien ! Mais ses classes C++ ne sont que des structs ! Il perd le bénéfice des données et fonctions protégées.

La génération du DCC est du même type que celui de la première version présentée dans mon premier articles : http://www.locoduino.org/spip.php?article17.
Un ensemble de 12 tableaux de bits (sur 10 octets) contiennent des trames prêtes à émettre et une routine sous interruption émet les bits avec des timers. C'est différent de CMDRArduino.
A coté de cela il y a un module de préparation des trames (registres), gestionnaire des "files à émettre", à partir des commandes reçues par la liaison série.

Ce qui est assez simple, c'est que les commandes reçues sous forme de message texte sont directement traduites en série de bits placés dans un registre (le numéro de registre est même dans la commande, il faut donc faire attention !).

Ce qui fait que le programme LOOP ne fait pas grand chose d'autre que :

void loop(){
 
  SerialCommand::process();              // check for, and process, and new serial commands
 
  if(CurrentMonitor::checkTime()){      // if sufficient time has elapsed since last update, check current draw on Main and Program Tracks
    mainMonitor.check();
    progMonitor.check();
  }

  Sensor::check();    // check sensors for activate/de-activate
 
} // loop

Le logiciel semble couvrir toutes les fonctions de la NMRA (du moins c'est à vérifier)

Il y a un beau "parser" de commandes pour piloter la bête.

Il y a surtout, pour les anglophiles, un blog de 46 pages qui commence là :

http://www.trainboard.com/highball/index.php?threads/introducing-dcc-a-complete-open-source-dcc-station-and-interface.84800/

On y trouve des discussions sur tout un tas d'interfaces de puissances (sauf le LMD18200 mais y compris l'IBT2 à base de double BTS7960 pouvant délivrer 43 ampères). Apparemment on peut faire du DCC de 2 à 5 A avec plein de cartes (shield Arduino pour 2 moteurs, cartes Polulu, etc.. qui coûtent néanmoins plus cher que le LMD18200.

Il y a aussi des tas de discussions sur le logiciel (open source) et les interfaces avec JMRI et autres gestionnaires. C'est très riche.
On a l'impression que ça marche, vu les commentaires des internautes qui l'on mis en oeuvre.

a suivre ....
Cordialement,
Dominique

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2870
  • 100% Arduino et N
    • Voir le profil
Re : DCC++ BaseStation
« Réponse #6 le: mars 08, 2016, 10:51:55 pm »
Je n'ai pas résisté non plus à télécharger et essayer le "Controller" écrit en Processing, dont voici une image ci-dessous.

Mais Denis nous en dira plus sur cette partie ...
Cordialement,
Dominique

Thierry

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 740
    • Voir le profil
Re : DCC++ BaseStation
« Réponse #7 le: mars 09, 2016, 09:08:30 am »
Au delà de la bonne utilisation ou non des structures, j'ai moi aussi jeté un oeil sur le code et je dois dire que c'est bien écrit, clair et très documenté. Il y a de très bonnes idées, mais il reste une syntaxe dans DCCpp_Uno.ino que je n'ai pas comprise (ligne 443) :

  if(R.currentReg->activePacket->buf[R.currentBit/8] & R.bitMask[R.currentBit%8]){
    OCR ## N ## A=DCC_ONE_BIT_TOTAL_DURATION_TIMER ## N;
    OCR ## N ## B=DCC_ONE_BIT_PULSE_DURATION_TIMER ## N;
  } else{ /* ELSE it is a ZERO */
    OCR ## N ## A=DCC_ZERO_BIT_TOTAL_DURATION_TIMER ## N;
    OCR ## N ## B=DCC_ZERO_BIT_PULSE_DURATION_TIMER ## N;
} /* END-ELSE */

est-ce que ## est un opérateur ?? J'avoue que je sèche.
A part ça, j'ai commencé à extraire la partie DCC de son code et je vais tenter (à mon rythme, donc pas trop vite...) de le comparer en terme de mémoire consommée à cmrdArduino.
La partie reconnaissance du ACK est aussi très intéressante. Il semble que le LMD18200 ait sa broche 8 qui permette de vérifier la consommation de courant instantanée, comme les broches 1 et 15 du L298N qu'emploie Greg . A creuser.
Pour ce qui est du prix de son montage, il faut voir les contraintes qu'il s'est imposé, c'est à dire aucune soudure, aucun composant autre que l'Arduino et le shield L298N (plutôt coûteux) au dessus... Pour le prix de ce shield, on peut utiliser deux LMD18200 qui rempliront le même rôle !
« Modifié: mai 04, 2017, 04:26:05 pm par Thierry »

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1691
    • Voir le profil
Re : DCC++ BaseStation
« Réponse #8 le: mars 09, 2016, 09:18:11 am »
Citer
mais il reste une syntaxe dans DCCpp_Uno.ino que je n'ai pas comprise (ligne 443) :

if(R.currentReg->activePacket->buf[R.currentBit/8] & R.bitMask[R.currentBit%8]){
  OCR ## N ## A=DCC_ONE_BIT_TOTAL_DURATION_TIMER ## N;
  OCR ## N ## B=DCC_ONE_BIT_PULSE_DURATION_TIMER ## N;
} else{ /* ELSE it is a ZERO */
  OCR ## N ## A=DCC_ZERO_BIT_TOTAL_DURATION_TIMER ## N;
  OCR ## N ## B=DCC_ZERO_BIT_PULSE_DURATION_TIMER ## N;
} /* END-ELSE */

est-ce que ## est un opérateur ?? J'avoue que je sèche.

C'est le token de concaténation de macros :

https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html#Concatenation

Donc là, OCR, N, A sont des macros qui sont respectivement expansées et concaténées

DCC_ONE_BIT_TOTAL_DURATION_TIMER (ou DCC_ONE_BIT_PULSE_DURATION_TIMER) et N sont également expansées et concaténées

Le résultat repasse par le préprocesseur pour traitement et éventuelle réexpansion.
Cordialement

DDEFF

  • Hero Member
  • *****
  • Messages: 730
    • Voir le profil
Re : DCC++ BaseStation
« Réponse #9 le: mars 09, 2016, 11:53:19 am »
Moi, j'ai regardé la partie Processing. On est complémentaires.

Le résultat est assez impressionnant, la programmation est propre, très bien documentée.
Cela donne une bonne idée de ce que l'on peut faire avec Processing.

Mais il y a quand même une ombre au tableau.

Analyse de la partie Processing (appellée DCCpp_Controller) :

J'ai trouvé où était décrit le réseau qu'on voit en jaune.   ;D

C'est dans "controllerConfig" (le deuxième onglet) des lignes 371-481 pour le réseau principal.
C'est le tracé en jaune.

Un supplément est fait pour déplacer la partie aérienne (la boucle supérieure) lignes 483-494 parce qu'elle a deux positions (voir les vidéos)
C'est le petit tracé en jaune.

Puis sont décrits les aiguilles (lignes 513-587), avec les différentes positions possibles :
- couleurs jaune (libre)
- vert                  (fait partie d'un circuit)
- rouge               (en mauvaise position pour le circuit considéré)

Puis les circuits pré-enregistrés (lignes 589-1037), avec les boutons elliptiques en bleu en bas à droite

Dit autrement, vous aurez à refaire toutes ces lignes (de 371 à 1037 !!) pour votre propre réseau.
Pas insurmontable, puisqu'on a des modèles, mais assez fastidieux.    :( :(

Il faudrait que je voie comment adapter mon "TCO en Processing" (qui, lui, a un éditeur intégré : tout se fait avec la souris et quelques touches) pour que cette partie soit plus simple à faire. Parce que, là, c'est "en dur" dans le programme !

Il y aurait du travail, mais ça me paraît faisable.  :D

La question est : y-a-t-il un "marché" ?
Dit autrement, qui voudrait que cette interface soit plus facile à adapter à son réseau ?
« Modifié: mars 09, 2016, 01:25:53 pm par DDEFF »
"Ce n'est pas le puits qui est trop profond, c'est ta corde qui est trop courte" (proverbe chinois)

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2870
  • 100% Arduino et N
    • Voir le profil
Re : Re : DCC++ BaseStation
« Réponse #10 le: mars 09, 2016, 01:39:57 pm »
Citer
mais il reste une syntaxe dans DCCpp_Uno.ino que je n'ai pas comprise (ligne 443) :

if(R.currentReg->activePacket->buf[R.currentBit/8] & R.bitMask[R.currentBit%8]){
  OCR ## N ## A=DCC_ONE_BIT_TOTAL_DURATION_TIMER ## N;
  OCR ## N ## B=DCC_ONE_BIT_PULSE_DURATION_TIMER ## N;
} else{ /* ELSE it is a ZERO */
  OCR ## N ## A=DCC_ZERO_BIT_TOTAL_DURATION_TIMER ## N;
  OCR ## N ## B=DCC_ZERO_BIT_PULSE_DURATION_TIMER ## N;
} /* END-ELSE */

est-ce que ## est un opérateur ?? J'avoue que je sèche.

C'est le token de concaténation de macros :

https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html#Concatenation

Donc là, OCR, N, A sont des macros qui sont respectivement expansées et concaténées

DCC_ONE_BIT_TOTAL_DURATION_TIMER (ou DCC_ONE_BIT_PULSE_DURATION_TIMER) et N sont également expansées et concaténées

Le résultat repasse par le préprocesseur pour traitement et éventuelle réexpansion.

Comme je ne suis pas encore familier avec ce type de Macros concatenées ou expansées, j'aimerai bien comparer cette écriture au langage C classique sans Macros.

D'ailleurs, dans ce cas, qu'est-ce qu'on gagne avec les Macros ? (Au vin blanc ou à la moutarde ?)

Cordialement,
Dominique

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1691
    • Voir le profil
Re : DCC++ BaseStation
« Réponse #11 le: mars 09, 2016, 01:45:45 pm »
Si je voulais être caustique, je dirais « le droit de concourir à The International Obfuscated C Code Contest »  http://www.ioccc.org ;D

Plus sérieusement, bien fait ça donne un code (légèrement) plus efficace tout en restant concis. Personnellement je n'aime pas. Il y a tellement de possibilités de se faire avoir par le préprocesseur qu'il ne vaut mieux pas s'y frotter de cette manière :)
Cordialement

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2870
  • 100% Arduino et N
    • Voir le profil
Re : Re : DCC++ BaseStation
« Réponse #12 le: mars 09, 2016, 01:57:52 pm »
Si je voulais être caustique, je dirais « le droit de concourir à The International Obfuscated C Code Contest »  http://www.ioccc.org ;D

Plus sérieusement, bien fait ça donne un code (légèrement) plus efficace tout en restant concis. Personnellement je n'aime pas. Il y a tellement de possibilités de se faire avoir par le préprocesseur qu'il ne vaut mieux pas s'y frotter de cette manière :)

Donc, qu'est-ce ça donne en clair ?
Cordialement,
Dominique

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2870
  • 100% Arduino et N
    • Voir le profil
Re : Re : DCC++ BaseStation
« Réponse #13 le: mars 09, 2016, 02:19:38 pm »
Au delà de la bonne utilisation ou non des structures, j'ai moi aussi jeté un oeil sur le code et je dois dire que c'est bien écrit, clair et très documenté. Il y a de très bonnes idées, mais il reste une syntaxe dans DCCpp_Uno.ino que je n'ai pas comprise (ligne 443) :

  if(R.currentReg->activePacket->buf[R.currentBit/8] & R.bitMask[R.currentBit%8]){
    OCR ## N ## A=DCC_ONE_BIT_TOTAL_DURATION_TIMER ## N;
    OCR ## N ## B=DCC_ONE_BIT_PULSE_DURATION_TIMER ## N;
  } else{ /* ELSE it is a ZERO */
    OCR ## N ## A=DCC_ZERO_BIT_TOTAL_DURATION_TIMER ## N;
    OCR ## N ## B=DCC_ZERO_BIT_PULSE_DURATION_TIMER ## N;
} /* END-ELSE */

est-ce que ## est un opérateur ?? J'avoue que je sèche.
A part ça, j'ai commencé à extraire la partie DCC de son code et je vais tenter (à mon rythme, donc pas trop vite...) de le comparer en terme de mémoire consommée à cmrdArduino.
La partie reconnaissance du ACK est aussi très intéressante. Il semble que le LMD18200 ait sa broche 8 qui permette de vérifier la consommation de courant instantannée, comme les broches 1 et 15 du L298N qu'emploie Gregg . A creuser.
Pour ce qui est du prix de son montage, il faut voir les contraintes qu'il s'est imposé, c'est à dire aucune sourude, auncun composant autre que l'Arduino et le shield L298N (plutôt couteux) au dessus... Pour le prix de ce shield, on peut utiliser deux LMD18200 qui rempliront le même rôle !

J'ai toujours trouvé mystérieuse cette mesure de courant dans les hacheurs 4Q. Qu'est-ce qu'on mesure quand la tension s'inverse toutes les 1/2 périodes ? Surtout quand la mesure est prise n'importe quand !

J'ai tenté d'utiliser la mesure du courant du LMD18200 en reliant la sortie C/S sur une entrée analogique de l'Arduino, en moyennant des dizaines voire des centaines de mesures et j'avoue que ce n'est pas convainquant !
Là dans DCC++, il fait une mesure de courant toutes les 10 ms (pourquoi pas à chaque loop ?), puis il pratique un "lissage exponentiel" qui prend du temps calcul, c'est le moins qu'on puisse dire.

Je ne suis toujours pas convaincu !

Finalement la solution fiable que j'ai trouvée est extrêmement simple et peu couteuse :



Un MAX471 que l'on trouve sous forme de petit BoB sur eBay est monté en série avec l'alim 12/15v du LMD18200.
Ce Max 471 peut mesurer des courants de 0 à 3 A avec une sortie en tension de 1 volt/ampère.

Pour de plus gros ampèrages, il y a l'ACS712T qui monte jusqu'à 5 A.

Là la mesure est très fiable avec un seul Analogwrite.
Je m'en sers évidemment pour la mesure de court-circuit et c'est une merveille !

Reste maintenant à l'appliquer au retour des commandes de programmation.


J'ai ajouté la recette à mon article Comment piloter trains et accessoires en DCC avec un Arduino (3)
http://www.locoduino.org/spip.php?article19.
Cordialement,
Dominique

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1691
    • Voir le profil
Re : Re : Re : DCC++ BaseStation
« Réponse #14 le: mars 09, 2016, 02:37:35 pm »
Si je voulais être caustique, je dirais « le droit de concourir à The International Obfuscated C Code Contest »  http://www.ioccc.org ;D

Plus sérieusement, bien fait ça donne un code (légèrement) plus efficace tout en restant concis. Personnellement je n'aime pas. Il y a tellement de possibilités de se faire avoir par le préprocesseur qu'il ne vaut mieux pas s'y frotter de cette manière :)

Donc, qu'est-ce ça donne en clair ?

Prenons la ligne

OCR ## N ## A=DCC_ONE_BIT_TOTAL_DURATION_TIMER ## N

OCR n'est pas une macro
N est l'argument de la macro dans laquelle cette ligne apparaît
A n'est pas une macro
DCC_ONE_BIT_TOTAL_DURATION_TIMER n'est pas une macro

Donc première passe, N est remplacé par sa valeur, 0 ou 1. Prenons 1

OCR1A=DCC_ONE_BIT_TOTAL_DURATION_TIMER1

OCR1A est une macro de l'AVR, DCC_ONE_BIT_TOTAL_DURATION_TIMER1 est défini à 3199

2e passe

OCR1A est défini dans iom328p.h

#define OCR1A _SFR_MEM16(0x88)

Et donc

_SFR_MEM16(0x88)=3199

« Modifié: mars 09, 2016, 02:53:00 pm par Jean-Luc »
Cordialement