Auteur Sujet: DccToolkit / SystemToolkit  (Lu 35118 fois)

AmadeusHF

  • Full Member
  • ***
  • Messages: 205
    • Voir le profil
DccToolkit / SystemToolkit
« le: mars 14, 2021, 12:02:37 pm »
Bonjour à tous

Je vous propose ci-dessous deux bibliothèques permettant de réaliser des montages notamment autour du DCC.

Pourquoi de nouvelles bibliothèques diront certains ?

Tranchons dans le vif une fois pour toute quant à cette question :
a) C'est un loisir, moi ça m'amusait de le faire, alors je l'ai fait et c'est ce qui compte le plus !
b) J'ai considéré que les bibliothèques existantes, issues de DCC++ de Gregg E Berman avait quelques lacunes, et j'ai souhaité proposer une approche beaucoup plus structurée et flexible.

Tout ceci n'enlève rien au travail de Gregg ni, plus encore, à celui de Thierry ici présent : j'ai juste une approche différente, chacun choisira la voie qui lui convient le mieux. Enfin notez que j'ai bien intégré à la fois Gregg et Thierry dans le README / Remerciements car je considère leur travail comme très important ET qu'il m'a servi de base de comparaison / reflexion / compréhension de pas mal de choses.

Ceci étant posé (je n'y reviendrait pas : je ne suis pas là pour pinailler), parlons de choses concretes !

Ces deux librairies vous proposent des classes relativement abouties pour gérer :
  • Des mécanismes assez complexes au niveau système, de façon plus simple / générique que si vous devez vous taper chaque spécificité de chaque modèle d'arduino / chaque timer, par exemple
  • Des briques de base spécialisées et très modulaires permettant de construire des dispositifs autour du DCC, là aussi sans devoir gérer les spécificités détaillées de nombre de choses

Installation des bibliotheques

Pour le moment elles ne sont pas dans le gestionnaire officiel (ça viendra). Vous pouvez les télécharger en pièce joint de ce message. Je mettrais un rappel dans les messages suivants qui pointera vers celui-ci.

Une fois ces bibliothèques installées, vous pouvez les ajouter à votre projet.

Il y a déjà pas mal de choses implémentées MAIS pour le moment je suis en phase de test de la partie échanges DCC sur la voie. Notamment : j'ai besoin de tests significatifs de lecture de CV.

Voici un sketch qui fait le job, à adapter selon votre matériel :

#include <SignalGenerator.h>
#include <TrackDriver.h>

#include <ACS712CurrentSensor.h>
#include <Max471CurrentSensor.h>

// Create a current sensor reading on A0 with VCC = 5.0 volts
ACS712CurrentSensor currentSensor(A0, 5000);
//Max471CurrentSensor currentSensor(A0, 5000);

// Create a signal generator using timer 1, and pin 12, allowed to issue service command
SignalGenerator generator(1, 12, true);

// Create a track driver using output pin 11 and previous generator & current sensor
TrackDriver driver(11, &generator, &currentSensor);

void readCV(byte cv)
{
 byte value = 0;
 bool result = driver.readCV(cv, &value);
 Serial.print("CV ");
 Serial.print(cv);
 Serial.print(" = ");
 Serial.print(value);
 if (result)
    Serial.println(" : OK");
 else
    Serial.println(" : Failed to read !");
}

void setup()
{
  Serial.begin(115200);
  Serial.println("Initializing !");

  // Start all the stuff : DCC signal is there and running starting from here
  driver.start();

  Serial.println("Initialization done !");
}

int x = 1;
bool up = true;

void loop()
{
  delay(2000);

  if (up)
    readCV(x++);
  else
    readCV(x--);

  if (x <= 1)
    up = true;
  if (x >= 140)
    up = false;
}

Notez bien les broches utilisées :
  • La sortie 12 du MEGA va sur l'entrée DIR du shield moteur
  • La sortie 11 du MEGA va sur l'entrée PWM du shield moteur

L'usage de la sortie 12 dépend du timer utilisé. Il faut dans tous les cas utiliser le signal OUTPUT COMPARE B du timer concerné. Sur le MEGA, OC1B est sur la sortie 12. Si vous changez de timer ou d'arduino il peut y avoir besoin d'ajuster le code.

L'usage de la sortie 11 pour faire le ON/OFF de génération du signal électrique est par contre un choix arbitraire, sans relation avec des contraintes du matériel. Ca marchera avec n'importe quelle sortie digitale pour peu que vous branchiez le fil sur la pin dont le numéro est passé en parametre lors de l'instanciation de l'objet TrackDriver.

Si vous utilisez une mesure de courant à base de MAX, vous devez utiliser la bonne classe de CurrentSensor, faute de quoi ça va délirer complètement. Pour le moment ce code fonctionne chez moi avec :

  • Un ACS712 placé en coupure sur la ligne d'alimentation de la VOIE (certains montages mesurent sur la ligne d'alimentation du shield moteur)
  • ou Un Max471 placé en coupure sur la ligne d'alimentation du SHIELD MOTEUR
  • Un MEGA 2560
  • Une carte L 9110 S
