Auteur Sujet: portique container  (Lu 66 fois)

marco58

  • Newbie
  • *
  • Messages: 3
    • Voir le profil
portique container
« le: juillet 11, 2025, 05:52:43 pm »
Bonjour a tous.
je souhaite faire bouger un portique pour mon train en H0 mais je ne sais pas comment faire.
Je voudrais utiliser des servomoteurs sg90 continu ou 360°.
Appui sur un BP pour lancer le programme.
Le moteur 1 se lance doucement, au bout d'un certain temps il s'arrête. Temps ajustable.
Le moteur 2 se lance doucement, au bout d'un certain temps il s'arrête. Temps ajustable.
Lorsque le BP est relâché.
Le moteur 2 se lance doucement en sens inverse, au bout d'un certain temps il s'arrête. Temps ajustable.
Le moteur 1 se lance doucement en sens inverse, au bout d'un certain temps il s'arrête. Temps ajustable.
fin du programme.
Je n'arrive pas a gérer l'enchainement des moteur ni a réduire leur vitesse.
Pouvez vous m'aider.
Merci.

Jean Marc

Brunotoutsimple

  • Jr. Member
  • **
  • Messages: 75
    • Voir le profil
Re : portique container
« Réponse #1 le: juillet 11, 2025, 08:23:53 pm »
Bonsoir
voici un code à tester:
#include <Servo.h>

// Création des objets servo pour les deux moteurs
Servo moteur1, moteur2;

// Définition des broches
const byte bpPin = 2;
const byte moteur1Pin = 3;
const byte moteur2Pin = 5;

// Valeurs PWM pour servomoteur 360° (arrêt, sens horaire, sens antihoraire)
const byte stopVitesse = 90;
const byte vitesseAvant = 60;
const byte vitesseArriere = 120;

// Temps d’activité pour chaque phase (en millisecondes)
const uint16_t t1 = 1500, t2 = 2000, t3 = 1800, t4 = 1600;

// Paramètres de rampe douce (durée totale et pas de variation)
const uint16_t rampeDuree = 500;
const byte rampePas = 5;

// Définition des états pour la machine à états
enum Etat {
  IDLE,             // Attente d'appui ou relâchement
  START_M1,         // Démarrage progressif moteur 1 en avant
  RUN_M1,           // Attente après démarrage moteur 1
  START_M2,         // Démarrage progressif moteur 2 en avant
  RUN_M2,           // Attente après démarrage moteur 2
  START_M2_REV,     // Démarrage progressif moteur 2 en arrière
  RUN_M2_REV,       // Attente après démarrage moteur 2 en arrière
  START_M1_REV,     // Démarrage progressif moteur 1 en arrière
  RUN_M1_REV        // Attente après démarrage moteur 1 en arrière
};

Etat etatActuel = IDLE; // État initial

// Variables de timing pour transitions
unsigned long horloge = 0;

// Variables de lecture du bouton
bool bpActuel = true;
bool bpPrecedent = true;

// Variables pour la rampe douce
bool rampeActive = false;
byte rampePWM = stopVitesse;
byte rampeCible = stopVitesse;
Servo* moteurRampe;

void setup() {
  pinMode(bpPin, INPUT_PULLUP);      // Bouton avec pull-up interne
  moteur1.attach(moteur1Pin);        // Association servo 1 à sa broche
  moteur2.attach(moteur2Pin);        // Association servo 2 à sa broche
}

void loop() {
  bpActuel = digitalRead(bpPin);     // Lecture de l’état du bouton

  // Détection des transitions (front montant ou descendant)
  if (etatActuel == IDLE && !bpActuel && bpPrecedent)
    etatActuel = START_M1;           // Passage à la séquence avant

  if (etatActuel == IDLE && bpActuel && !bpPrecedent)
    etatActuel = START_M2_REV;       // Passage à la séquence arrière

  bpPrecedent = bpActuel;            // Sauvegarde de l’état du bouton

  // Machine à états principale
  switch (etatActuel) {

    case START_M1:
      demarreRampe(moteur1, vitesseAvant);
      horloge = millis();
      etatActuel = RUN_M1;
      break;

    case RUN_M1:
      if (millis() - horloge >= t1) {
        moteur1.write(stopVitesse);
        demarreRampe(moteur2, vitesseAvant);
        horloge = millis();
        etatActuel = RUN_M2;
      }
      break;

    case RUN_M2:
      if (millis() - horloge >= t2) {
        moteur2.write(stopVitesse);
        etatActuel = IDLE;
      }
      break;

    case START_M2_REV:
      demarreRampe(moteur2, vitesseArriere);
      horloge = millis();
      etatActuel = RUN_M2_REV;
      break;

    case RUN_M2_REV:
      if (millis() - horloge >= t3) {
        moteur2.write(stopVitesse);
        demarreRampe(moteur1, vitesseArriere);
        horloge = millis();
        etatActuel = RUN_M1_REV;
      }
      break;

    case RUN_M1_REV:
      if (millis() - horloge >= t4) {
        moteur1.write(stopVitesse);
        etatActuel = IDLE;
      }
      break;
  }

  // ⏳ Rampe douce non bloquante pour moteurs
  if (rampeActive && millis() - horloge >= rampeDuree / (abs(rampeCible - stopVitesse) / rampePas)) {
    horloge = millis();

    if (rampePWM != rampeCible) {
      rampePWM += (rampeCible > stopVitesse) ? rampePas : -rampePas;
      moteurRampe->write(rampePWM);
    } else {
      rampeActive = false; // Rampe terminée
    }
  }
}

// 🌀 Démarre une rampe pour le moteur donné jusqu’à la valeur cible
void demarreRampe(Servo& moteur, byte cible) {
  rampePWM = stopVitesse;
  rampeCible = cible;
  moteurRampe = &moteur;
  rampeActive = true;
  horloge = millis();
}

Cordialement
Bruno

Fantasio

  • Newbie
  • *
  • Messages: 47
    • Voir le profil
Re : portique container
« Réponse #2 le: juillet 11, 2025, 09:11:40 pm »
Bonsoir Marco et Brunotoutsimple

Voici une simulation du code proposé par Bruno:
https://wokwi.com/projects/436209861266463745