Ajout Doc

This commit is contained in:
Serge NOEL
2026-08-11 11:02:30 +02:00
parent 13930c5279
commit c505ecbd4a
2 changed files with 84 additions and 83 deletions
+38 -47
View File
@@ -23,70 +23,61 @@ Sur les réseaux ferroviaires miniatures en DCC, il n'y a pas d'adresse unique p
Certains modules multi- Sorties (Notre cas car on a bseoin de 3 informations) reçoivent par défaut le premier groupe d'adresses (ex. sorties 1 à 4). Certains modules multi- Sorties (Notre cas car on a bseoin de 3 informations) reçoivent par défaut le premier groupe d'adresses (ex. sorties 1 à 4).
Pour modifier son adresse ? ## Comment modifier son adresse ?
La norme NMRA prévoit deux méthodes principales pour régler l'adresse d'un accessoire : La norme NMRA prévoit deux méthodes principales pour régler l'adresse d'un accessoire, nous utilisons les CVs.
1. Via les CVs (Configuration Variables)
Pour la plupart des décodeurs modernes réglables par CV, l'adresse principale n'est pas stockée dans un seul CV, mais est répartie sur deux CVs distincts pour pouvoir dépasser la valeur 255 (comme pour l'adresse longue des locomotives) : Pour la plupart des décodeurs modernes réglables par CV, l'adresse principale n'est pas stockée dans un seul CV, mais est répartie sur deux CVs distincts pour pouvoir dépasser la valeur 255 (comme pour l'adresse longue des locomotives) :
- CV 513 (Adresse basse / Decoder Address LSB) - CV 513 (Adresse basse / Decoder Address LSB)
- CV 521 (Adresse haute / Decoder Address MSB) - CV 521 (Adresse haute / Decoder Address MSB)
Attention à l'adressage par sortie / par décodeur : Attention à l'adressage par sortie / par décodeur :
Selon les marques, certains décodeurs attribuent une adresse par boîtier (4 sorties regroupées), tandis que d'autres permettent d'attribuer une adresse individuelle à chaque sortie. Sur les décodeurs gérant chaque sortie séparément, les CVs d'adresses individuelles sont souvent organisés par blocs de CVs spécifiques (consultez la notice du fabricant). Le boitier contient une adresse (3 sorties regroupées).
Récapitulatif des CVs de notre accessoire
Récapitulatif des CVs standards NMRA pour accessoires (S-9.2.2) | CV | Description |
| -------- | ---------------------------------------------------------------------------------- |
| CV | Description | | CV 513 | Adresse d'accessoire (Bits de poids faible) |
| -------- | ------------------------------------------- | | CV 521 | Adresse d'accessoire (Bits de poids fort) |
| CV 513 | Adresse d'accessoire (Bits de poids faible) | | CV 100 | Vitesse de rotation du moteur de pale (0 à 255) |
| CV 521 | Adresse d'accessoire (Bits de poids fort) | | CV 101 | Valeur maximale du servo (0 à 180) |
| CV 519 | Version du décodeur (Lecture seule) | | CV 102 | Valeur minimale du servo (0 à 180) |
| CV 520 | Identifiant fabricant (Lecture seule) | | CV 519 | Version du décodeur (Lecture seule) -1- Hélico module |
| CV 520 | Identifiant fabricant (Lecture seule) -13- Construction amateur |
| CV 512/8 | Reset d'usine (Écrire la valeur 8 réinitialise souvent le décodeur à l'adresse 1) | | CV 512/8 | Reset d'usine (Écrire la valeur 8 réinitialise souvent le décodeur à l'adresse 1) |
# Matériel
Je vous réponds concrètement sur la compatibilité de la LED et la valeur de résistance à choisir. 1. Une led blanche 'Strobe' est connectée sur la broche 3 du Nano, elle est branchée avec une résistance de 470𝛺 ce qui donne une intensité suffisante et un courant consommé d'environ 5mA
2. Le moteur qui entraine les pales (coreless réducté) est un modèle 720, il est piloté par un transitor MOSFET 2N7002 avec une diode 1N4148 en roue libre et un polyswitch de 250mA
3. Un servo standard est dédié au mouvement de montée descente
Oui, vous pouvez brancher une LED blanche directement sur la broche LED_PIN, à condition de mettre une résistance en série. ## Configuration
Pour une LED blanche sur une sortie Arduino Nano à 5 V : Cette configuration de broches (D2 pour le DCC, D9 pour le servo, D5 pour le PWM) est parfaitement optimisée pour un Arduino Nano. L'Atmega328P sera tout à fait capable de gérer ces trois tâches de front, car les composants matériels utilisés n'entrent pas en conflit.
tension de la LED blanche : environ 3,0 à 3,3 V 1. Pourquoi le choix des broches est idéal (Conflits évités)
courant souhaité : 5 mA
résistance idéale :
𝑅
=
5
𝑉
3.2
𝑉
0.005
𝐴
360
 