« Modifié: mai 05, 2021, 10:40:42 am par AmadeusHF »
Sébastien.
La perfection est un chemin, non un but...

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 3013
  • 100% Arduino et N
    • Voir le profil
Re : DccToolkit / SystemToolkit
« Réponse #1 le: mars 14, 2021, 01:29:19 pm »
Très intéressant Sébastien,

Depuis que j’ai commencé à m’intéresser aux centrales DCC en DIY (ca fait bien 5 ans), l’eau a pas mal coulé sous les ponts.

Apres CmdrArduino, DCC++, Flexitimer, DCCpp, DCC++EX, LaBox ESP32, voici un nouveau candidat que j’ai hâte de regarder.

Cela prouve la grande vitalité de Locoduino !
Cordialement,
Dominique

msport

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2217
  • HO avec DCC++ en DIY Réseaux très éphémères
    • Voir le profil
Re : DccToolkit / SystemToolkit
« Réponse #2 le: mars 14, 2021, 05:16:48 pm »
Bravo pour cette première implémentation.

Un retour concernant la compilation :
j'ai du modifier dans dcctoolkit-master :

dans TrackDriver.h

#include "../SystemToolkit/SystemToolkit.h" par #include "SystemToolkit.h"

Par ailleurs le Mega semble obligatoire compte tenu des timers utilisés.
Cordialement

AmadeusHF

  • Full Member
  • ***
  • Messages: 205
    • Voir le profil
Re : DccToolkit / SystemToolkit
« Réponse #3 le: mars 14, 2021, 05:39:35 pm »
Oui j'ai déjà commit la meme correction.

Normalement tu peux utiliser autre chose qu'un mega : il y a les éléments de compilation conditionnelle qui vont bien.
Sébastien.
La perfection est un chemin, non un but...

msport

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2217
  • HO avec DCC++ en DIY Réseaux très éphémères
    • Voir le profil
Re : DccToolkit / SystemToolkit
« Réponse #4 le: mars 14, 2021, 07:36:03 pm »
J'ai ça avec un UNO  : conflit avec d'autres cartes ?
Cordialement

AmadeusHF

  • Full Member
  • ***
  • Messages: 205
    • Voir le profil
Re : DccToolkit / SystemToolkit
« Réponse #5 le: mars 14, 2021, 08:28:50 pm »
Non, une erreur de ma part : sur un UNO, le timer 1  n'implémente pas le COMPARE "C", seulement compare A et B.
Je vais corriger ça. ;)
Sébastien.
La perfection est un chemin, non un but...

AmadeusHF

  • Full Member
  • ***
  • Messages: 205
    • Voir le profil
