synchroniser plusieurs PWM sur plusieurs cartes arduino

Bonjour,

Grâce au forum et à tout ce que j'ai pu lire ici, je suis arrivé à gérer mon circuit de train miniature avec ma propre philosophie.

Pour résumer, le circuit de train est divisé en X sections, j'utilise une carte arduino uno par section pour gérer la vitesse, l’accélération, le ralenti, le freinage de la locomotive suivant l'occupation de la section suivante pour ne pas que les trains se rentrent dedans. l'allumage du feu de signalisation et d'autres choses encore.

J'ai un unique potentiomètre qui me sert à régler l'ensemble des PWM de toutes les cartes.

Je rencontre un problème de changement de vitesse bref quand la locomotive passe du PWM d'une carte à l'autre.

Mon analyse est la suivante, les PWM n'étant pas en phase, quand la locomotive est à chevale entre deux, elle accélère car elle reçois "plus de temps"

Il faudrait que tous les PWM des cartes lors de la mise sous tension démarrent tous en même temps ou bien que le PWM de l'arduino soit contrôlé par quelque chose ou une autre solution que je n'ai pas!

Je me tourne vers vous pour envisager une solution.
Merci de votre aide.

L’IDE arduino fixe la fréquence de récurence de la PWM à 500Hz (448,28 Hz). L’opération se fait dans la fonction init() du core arduino. 500 Hz est une fréquence élevée pour un moteur. AMHA il ne devrait pas être sensible au saut de phase.
Pour lever le doute tu peux grâce à la lecture de la datasheet du micro-contrôleur et la manipulation de quelques registres augmenter la fréquence de la PWM sur toutes tes cartes.

Personnellement je pencherai plutôt sur un saut d’alim bien que cela s’oppose à ce que tu as écrit :"un problème de changement de vitesse bref quand la locomotive passe… "
:
Je m’explique l’amplitude des signaux de PWM est directement liée à la tension d’alim de la carte.
Il faut savoir qu’un régulateur de tension ne donnera jamais 5V pile mais 5V +/- 5%, donc entre 2 cartes la différence de tension d’alim peut atteindre 0,5 V.

Autre cause possible, qui peut s’additionner à la précédente : une pin de sortie ne délivrera jamais une tension exactement égale à Vcc : ce n’est pas possible car les transistors de sortie ont une résistance Rdson non nulle et comme ils sont tout petit leur Rdson est bien plus grand que celui des MosFet de puissance. Il faut compter entre 20 et 50 ohms et comme "l’emmerdement est toujours maximum" cette résistance Rdson n’est pas constante et dépend directement du lot de fabrication.

Si c’est un de ces cas là il suffit de mesurer les niveaux de sortie des pins chargés et surtout pas à vide des différentes cartes et d’appliquer un coefficient correcteur par cartes ( pour avoir un seul programme le coefficient correcteur peut être inscrit dans l’EEprom c’est à cela qu’elle sert).

jean-loik:
...

Mon analyse est la suivante, les PWM n'étant pas en phase, quand la locomotive est à chevale entre deux, elle accélère car elle reçois "plus de temps"

Il faudrait que tous les PWM des cartes lors de la mise sous tension démarrent tous en même temps ou bien que le PWM de l'arduino soit contrôlé par quelque chose ou une autre solution que je n'ai pas!

Je me tourne vers vous pour envisager une solution.
Merci de votre aide.

Bonsoir Jean-Loïc
J'ai "à chaud" un peu la meme reflexion que 68tjs :grin:
je ne pense pas qu'une desynchro de PWM soit perceptible au changement de canton, je penche aussi plus pour des cantons alimentés avec des V "différents" ( pour du PWM à 100%) , = l'influence et la perceptibilité du facteur V.

Pas de meilleurs conseils "pour l'instant" que celui de 68tjs que de verifier le V "injecté" par canton "chargé" , meme si l'alim est commune , faire un relevé de V (U) par canton "chargé" à 10/20/50/80/100 % me semble un bon début d'approche 8)

jean-loik:
Je rencontre un problème de changement de vitesse bref quand la locomotive passe du PWM d'une carte à l'autre.

