Messages récents

Pages: [1] 2 3 ... 10
1
Vos projets / Re : Train HO avec pilotage par ESP8266 à l'intérieur
« Dernier message par JPM06 le Aujourd'hui à 12:08:39 pm »
Bonjour,
Je découvre ce fil alors que je suis sur une réalisation du même genre depuis quelques semaines.
Mon objectif est de faire fonctionner une petite automotrice Egger-Bahn HOe sur batterie, pour s'affranchir de la mauvaise prise de courant et pouvoir rouler sur des voies "pittoresquement délabrées".
Je me suis inspiré d'une réalisation pour Car-System Faller:
http://letraindejc.free.fr/pages/index.php?v=ESP00[/i]]http://letraindejc.free.fr/pages/index.php?v=ESP00
J'ai fait pour l'ESP12s un petit circuit imprimé qui se loge dans le plafond de la motrice. Le convertisseur "step-up" est logé, lui, sous le plancher.
Tout ça fonctionne bien, mais l'automotrice étant articulée j'ai utilisé du fil un peu trop raide pour la connexion à la cabine. J'attends livraison de fil plus fin pour re-câbler.
Coté logiciel, je ne fonctionne pas en HTTP comme JC, mais en UDP avec l'appli Z21 de Roco.
Si vous souhaitez discuter de ça plus avant, je suis à votre disposition.
Cordialement,
JPM06
2
Vos projets / Re : Asservissement de vitesse pour les (trains des) nuls
« Dernier message par simontpellier le juillet 30, 2021, 09:16:02 pm »
Bonsoir Dominique,

Merci pour cette attention !
Et note bien que quand tu te lanceras, ça sera un grand plaisir pour moi si tu veux qu'on échange (d'autant que j'en tirerai profit, j'en suis certain !).

Amicalement
Philippe

NB : Ça sera également un vrai plaisir de répondre sur ce sujet à quiconque le souhaiterait. Je joins d'ailleurs à titre documentaire et pour démystifier le bout de code, commenté, qui permet d'obtenir, pour chaque train, un signal FCEM exploitable par un gestionnaire (dans une logique à 1 satellite pour 4 sections (au plus), communiquant avec un gestionnaire central)


const uint16_t PWM_OFF = 300;                           // 300 microSeconds
const uint16_t PWM_ON = 10000;                          // 10 milliSeconds - période "ON", moteur alimenté
uint8_t  EMIT_TIMER = 10;                               // compte les cycles PWM_ON, RAZ tous les 8x10300 millisec
uint32_t time_ON;                                       // timer "PWM_ON"

uint8_t trainNum[NB_SECTIONS] = { 0, 0, 0, 0 };         // numéros des trains présents sur les sections du satellite EN NUMEROTION EPHEMERE PROPRE AU SATELLITE
uint8_t trains;                                         // nb de sections occupées par un train (et pas forcément pas des trains différents)
uint16_t sumFCEM[NB_SECTIONS];
uint16_t count[NB_SECTIONS];
int16_t reading[NB_SECTIONS][6];                        // 6 mesures sur chaque section (si occupée)