Re : DccToolkit / SystemToolkit
« Réponse #6 le: mars 15, 2021, 09:36:31 am »
Je vous met en pièce jointe deux nouvelles release améliorées des bibliothèques, qui integrent pas mal de correctifs et de nouvelles fonctions. Il y a notamment un premier morceau d'implémentation du protocole de commande DCC++ ce qui permet, en assemblant les classes comme il faut, d'utiliser DecoderPro pour dialoguer avec l'équipement.

Voici les deux sketchs utiles mis à jour :

Test de lecture des CV
#include <SignalGenerator.h>
#include <TrackDriver.h>

#include <ACS712CurrentSensor.h>
#include <Max471CurrentSensor.h>

// Create a current sensor reading on A0 with VCC = 5.0 volts
//ACS712CurrentSensor currentSensor(A0, 5000);
Max471CurrentSensor currentSensor(A0, 5000);

// Create a signal generator using timer 1, allowed to issue service command
SignalGenerator generator(1,12, true);

// Create a track driver using previous generator & current sensor
TrackDriver driver(11,&generator, &currentSensor);

void readCV(byte cv)
{
  Serial.print("CV ");
  Serial.print(cv);
  Serial.print(" = ");

  byte value;
  if (driver.readCV(cv, &value))
  {
    Serial.println(value);
  }
  else
  {
    Serial.print(value);
    Serial.println(" : Failed to read !");
  }
}

void setup()
{
  Serial.begin(115200);
  Serial.println("Initializing !");

  // Start all the stuff : DCC signal is there and running starting from here
  driver.start();
  driver.powerOn();

  Serial.println("Initialization done !");
}

int x = 1;
bool up = true;

void loop()
{
  delay(500);

  if (up)
    readCV(x++);
  else
    readCV(x--);

  if (x <= 1)
    up = true;
  if (x >= 140)
    up = false;
}

Sketch de test avec DecoderPRO en USB

NOTE 1 : les fonctions sont partiellement implémentées. Ne pas faire d'écriture de CV pour le moment pour ne pas perturber vos décodeurs, "au cas ou" : je n'ai pas encore assez testé cette partie.

NOTE 2 : Le code pour la partie ethernet n'est pas encore au point...mais je bosse dessus...donc ne l'activez pas (compilation conditionnée par les defines DCC_ETHERNET_xxx)

// Do not remove the include below

#include "DuinoBaseStation.h"

#include "SystemToolkit.h"
#include "DccToolkit.h"

// Create a current sensor reading on A0 with VCC = 5.0 volts
//ACS712CurrentSensor currentSensor(A0, 5000);
Max471CurrentSensor currentSensor(A0, 5000);

// Create a signal generator using timer 1, pin 12 which is OUTPUT COMPARE B
// for timer 1 on MEGA for example
SignalGenerator generator(1, 12, true);

// Create a track driver using previous generator & current sensor, also using
// pin 11 to switch track power ON/OFF
TrackDriver driver(11, &generator, &currentSensor);

// Create a command stream using USB serial port
SerialPortCommandStream usbStream;

// Create a command parser using the stream and our single track driver
CommandParser usbParser(&usbStream, &driver, NULL);

#if defined(DCC_ETHERNET_WIZNET_5100_ENABLED) || defined(DCC_ETHERNET_WIZNET_5200_ENABLED) || defined(DCC_ETHERNET_WIZNET_5500_ENABLED)
// Create a command stream using ETHERNET port
SocketCommandStream ipStream;

// Create a command parser using the stream and our single track driver
CommandParser ipParser(&ipStream, &driver, NULL);
#endif

void setup()
{
driver.start();
usbParser.start();
#if defined(DCC_ETHERNET_WIZNET_5100_ENABLED) || defined(DCC_ETHERNET_WIZNET_5200_ENABLED) || defined(DCC_ETHERNET_WIZNET_5500_ENABLED)
ipParser.start();
#endif
}

