1/160 - Echelle N

Le Forum consacré à l'Echelle N
 
AccueilAccueil  PortailPortail  ÉvènementsÉvènements  Dernières imagesDernières images  S'enregistrerS'enregistrer  Connexion  
N'hésitez pas à consulter le calendrier et les événements du forum pour voir les manifestations près de chez vous !
Le Deal du moment : -50%
-50% Baskets Nike Air Huarache Runner
Voir le deal
69.99 €

 

 PN actionné par servo-moteurs: électronique

Aller en bas 
3 participants
AuteurMessage
SavignyExpress
Membre
Membre
SavignyExpress


Masculin Age : 61
Localisation : yyy
Nombre de messages : 2032
Date d'inscription : 10/10/2010

PN actionné par servo-moteurs: électronique Empty
MessageSujet: PN actionné par servo-moteurs: électronique   PN actionné par servo-moteurs: électronique Icon_minitimeMar 13 Déc 2011 - 12:54

Réalisation d'un PN actionné par servo-moteurs: électronique

Signal de commande du servo-moteur

Un servo-moteur de modélisme (modèle analogique) comporte 3 fils: 2 pour l'alimentation (5V), 1 pour le signal de commande (variant entre 0-5V). Le signal de commande consiste en une impulsion d'une durée comprise entre 1 et 2 millisecondes (ms), répétée toutes les 20 ms environ.

L'image ci-après, tirée de http://fribotte.free.fr, montre à quoi doit ressembler ce signal. En variant la durée de l'impulsion, on commande directement la position du servo-moteur.

PN actionné par servo-moteurs: électronique Smci10

Avec un microcontrôleur AVR Attiny2313, on procède comme suit. La commande du servo est reliée à la pin OC1A, configurée pour être la sortie du timer 16 bits. L'Attiny2313 tourne à 1 MHz, le timer 16 bits est configuré pour compter directement les impulsions d'horloge à cette fréquence sans division. Avec un timer 16 bits, on peut ainsi compter jusqu'à ~65 ms.

En C, le fragment de code à utiliser est le suivant:

Code:

    #define CONFIG_TCCR1A  (_BV(COM1A1)|_BV(WGM11))
    #define CONFIG_TCCR1B  (_BV(CS10)|_BV(WGM12)|_BV(WGM13))
    #define  PERIODE_SERVO      20000

            ...

    ICR1 = PERIODE_SERVO;
    OCR1A = MIN_SERVO; 
    TCCR1A = CONFIG_TCCR1A;
    TCCR1B = CONFIG_TCCR1B;

          ...

    // Utilisation, nLen est compris entre 1000 et 2000, le point milieu est 1500.
    OCR1A = nLen;