void mesureFCEM() {
  if (micros() - time_ON < PWM_ON) /*=>*/ return;

  sendFCEM();                              // nécessairement ici pour une première nomenclature des trains présents sur les sections surveillées

  if (trains) {
    PORTB &= ~_BV(PB0); (par exemple)      /* au moins 1 section occupée : pin RESET du 74HC595 sur LOW => toutes pins de polarisation des ponts H à zéro (=> traction coupée) */
    set74HC595();                          // registre à décalage des datas POLARISATION(*) des ponts : 2 ponts = 4 sections = 1 registre (* les datas PWM sont câblées sur le gestionnaire)
    delayMicroseconds(PWM_OFF);                                // attente avant mesures
    for (uint8_t i=0; i<NB_SECTIONS; i++) {
      if (trainOnSection[i] > 0) {                             // TOUT OU PARTIE du train numéro "trainOnSection[i] occupe la section i
        for (uint8_t j = 0; j < 6; j++) {                      // six mesures de la FCEM
          reading[i][j] = analogRead(DATAS_SECTION[i][3]);
        }
        pin74HC[DATAS_SECTION[i][1]] = polarization[i];        // réaffectation des polarisations initiales à chaque section
        pin74HC[DATAS_SECTION[i][2]] = !polarization[i];
      }
    }
    time_ON = micros();
    PORTB |= _BV(PB0);                                         // RESET du 74HC595 sur HIGH...
    set74HC595();                                              // ... et rétablissement des polarisations de toutes les sections

/* DATA PROCESSING */
    int16_t read[NB_SECTIONS] = {0, 0, 0, 0}, maxRead[NB_SECTIONS] = {0, 0, 0, 0}, minRead[NB_SECTIONS] = {0, 0, 0, 0};
 
    for (uint8_t i=0; i<NB_SECTIONS; i++) {
      if (trainOnSection[i]) {                                 // il y a un train dans la section i => on repère les deux extrêmes parmi les 6 relevés
        maxRead[i] = reading[i][0];
        minRead[i] = reading[i][0];
        read[i] = reading[i][0];
        for (uint8_t j = 1; j < 6; j++) {
          maxRead[i] = max(reading[i][j], maxRead[i]);
          minRead[i] = min(reading[i][j], minRead[i]);
          read[i] = (read[i] + reading[i][j]);
        }
        read[i] = (read[i] - maxRead[i] - minRead[i])/4;       //moyenne des 4 valeurs retenues
        maxRead[i] = 0;
      }
    }
    /* si train sur 2 sections (ou plus), on filtre les résultats "fake" (wagons) en comparant les mesures de ce train */
    for (uint8_t j=0; j<trains; j++) {           // à ce stade, "trains" est forcément au moins égal à 1, nomenclaturé dans "trainNum[0]"
      uint8_t overlap=0;
      for (uint8_t i=0; i<NB_SECTIONS; i++) {    /* on recherche ce train sur toutes les sections et on repère son read max */
        if (trainOnSection[i] == trainNum[j]) {  /* un train a été nomenclaturé à l'indice j (toujours vrai une fois au moins) */
          maxRead[j] = max(read[i], maxRead[j]); // max des max pour le train j de numéro trainNum[j]
        }
      }
      for (uint8_t i=0; i<NB_SECTIONS; i++) {    /* on compare les résultats section par section, on garde ou non */
        if (trainOnSection[i]==trainNum[j] && read[i]> maxRead[j]/2) { /* écart "normal" => on prend en compte la mesure (maxRead répond à la condition !) */
          overlap++;
          sumFCEM[j] = sumFCEM[j] + read[i];
          count[j]++;                            // sumFCEM == première ou nouvelle sommation pour ce train, puis comptage des sommations
        }
      }

      if (overlap>1) /*=>*/ sumFCEM[j] -= 15;    // compensation forfaitaire d'un excès lors de lectures multiples   
    }
  }
}