void loop()
{
usbParser.run();
#if defined(DCC_ETHERNET_WIZNET_5100_ENABLED) || defined(DCC_ETHERNET_WIZNET_5200_ENABLED) || defined(DCC_ETHERNET_WIZNET_5500_ENABLED)
ipParser.run();
#endif
}
« Modifié: mars 19, 2021, 06:59:06 pm par AmadeusHF »
Sébastien.
La perfection est un chemin, non un but...

AmadeusHF

  • Full Member
  • ***
  • Messages: 205
    • Voir le profil
Re : DccToolkit / SystemToolkit
« Réponse #7 le: mars 15, 2021, 12:04:51 pm »
Allez, une dernière pour la matinée : les  écritures de CV sont validées ainsi que les commandes de fonctions.
« Modifié: mars 19, 2021, 06:59:23 pm par AmadeusHF »
Sébastien.
La perfection est un chemin, non un but...

AmadeusHF

  • Full Member
  • ***
  • Messages: 205
    • Voir le profil
Re : DccToolkit / SystemToolkit
« Réponse #8 le: mars 19, 2021, 10:13:08 am »
Bonjour à tous,

Nouvelle version des bibliothèques intégrant de multiples corrections et ajustements.

Vous pouvez récupérer les libs ET le code de test dans le premier message de ce sujet, en pièce jointe.
Il se trouve ICI !

Merci à ceux qui font quelques tests !

Précision : si vous obtenez une lecture partielle de vos CVs, vous pouvez essayer d'ajuster le seuil de sensibilité de l'ack de la façon suivante :

drivers.setAckThresholdCurrent(40);

Cette ligne de code, à mettre apres le driver.start() dans le SETUP, permet de fixer le seuil bas du niveau de courant , en milli-amperes.

Dans les versions précédentes, le seuil était forcé à  60 mA, probablement trop élevé pour des moteurs de petite taille (sur du N par exemple ?).

La valeur par défaut actuelle est de 40 mA.

Bons tests !
Sébastien.
La perfection est un chemin, non un but...

msport

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2217
  • HO avec DCC++ en DIY Réseaux très éphémères
    • Voir le profil
Re : DccToolkit / SystemToolkit
« Réponse #9 le: mars 19, 2021, 10:20:08 pm »
Bonsoir,

résultat variable pour moi (même configuration : LMD18200 + MAX471- testé-, 5V sur PWM)
"sketch qui fait le job" + bibliothèques du 1er message (pas compatible avec le git)

sketch avec Max471CurrentSensor : premier essai pas mal
Initializing !
Initialization done !
CV 1 = 0 : Failed to read ! mais repositionnement loco partie toute seule.
CV 2 = 2 : OK
CV 3 = 4 : OK
CV 4 = 4 : OK
CV 5 = 10 : OK
CV 6 = 1 : OK
CV 7 = 1 : OK
CV 8 = 99 : OK
CV 9 = 255 : OK
CV 10 = 255 : OK
CV 11 = 255 : OK
CV 12 = 255 : OK
CV 13 = 255 : OK
mais le coup d'après :
Initializing !
Initialization done !
CV 1 = 255 : OK
CV 2 = 243 : OK
CV 3 = 147 : OK
CV 4 = 80 : OK
CV 5 = 64 : Failed to read !
CV 6 = 58 : OK
CV 7 = 16 : OK
CV 8 = 32 : Failed to read !
CV 9 = 0 : Failed to read !
CV 10 = 0 : Failed to read !
CV 11 = 0 : Failed to read !
CV 12 = 0 : Failed to read !
Les retours sont donc aléatoires ...Auraient du être :
1 8
2 2
3 4
4 4
5 10
6 1
7 1
8 99
9 255
10 255
11 255
12 255
13 255
Moteur HO mais calibre N, décodeur LENZ d'usine


« Modifié: mars 20, 2021, 12:46:25 pm par msport »
Cordialement

AmadeusHF

  • Full Member
  • ***
  • Messages: 205
    • Voir le profil
Re : DccToolkit / SystemToolkit
« Réponse #10 le: mars 19, 2021, 10:46:27 pm »
Super, merci pour ton retour.
C'est déjà mieux que sur tes premiers tests non ?

Est-ce que tu as fait un essai en réduisant légèrement le seuil de détection, par exemple en passant à 30 mA au lieu des 40 mA ?

En tout cas merci pour ce test qui me rassure : c'est déjà nettement mieux que ta première expérience.

Ce WE je ferais des essais de mon coté avec les Max472 sur la base des montages que tu as posté.
Sébastien.
La perfection est un chemin, non un but...

msport

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2217
  • HO avec DCC++ en DIY Réseaux très éphémères
    • Voir le profil
Re : DccToolkit / SystemToolkit
« Réponse #11 le: mars 20, 2021, 12:43:32 pm »
Avec driver.setAckThresholdCurrent(30); (sans s) c'est très fantaisiste ... (même loco)
Initializing !
Initialization done !
CV 1 = 0 : Failed to read !
CV 2 = 0 : Failed to read !
CV 3 = 0 : Failed to read !
CV 4 = 0 : Failed to read !
CV 5 = 23 : OK
CV 6 = 9 : OK
CV 7 = 48 : OK
Initializing !
Initialization done !
CV 1 = 213 : OK
CV 2 = 100 : OK
CV 3 = 0 : Failed to read !
CV 4 = 0 : Failed to read !
Initializing !
Initialization done !
CV 1 = 109 : OK
CV 2 = 41 : OK
CV 3 = 1 : OK
CV 4 = 86 : OK
CV 5 = 224 : OK
CV 6 = 82 : OK
CV 7 = 28 : OK
CV 8 = 88 : OK
CV 9 = 144 : OK
CV 10 = 61 : OK
CV 11 = 207 : OK
CV 12 = 155 : OK
CV 13 = 85 : OK
CV 14 = 197 : OK
CV 15 = 0 : Failed to read !
CV 16 = 0 : Failed to read !
CV 17 = 0 : Failed to read !
CV 18 = 0 : Failed to read !
CV 19 = 0 : Failed to read !
CV 20 = 0 : Failed to read !
CV 21 = 0 : Failed to read !
CV 22 = 0 : Failed to read !
CV 23 = 0 : Failed to read !
CV 24 = 0 : Failed to read !
CV 25 = 0 : Failed to read !
CV 26 = 0 : Failed to read !
Cordialement

AmadeusHF

  • Full Member
  • ***
  • Messages: 205
    • Voir le profil
Re : DccToolkit / SystemToolkit
« Réponse #12 le: mars 28, 2021, 02:32:25 pm »
Mise à jour du premier message avec de nouvelles versions comportant quelques corrections & améliorations notamment en ce qui concerne :

  • Compatibilité UNO
  • Compatibilité NANO
  • Adaptation des timings pour les CPU à 20 et 32 Mhz
  • Intégration d'un CurrentSensor pour LM358 prenant en compte ses spécificités
  • Divers petits bugs éliminés

Pour rappel, voici le code du sketch à adapter selon votre matériel et le cablage que vous utilisez ,qui permet de tester l'ensemble en lisant en boucle les CVs d'un décodeur :

#include "SystemToolkit.h"
#include "DccToolkit.h"

// Create a current sensor reading on A0 with VCC = 5.0 volts
//ACS712CurrentSensor currentSensor(A0, 5000);
//Max471CurrentSensor currentSensor(A0, 5000);
LM358CurrentSensor currentSensor(A0, 5000);

// Create a signal generator using timer 1, pin 12 which is OUTPUT COMPARE B
// for timer 1 on MEGA for example
SignalGenerator generator(1, 10, true);

// Create a track driver using previous generator & current sensor, also using
// pin 11 to switch track power ON/OFF
TrackDriver driver(11, &generator, &currentSensor);