Mon analyse est la suivante, les PWM n'étant pas en phase, quand la locomotive est à chevale entre deux, elle accélère car elle reçois "plus de temps"

Ou alors les alims des sections sont un peu limite en courant. Lorsque la locomotive se trouve à cheval sur 2 sections elle reçoit plus de courant et du coup elle accélère.

Yep!

Ayant déjà expérimenté un seul quartz pour 2 µC, je pense qu'il est tout à fait possible d'étendre cette possibilité sur 3, voire 4 µC simultanément. Tous les micro-controlleurs fonctionneront à la même vitesse et seront ainsi parfaitement synchronisés.

@+

Zoroastre.

Bonjour,
Il me semble de l'ami Artouste a fait des essais dans ce sens.

icare:
Bonjour,
Il me semble de l'ami Artouste a fait des essais dans ce sens.

bonjour
oui , j'avais fait une expe avec 4 328P et un seul oscillateur TTL (clock en serie entre les 328P pas en // )
ça fonctionnait bien avec un simple blink sur des longues periodes, entendre par là .

Maintenant horloge commune , ne veut pas nécessairement dire action synchro
meme avec un simple blink , il faut aussi avoir à l'esprit qu'il faut prendre temporellement en compte un reset commun (ou peut etre un init commun de registres, là pwm affectés ) pour avoir des flancs synchrones (ce que je n'ai pas fait)
la seule chose "à peu pres certaine" :grin: est simplement que chacun des MCU aura reçu la meme horloge (en theorie le meme nombre de flancs)

Bonjour,

Artouste:
un seul oscillateur TTL (clock en serie entre les 328P pas en // )

En série ? Avantages ? Inconvénients ? Comment procède-t'on ?

Perso, j'avais testé 2 AT644 sur une carte unique avec un seul oscillateur en parallèle : Syncro parfaite.

Artouste:
Maintenant horloge commune , ne veut pas nécessairement dire action synchro

C'est trés juste. Les cartes devraient avoir à partager un certain nombre de chose pour qu'elles puissent fonctionner toutes de concert.

@+

Zoroastre.

Bonjour,

Lors du passage d'un canton à l'autre, la loco met en parallèle les sorties des interfaces pwm des 2 cantons. S'il s'agissait de sorties analogiques, la plus forte tension l'emporterait, et la loco irait à l'allure correspondant au canton le plus rapide.

S'agissant de signaux pwm non synchronisés, les 2 tensions s'ajoutent aléatoirement : au pire, on aurait la vitesse max alors que les 2 cantons ne seraient qu'à 1/2 vitesse ...

La solution est donc effectivement de synchroniser les signaux pwm, mais, jean-loik l'a préssenti - ça se corse : il faut synchroniser les timers générant les différents signaux pwm !

Synchroniser les horloges semble faisable, soit en synchronisant les arduinos comme expliqué par Artouste, soit en n'utilisant que les timer 1, dont les horloges externes seraient communes.

Mais comment faire démarrer tous les timers en même temps ? Pas évident, ni avec des arduinos différents, ni même à l'intérieur d'un même arduino !

Cela doit quand-même être faisable au prix de petites erreurs sans incidence visible sur le fonctionnement.
Intéressant, n'est-ce pas ?

Par ailleurs jean-loik ne nous dit pas comment il inverse le sens de marche des locos ?

Bonjour,

Je réalise également l’électronique de mon réseau et le problème de recouvrement de PWM non synchronisées au passage de canton qui provoque une augmentation de vitesse tant que les prises de courant de la locomotive sont à cheval sur deux cantons s’est également posé. Je travaille deux camarades, le problème a été resolu par l’un d’entre eux.

Il a été résolu de la maniere suivante:

Un des micro diffuse un signal carré à la fréquence de la PWM. Ce signal est diffusé via des drivers différentiels. Ce signal sert de référence pour synchroniser les PWM, appelons le SYNC. Le point de reference va etre soit le front montant soit le front descendant de SYNC. Choisissons le front descendant pour la suite

Sur un Arduino la PWM doit être en mode CTC je pense de manière à régler finement sa période.

On met une ISR sur la comparaison TCNT et OCR du timer qui pilote la PWM sur chaque Arduino. Dans cette ISR on lit le SYNC deux fois de suite. Si la première lecture donne HIGH et la seconde LOW. La PWM est calée. Si Les deux lectures donnent HIGH la PWM est en avance, on diminue sa fréquence de 1 en augmentant OCR. Si les deux lectures donnent LOW la PWM est en retard, on augmente sa fréquence de 1 en diminuant OCR.

La valeur nominale d’OCR est fixée : NOMINAL_OCR

Dans la dernière version on fait 4 lectures de SYNC.

Si on a le pattern 0b1100, on est ok
Si on a le pattern 0b1000, la PWM est un peu en retard → OCR = NOMINAL_OCR - 1
Si on a le pattern 0b0000, la PWM est très en retard → OCR = NOMINAL_OCR - 2
Si on a le pattern 0b1110, la PWM est un peu en avance → OCR = NOMINAL_OCR + 1
Si on a le pattern 0b1111, la PWM est très en avance → OCR = NOMINAL_OCR + 2

Il faut lire SYNC directement dans le registre. digitalRead est trop lent je pense.

Petite question de la part d'un néophyte des petits trains :
Comment est faite la prise "d'alimentation de la locomotive :

  • par les rails ? Dans ce cas combien d'essieux par boogie sont capteur de courant ?
  • par couple pentographe/caténaire ?
  • autres ?

Les explication sur la sommation de PWM m'ont convaincu dans la mesure où le temps de chevauchement de canton est long alors que dans ma tête il devait être très court. N'est-il pas possible d'agir " mécaniquement" en réduisant les zones de chevauchement par exemple en n'utilisant qu'un seul essieu pour capter le courant , ou un seul pentographe ?

68tjs:
Comment est faite la prise "d'alimentation de la locomotive :

  • par les rails ?

Oui

Dans ce cas combien d'essieux par boogie sont capteur de courant ?

Ça dépend de la locomotive. Plus il y en a mieux c'est sinon le matériel se plante sur les zones ou la voie est moins propre ou moins bien posée

  • par couple pentographe/caténaire ?

Ca arrive mais ça ne concerne que les motrices électriques et c'est difficile à mettre en œuvre si on veut faire une caténaire à l'échelle

  • autres ?

On peut avoir des batteries sur les trains de jardin mais ce sont des modèles à grande échelle.

Les explication sur la sommation de PWM m'ont convaincu dans la mesure où le temps de chevauchement de canton est long alors que dans ma tête il devait être très court. N'est-il pas possible d'agir " mécaniquement" en réduisant les zones de chevauchement par exemple en n'utilisant qu'un seul essieu pour capter le courant , ou un seul pentographe ?

Aucune loco n'a un seul essieu capteur. Ça serait la cata.

Bonjour,

J’ai mis en œuvre une synchro des PWM entre plusieurs Arduino. Un Arduino est dédié à la génération d’un signal carré de période égale à la période de la PWM à synchroniser.

Tous les autres Arduino reçoivent ce signal sur une entrée numérique.

Voici le programme de génération du signal

void setup() {
  // Programme le timer 2 pour etre en fast PWM avec OCR2A comme TOP
  // La sortie PWM est la broche 3
  pinMode(3,OUTPUT);
  // Controle de la sortie OC2A (broche 11 de l'Arduino). Comme on
  // veut pouvoir utiliser le SPI, OC2A est positionnée en mode normal
  // Donc les champs COM2A1 et COM2A0 sont tous les 2 à 0
  // On se place en Compare Output Mode / Fast PWM Mode
  // La PWM doit etre non inversée, donc COM2B1 est à 1 et COM2B0 à 0
  // Enfin, on veut etre en Fast PWM, terminer le cycle sur un match
  // de OCRA et repartir à BOTTOM donc les WGMx sont tous à 1
  TCCR2A = _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
  TCCR2B = _BV(WGM22) | _BV(CS22);
  OCR2A = 200;
  OCR2B = 100;  
}

void loop() {
  // put your main code here, to run repeatedly:
}

J’ai fait une petite appli de démo sur un Uno. Le timer 2 est utilisé et la PWM est forcément celle de la broche 3. Celle de la broche 11 n’est pas utilisable. La broche 8 est utilisée comme entrée de synchronisation :

const byte valeurNominaleOCR2A = 200;

ISR(TIMER2_COMPA_vect) {
  byte signal = (PINB & 0b0000001) << 1;
  signal |= (PINB & 0b0000001);
  switch (signal) {
    case 0b00:
    case 0b01:
      // en retard ou opposition de phase, on diminue la période
      OCR2A = valeurNominaleOCR2A - 1;
      break;
    case 0b11:
      // en avance, on augmente la periode
      OCR2A = valeurNominaleOCR2A + 1;
  }    
  // acquitte l'interruption
  TIFR2 = _BV(OCF2A);
}

void setup() {
  // Programme le timer 2 pour etre en fast PWM avec OCR2A comme TOP
  // La sortie PWM est la broche 3
  pinMode(3,OUTPUT);
  pinMode(8,INPUT);
  // Controle de la sortie OC2A (broche 11 de l'Arduino). Comme on
  // veut pouvoir utiliser le SPI, OC2A est positionnée en mode normal
  // Donc les champs COM2A1 et COM2A0 sont tous les 2 à 0
  // On se place en Compare Output Mode / Fast PWM Mode
  // La PWM doit etre non inversée, donc COM2B1 est à 1 et COM2B0 à 0
  // Enfin, on veut etre en Fast PWM, terminer le cycle sur un match
  // de OCRA et repartir à BOTTOM donc les WGMx sont tous à 1
  TCCR2A = _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
  TCCR2B = _BV(WGM22) | _BV(CS22);
  OCR2A = valeurNominaleOCR2A;
  OCR2B = 50;
  
  // Autorise les interruptions sur Compare and Match de OCR2A, ie à chaque 
  // periode de la PWM
  TIMSK2 = _BV(OCIE2A);
}

byte vitesse = 1;

void loop() {
}

Salut,
un arduino pour chaque canton ?

C'est l'idée.

Bonsoir,

J'ai pris le temps de packager tout ça dans une bibliothèque. C'est ici :

SyncPWM

merci pour le programme !

pourquoi pas, cependant il y a 6 sorties pwm sur un arduino, vous pouriez diviser le nombre d'arduinos par 6!

bien entendu ma remarque n'a de sens que s'il s'agit d'un grand réseau, et je sais que l'électronique n'est en principe pas la priorité du modéliste ...

et puis j'arrête ce post avant de parler de dcc

Bonjour,

Le mode permettant d'ajuster la frequence de la PWM ne permet pas deux sorties PWM par timer. Donc il n'y en aurait que 3 quoiqu'on fasse. Ensuite modifier le fonctionnement du timer 0 casserait la mesure de temps et je ne suis pas sûr que les utilisateurs veuillent renoncer à ça.

Mais l'Arduino peut également s'occuper de la détection en pleine voie et en zone d'arrêt ainsi que de la signalisation. Il ne serait donc pas sous-employé.

Le mode permettant d'ajuster la frequence de la PWM ne permet pas deux sorties PWM par timer. Donc il n'y en aurait que 3 quoiqu'on fasse.

Sûr ?
Ce n'est pas une critique mais un approfondissement.

Sur un 328p, a ce que j'ai compris :
On peut faire varier la fréquence en fonction du choix du préscaler

  • 5 choix possibles avec T0 et T1
  • 7 choix possibles avec T2
    Je met de coté la possibilité d'entrer une fréquence sur les pins T0,T1 ou T2.
    Ces valeurs de fréquences sont des valeurs fixes.

Obtenir des valeurs quelconques pour la fréquence (entre 0 et la valeur max qui correspond à un préscaler égal à 1) n'est possible qu'avec T1.
Cela n'a rien à voir avec le fait que ce soit le seul timer 16 bits mais cela à voir avec le fait qu'il possède un registre suplémentaire (ICR1) qui permet de régler le "TOP".

Ai-je bien compris ?

Il faut pouvoir régler finement la fréquence et pour ça il faut utiliser le registre OCRA comme TOP. Le registre OCRB du timer sert à fixer le duty cycle.

Si j'ai bien compris la datasheet, quand OCRA est le top, on n'a plus de PWM sur la sortie OC correspondante.

J'ai fait ça avec le Timer 2 mais j'avoue que je n'ai pas regardé en détail le Timer 1