void sendFCEM() {
  EMIT_TIMER++;
  if (EMIT_TIMER <10) /*=>*/ return;                      // 10 cycles de mesures avant chaque envoi compilé
  EMIT_TIMER=0;

  for (uint8_t j=0; j<trains; j++) {
    if (sumFCEM[j]) {
      messageCAN_FCEM.id = 31 + trainNum[j];              // 31+trainNum[j]==32+(trainNum[j]-1) ; conversion en valeur "code" du n° de train
      messageCAN_FCEM.data16[0] = sumFCEM[j]/count[j];    // on ne transmet pas la section, c'est une donnée connue du master
      const bool OK = controleurCAN.tryToSend(messageCAN_FCEM);
      if (OK) {} // { Serial.print(trainNum[j]); Serial.print(" <-train / FCEM-> "); Serial.println(messageCAN_FCEM.data16[0]); }
      sumFCEM[j] = 0; count[j] = 0; trainNum[j] = 0;
    }   
  }

/* POUR LA PROCHAINE CAMPAGNE DE MESURE, ON REFAIT LA NOMENCLATURE DES TRAINS EN PRESENCE*/
  trains=0;
  for (uint8_t i=0; i<NB_SECTIONS; i++) {    // on regarde l'occupation des sections
    if (trainOnSection[i]) {                 // la section contient un train (numéro>0), mais pas forcément la loco !
      trainNum[trains] = trainOnSection[i];
      trains++;
    }
  }
  if (trains>1) {
    for (uint8_t train=trains; train>0; train--) {   // "train" EST EN VALEURS "VRAIES" (de 1 à n) - on doit éliminer les doublons
      for (uint8_t rang=train; rang>0; rang--) {     // on va regarder chaque "train" enregistré et comparer avec les autres
        if (trainNum[rang] == trainNum[rang-1]) {    // on rétrograde le rang du train dans la table trainNum
          trainNum[rang] = 0;                        // means no train
          trains--;
          break;                                     // important ; si train sur + de 2 sections, 1 seul décompte à chaque "for"
        }       

      }
    }
  }
}

3
Vos projets / Re : Asservissement de vitesse pour les (trains des) nuls
« Dernier message par Dominique le juillet 30, 2021, 09:09:21 am »
Bravo Philippe et un grand merci pour ce partage vraiment détaillé qui va permettre au plus grand nombre de comprendre ce qu’on peut faire en « analogique ».

Bien qu’ayant la plupart de mes locos en digital, il reste quelques « gauloises analogiques » que j’aimerai faire tourner de temps en temps. L’idée de faire un tronçon analogique progresse donc, grâce à toi.

