Messages récents

Pages: 1 ... 6 7 [8] 9 10
71
Vos projets / Re : Identification des trains par infrarouge
« Dernier message par Dominique le mai 09, 2025, 11:55:02 pm »
Pour l’alimentation à partir du DCC, un bout fil dénudé enroulé autour de l’essieu avant, côté + avec une diode en série; un autre bout de fil dénudé autour de l’essieu arrière retourné côté -; une capa de stockage et un regulateur : ça doit le faire !
72
Vos projets / Re : Identification des trains par infrarouge
« Dernier message par bobyAndCo le mai 09, 2025, 08:09:43 pm »
Merci Dominique.

De mon côté, je veux remercier Jean-Pierre (JPM06) d'avoir apporté ce sujet sur un autre outil d'identification à côté de Railcom et du RFID. Il y a beaucoup de côtés positifs dont la fiabilité et le cout très raisonnable.

Deux petites ombres au tableau toutefois : l'encombrement qui oblige à placer l'ensemble dans un wagon "suiveur" et la nécessité de s'alimenter sur la voie (DCC ou DC).

Christophe
73
Vos projets / Re : Identification des trains par infrarouge
« Dernier message par Dominique le mai 09, 2025, 07:51:18 pm »
👏 Bravo !
74
Vos projets / Re : Identification des trains par infrarouge
« Dernier message par bobyAndCo le mai 09, 2025, 07:35:43 pm »
Bonsoir à tous,

Heureusement pour moi, la journée se termine sur une note beaucoup plus positive que la presque totalité de ma journée. J'ai en effet passé de nombreuses heures à tenter de faire fonctionner la réception sur un ESP32 sans jamais parvenir à quelque chose de fiable. L'ESP me renvoyant de nombreuses erreurs de lecture sur les interruptions renvoyant donc des valeurs erronées.

Jusqu'à ce que je me décide à passer sur un Raspberry Pi Pico. Et là, oh merveille, tout c'est mis à fonctionner parfaitement du premier coup !!!



Jusqu'ici je n'avais réalisé que quelques projets avec le Raspberry. Ayant un peu la flemme de changer ma façon de coder. Mais là, je vais revoir mon approche et chercher à systématiser le Raspberry, plus puissant, moins cher, disposant de plus de broches qu'un ESP32 et au final plus fiable.

Voici le code (de test) du récepteur qui ne cherche qu'à afficher la valeur transmise au travers de la led et du TSOP.

#include <Arduino.h>
#include "pico/multicore.h"
#include "pico/util/queue.h"

volatile uint32_t duration = 0;

constexpr byte pinIn = 15;  // Broche du TSOP

bool receiving = false;
uint8_t currentByte = 0;
int8_t bitIndex = 7;

// File pour les bits détectés
queue_t durationQueue;

enum DecodeState {
  IDLE,
  RECEIVING
};
DecodeState currentState = IDLE;

void handleIR() {
  static uint32_t lastTime = 0;
  uint32_t now = micros();
  uint32_t duration = now - lastTime;
  lastTime = now;
  queue_try_add(&durationQueue, &duration);
}

void setup() {
  Serial.begin(115200);
  pinMode(pinIn, INPUT);
  // Initialisation de la queue pour 16 durées
  queue_init(&durationQueue, sizeof(duration), 16);
  attachInterrupt(digitalPinToInterrupt(pinIn), handleIR, RISING);
}

void loop() {
  uint32_t duration = 0;
  if (queue_try_remove(&durationQueue, &duration)) {
   
    switch (currentState) {

      case IDLE:
        if (duration > 1600 && duration < 2400) {
          // Début de trame détecté
          currentByte = 0;
          bitIndex = 7;
          currentState = RECEIVING;
        }
        break;

      case RECEIVING:

        if (duration >= 400 && duration <= 700) {
          // Bit 1
          currentByte |= (1 << bitIndex);
          bitIndex--;
        } else if (duration >= 800 && duration <= 1200) {
          // Bit 0
          currentByte &= ~(1 << bitIndex);
          bitIndex--;
        } else {
          // Durée invalide
          currentState = IDLE;
          break;
        }

        if (bitIndex < 0) {
          Serial.printf("Octet reçu : 0x%02X\n", currentByte);
          currentState = IDLE;
        }
        break;
    }
  }
}


