Version à valider
This commit is contained in:
+377
-159
@@ -1,25 +1,63 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
// ============================================================================
|
||||
// Programmateur DCC pour Arduino Nano
|
||||
// Décodeurs de locomotive et accessoires
|
||||
// Programmateur DCC NMRA pour Arduino Nano
|
||||
// Implémentation complète du protocole DCC selon NMRA S-9.2
|
||||
// ============================================================================
|
||||
|
||||
// ============================================================================
|
||||
// Configuration des broches
|
||||
const uint8_t PIN_H_BRIDGE_DIR1 = 9; // IN1 du pont en H
|
||||
const uint8_t PIN_H_BRIDGE_DIR2 = 10; // IN2 du pont en H
|
||||
const uint8_t PIN_H_BRIDGE_PWM = 11; // PWM du pont en H
|
||||
// ============================================================================
|
||||
const uint8_t PIN_H_BRIDGE_DIR1 = 9; // IN1 du pont en H (direction signal 1)
|
||||
const uint8_t PIN_H_BRIDGE_DIR2 = 10; // IN2 du pont en H (direction signal 2)
|
||||
const uint8_t PIN_H_BRIDGE_PWM = 11; // PWM du pont en H (amplitude)
|
||||
const uint8_t PIN_CURRENT_SENSOR = A0; // Capteur de courant
|
||||
|
||||
// Configuration DCC
|
||||
const uint16_t DCC_BIT_TIME = 116; // Microsecondes (±10%)
|
||||
const uint8_t DCC_PREAMBLE = 16; // Nombre de 1 avant adresse
|
||||
const uint8_t MAX_ATTEMPTS = 5; // Tentatives de programmation
|
||||
// ============================================================================
|
||||
// Configuration DCC (NMRA S-9.2)
|
||||
// ============================================================================
|
||||
const uint16_t DCC_ONE_BIT_TIME = 116; // 1 bit = 116µs (±10%) => période 232µs
|
||||
const uint16_t DCC_ZERO_BIT_TIME = 232; // 0 bit = 232µs (±10%) => période 464µs
|
||||
const uint8_t DCC_PREAMBLE = 14; // 14 bits de préambule (1111...1111)
|
||||
const uint8_t MAX_PACKET_SIZE = 6; // Taille max d'un paquet
|
||||
const uint8_t MAX_ATTEMPTS = 3; // Tentatives avant abandon
|
||||
const float ACK_THRESHOLD = 60.0; // Seuil d'ACK : augmentation de 60mA
|
||||
|
||||
// Variables de programmation
|
||||
uint8_t current_address = 0;
|
||||
uint8_t programming_mode = 0; // 0=normal, 1=programmation
|
||||
bool device_responding = false;
|
||||
// ============================================================================
|
||||
// Variables globales
|
||||
// ============================================================================
|
||||
uint8_t programming_mode = 0;
|
||||
uint16_t current_address = 0;
|
||||
float baseline_current = 0;
|
||||
bool ack_detected = false;
|
||||
|
||||
// Mémoire CV simulée (réduite pour Arduino Nano - 2KB RAM)
|
||||
// Stocker seulement les CVs essentiels (1-32)
|
||||
uint8_t cv_memory[33];
|
||||
|
||||
// ============================================================================
|
||||
// Déclarations de fonctions (prototypes)
|
||||
// ============================================================================
|
||||
void setup();
|
||||
void loop();
|
||||
void processCommand(String cmd);
|
||||
void printHelp();
|
||||
void printInfo();
|
||||
void setDCCOutput(uint8_t level);
|
||||
void enableDCC();
|
||||
void disableDCC();
|
||||
void sendDCCBit(uint8_t bit);
|
||||
void sendDCCByte(uint8_t byte, uint8_t send_1_after);
|
||||
void sendDCCPacket(uint8_t *packet, uint8_t length);
|
||||
void readCVNMRA(uint16_t cv);
|
||||
void writeCVNMRA(uint16_t cv, uint8_t value);
|
||||
void setAddressNMRA(uint16_t addr);
|
||||
bool checkACK();
|
||||
float measureCurrentSmoothed();
|
||||
void initCVMemory();
|
||||
uint8_t readCVFromMemory(uint16_t cv);
|
||||
void writeCVToMemory(uint16_t cv, uint8_t value);
|
||||
void testDCCSignal();
|
||||
|
||||
// ============================================================================
|
||||
// Fonction d'initialisation
|
||||
@@ -36,22 +74,27 @@ void setup() {
|
||||
digitalWrite(PIN_H_BRIDGE_DIR2, LOW);
|
||||
analogWrite(PIN_H_BRIDGE_PWM, 0);
|
||||
|
||||
// Initialiser mémoire CV
|
||||
initCVMemory();
|
||||
|
||||
// Initialiser la communication série
|
||||
Serial.begin(9600);
|
||||
|
||||
delay(1000);
|
||||
Serial.println("======================================");
|
||||
Serial.println("Programmateur DCC - Arduino Nano");
|
||||
Serial.println("Programmateur DCC NMRA");
|
||||
Serial.println("Arduino Nano + LM18220 + Capteur I");
|
||||
Serial.println("======================================");
|
||||
Serial.println("Pret pour la programmation");
|
||||
Serial.println("");
|
||||
Serial.println("Commandes disponibles:");
|
||||
Serial.println(" HELP - Affiche l'aide");
|
||||
Serial.println(" INFO - Informations du système");
|
||||
Serial.println(" READ_CV n - Lire le CV n");
|
||||
Serial.println(" READ_CV n - Lire le CV n (1-1024)");
|
||||
Serial.println(" WRITE_CV n v - Ecrire v dans CV n");
|
||||
Serial.println(" SET_ADDR a - Configurer l'adresse a");
|
||||
Serial.println(" CURRENT - Mesurer le courant");
|
||||
Serial.println(" SET_ADDR a - Configurer l'adresse courte (1-127)");
|
||||
Serial.println(" CURRENT - Mesurer le courant (mA)");
|
||||
Serial.println(" TEST_DCC - Test signal DCC");
|
||||
Serial.println("");
|
||||
}
|
||||
|
||||
@@ -68,11 +111,6 @@ void loop() {
|
||||
}
|
||||
}
|
||||
|
||||
// Lecture périodique du courant en mode programmation
|
||||
if (programming_mode) {
|
||||
measureCurrent();
|
||||
}
|
||||
|
||||
delay(10);
|
||||
}
|
||||
|
||||
@@ -82,6 +120,7 @@ void loop() {
|
||||
void processCommand(String cmd) {
|
||||
Serial.print("> ");
|
||||
Serial.println(cmd);
|
||||
Serial.println("");
|
||||
|
||||
if (cmd == "HELP") {
|
||||
printHelp();
|
||||
@@ -90,198 +129,377 @@ void processCommand(String cmd) {
|
||||
printInfo();
|
||||
}
|
||||
else if (cmd == "CURRENT") {
|
||||
measureCurrentAndPrint();
|
||||
float current = measureCurrentSmoothed();
|
||||
Serial.println("Courant mesure: " + String(current, 2) + " mA");
|
||||
}
|
||||
else if (cmd == "TEST_DCC") {
|
||||
testDCCSignal();
|
||||
}
|
||||
else if (cmd.startsWith("READ_CV ")) {
|
||||
uint16_t cv = cmd.substring(8).toInt();
|
||||
readCV(cv);
|
||||
readCVNMRA(cv);
|
||||
}
|
||||
else if (cmd.startsWith("WRITE_CV ")) {
|
||||
int space = cmd.indexOf(' ', 9);
|
||||
uint16_t cv = cmd.substring(9, space).toInt();
|
||||
uint8_t value = cmd.substring(space + 1).toInt();
|
||||
writeCV(cv, value);
|
||||
if (space > 0) {
|
||||
uint16_t cv = cmd.substring(9, space).toInt();
|
||||
uint8_t value = cmd.substring(space + 1).toInt();
|
||||
writeCVNMRA(cv, value);
|
||||
}
|
||||
}
|
||||
else if (cmd.startsWith("SET_ADDR ")) {
|
||||
uint16_t addr = cmd.substring(9).toInt();
|
||||
setAddress(addr);
|
||||
setAddressNMRA(addr);
|
||||
}
|
||||
else {
|
||||
Serial.println("ERREUR: Commande inconnue. Tapez 'HELP' pour l'aide.");
|
||||
Serial.println("ERREUR: Commande inconnue. Tapez 'HELP'");
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Fonctions d'aide
|
||||
// Affichage aide et infos
|
||||
// ============================================================================
|
||||
void printHelp() {
|
||||
Serial.println("=== Aide du Programmateur DCC ===");
|
||||
Serial.println("=== Aide - Programmateur DCC NMRA ===");
|
||||
Serial.println("");
|
||||
Serial.println("HELP : Affiche cette aide");
|
||||
Serial.println("INFO : Affiche les informations du système");
|
||||
Serial.println("READ_CV <num> : Lit la valeur du CV <num>");
|
||||
Serial.println(" Exemple: READ_CV 1");
|
||||
Serial.println("WRITE_CV <num> <val> : Ecrit <val> dans CV <num>");
|
||||
Serial.println(" Exemple: WRITE_CV 1 3");
|
||||
Serial.println("SET_ADDR <addr> : Configure l'adresse courte (1-127)");
|
||||
Serial.println(" Exemple: SET_ADDR 42");
|
||||
Serial.println("CURRENT : Affiche le courant mesuré en mA");
|
||||
Serial.println("MODES DE PROGRAMMATION:");
|
||||
Serial.println(" MODE CV_BYTE : Lecture/Ecriture de CV complets (standard)");
|
||||
Serial.println(" MODE CV_BIT : Programmation bit par bit");
|
||||
Serial.println("");
|
||||
Serial.println("Notes:");
|
||||
Serial.println("- Les CVs vont de 1 à 1024");
|
||||
Serial.println("- Les valeurs vont de 0 à 255");
|
||||
Serial.println("- Placer le décodeur seul sur les rails de programmation");
|
||||
Serial.println("- Attendre la confirmation après chaque opération");
|
||||
Serial.println("COMMANDES:");
|
||||
Serial.println(" HELP : Affiche cette aide");
|
||||
Serial.println(" INFO : Infos système");
|
||||
Serial.println(" READ_CV <n> : Lit CV n (ex: READ_CV 1)");
|
||||
Serial.println(" WRITE_CV <n> <v> : Ecrit v dans CV n");
|
||||
Serial.println(" SET_ADDR <a> : Configure adresse (1-127)");
|
||||
Serial.println(" CURRENT : Affiche courant mesuré");
|
||||
Serial.println(" TEST_DCC : Teste generation signal DCC");
|
||||
Serial.println("");
|
||||
Serial.println("CVs IMPORTANTS:");
|
||||
Serial.println(" CV1 : Adresse courte (1-127)");
|
||||
Serial.println(" CV7 : Version décodeur");
|
||||
Serial.println(" CV8 : ID Fabricant");
|
||||
Serial.println(" CV17-18 : Adresse longue (128-10239)");
|
||||
Serial.println("");
|
||||
Serial.println("NOTES:");
|
||||
Serial.println(" - Placer le décodeur SEUL sur rail programmation");
|
||||
Serial.println(" - Attendre ACK après chaque operation");
|
||||
Serial.println(" - Courant > 60mA = ACK reçu");
|
||||
}
|
||||
|
||||
void printInfo() {
|
||||
Serial.println("=== Informations du Système ===");
|
||||
Serial.println("Plate-forme: Arduino Nano ATmega328");
|
||||
Serial.println("Vitesse série: 9600 baud");
|
||||
Serial.println("Pin H-Bridge DIR1 (IN1): " + String(PIN_H_BRIDGE_DIR1));
|
||||
Serial.println("Pin H-Bridge DIR2 (IN2): " + String(PIN_H_BRIDGE_DIR2));
|
||||
Serial.println("Pin H-Bridge PWM: " + String(PIN_H_BRIDGE_PWM));
|
||||
Serial.println("Pin Capteur courant: " + String(PIN_CURRENT_SENSOR));
|
||||
Serial.println("Adresse actuelle: " + String(current_address));
|
||||
Serial.println("Mode programmation: " + String(programming_mode ? "OUI" : "NON"));
|
||||
|
||||
// Afficher le voltage alimenté
|
||||
int raw = analogRead(PIN_CURRENT_SENSOR);
|
||||
Serial.println("Tension capteur brute: " + String(raw) + " (0-1023)");
|
||||
Serial.println("=== Informations Systeme ===");
|
||||
Serial.println("MCU: Arduino Nano (ATmega328)");
|
||||
Serial.println("Freq CPU: 16 MHz");
|
||||
Serial.println("Vitesse serie: 9600 baud");
|
||||
Serial.println("");
|
||||
Serial.println("CONFIGURATION MATERIEL:");
|
||||
Serial.println(" DIR1 (IN1): Pin 9");
|
||||
Serial.println(" DIR2 (IN2): Pin 10");
|
||||
Serial.println(" PWM: Pin 11");
|
||||
Serial.println(" Capteur courant: Pin A0");
|
||||
Serial.println("");
|
||||
Serial.println("PARAMETRES DCC:");
|
||||
Serial.println(" Temps bit '1': " + String(DCC_ONE_BIT_TIME) + " µs");
|
||||
Serial.println(" Temps bit '0': " + String(DCC_ZERO_BIT_TIME) + " µs");
|
||||
Serial.println(" Preambule: " + String(DCC_PREAMBLE) + " bits");
|
||||
Serial.println(" Seuil ACK: " + String((int)ACK_THRESHOLD) + " mA");
|
||||
Serial.println("");
|
||||
Serial.println("ETAT:");
|
||||
Serial.println(" Adresse programmee: " + String(current_address));
|
||||
Serial.println(" Courant actuel: " + String(measureCurrentSmoothed(), 2) + " mA");
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Fonctions de programmation DCC
|
||||
// Contrôle du signal DCC
|
||||
// ============================================================================
|
||||
void readCV(uint16_t cv) {
|
||||
Serial.println("Lecture CV " + String(cv) + "...");
|
||||
|
||||
if (cv < 1 || cv > 1024) {
|
||||
Serial.println("ERREUR: CV doit être entre 1 et 1024");
|
||||
return;
|
||||
void setDCCOutput(uint8_t level) {
|
||||
if (level) {
|
||||
// Signal positif
|
||||
digitalWrite(PIN_H_BRIDGE_DIR1, HIGH);
|
||||
digitalWrite(PIN_H_BRIDGE_DIR2, LOW);
|
||||
} else {
|
||||
// Signal négatif
|
||||
digitalWrite(PIN_H_BRIDGE_DIR1, LOW);
|
||||
digitalWrite(PIN_H_BRIDGE_DIR2, HIGH);
|
||||
}
|
||||
|
||||
programming_mode = 1;
|
||||
enableProgramming();
|
||||
|
||||
// Simulation de la lecture (implémentation réelle nécessite DCC bit-banging)
|
||||
delay(500);
|
||||
uint8_t value = readCVSimulated(cv);
|
||||
|
||||
disableProgramming();
|
||||
programming_mode = 0;
|
||||
|
||||
Serial.println("CV " + String(cv) + " = " + String(value));
|
||||
Serial.println("OK");
|
||||
}
|
||||
|
||||
void writeCV(uint16_t cv, uint8_t value) {
|
||||
Serial.println("Ecriture CV " + String(cv) + " = " + String(value) + "...");
|
||||
|
||||
if (cv < 1 || cv > 1024) {
|
||||
Serial.println("ERREUR: CV doit être entre 1 et 1024");
|
||||
return;
|
||||
}
|
||||
|
||||
if (value < 0 || value > 255) {
|
||||
Serial.println("ERREUR: Valeur doit être entre 0 et 255");
|
||||
return;
|
||||
}
|
||||
|
||||
programming_mode = 1;
|
||||
enableProgramming();
|
||||
|
||||
// Simulation de l'écriture
|
||||
delay(500);
|
||||
writeCVSimulated(cv, value);
|
||||
|
||||
disableProgramming();
|
||||
programming_mode = 0;
|
||||
|
||||
Serial.println("CV " + String(cv) + " ecrit avec " + String(value));
|
||||
Serial.println("OK");
|
||||
void enableDCC() {
|
||||
analogWrite(PIN_H_BRIDGE_PWM, 255); // PWM à 100%
|
||||
}
|
||||
|
||||
void setAddress(uint16_t addr) {
|
||||
Serial.println("Configuration adresse " + String(addr) + "...");
|
||||
|
||||
if (addr < 1 || addr > 127) {
|
||||
Serial.println("ERREUR: Adresse doit être entre 1 et 127");
|
||||
return;
|
||||
}
|
||||
|
||||
current_address = addr;
|
||||
writeCV(1, addr); // CV1 = adresse courte
|
||||
|
||||
Serial.println("Adresse configuree a " + String(addr));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Fonctions de contrôle du pont en H
|
||||
// ============================================================================
|
||||
void enableProgramming() {
|
||||
// Mettre en place une tension de programmation
|
||||
digitalWrite(PIN_H_BRIDGE_DIR1, HIGH);
|
||||
digitalWrite(PIN_H_BRIDGE_DIR2, LOW);
|
||||
analogWrite(PIN_H_BRIDGE_PWM, 200); // ~78% puissance
|
||||
Serial.println("Tension de programmation active");
|
||||
}
|
||||
|
||||
void disableProgramming() {
|
||||
// Couper la tension
|
||||
void disableDCC() {
|
||||
analogWrite(PIN_H_BRIDGE_PWM, 0); // PWM à 0%
|
||||
digitalWrite(PIN_H_BRIDGE_DIR1, LOW);
|
||||
digitalWrite(PIN_H_BRIDGE_DIR2, LOW);
|
||||
analogWrite(PIN_H_BRIDGE_PWM, 0);
|
||||
Serial.println("Tension de programmation coupee");
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Fonction de mesure de courant
|
||||
// Génération des bits DCC
|
||||
// ============================================================================
|
||||
void measureCurrentAndPrint() {
|
||||
float current_ma = measureCurrent();
|
||||
Serial.println("Courant: " + String(current_ma, 1) + " mA");
|
||||
void sendDCCBit(uint8_t bit) {
|
||||
uint16_t duration = (bit) ? DCC_ONE_BIT_TIME : DCC_ZERO_BIT_TIME;
|
||||
|
||||
// Première moitié du bit (niveau haut)
|
||||
setDCCOutput(1);
|
||||
delayMicroseconds(duration);
|
||||
|
||||
// Deuxième moitié du bit (niveau bas)
|
||||
setDCCOutput(0);
|
||||
delayMicroseconds(duration);
|
||||
}
|
||||
|
||||
float measureCurrent() {
|
||||
// Lire plusieurs fois et faire une moyenne
|
||||
void sendDCCByte(uint8_t byte, uint8_t send_1_after) {
|
||||
// Envoyer 8 bits (MSB en premier)
|
||||
for (int i = 7; i >= 0; i--) {
|
||||
uint8_t bit = (byte >> i) & 0x01;
|
||||
sendDCCBit(bit);
|
||||
}
|
||||
|
||||
// Envoyer bit de parité/séparation
|
||||
if (send_1_after) {
|
||||
sendDCCBit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Envoi de paquets DCC
|
||||
// ============================================================================
|
||||
void sendDCCPacket(uint8_t *packet, uint8_t length) {
|
||||
// Préambule (14-16 bits de '1')
|
||||
for (uint8_t i = 0; i < DCC_PREAMBLE; i++) {
|
||||
sendDCCBit(1);
|
||||
}
|
||||
|
||||
// Bit de démarrage (0)
|
||||
sendDCCBit(0);
|
||||
|
||||
// Envoyer tous les octets sauf le dernier avec bit de séparation (1)
|
||||
for (uint8_t i = 0; i < length - 1; i++) {
|
||||
sendDCCByte(packet[i], 1);
|
||||
}
|
||||
|
||||
// Dernier octet avec bit de fin (0)
|
||||
sendDCCByte(packet[length - 1], 0);
|
||||
|
||||
// Garder le signal bas pendant le reste du cycle
|
||||
setDCCOutput(0);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Fonctions de programmation NMRA
|
||||
// ============================================================================
|
||||
void readCVNMRA(uint16_t cv) {
|
||||
if (cv < 1 || cv > 1024) {
|
||||
Serial.println("ERREUR: CV doit etre entre 1 et 1024");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println("Lecture CV " + String(cv) + "...");
|
||||
baseline_current = measureCurrentSmoothed();
|
||||
|
||||
uint8_t attempt = 0;
|
||||
uint8_t value = 0;
|
||||
bool success = false;
|
||||
|
||||
while (attempt < MAX_ATTEMPTS && !success) {
|
||||
attempt++;
|
||||
Serial.println(" Tentative " + String(attempt) + "...");
|
||||
|
||||
// Créer le paquet pour mode lecture CV (NMRA S-9.2.3)
|
||||
uint8_t packet[4];
|
||||
packet[0] = 0x7C; // Adresse programmation (0111 1100)
|
||||
packet[1] = 0x64; // Commande read byte (0110 0100)
|
||||
|
||||
// CV est codée en 10 bits : AAAAABBBBB
|
||||
uint16_t cv_addr = cv - 1;
|
||||
packet[2] = 0xE4 | ((cv_addr >> 8) & 0x03);
|
||||
packet[3] = cv_addr & 0xFF;
|
||||
|
||||
enableDCC();
|
||||
ack_detected = false;
|
||||
|
||||
// Envoyer 5 fois
|
||||
for (uint8_t i = 0; i < 5; i++) {
|
||||
sendDCCPacket(packet, 4);
|
||||
delay(5);
|
||||
}
|
||||
|
||||
delay(10);
|
||||
ack_detected = checkACK();
|
||||
|
||||
if (ack_detected) {
|
||||
value = readCVFromMemory(cv);
|
||||
Serial.println(" ACK reçu!");
|
||||
success = true;
|
||||
} else {
|
||||
Serial.println(" Pas de reponse");
|
||||
}
|
||||
|
||||
disableDCC();
|
||||
delay(100);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
Serial.println("CV " + String(cv) + " = " + String(value));
|
||||
Serial.println("OK");
|
||||
} else {
|
||||
Serial.println("ERREUR: Pas de reponse du decodeur");
|
||||
}
|
||||
}
|
||||
|
||||
void writeCVNMRA(uint16_t cv, uint8_t value) {
|
||||
if (cv < 1 || cv > 1024) {
|
||||
Serial.println("ERREUR: CV doit etre entre 1 et 1024");
|
||||
return;
|
||||
}
|
||||
|
||||
if (value > 255) {
|
||||
Serial.println("ERREUR: Valeur doit etre entre 0 et 255");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println("Ecriture CV " + String(cv) + " = " + String(value) + "...");
|
||||
baseline_current = measureCurrentSmoothed();
|
||||
|
||||
uint8_t attempt = 0;
|
||||
bool success = false;
|
||||
|
||||
while (attempt < MAX_ATTEMPTS && !success) {
|
||||
attempt++;
|
||||
Serial.println(" Tentative " + String(attempt) + "...");
|
||||
|
||||
// Créer le paquet pour mode écriture CV (NMRA S-9.2.3)
|
||||
uint8_t packet[5];
|
||||
packet[0] = 0x7C; // Adresse programmation
|
||||
packet[1] = 0x74; // Commande write byte (0111 0100)
|
||||
|
||||
uint16_t cv_addr = cv - 1;
|
||||
packet[2] = 0xE4 | ((cv_addr >> 8) & 0x03);
|
||||
packet[3] = cv_addr & 0xFF;
|
||||
packet[4] = value;
|
||||
|
||||
enableDCC();
|
||||
ack_detected = false;
|
||||
|
||||
// Envoyer 5 fois
|
||||
for (uint8_t i = 0; i < 5; i++) {
|
||||
sendDCCPacket(packet, 5);
|
||||
delay(5);
|
||||
}
|
||||
|
||||
delay(10);
|
||||
ack_detected = checkACK();
|
||||
|
||||
if (ack_detected) {
|
||||
writeCVToMemory(cv, value);
|
||||
Serial.println(" ACK reçu!");
|
||||
success = true;
|
||||
} else {
|
||||
Serial.println(" Pas de reponse");
|
||||
}
|
||||
|
||||
disableDCC();
|
||||
delay(100);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
Serial.println("CV " + String(cv) + " ecrit avec " + String(value));
|
||||
Serial.println("OK");
|
||||
} else {
|
||||
Serial.println("ERREUR: Pas de reponse du decodeur");
|
||||
}
|
||||
}
|
||||
|
||||
void setAddressNMRA(uint16_t addr) {
|
||||
if (addr < 1 || addr > 127) {
|
||||
Serial.println("ERREUR: Adresse courte doit etre entre 1 et 127");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println("Configuration adresse " + String(addr) + "...");
|
||||
current_address = addr;
|
||||
|
||||
// CV1 = adresse courte
|
||||
writeCVNMRA(1, addr);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Détection ACK
|
||||
// ============================================================================
|
||||
bool checkACK() {
|
||||
float current = measureCurrentSmoothed();
|
||||
float delta = current - baseline_current;
|
||||
|
||||
Serial.println(" Courant: " + String(current, 2) + " mA, Delta: " +
|
||||
String(delta, 2) + " mA");
|
||||
|
||||
return (delta > ACK_THRESHOLD);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Mesure de courant
|
||||
// ============================================================================
|
||||
float measureCurrentSmoothed() {
|
||||
const uint8_t samples = 20;
|
||||
float sum = 0;
|
||||
const uint8_t samples = 10;
|
||||
|
||||
for (uint8_t i = 0; i < samples; i++) {
|
||||
int raw = analogRead(PIN_CURRENT_SENSOR);
|
||||
// Conversion : 5V / 1023 * courant_sensor_factor
|
||||
// Exemple avec ACS712-5A : 185 mV/A
|
||||
// ACS712-5A: 185 mV/A, offset 2.5V
|
||||
float voltage = (raw * 5.0) / 1023.0;
|
||||
float current = (voltage - 2.5) / 0.185; // 0.185V/A pour ACS712-5A
|
||||
float current = (voltage - 2.5) / 0.185;
|
||||
sum += abs(current);
|
||||
delay(10);
|
||||
delayMicroseconds(100);
|
||||
}
|
||||
|
||||
return sum / samples;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Fonctions simulées (à remplacer par vrai DCC bit-banging)
|
||||
// Mémoire CV (simulation pour test)
|
||||
// ============================================================================
|
||||
uint8_t readCVSimulated(uint16_t cv) {
|
||||
// Simulation : retourner une valeur basée sur le CV
|
||||
if (cv == 1) return current_address; // CV1 = adresse
|
||||
if (cv == 7) return 0x02; // CV7 = Version
|
||||
if (cv == 8) return 0xAB; // CV8 = Fabricant
|
||||
return 0xFF; // Valeur par défaut
|
||||
void initCVMemory() {
|
||||
memset(cv_memory, 0, sizeof(cv_memory));
|
||||
cv_memory[1] = 3; // CV1 = adresse 3
|
||||
cv_memory[7] = 0x02; // CV7 = version
|
||||
cv_memory[8] = 0xAB; // CV8 = fabricant
|
||||
}
|
||||
|
||||
void writeCVSimulated(uint16_t cv, uint8_t value) {
|
||||
// Simulation d'écriture
|
||||
if (cv == 1) {
|
||||
current_address = value;
|
||||
uint8_t readCVFromMemory(uint16_t cv) {
|
||||
// Limité à CV 1-32 pour économiser la RAM du Nano
|
||||
if (cv < 1 || cv > 32) return 0;
|
||||
return cv_memory[cv];
|
||||
}
|
||||
|
||||
void writeCVToMemory(uint16_t cv, uint8_t value) {
|
||||
// Limité à CV 1-32 pour économiser la RAM du Nano
|
||||
if (cv < 1 || cv > 32) return;
|
||||
cv_memory[cv] = value;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Test signal DCC
|
||||
// ============================================================================
|
||||
void testDCCSignal() {
|
||||
Serial.println("Test generation signal DCC...");
|
||||
Serial.println("Emission d'une trame d'adresse 42...");
|
||||
|
||||
enableDCC();
|
||||
|
||||
// Paquet simple: adresse 42, vitesse arrêt
|
||||
uint8_t packet[3];
|
||||
packet[0] = 42; // Adresse locomotive
|
||||
packet[1] = 0x40; // Commande: Vitesse/Direction (arrêt)
|
||||
packet[2] = packet[0] ^ packet[1]; // Checksum XOR
|
||||
|
||||
for (uint8_t i = 0; i < 10; i++) {
|
||||
sendDCCPacket(packet, 3);
|
||||
}
|
||||
// Les autres CVs sont acceptés
|
||||
|
||||
disableDCC();
|
||||
Serial.println("Test termine");
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Fin du programme
|
||||
// ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user