void setup()
{
Serial.begin(115200);

driver.setAckThresholdCurrent(60);

driver.start();
driver.powerOn();
}

void readCV(byte cv)
{
byte value = 0;
bool result = driver.readCV(cv, &value);
Serial.print("CV ");
Serial.print(cv);
Serial.print(" = ");
Serial.print(value);

if (result)
Serial.println(" : OK");
else
Serial.println(" : Failed to read !");
}

int x = 1;
bool up = true;

void loop()
{
delay(2000);

if (up)
readCV(x++);
else
readCV(x--);

if (x <= 1)
up = true;
if (x >= 140)
up = false;
}

Adaptations à faire :

1 / Ce code utilise le timer 1, présent sur tous les arduinos, donc il n'y a pas de raison de changer.
En revanche, OC1B, la broche utile du timer 1, n'est pas à la meme place sur tous les Arduino.
Sur un UNO c'est la broche D10. Si vous utilisez un autre modele il faut modifier la déclaration du SignalGenerator pour lui passer le bon numéro de broche....et cabler en conséquence.

2 / La broche de sortie du TIMER 1 se connecte à l'entrée DIR du shield moteur

3 / Une seconde broche libre de choix permet de piloter l'entrée PWM du shield moteur. Dans l'exemple ci-dessus c'est la broche 11 que j'ai choisi, le premier parametre de l'objet TrackDriver. Si vous utilisez une autre broche, changez ce paramètre en conséquence

4 / Selon votre capteur de courant, utilisez la bonne ligne et indiquez la bonne entrée (ici A0) pour la déclaration du currentSensor.

5 / Si votre Arduino n'est pas alimenté en 5V il faut adapter aussi sur cette ligne le second parametre (5000) qui donne la tension d'alimentation VCC en millivolts.

Ensuite il suffit de compiler et charger l'arduino.

Si la lecture n'est pas satisfaisante, vous pouvez essayer d'augmenter le SEUIL de courant (ou de le baisser) via la ligne :
driver.setAckThresholdCurrent(60);
qui se trouve au début du SETUP

La valeur passée est le seuil recherché, ici 60 mA, valeur de la norme DCC
« Modifié: mars 28, 2021, 02:33:59 pm par AmadeusHF »
Sébastien.
La perfection est un chemin, non un but...

AmadeusHF

  • Full Member
  • ***
  • Messages: 205
    • Voir le profil
Re : DccToolkit / SystemToolkit
« Réponse #13 le: mars 28, 2021, 03:30:40 pm »
Précision importante : la classe LM358CurrentSensor calcule le courant en appliquant 500 mV par ampere. Si l'échelle est différente (changement de la résistance comme évoquée par msport par ailleurs), il faut adapter le code de la classe en surchargeant la méthode convertSample.
Sébastien.
La perfection est un chemin, non un but...

Dominique

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 3013
  • 100% Arduino et N
    • Voir le profil
Re : DccToolkit / SystemToolkit
« Réponse #14 le: mars 28, 2021, 04:20:56 pm »
premier test avec tes biblios sur UNO avec la carte L6203-LM358 mais avec une loco très encrassée:

CV 1 = 16 : Failed to read ! pas loin c'est 18 !
CV 2 = 0 : Failed to read !
CV 3 = 0 : Failed to read !
CV 4 = 8 : OK
CV 5 = 93 : Failed to read !
CV 6 = 0 : OK
CV 7 = 14 : Failed to read !
CV 8 = 126 : Failed to read !
CV 9 = 4 : Failed to read !
CV 10 = 0 : Failed to read !
CV 11 = 0 : OK
CV 12 = 1 : OK
CV 13 = 0 : Failed to read !
CV 14 = 0 : Failed to read !
CV 15 = 0 : Failed to read !
CV 16 = 0 : Failed to read !
CV 17 = 128 : OK
CV 18 = 0 : OK

Cordialement,
Dominique