Je n'ai aucune erreur et donc je ne pense pas nécessaire de mettre en place un mécanisme de contrôle. (checksum)

Je vais maintenant passer le code de l'emetteur sur un ATTiny (25/45/85) et dessiner des PCB pour toute la partie emission et réception. Je communiquerai les schémas dès que je les aurai réalisés.

Christophe

75
Vos projets / Re : Identification des trains par infrarouge
« Dernier message par bobyAndCo le mai 08, 2025, 08:03:25 pm »
Bonjour à tous,

Aujourd’hui, travail sur le codage des bits. J’ai retenu le principe qui est que un bit est toujours constitué d’un front montant et d’un front descendant de même durée (comme pour le DCC).



Un bit 1 a une durée de 560µs (2 x 280µs).



Un bit 0 a une durée de 1000µs (2 x 500µs).



Ls bits de synchro qui séparent les octets de données ont une durée de 2000µs environ (2 x 1 ms)



Voici par exemple représenté l’octet de data 0xAA qui est une alternance de 0 et de 1 10101010 pour une durée moyenne de 6 ms ce qui fait avec le bit de synchro plus de 100 envois par seconde.

Je précise que les copies d’écran correspondent à des mesures en sortie du TSOP4838. Vous pouvez constater que le signal est très propre.

Le code définitif pour l'émetteur, qui sera sur un ATTiny (25, 45 ou 85) est très simple mais j'ai repris le fichier IRTimer.hpp de IRremeote :


```cpp
#include <Arduino.h>

// Configuration du timer pour PWM IR
#define IR_USE_AVR_TIMER2              // Utilise Timer2 pour l'envoi (pin D3)
#define SEND_PWM_BY_TIMER              // Active le mode PWM matériel

#include "IRTimer.hpp" // Part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.

#define IR_SEND_PIN 3                   // Broche utilisée
constexpr uint8_t DATA = 0xAA;          // Octet à envoyer
constexpr uint16_t BIT_DURATION = 500;  // Durée d’un bit en µs

// Envoie un octet codé via LED IR
void sendManchesterByte(uint8_t value) {
  for (int i = 7; i >= 0; i--) {
    bool bit = (value >> i) & 0x01;
    if (bit) {
      // 1
      disableSendPWMByTimer();  delayMicroseconds(BIT_DURATION / 2);
      enableSendPWMByTimer();   delayMicroseconds(BIT_DURATION / 2);
    } else {
      // 0
      disableSendPWMByTimer();  delayMicroseconds(BIT_DURATION );
      enableSendPWMByTimer();   delayMicroseconds(BIT_DURATION );
    }
  }
  // Fin de trame
  disableSendPWMByTimer();
  delayMicroseconds(BIT_DURATION * 2);
  enableSendPWMByTimer();
  delayMicroseconds(BIT_DURATION * 2);
}

void setup() {
  pinMode(IR_SEND_PIN, OUTPUT);
  timerConfigForSend(38);             // Fréquence IR : 38 kHz
  disableSendPWMByTimer();            // Démarre éteint
}

void loop() {
  sendManchesterByte(DATA);
}

```


Reste à tester maintenant avec le code sur le récepteur (ESP32) ce que j'espère pouvoir terminer rapidement. Cela permettra de voir s'il faudra ajouter un checksum pour vérifier la conformité de l'envoi.

Christophe


76
Vos projets / Re : Identification des trains par infrarouge
« Dernier message par bobyAndCo le mai 07, 2025, 07:10:38 pm »
Bonjour à tous,

Premiers tests aujourd’hui avec les composants tout juste reçus. Pour les leds émettrices, j’ai pris des TSAL6400 de VISHAY 5mm (0,31€ pièce) et comme récepteur le TSOP4838 de chez VISHAY également.

Premier constat, les performances sont assez stupéfiantes, aucun problème de distance et l’angle dans lequel le faisceau est actif est également assez stupéfiant ce qui peut permettre des mesures sur une durée assez longue.

Les signaux mesurés à l’oscillo à la sortie du TSOP4838 sont très propres. Pour les fronts les plus courts, je mesure environ 600µS ce qui devrait me permettre d’allonger les alternances telles que je les avais envisagées au départ (13µs !!!). Il y a de la marge.

Premiers résultats encourageants donc… à suivre

Christophe


77
JMRI et Arduino / Re : erreur 308 sur decoderpro
« Dernier message par nopxor le mai 06, 2025, 06:51:18 am »
Bonjour,
Pour DCC-EX et les problèmes de décodeur,il y a les diagnostics commands:
https://dcc-ex.com/support/troubleshooting-decoders.html#gsc.tab=0
Qui génèrent un log que tu peux fournir au discord de DCC-EX
78
JMRI et Arduino / Re : erreur 308 sur decoderpro
« Dernier message par trainalain le mai 05, 2025, 07:26:05 pm »
Bonjour.
J'ai le même problème : erreur 308.
Par contre J'ai ARDUINO, avec un Motor Shield qui pilote un testeur de décodeur LaisDCC.
 
Procédure réalisée :  Nouvelle loco dans JMRI, et recherche d'un décodeur par : "Lire le type de décodeur", il ressort Erreur 308. J'ai bien sur mis un décodeur neuf (LaisDCC) sur le testeur. Par contre le moteur du décodeur tourne, et des diodes sont allumées sur ce testeur.
Si je fais lecture des Cv, il me ressort des valeurs fantaisistes.

Mais si je veux écrire une nouvelle adresse, je remplace en ligne 1 Cv=3 par Cv=25, la valeur est bien enregistrée et elle apparait au niveau de la nouvelle loco créée.

Par contre je ne peux pas faire aucune action avec le régulateur, aucune des fonction ne répond, le réglage de la vitesse est inopérant, tout comme l'inversion du sens de rotation du moteur. Seul le bouton "Arrêt", "Marche" fonctionne. Si quelqu'un peut me porter secours je lui en serais très reconnaissant, au début, tout parait simple, mais ans la réalisation, ça l'est beaucoup moins, je n'ai rien trouvé dans les posts qui donnent une solution pour résoudre ce problème.

Merci
79
Vos projets / Re : Re : Identification des trains par infrarouge
« Dernier message par bobyAndCo le mai 02, 2025, 09:43:16 pm »
Concernant la modulation de l'IR, elle n'est nécessaire que pour une transmission à plus longue distance avec de la lumière parasite. Mais la distance émetteur-récepteur est ici de l'ordre du centimètre, et les deux sont face à face.

Par ailleurs, si on modulait l'IR, il faudrait bien entendu le démoduler ensuite au niveau du récepteur pour filtrer. Il existe justement des démodulateurs tout faits (pour télécommandes TV et autres) et j'en ai essayé. Mais on perd énormément en débit, pour des raisons autant théoriques (filtrage = retard) que pratiques.

Il y a plusieurs avantages à coder comme je le propose. Je profite de la fréquence à 38Khz pour créer un signal codé sur 2 * 8 bits. Simple et efficace et suffisant. Nul besoin de recourir à des biblio extérieures comme SoftwareSerial (pas très performante) ou IR Remote (lourde et complexe).

Effectivement, côté réception, j’utilise cette fois une routine d’interruption qui, en fonction de plages de durées peut facilement décoder les messages.

J’ai justement développé le code pour la réception sur un ESP32. Là aussi, pas besoin de biblio externe et l’on obtient un code léger et rapide.

Ultérieurement, j’envisagerai peut-être de passer sur RMT qui dans ce cas devrait pouvoir mettre environ 8 à 10 émetteurs IR sous surveillance. Intéressant.

https://www.makerguides.com/esp32-and-ir-remote-interface/

https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/peripherals/rmt.html

Voici le code pour un ESP32 sous interruption :