Amicalement
Dominique
4
Vos projets / Re : Asservissement de vitesse pour les (trains des) nuls
« Dernier message par simontpellier le juillet 29, 2021, 10:02:14 pm »
Suite 3 ET FIN
- avec ABANDON de la piste asservissement
car ça marche... fort mal ou sinon dans des conditions extrêmement étroites (mais si c'est faux, je suis vivement intéressé par une démonstration).
Le signal de la mesure FCEM se contredisant régulièrement d'une mesure à l'autre, impossible d'en déduire la moindre action Proportionnelle. Et si l'Intégrale permet d'isoler une tendance, une action intégrale trop majoritaire, ça pompe, c'est obligé.

- MAIS...
idée : substituer à l'action proportionnelle une PWM "classique" : un cran donné de réglage => un équivalent tension => une vitesse... plus OU MOINS assurée compte tenu des nombreux facteurs quasiment tous d'accord pour ralentir (si ça n'est bloquer) la loco.
Plein d'excellentes occasions pour l'intégrale de faire son retour !
Et ça s'appelle de la COMPENSATION DE CHARGE ; dès que quoique se soit ralentit la loco, la FCEM diminuant, l'intégrale se réveille et... compense. (L'intégrale pourrait aussi faire du moins... il faut juste que ça soit à bon escient sinon on retrouve le souci du pompage)

J'aurais tout de suite compris toute la substantifique signification de "compensation de charge"... que j'aurais gagné bien du temps !
Car ça, ça marche ! Et sans aucun besoin d'électronique (problème réglé !) et ça donne enfin un fonctionnement en analogique propre, fluide, régulier, reproductible. Réaliste !

(j'admire au passage le fait que le DCC puisse intégrer, "in situ" qui plus est, une fonction tout de même complexe mais tellement indispensable).

Et pour ce qui est de la marche à basse vitesse... match nul non ? Analogique (avec compensation de charge donc !) et DCC se rejoignent forcément sur les mêmes réalités : selon la loco on obtient effectivement du 5kmh régulier, pour d'autres ça sera jamais moins que 25kmh (et ceci bien sûr ::) à condition que les roues soient astiquées, les rails décapés, les contacts nickels...).
Dernière remarque ; sous réserve que j'ai à peu près compris ce qu'est un réseau en DCC : la loco se charge de tout ! Alors que dans l'analogique ça sera loin d'être aussi simple ; le problème à résoudre sera celui du sectionnement électrique qui impose de compiler et traiter plusieurs relevés de FCEM pour un même train, tant en traction qu'en refoulement (même dans le cas d'une loco solo !).
Mais ça se fait et c'est typiquement le plaisir collatéral de l'analogique, faire tourner un code !

Peut-être à bientôt pour de nouvelles aventures ?
En tous cas bien cordialement

Philippe


5
Composants / Re : Nouveau ATtiny 417, 814, 816, 817
« Dernier message par trimarco232 le juillet 26, 2021, 04:02:34 pm »
quelques nouvelles "neuves" ...
suite à la pénurie occidentale de semiconducteurs, la plupart des nouveaux avr et attiny sont indisponibles pour au moins un an  :(
j'ai toutefois pu récupérer un (seul !) attiny3216, chez un chinois, à prix d'or, et commencer la programmation ; ça marche bien, au moins une bonne chose ; j'ouvrirai un topic dédié pour ce projet, qui utilise bien les nouveaux périphériques embarqués de ces composants : c'est un peu + performant mais moins simple que les uno/nano de base

le développement du core arduino spécifique est bien avancé, et continue son cours : voir le github de SpenceKonde
à noter qu'il n'est plus recommandé d'utiliser un nano pour faire son programmateur, un simple adaptateur usb/série suffit ; il faut juste ajouter une schottky ;  je l'ai fait avec ce que j'avais en fond de tiroir, ça marche bien
6
Les réseaux / Re : bonjour à tous
« Dernier message par Dominique le juillet 25, 2021, 10:49:19 pm »
Bonjour,

Pour un tel programme c’est à vous de tester et de nous dire ce que vous avez pensé  ;D

Pour comprendre ce qu’il s’y passe, insérez des Serial.println(“voila ce qui se passe là “);
Vous pourrez voir cela à l’exécution sur le moniteur de l’IDE et en déduire si c’est conforme à ce que vous attendez.
7
Les réseaux / Re : bonjour à tous
« Dernier message par msport le juillet 25, 2021, 10:15:37 pm »

Bonjour,

juste quelques remarques :
pour que votre programme soit lisible par d'autres, utilisez des noms significatifs pour vos données incluant la fonction comme Arret et Inverse dans le nom. Et indentez correctement les if.
Vos ILS sont certainement à chaque extrémité, donc commencez par écrire un programme de va-et-vient qui inverse le sens à chaque extrémité.
Vous l'enrichirez ensuite avec un compteur pour l'arrêter au bout de deux fois ou avec un arrêt par temporisation. Il faut choisir.
Par ailleurs, la fonction PULLUP maintient une entrée à HIGH tant qu'elle n'est pas mise au GND. Le module à ILS élimine probablement les rebonds, son sens est à vérifier si il est bien LOW quand un aimant est présent et en tenir compte dans votre programme.

Mais testez donc votre programme et dites nous ce que vous en pensez.

Cordialement
8
Les réseaux / Re : bonjour à tous
« Dernier message par frederic le juillet 25, 2021, 08:28:50 pm »
bonjour la team

après une absence pour prendre le temps de mieux connaitre la programmation sur Arduino
voici mon nouveau code pouvez-vous me dire se que vous en pensé
sachant que le train entre sur la zone d'arrêt et d'inverseur "inverseur activé"const int Broche_ILS1 = 3; //ILS commande d'arret (on relais 1 pendent une durer x)
const int Broche_ILS2 = 4; //ILS commande de l'inverseur de polariter après un temps x

const int Broche_LED1 = 6; //LED1 commande d'arret activé
const int Broche_LED2 = 7; //LED2 commande de l' inverseur activé

const int Broche_RELAIS1 = 9;  //arret
const int Broche_RELAIS2 = 10;  //inverseur

int Etat_ILS1 = 0;    //arret
int Ordre_Tempo1 = 0; //arret
int Moteur1 = 0;      //arret

int Etat_ILS2 = 0;     //inverseur
int Ordre_Tempo2 = 0;  //inverseur
int Moteur2 = 0;       //inverseur

unsigned long Temps_Actuel1;      //arret
unsigned long Temps_Precedent1;   //arret

unsigned long Temps_Actuel2;      //inverseur
unsigned long Temps_Precedent2;   //inverseur

unsigned long Tempo_Repos1 = 10000;      //arret

unsigned long Tempo_Repos2 = 8000;      //inverseur


void setup()
{

 Serial.begin (9600);
 pinMode(Broche_ILS1, INPUT_PULLUP);     //arret
 pinMode(Broche_LED1, OUTPUT);          //arret
 pinMode(Broche_RELAIS1, OUTPUT);        //arret

 pinMode(Broche_ILS2, INPUT_PULLUP);    //inverseur
 pinMode(Broche_LED2, OUTPUT);          //inverseur
 pinMode(Broche_RELAIS2,OUTPUT);        //inverseur

}
void loop()
{
//debut Loop arret
 Temps_Actuel1 = millis();
 Etat_ILS1 = digitalRead(Broche_ILS1);

 if (Etat_ILS1 == HIGH)
 {
    digitalWrite(Broche_LED1,HIGH);
    Temps_Precedent1 = Temps_Actuel1;
    Ordre_Tempo1 = 1;
 }
 if (Ordre_Tempo1 == 1)
 {
    if ((Temps_Actuel1 - Temps_Precedent1) < Tempo_Repos1) {
      Moteur1 = 1;
    }
    else {
      Moteur1 = 0;
      Ordre_Tempo1 = 0;
    }
 }

 if (Moteur1 == 1)
 {
   
    digitalWrite(Broche_RELAIS1, HIGH);
    }
    else
    {
      digitalWrite(Broche_LED1, LOW);
      digitalWrite(Broche_RELAIS1, LOW);
      }
      //fin Loop arret et debut LOOP inverseur
 Temps_Actuel2 = millis();
 Etat_ILS2 = digitalRead(Broche_ILS2);

 if (Etat_ILS2 == HIGH)
 {
    digitalWrite(Broche_LED2,HIGH);
    Temps_Precedent2 = Temps_Actuel2;
    Ordre_Tempo2 = 1;
 }
 if (Ordre_Tempo2 == 1)
 {
    if ((Temps_Actuel2 - Temps_Precedent2) < Tempo_Repos2) {
      Moteur2 = 1;
    }
    else {
      Moteur2 = 0;
      Ordre_Tempo2 = 0;
    }
 }

 if (Moteur2 == 0)
 {
   
    digitalWrite(Broche_RELAIS2, HIGH);
    }
    else
    {
      digitalWrite(Broche_LED2, LOW);
      digitalWrite(Broche_RELAIS2, LOW);
      }
     //fin LOOP inverseur
     //affichage serie
     Serial.print("; Etat_ILS1:"); Serial.print(Etat_ILS1);
     Serial.print("; Etat_ILS2:"); Serial.print(Etat_ILS2);
}
9
Vos projets / Re : Train HO avec pilotage par ESP8266 à l'intérieur
« Dernier message par Gboule le juillet 19, 2021, 10:33:57 pm »
La suite...

Une fois tout monté dans la loco, on peut envoyer le "firmware" : le premier download nécessite de brancher l'ESP par port USB, mais si vous faites des modifs du softs, les autres téléchargement peuvent se faire par OTA (over the air), c'est à dire sans être obliger de brancher l'ESP par USB et donc pas besoin de démonter le train.

Le code est fourni est en pièce jointe, mais il faut l'adapter avec votre SSID Wifi et le mot de passe associè. Il faut aussi mettre une adresse statique par DHCP via votre box et la mettre dans le tableau "tabTrain" du code.
Vous pouvez mettre aussi une photo du train (au format 100x40 à peu près) et éventuellement un fichier son, mais c'est 2 fichiers ne doivent pas être trop gros pour ne pas remplir la mémoire de l'ESP. Le son en mono et en 22 khz suffit. Ces 2 fichiers doivent se trouver dans un dossier Data du projet Arduino et doivent être uploader grâce au plug-in "upload SPIFFS".
Comme avec l'interface, vous pouvez gérer plusieurs trains, il faut ces éléments pour chacun des trains dans le tableau "tabTrain". Il faut aussi définir le nombre de trains avec le #define NB_TRAIN

Il est possible d'utiliser un ESP8266 non embarqué dans un train qui servirait à piloter tous les autres.
Pour accéder à l'interface, il suffit d'un browser (PC, Tablette, smartphone) et d'ouvrir l'URL via http://adresse_IP_du_train.
L'écran est divisé en autant de section qu'il y a des trains configurés dans le tableau tabTrain. Pour chaque section, un voyant rouge-vert indique si le train est joignable, une échelle de 10% à 100% permet de choisir la puissance moteur, et un bouton permet de choisir le sens de marche. Les boutons "marche" et "arrêt' sont évidents, et le bouton sonnerie activera le son si vous avez équipez le train d'un moyen de reproduction sonore.

Une partie du code est commenté et devait servir à gérer les cantons par RFID, mais comme la détection RFID n'était pas fiable à 100%, le code n'a pas pu être débbugué..

Le code n'est pas 100% propre, car je n'ai pas encore y le temps de le "nettoyer", mais il est fonctionnel.

10
Vos projets / Re : Train HO avec pilotage par ESP8266 à l'intérieur
« Dernier message par bobyAndCo le juillet 18, 2021, 10:56:50 am »
Bonjour à tous,

Assurément, en nous proposant ce sujet, Gboule a en quelque sorte ouvert une boîte de Pandore. Catplus (Marcel pour les intimes) m’a fait passer un lien sur un article de MRH numéro de juin 2021 qui apporte des éclairages intéressants au sujet que nous abordons.

Le principe qui y est décrit est encore différent de tous ce dont nous avons pu parler mais soulève des problématiques que nous rencontrons nous-mêmes dont, par exemple, les questions d’encombrement.

Il s’agit ici de commander les locomotives en DCC mais avec la technologie radio.



Ce que je trouve intrigant, c’est que l’on ne cherche pas à s’affranchir de l’alimentation par les rails en DCC qui sert notamment à recharger la batterie (comme je souhaite le faire), et que l’on ne cherche pas non plus à s’affranchir du DCC comme Gboule et moi-même souhaitons le faire.

En fouillant, vous verrez qu’il est abordé un système à base de micro-receivers en 2,4 GHz qui mérite que l’on s’y intéresse. Voici le lien sur le site du fabricant : http://www.deltang.co.uk/index.htm

Par ailleurs, il y a les questions de stockage d’énergie, de step-converter et de BMS (Battery Management System) qui nous intéressent et qui sont abordées dans l’article et aussi dans le forum.

Pour ma part, j’ai particulièrement retenu la question du « wagon suiveur ». Certains pensent comme moi que c’est la solution pour « transporter » une partie du matériel qu’il sera difficile d’embarquer autrement.



Pourtant, il y a dans le forum, cette présentation que je trouve extraordinaire.

Toute l’électronique et la batterie sont glissées dans le toit de ce petit locotracteur qui est donné pour 55 minutes d’autonomie et 15 de charge ! Il y a clairement ici des sources d’inspiration pour nos réflexions.





Article à lire donc pour tous ceux qui s’intéressent à ces questions : https://online.fliphtml5.com/buups/cjfs/index.html#p=9

Le forum ici : https://model-railroad-hobbyist.com/magazine/mrh2021-06/publishers-musings?page=1

Pages: [1] 2 3 ... 10