𝛺
R=
0.005A
5V3.2V
≈360 Ω
Valeur pratique recommandée : L'Arduino Nano gère ses tâches internes via des horloges appelées Timers. Votre configuration répartit parfaitement la charge de ces timers :
330 Ω si vous voulez un peu plus de luminosité - *D2 (Signal DCC)* : La bibliothèque standard NmraDcc nécessite une interruption matérielle externe. Sur un Nano, seules les broches D2 (Interruption 0) et D3 (Interruption 1) possèdent cette capacité. Placer le DCC sur la broche D2 est donc obligatoire et indispensable. La bibliothèque utilise l'interruption matérielle et la fonction micros(). Elle ne monopolise aucun timer majeur pour son calcul
470 Ω si vous voulez être plus prudent
En pratique : - *D9 (Servomoteur)* : La bibliothèque Servo.h de l'Arduino utilise par défaut le Timer 1. Lorsqu'elle s'active, elle désactive le PWM natif des broches D9 et D10. En branchant votre servo sur D9, vous utilisez la broche idéale puisqu'elle est nativement liée à ce timer.
330 Ω est un bon choix pour 5 mA - *D5 (Moteur PWM)* : Le signal PWM de la broche D5 est généré de manière 100 % matérielle par le Timer 0 (partagé avec millis()). Comme le servo confisque le Timer 1 (D9/D10), votre PWM sur D5 reste totalement indépendant et stable, oscillant à sa fréquence normale d'environ 976 Hz sans subir de distorsion.
470 Ω est encore correct et plus sûr pour la broche
Conseil :
si vous utilisez une LED blanche très brillante, commencez avec 470 Ω 2. Le comportement face à vos contraintes de fonctionnementL'Arduino exécutera ces fonctions de manière virtuellement simultanée grâce aux interruptions :
si elle est trop faible, passez à 330 Ω
- *Peu de changements de commandes DCC* : Le signal DCC applique une charge constante de micro-interruptions sur la broche D2 (détection des fronts d'ondes à haute fréquence). Toutefois, le décodage d'un message d'accessoire se fait en quelques microsecondes. Le fait qu'il y ait peu de changements de commandes signifie que la fonction principale de votre code (loop) sera très souvent disponible pour d'autres tâches.
- *ON / OFF ou variation du PWM de 0 à 255* : La fonction analogWrite(5, valeur); demande un effort nul au processeur. Une fois la valeur envoyée, cest le circuit électronique (Timer 0) qui maintient le signal de manière autonome. Changer le paramétrage n'impactera pas le reste du système.
- *Changement lent de position du servo* : Pour faire bouger un servo lentement, la technique consiste à incrémenter sa position degré par degré avec un petit intervalle de temps
**Le piège absolu à éviter** :
Les delay()Pour garantir la simultanéité des tâches, vous ne devez pas utiliser la fonction delay() pour ralentir votre servo.Si vous écrivez delay(20); entre chaque degré du servo, l'Arduino va "geler". Bien que le DCC continue de fonctionner en tâche de fond grâce à son interruption, l'appel à la fonction cruciale Dcc.process(); (qui doit être exécutée en boucle continue dans le loop) sera bloqué pendant ce délai. Cela entraînera des pertes de paquets DCC ou des saccades.
**La bonne pratique** : Utilisez la technique des minuteurs logiciels sans blocage basée sur millis() (comme dans l'exemple officiel Blink Without Delay d'Arduino) pour cadencer le déplacement lent du servo.
+46 -36
View File
@@ -4,28 +4,32 @@
#include <EEPROM.h> #include <EEPROM.h>
// Affectation des PINs Arduino // Affectation des PINs Arduino
#define DCC_SIGNAL_PIN 2 #define DCC_SIGNAL_PIN 2 // Pin pour le signal DCC
#define LED_PIN 3 #define LED_PIN 3 // Pin pour la LED de signalisation
#define PWM_PIN 5 #define PWM_PIN 5 // Pin pour le signal PWM du moteur des pales
#define SERVO_PIN 6 #define SERVO_PIN 9 // Pin pour le signal du servo moteur
// Valeurs des CV (Configuration Variables) // Valeurs des CV (Configuration Variables)
#define CV_ADDRESS_LSB 513 #define CV_ADDRESS_LSB 513
#define CV_ADDRESS_MSB 521 #define CV_ADDRESS_MSB 521
#define CV_PALES_SPEED 100 #define CV_PALES_SPEED 100
#define CV_MAX_UP 101 #define CV_MAX_UP 101
#define CV_MAX_DOWN 102 #define CV_MAX_DOWN 102
#define CV_RESET 512 // CV pour réinitialiser les valeurs par défaut (standard NMRA DCC)
// Valeurs par défaut des CV // Valeurs par défaut des CV
#define DEFAULT_PALES_SPEED 255 #define DEFAULT_PALES_SPEED 255 // Vitesse par défaut du moteur des pales (0-255)
#define DEFAULT_MAX_UP 180 #define DEFAULT_MAX_UP 180 // Position maximale par défaut pour le servo en haut (0-180)
#define DEFAULT_MAX_DOWN 0 #define DEFAULT_MAX_DOWN 0 // Position maximale par défaut pour le servo en bas (0-180)
#define DEFAULT_ADDRESS 1 #define DEFAULT_ADDRESS 1 // Adresse DCC par défaut du décodeur d'accessoire
#define VITESSE 40 // Temps en millisecondes entre chaque pas de servo #define VITESSE 40 // Temps en millisecondes entre chaque pas de servo
#define EEPROM_SIG_ADDR 0 #define EEPROM_SIG_ADDR 0 // Position dans l'EEPROM pour stocker la signature de validation de la structure de configuration
#define EEPROM_SIG_VALUE 0xA5 #define EEPROM_SIG_VALUE 0xA5 // Valeur de signature pour vérifier la validité de la structure de configuration dans l'EEPROM
#define DIY_MANUFACTURER_ID 13 #define DIY_MANUFACTURER_ID 200 // Non utilisé actuellement d'après la spécification NMRA DCC,
// mais peut être utilisé pour identifier le fabricant du décodeur.
#define DIY_MODEL_ID 1 // Carte pilote Helicoptère, non utilisé actuellement d'après la spécification NMRA DCC,
// mais peut être utilisé pour identifier le modèle du décodeur.
#define DEBUG 1 #define DEBUG 1
@@ -69,8 +73,10 @@ unsigned long servoNextMillis = 0;
void notifyCVAck(void) void notifyCVAck(void)
{ {
digitalWrite(LED_PIN, HIGH); digitalWrite(LED_PIN, HIGH);
digitalWrite(LED_BUILTIN, HIGH);
delay(6); delay(6);
digitalWrite(LED_PIN, LOW); digitalWrite(LED_PIN, LOW);
digitalWrite(LED_BUILTIN, LOW);
} }
/** /**
@@ -81,27 +87,30 @@ void notifyCVAck(void)
*/ */
void notifyCVChange(uint16_t CV, uint8_t Value) void notifyCVChange(uint16_t CV, uint8_t Value)
{ {
if (CV == CV_PALES_SPEED) { if (CV == CV_PALES_SPEED)
PalesSpeed = Value; {
} else if (CV == CV_MAX_UP) { // Taux du PWM de 0 à 255 pour la vitesse du moteur des pales
ServoMaxUp = Value; MyConfig.MotorSpeed = Value;
} else if (CV == CV_MAX_UP)
{
// La valeur maximale pour la position du servo en haut (0-180)
if (Value > 180) Value = 180; // Limite la valeur à 180
MyConfig.ServoMaxUp = Value;
} else if (CV == CV_MAX_DOWN) { } else if (CV == CV_MAX_DOWN) {
ServoMaxDown = Value; // La valeur maximale pour la position du servo en bas (0-180)
if (Value > 180) Value = 180; // Limite la valeur à 180
MyConfig.ServoMaxDown = Value;
} else if (CV == CV_ADDRESS_LSB || CV == CV_ACCESSORY_DECODER_ADDRESS_LSB) { } else if (CV == CV_ADDRESS_LSB || CV == CV_ACCESSORY_DECODER_ADDRESS_LSB) {
currentAddress = (currentAddress & 0xFF00) | Value; MyConfig.address = (MyConfig.address & 0xFF00) | Value;
if (CV == CV_ADDRESS_LSB) {
Dcc.setCV(CV_ACCESSORY_DECODER_ADDRESS_LSB, Value);
} else {
Dcc.setCV(CV_ADDRESS_LSB, Value);
}
} else if (CV == CV_ADDRESS_MSB || CV == CV_ACCESSORY_DECODER_ADDRESS_MSB) { } else if (CV == CV_ADDRESS_MSB || CV == CV_ACCESSORY_DECODER_ADDRESS_MSB) {
currentAddress = (currentAddress & 0x00FF) | ((Value & 0x07) << 8); MyConfig.address = (MyConfig.address & 0x00FF) | ((Value & 0x07) << 8);
if (CV == CV_ADDRESS_MSB) { } else if (CV == CV_RESET && Value == 8) {
Dcc.setCV(CV_ACCESSORY_DECODER_ADDRESS_MSB, Value & 0x07); // Réinitialiser les valeurs par défaut
} else { initDefaultConfig();
Dcc.setCV(CV_ADDRESS_MSB, Value);
}
} }
// Sauver les nouvelles valeurs dans l'EEPROM
EEPROM.write(EEPROM_SIG_ADDR, EEPROM_SIG_VALUE);
EEPROM.put(1, MyConfig);
} }
/** /**
@@ -113,7 +122,8 @@ void notifyCVChange(uint16_t CV, uint8_t Value)
uint8_t notifyCVValid (uint16_t CV, uint8_t Writable) uint8_t notifyCVValid (uint16_t CV, uint8_t Writable)
{ {
if (CV == CV_PALES_SPEED || CV == CV_MAX_UP || CV == CV_MAX_DOWN || if (CV == CV_PALES_SPEED || CV == CV_MAX_UP || CV == CV_MAX_DOWN ||
CV == CV_ADDRESS_LSB || CV == CV_ADDRESS_MSB || CV == CV_ADDRESS_LSB || CV == CV_ADDRESS_MSB) { CV == CV_ADDRESS_LSB || CV == CV_ADDRESS_MSB ||
CV == CV_RESET) {
return 1; return 1;
} }
@@ -124,7 +134,7 @@ void initDefaultConfig()
{ {
MyConfig.Sig = EEPROM_SIG_VALUE; MyConfig.Sig = EEPROM_SIG_VALUE;
MyConfig.ManufacturerID = DIY_MANUFACTURER_ID; MyConfig.ManufacturerID = DIY_MANUFACTURER_ID;
MyConfig.Version = 1; MyConfig.Version = DIY_MODEL_ID;
MyConfig.address = DEFAULT_ADDRESS; MyConfig.address = DEFAULT_ADDRESS;
MyConfig.MotorSpeed = DEFAULT_PALES_SPEED; MyConfig.MotorSpeed = DEFAULT_PALES_SPEED;
MyConfig.ServoMaxUp = DEFAULT_MAX_UP; MyConfig.ServoMaxUp = DEFAULT_MAX_UP;