Le registre ICR1 reçoit la valeur maximale du timer, ici 20000 microsecondes, donc 20 millisecondes. Le registre OCR1A reçoit la durée de l'impulsion, elle aussi exprimée en microsecondes. Ainsi pour parcourir toute la plage de rotation du servo, cette valeur varie entre 1000 et 2000 microsecondes. Les registres TCCR1A et TCCR1B reçoivent la configuration du timer 16 bits pour qu'il génère un signal PWM (modulation largeur d'impulsion).

Une fois configuré, le timer 16 bits fonctionne parallèlement au reste du microcontrôleur qui peut ainsi continuer à exécuter son programme.

Le timer fonctionne ainsi:

  • Démarrage à 0. Mettre la sortie à 1 (5V).
  • S'incrémenter chaque microseconde.
  • Lorsque la valeur du timer atteint la valeur contenue dans OCR1A, mettre la sortie à 0 (0V).
  • S'incrémenter chaque microseconde.
  • Lorsque la valeur du timer atteint la valeur contenue dans ICR1, réinitialiser le timer à 0 et recommencer.


Pour monter et descendre la barrière du PN, le programme principal procède comme suit:

  • Valeur initiale dans OCR1A. Cette valeur est gérée dans la variable nLen, contrôlée par le programme principal.
  • Attendre un peu (valeur à déterminer).
  • Ajouter une petite valeur (typiquement 1 ms) à OCR1A.
  • Attendre un peu.
  • S'arrêter lorsque OCR1A contient la position finale voulue du servo.


En jouant sur l'attente entre 2 mises à jour de OCR1A, la valeur ajoutée à OCR1A, on obtient un mouvement précis de la barrière à la vitesse la plus appropriée. Il faut également procéder à plusieurs tests pour déterminer quelles sont les positions début et fin du servo à prendre en compte. Dans mon cas, ce sont les 2 positions extrêmes, soient des valeurs de OCR1A comprises entre 1000 et 2000.

La même méthode peut certainement être adaptée aux microcontrôleurs PIC, mais je n'ai aucune expérience de cette famille de microcontrôleurs.

La mécanique du PN est décrite ici:
https://le-forum-du-n.1fr1.net/t12789-pn-actionne-par-servo-moteurs-montage-et-mecanique


Dernière édition par SavignyExpress le Lun 18 Mar 2013 - 12:37, édité 7 fois
Revenir en haut Aller en bas
Décau45
Membre
Membre
Décau45


Masculin Age : 72
Localisation : Nord Loiret, 45
Nombre de messages : 201
Date d'inscription : 18/01/2009

PN actionné par servo-moteurs: électronique Empty
MessageSujet: Re: PN actionné par servo-moteurs: électronique   PN actionné par servo-moteurs: électronique Icon_minitimeSam 17 Déc 2011 - 9:56

Belle réalisation,

il y a bien longtemps (30ans) j"avais fait un montage avec deux NE555 pour commander des servos mais le prix de ces derniers était prohibitif. Connais_tu le timing des servos d'aujourd'hui ? j'utilise des PIC pour mes réalisations.

Bonnes réalisations et je pense que le Pére Noël va m'apporter le même PN §
Revenir en haut Aller en bas
SavignyExpress
Membre
Membre
SavignyExpress


Masculin Age : 61
Localisation : yyy
Nombre de messages : 2032
Date d'inscription : 10/10/2010

PN actionné par servo-moteurs: électronique Empty
MessageSujet: Re: PN actionné par servo-moteurs: électronique   PN actionné par servo-moteurs: électronique Icon_minitimeLun 19 Déc 2011 - 12:52

Je viens d'éditer le post initial de ce tuto avec des explications sur la génération du signal de commande du servo-moteur avec un microcontrôleur Attiny2313.
Revenir en haut Aller en bas
aladin91
Membre
Membre
aladin91


Masculin Age : 72
Localisation : ESSONNE Gif sur Yvette
Nombre de messages : 455
Date d'inscription : 30/11/2008

PN actionné par servo-moteurs: électronique Empty
MessageSujet: Re: PN actionné par servo-moteurs: électronique   PN actionné par servo-moteurs: électronique Icon_minitimeMar 20 Déc 2011 - 15:47

Bonjour, Savignyexpress, que penses tu de ce module somme toute assez bon marché ? ne remplirait il pas tes besoins ? (c'est ce que j'envisageait d'acheter pour commander mon PN)
Cordialement
http://www.conrad.fr/entrainement_universel_pour_modeles_reduits_de_trains_p_50802_51038_834282_315951_FAS
Revenir en haut Aller en bas
Décau45
Membre
Membre
Décau45


Masculin Age : 72
Localisation : Nord Loiret, 45
Nombre de messages : 201
Date d'inscription : 18/01/2009

PN actionné par servo-moteurs: électronique Empty
MessageSujet: Re: PN actionné par servo-moteurs: électronique   PN actionné par servo-moteurs: électronique Icon_minitimeMar 20 Déc 2011 - 22:30

Bonjour SavignyExpress,

"j'avais pas vu" comme dit la pub
les timings n'ont donc pas changé.
A voir, la programmation des PIC est équivalente à celle des AVR

Pour Aladin, la carte conrad est tout juste au prix des composants, très intéressant

Bonnes réalisations
Revenir en haut Aller en bas
SavignyExpress
Membre
Membre
SavignyExpress


Masculin Age : 61
Localisation : yyy
Nombre de messages : 2032
Date d'inscription : 10/10/2010

PN actionné par servo-moteurs: électronique Empty
MessageSujet: Re: PN actionné par servo-moteurs: électronique   PN actionné par servo-moteurs: électronique Icon_minitimeSam 5 Mai 2012 - 16:51

Voici l'état le plus à jour du programme de contrôle du PN. Il gère le PN et ses signaux, ainsi que 2 autres signaux mais sans barrières, à l'entrée de la gare. Le "multi-tâches" est géré à l'aide de la notion de protothread décrite ici: http://www.sics.se/~adam/pt/.

Code:

//
//   PassageNiveau.c
//
//   Programme de contrôle du passage à niveau.
//
//   2010.06.12   MHP   Création.
//   2011.06.14   MHP   Premiers tests concluants de commande du servo-moteur.
//   2011.06.20   MHP   Utilisation des protothreads PC (Adam Dunkels, adam@sics.se).
//   2011.06.22   MHP   Premier essai des prothothreads AVR.
//   2011.06.24   MHP   Correction des timings ville et prise en compte du transistor de sortie (inverser PWM).
//   2011.07.06   MHP   Configuration des entrées/sorties définitive!
//   2011.07.07   MHP   Réglage des délais pour la ville.
//   2011.09.10   MHP   Raccourcissement de la période et attente avant de redécter le train au PN ville.
//   2011.12.20   MHP   Suppression de l'anti-rebond pour la détection des trains et ralentissement des mouvements
//            des barrières.
//   2012.04.01   MHP   Suppression du délai entre 2 détections PN ville car nouveaux circuits de détection unidirectionnels.
//
//   Directives de compilation: PC ou AVR.
//

// Includes standard: types, IO.
#ifdef PC
#include   <stdint.h>
#include   <stdio.h>
#endif

#ifdef AVR
#include <inttypes.h>
#include <avr/io.h>
#endif


// Protothreads.
#include "pt.h"

static struct pt ptGererSignalVille, ptGererBarrieresVille, ptGererSignalGare;


// Timers.
typedef uint16_t   tTimer;

static tTimer   tmrBaisserBarrieresVille, tmrBarrieresVille, tmrClignSignalVille, tmrMvtBarrieresVille;
static tTimer   tmrGareA, tmrGareB, tmrClignSignalGare;

// Tous les délais sont exprimés nombres de périodes de PERIODE millisecondes.
// Période en ms.
#define   PERIODE   10

// La durée durant laquelle le signal fonctionne est exprimée en nombre d'itérations
// plutôt qu'à l'aide d'un timer.
#define DELAI_CLIGN_VILLE   (300/PERIODE)

#define   DUREE_SIGNAL_VILLE   (14000/PERIODE)
#define   NB_ITER_SIGNAL_VILLE   (DUREE_SIGNAL_VILLE/(2*DELAI_CLIGN_VILLE)+1)
#define   DELAI_BAISSER_BARRIERES_VILLE   (400/PERIODE)

// La durée durant laquelle le signal fonctionne est exprimée en nombre d'itérations
// plutôt qu'à l'aide d'un timer.
#define DELAI_CLIGN_GARE   (300/PERIODE)
#define DUREE_SIGNAL_GARE   (8000/PERIODE)
#define NB_ITER_SIGNAL_GARE   (DUREE_SIGNAL_GARE/(2*DELAI_CLIGN_GARE))

// Le délai lorsque les barrières sont à nouveau levées est plus grand que le délai entre
// le début du signal de ville et la descente des barrières.
#define   DELAI_BARRIERES_VILLE   (DUREE_SIGNAL_VILLE - 5*DELAI_BAISSER_BARRIERES_VILLE)
#define   DELAI_SERVO      (60/PERIODE)


// Constantes communes PC et AVR


// Spécifique AVR.
#ifdef AVR

#define F_CPU 1000000UL
#include <util/delay.h>

// Configuration des ports
#define INPUT_VILLE   PD1
#define   INPUT_GARE_A   PD2
#define   INPUT_GARE_B   PD3
#define INPUT_ATTENTE_A   PD4
#define   INPUT_ATTENTE_B   PD5

#define   OUTPUT_SERVO   PB3
#define OUTPUT_SIGNAL_VILLE   PB1
#define   OUTPUT_SIGNAL_GARE   PB0


#define CONFIG_DDRB   (_BV(OUTPUT_SERVO)|_BV(OUTPUT_SIGNAL_VILLE)|_BV(OUTPUT_SIGNAL_GARE))

#define PASSAGE_VILLE   (!(PIND & _BV(INPUT_VILLE)))
#define PASSAGE_GARE_A   (!(PIND & _BV(INPUT_GARE_A)))
#define PASSAGE_GARE_B   (!(PIND & _BV(INPUT_GARE_B)))

#define   CONFIG_PULLUPD   (_BV(INPUT_VILLE)|_BV(INPUT_GARE_A)|_BV(INPUT_GARE_B)|_BV(INPUT_ATTENTE_A)|_BV(INPUT_ATTENTE_B))
#define CONFIG_DDRD   ~CONFIG_PULLUPD

#define   ATTENTE_A   (!(PIND & _BV(INPUT_ATTENTE_A)))
#define   ATTENTE_B   (!(PIND & _BV(INPUT_ATTENTE_B)))

#define   SetClignVille   (PORTB |= _BV(OUTPUT_SIGNAL_VILLE))
#define ClrClignVille   (PORTB &= ~_BV(OUTPUT_SIGNAL_VILLE))

#define   SetClignGare   (PORTB |= _BV(OUTPUT_SIGNAL_GARE))
#define   ClrClignGare   (PORTB &= ~_BV(OUTPUT_SIGNAL_GARE))
#endif

#ifdef PC
// Pour simuler le passage des trains.
static uint8_t   PASSAGE_VILLE, PASSAGE_GARE_A, PASSAGE_GARE_B, ATTENTE_A, ATTENTE_B;
#endif

#define   MIN_SERVO      1000
#define   MAX_SERVO      1900
#define   PAS_SERVO      20

#ifdef AVR

#define CONFIG_TCCR1A   (_BV(COM1A1)|_BV(WGM11))

// Pour le test, prescaler sur 1024.
#if 0
#define CONFIG_TCCR1B   (_BV(CS12)|_BV(CS10)|_BV(WGM12)|_BV(WGM13))
#endif
// Fonctionnement normal, prescaler sur 1.
#define CONFIG_TCCR1B   (_BV(CS10)|_BV(WGM12)|_BV(WGM13))

#define   PERIODE_SERVO      20000
#endif


static PT_THREAD(GererSignalGare(struct pt *pt))
{

   // On doit pouvoir traiter ces événements quelque soit l'endroit où
   // on se trouve dans le protothread.
   if (ATTENTE_A && (tmrGareA > 0))
   {
#ifdef PC
      printf("Train en attente gare A\n");
#endif
      tmrGareA = DUREE_SIGNAL_GARE;
   } // if

   if (ATTENTE_B && (tmrGareB > 0))
   {
#ifdef PC
      printf("Train en attente gare B\n");
#endif
      tmrGareB = DUREE_SIGNAL_GARE;
   } // if

   PT_BEGIN(pt);

   while (1)
   {
      PT_WAIT_UNTIL(pt, PASSAGE_GARE_A || PASSAGE_GARE_B);

      if (PASSAGE_GARE_A && (tmrGareA == 0))
      {
#ifdef PC
         printf("Passage gare A\n");
#endif
         tmrGareA = DUREE_SIGNAL_GARE;
      } // if

      if (PASSAGE_GARE_B && (tmrGareB == 0))
      {
#ifdef PC
         printf("Passage gare B\n");
#endif
         tmrGareB = DUREE_SIGNAL_GARE;
      } // if

      while ((tmrGareA > 0) || (tmrGareB > 0))
      {
#ifdef PC
         printf("Signal gare ON\n");
#endif
#ifdef AVR
         SetClignGare;
#endif

         tmrClignSignalGare = DELAI_CLIGN_GARE;
         PT_WAIT_UNTIL(pt, tmrClignSignalGare == 0);

#ifdef PC
         printf("Signal gare OFF\n");
#endif
#ifdef AVR
         ClrClignGare;
#endif
         tmrClignSignalGare = DELAI_CLIGN_GARE;
         PT_WAIT_UNTIL(pt, tmrClignSignalGare == 0);
      } // while
   } // while

   PT_END(pt);
} // GererSignalGare


static PT_THREAD(GererSignalVille(struct pt *pt))
{
static uint16_t   nIter;

   PT_BEGIN(pt);

   while (1)
   {
      PT_WAIT_UNTIL(pt, PASSAGE_VILLE);

      for (nIter = 0; nIter < NB_ITER_SIGNAL_VILLE; nIter++)
      {
#ifdef PC
         printf("Signal ville ON\n");
#endif
#ifdef AVR
         SetClignVille;
#endif
         tmrClignSignalVille = DELAI_CLIGN_VILLE;
         PT_WAIT_UNTIL(pt, tmrClignSignalVille == 0);

#ifdef PC
         printf("Signal ville OFF\n");
#endif
#ifdef AVR
         ClrClignVille;
#endif
         tmrClignSignalVille = DELAI_CLIGN_VILLE;
         PT_WAIT_UNTIL(pt, tmrClignSignalVille == 0);
      } // for

#ifdef PC
      printf("Fin signal ville\n");
#endif
   } // while

   PT_END(pt);
} // GererSignalVille


static PT_THREAD(GererBarrieresVille(struct pt *pt))
{
static uint16_t   nLen;   // Longueur de l'impulsion des servos.


   PT_BEGIN(pt);

   while (1)
   {
      PT_WAIT_UNTIL(pt, PASSAGE_VILLE);

#ifdef PC
      printf("Attendre pour baisser les barrières\n");
#endif

      tmrBaisserBarrieresVille = DELAI_BAISSER_BARRIERES_VILLE;
      PT_WAIT_UNTIL(pt, tmrBaisserBarrieresVille == 0);

#ifdef PC
      printf("Début baisser les barrières\n");
#endif
      tmrBarrieresVille = DELAI_BARRIERES_VILLE;

      nLen = MIN_SERVO;
      while (nLen <= MAX_SERVO)
      {
#ifdef PC
         printf("Baisser barrières, servo: %0d\n", nLen);
#endif
#ifdef AVR
         OCR1A = nLen;
#endif
         nLen += PAS_SERVO;

         tmrMvtBarrieresVille = DELAI_SERVO;
         PT_WAIT_UNTIL(pt, tmrMvtBarrieresVille == 0);
      } // while

#ifdef PC
      printf("Barrières baissées\n");
#endif
      PT_WAIT_UNTIL(pt, tmrBarrieresVille == 0);

      nLen -= PAS_SERVO;
      while (nLen >= MIN_SERVO)
      {
#ifdef PC
         printf("Lever barrières, servo: %0d\n", nLen);
#endif
#ifdef AVR
         OCR1A = nLen;
#endif
         nLen -= PAS_SERVO;

         tmrMvtBarrieresVille = DELAI_SERVO;
         PT_WAIT_UNTIL(pt, tmrMvtBarrieresVille == 0);
      } // while

#ifdef PC
      printf("Barrières levées\n");
#endif
   } // while

   PT_END(pt);
} // GererBarrieresVille


void main(void)
{
   // Initialiser les protothreads.
   PT_INIT(&ptGererSignalVille);
   PT_INIT(&ptGererBarrieresVille);
   PT_INIT(&ptGererSignalGare);

   // Configuration spécifique AVR.
#ifdef AVR
   DDRD   = CONFIG_DDRD;
   PORTD   = CONFIG_PULLUPD;
   DDRB   = CONFIG_DDRB;

   ICR1 = PERIODE_SERVO;
   OCR1A = MIN_SERVO;   
   TCCR1A = CONFIG_TCCR1A;
   TCCR1B = CONFIG_TCCR1B;
#endif

#ifdef PC
uint16_t   nIter;

   //PASSAGE_VILLE = 1;
   PASSAGE_GARE_A = 1;

   for (nIter = 0; nIter <= 1000; nIter++)
   {
      printf("Temps: %0000d\n", nIter * PERIODE);

      if (nIter == 2)
         PASSAGE_GARE_A = 0;

      if (nIter == 40)
      {
         printf("ATTENTE_A = 1\n");
         ATTENTE_A = 1;
      }
      if (nIter > 45)
         ATTENTE_A = 0;


      if (nIter == 50)
      {
         printf("PASSAGE_GARE = 1\n");
         PASSAGE_GARE_B = 1;
      }
      if (nIter > 50)
         PASSAGE_GARE_B = 0;
#endif

#ifdef AVR
   while (1)
   {
#endif
      // Mettre à jour tous les timers.
      if (tmrBaisserBarrieresVille > 0)   tmrBaisserBarrieresVille--;
      if (tmrBarrieresVille > 0)      tmrBarrieresVille--;
      if (tmrClignSignalVille > 0)      tmrClignSignalVille--;
      if (tmrMvtBarrieresVille > 0)      tmrMvtBarrieresVille--;
      if (tmrGareA > 0)         tmrGareA--;
      if (tmrGareB > 0)         tmrGareB--;
      if (tmrClignSignalGare > 0)      tmrClignSignalGare--;

      // Traiter les événements.
      GererSignalVille(&ptGererSignalVille);
      GererBarrieresVille(&ptGererBarrieresVille);
      GererSignalGare(&ptGererSignalGare);

#ifdef AVR
      _delay_ms(PERIODE);
#endif
   } // while, for
} // main
Revenir en haut Aller en bas
SavignyExpress
Membre
Membre
SavignyExpress


Masculin Age : 61
Localisation : yyy
Nombre de messages : 2032
Date d'inscription : 10/10/2010

PN actionné par servo-moteurs: électronique Empty
MessageSujet: Re: PN actionné par servo-moteurs: électronique   PN actionné par servo-moteurs: électronique Icon_minitimeMer 1 Mai 2013 - 22:19

Une photo de la carte qui contrôle le PN.

PN actionné par servo-moteurs: électronique Dsc_1910

La détection des trains se fait à l'aide de diodes (non visibles ici) série et la chute de tension qui résulte de la consommation de courant des locos est utilisée pour commander des opto-coupleurs (chips du bas).
Revenir en haut Aller en bas
Contenu sponsorisé





PN actionné par servo-moteurs: électronique Empty
MessageSujet: Re: PN actionné par servo-moteurs: électronique   PN actionné par servo-moteurs: électronique Icon_minitime

Revenir en haut Aller en bas
 
PN actionné par servo-moteurs: électronique
Revenir en haut 
Page 1 sur 1
 Sujets similaires
-
» PN actionné par servo-moteurs: montage et mécanique
» Moteurs d'aiguillages DIY avec servo-moteurs
» Utilisation des servo-moteurs
» servo-moteurs et aiguillages
» Moteurs d'aiguillage à servo-moteur

Permission de ce forum:Vous ne pouvez pas répondre aux sujets dans ce forum
1/160 - Echelle N :: Modèles réduits à l'echelle N :: Les tutos-
Sauter vers: