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
+35 -44
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).
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 :
1. Via les CVs (Configuration Variables)
La norme NMRA prévoit deux méthodes principales pour régler l'adresse d'un accessoire, nous utilisons les CVs.
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 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 standards NMRA pour accessoires (S-9.2.2)
Récapitulatif des CVs de notre accessoire
| CV | Description |
| -------- | ------------------------------------------- |
| -------- | ---------------------------------------------------------------------------------- |
| CV 513 | Adresse d'accessoire (Bits de poids faible) |
| CV 521 | Adresse d'accessoire (Bits de poids fort) |
| CV 519 | Version du décodeur (Lecture seule) |
| CV 520 | Identifiant fabricant (Lecture seule) |
| CV 100 | Vitesse de rotation du moteur de pale (0 à 255) |
| CV 101 | Valeur maximale du servo (0 à 180) |
| CV 102 | Valeur minimale du servo (0 à 180) |
| 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) |
# 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
courant souhaité : 5 mA
résistance idéale :
𝑅
=
5
𝑉
3.2
𝑉
0.005
𝐴
360
 
𝛺
R=
0.005A
5V3.2V
≈360 Ω
1. Pourquoi le choix des broches est idéal (Conflits évités)
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é
470 Ω si vous voulez être plus prudent
En pratique :
- *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
330 Ω est un bon choix pour 5 mA
470 Ω est encore correct et plus sûr pour la broche
Conseil :
- *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.
si vous utilisez une LED blanche très brillante, commencez avec 470 Ω
si elle est trop faible, passez à 330 Ω
- *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.
2. Le comportement face à vos contraintes de fonctionnementL'Arduino exécutera ces fonctions de manière virtuellement simultanée grâce aux interruptions :
- *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.
+40 -30
View File
@@ -4,10 +4,10 @@
#include <EEPROM.h>
// Affectation des PINs Arduino
#define DCC_SIGNAL_PIN 2
#define LED_PIN 3
#define PWM_PIN 5
#define SERVO_PIN 6
#define DCC_SIGNAL_PIN 2 // Pin pour le signal DCC
#define LED_PIN 3 // Pin pour la LED de signalisation
#define PWM_PIN 5 // Pin pour le signal PWM du moteur des pales
#define SERVO_PIN 9 // Pin pour le signal du servo moteur
// Valeurs des CV (Configuration Variables)
#define CV_ADDRESS_LSB 513
@@ -15,17 +15,21 @@
#define CV_PALES_SPEED 100
#define CV_MAX_UP 101
#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
#define DEFAULT_PALES_SPEED 255
#define DEFAULT_MAX_UP 180
#define DEFAULT_MAX_DOWN 0
#define DEFAULT_ADDRESS 1
#define DEFAULT_PALES_SPEED 255 // Vitesse par défaut du moteur des pales (0-255)
#define DEFAULT_MAX_UP 180 // Position maximale par défaut pour le servo en haut (0-180)
#define DEFAULT_MAX_DOWN 0 // Position maximale par défaut pour le servo en bas (0-180)
#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 EEPROM_SIG_ADDR 0
#define EEPROM_SIG_VALUE 0xA5
#define DIY_MANUFACTURER_ID 13
#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 // Valeur de signature pour vérifier la validité de la structure de configuration dans l'EEPROM
#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
@@ -69,8 +73,10 @@ unsigned long servoNextMillis = 0;
void notifyCVAck(void)
{
digitalWrite(LED_PIN, HIGH);
digitalWrite(LED_BUILTIN, HIGH);
delay(6);
digitalWrite(LED_PIN, LOW);
digitalWrite(LED_BUILTIN, LOW);
}
/**
@@ -81,27 +87,30 @@ void notifyCVAck(void)
*/
void notifyCVChange(uint16_t CV, uint8_t Value)
{
if (CV == CV_PALES_SPEED) {
PalesSpeed = Value;
} else if (CV == CV_MAX_UP) {
ServoMaxUp = Value;
if (CV == CV_PALES_SPEED)
{
// Taux du PWM de 0 à 255 pour la vitesse du moteur des pales
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) {
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) {
currentAddress = (currentAddress & 0xFF00) | Value;
if (CV == CV_ADDRESS_LSB) {
Dcc.setCV(CV_ACCESSORY_DECODER_ADDRESS_LSB, Value);
} else {
Dcc.setCV(CV_ADDRESS_LSB, Value);
}
MyConfig.address = (MyConfig.address & 0xFF00) | Value;
} else if (CV == CV_ADDRESS_MSB || CV == CV_ACCESSORY_DECODER_ADDRESS_MSB) {
currentAddress = (currentAddress & 0x00FF) | ((Value & 0x07) << 8);
if (CV == CV_ADDRESS_MSB) {
Dcc.setCV(CV_ACCESSORY_DECODER_ADDRESS_MSB, Value & 0x07);
} else {
Dcc.setCV(CV_ADDRESS_MSB, Value);
}
MyConfig.address = (MyConfig.address & 0x00FF) | ((Value & 0x07) << 8);
} else if (CV == CV_RESET && Value == 8) {
// Réinitialiser les valeurs par défaut
initDefaultConfig();
}
// 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)
{
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;
}
@@ -124,7 +134,7 @@ void initDefaultConfig()
{
MyConfig.Sig = EEPROM_SIG_VALUE;
MyConfig.ManufacturerID = DIY_MANUFACTURER_ID;
MyConfig.Version = 1;
MyConfig.Version = DIY_MODEL_ID;
MyConfig.address = DEFAULT_ADDRESS;
MyConfig.MotorSpeed = DEFAULT_PALES_SPEED;
MyConfig.ServoMaxUp = DEFAULT_MAX_UP;