const byte irPin = 2;  // D2 (INT0) connecté à la sortie du TSOP4838

volatile uint64_t lastTime = 0;
volatile uint64_t pulseWidth = 0;

volatile byte receivedBytes[2]; // [0] = identifiant, [1] = checksum
volatile byte bitCount = 0;
volatile byte byteIndex = 0;
volatile bool receiving = false;
volatile bool newData = false;

void setup() {
  Serial.begin(115200);
  pinMode(irPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(irPin), handleIR, CHANGE);
}

void loop() {
  if (newData) {
    byte id = receivedBytes[0];
    byte chk = receivedBytes[1];

    if ((id ^ 0xA5) == chk) {
      Serial.print("ID valide : 0x");
      Serial.println(id, HEX);
    } else {
      Serial.print("Erreur checksum - ID: 0x");
      Serial.print(id, HEX);
      Serial.print(" / Checksum: 0x");
      Serial.println(chk, HEX);
    }
   
    newData = false;
    byteIndex = 0;
    bitCount = 0;
  }
}

// Interruption sur changement d’état du signal TSOP
void handleIR() {
  uint64_t now = micros();
  pulseWidth = now - lastTime;
  lastTime = now;

  // Détecter le bit de start : burst long (2.4 ms)
  if (pulseWidth > 2000 && pulseWidth < 3000) {
    receiving = true;
    bitCount = 0;
    byteIndex = 0;
    receivedBytes[0] = 0;
    receivedBytes[1] = 0;
    return;
  }

  if (!receiving) return;

  // Interprétation des bits en fonction des durées mesurées
  if (pulseWidth >= 1000 && pulseWidth < 1300) {
    // Bit 1 = 600 burst + 600 silence
    receivedBytes[byteIndex] = (receivedBytes[byteIndex] << 1) | 1;
    bitCount++;
  } else if (pulseWidth >= 1600 && pulseWidth < 2000) {
    // Bit 0 = 600 burst + 1600 silence
    receivedBytes[byteIndex] = (receivedBytes[byteIndex] << 1);
    bitCount++;
  }

  // Passage à l'octet suivant
  if (bitCount == 8) {
    bitCount = 0;
    byteIndex++;
    if (byteIndex >= 2) {
      receiving = false;
      newData = true;
    }
  }
}




Christophe

PS : J'ai codé une centrale MFX avec RMT sur ESP32, c'est top : https://github.com/BOBILLEChristophe/directMFX_ESP32/blob/main/src/MfxRMT.cpp
80
Vos projets / Re : Identification des trains par infrarouge
« Dernier message par JPM06 le mai 02, 2025, 07:34:44 pm »
Bonjour Christophe,

J'ai d'abord eu du mal à comprendre pourquoi tu utilises dans ton code un PWM à 38kHz, mais je crois que l'illumination m'est venue: tu veux moduler le signal IR à 38kHz?

Mais dans le système présenté, l'IR n'est PAS modulé. Il y a de l'IR sur les 0 et rien sur les 1. C'est très simple, et ça marche.
Le programme de l'émetteur est d'ailleurs présenté là: http://amfn.nice.free.fr/microcontroleurs/localir/Lotir.mbas. C'est du MikroBASIC, mais ça se lit facilement, vu la simplicité de la chose.
(Simplement, le SoftSerial de mon IDE ne marchait pas bien, c'est pourquoi j'ai ré-écrit et étalonné la procédure).

Concernant la modulation de l'IR, elle n'est nécessaire que pour une transmission à plus longue distance avec de la lumière parasite. Mais la distance émetteur-récepteur est ici de l'ordre du centimètre, et les deux sont face à face.

Par ailleurs, si on modulait l'IR, il faudrait bien entendu le démoduler ensuite au niveau du récepteur pour filtrer. Il existe justement des démodulateurs tout faits (pour télécommandes TV et autres) et j'en ai essayé. Mais on perd énormément en débit, pour des raisons autant théoriques (filtrage = retard) que pratiques.

Affaire à suivre...

Jean-Pierre
Pages: 1 ... 6 7 [8] 9 10