Projet : Dolly autonome avec 2 steppers

Bonjour à tous ! :slight_smile:

Après d'intenses recherches PASSIONNANTES je suis en phase de validation de mon projet !

Un dolly automatique avec 2 bumpers aller/retour et un capteur RGB embarqué. Ce dernier permettra selon la couleur captée d’exécuter telle ou telle action (rotation de la caméra, pause) représentée en vert, gris et bleu sur mon schéma de principe.

Sur le rail du dolly, j'aimerai fixer des petits "poteaux" arborant chacun 2 carrés de couleurs différentes permettant le déclenchement des actions

Image en PJ

Ainsi dans le sens aller, le capteur va lire le rouge, puis le vert et vice-versa au retour.
Chaque couleur correspond à une action particulière.

Je commence à bien comprendre le langage mais je ne parviens pas à déterminer si cela est possible :

Si "couleur vert détectée en 1er" alors "ignorer couleur rouge" + exécuter une autre action"

Dans ce contexte le rouge arrive en 2eme position après le vert.

Est-ce possible d’après vous ? (ou bien me compliquerai-je la vie ?)

Avec mes remerciements.

poteaux.png

votre image:

cc5108d7a2f9a7106ab8fe006937aa30259debe7.png

vous vous compliquez peut-être la vie s'il n'y a que 2 couleurs toujours dans le même ordre, votre arduino saura si vous êtes sur la phase aller ou retour donc pourra décider de lui même lors du passage d'un poteau quelle action effectuer

A moins que vous n'ayez plein de couleur possibles et que vous vouliez donc suivant le poteau des actions différentes à l'aller et au retour ? --> oui, c'est possible et votre arduino lorsqu'il verra une couleur fait une action et s'il voit tout de suite après une autre couleur sans s'être bcp déplacé c'est qu'il sagit du même poteau et donc il l'ignorera... ça se code :slight_smile:

Bonjour J-M-L

Merci pour votre éclairage !

Effectivement j'avais imagine un ensemble de couleur spécifique à l'aller et un autre pour le retour.

Pourquoi des poteaux ?

J'ai prévu des poteaux amovibles qu'on peut fixer n'importe où sur le rail pour que le cadrage et panoramique de la caméra s'adapte en fonction du placement du sujet. Ou comment remplacer un cadreur humain ou un opérateur avec un joystick
C'est l'astuce la plus évidente pour moi...

:slight_smile:

Oui l'idée est bonne et simple à mettre en oeuvre

en gros

  • votre dolly bouge en fonction d'un séquencement donné (ou d'un bout à l'autre du chemin)
  • quel que soit le sens du déplacement, vous essayez de détecter une couleur
  • Si vous en voyez une:
  • vous regardez quand (ou où si vous mesurez le déplacement) pour la dernière fois vous avez vu une couleur
  • si c'est très récent, c'est le même poteau (voire la même couleur car vous n'avez pas assez avancé) et donc vous ne faites rien sinon c'est un nouveau poteau et vous déclenchez l'action associée à cette couleur (vous pouvez aussi détecter qu'il n'y avait plus de poteau et donc la prochaine couleur, même proche pourrait déclencher).

NB --> Il faut prévoir une couleur pour "pas d'action" car vos poteaux devront toujours comporter 2 actions sinon au retour vous aurez la même action qu'à l'aller

Oui l'idée est bonne

bonne nouvelle !

et simple à mettre en oeuvre

Euh... :smiley:

Je comprend un peu mieux avec votre réponse

Et voici le schéma de principe avec l'ordonnancement des poteaux et de leurs couleurs:

5 couleurs sont suffisantes pour ce projet et cela implique à mon avis une mise en ordre, en priorité des conditions que j'avais indiqué dan sinon 1er message.
Au final chaque sujet/cible dispose de 3 poteaux pour gérer le cadrage

Il faut prévoir une couleur pour "pas d'action"

Je pense qu'il s'agit du poteau gris si on nous nous comprenons bien

un bon point de départ c'est de lire les tutos d'eskimon

Pour bien comprendre les moteurs (et pour bien débuter avec l'arduino), c'est bien de lire Le mouvement grâce aux moteurs - les tutos d'eskimon. (commencez par la partie Le moteur à courant continu)

ensuite jouez avec votre capteur de couleur pour le maitriser

c'est typiquement une définition de programme qui se prête bien à la programmation par machine à états (cf mon tuto éventuellement)

un bon point de départ c'est de lire les tutos d'eskimon

Pour bien comprendre les moteurs (et pour bien débuter avec l'arduino), c'est bien de lire Le mouvement grâce aux moteurs - les tutos d'eskimon. (commencez par la partie Le moteur à courant continu)

ensuite jouez avec votre capteur de couleur pour le maitriser

Oui je commence à bien assimiler cela et j'avais commencé par là en plus
Merci

Le seul point ou je coince est la mise en forme du codage car j'ai l'impression il y a comme une imbrication de conditions avec des priorités selon si elles sont vérifiées ou pas

programmation par machine à états

Ah ça tombe bien car j'ai découvert cette notion et je me suis dit que pourrait servir.

Merci beaucoup je vais creuser dans cette voie !

J'avance lentement (mais surement ?)

#include <Stepper.h>
const int stepsPerRevolution = 4096;  // nombre de pas dans un tour pour le moteur unipolaire byj48 ou mettre 4076 a tester

// indique sur quels pins le moteur est branche:
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);

void setup()
{
// set the speed at 60 rpm:
	myStepper.setSpeed(60);
// initialize the serial port:
	Serial.begin(9600);   
}


void loop()
{


// la liste des états possible de notre système
// ainsi qu'une variable etatCourant prenant une de ces valeurs
enum {estrouge, estbleu, estjaune, estgris, estmauve} couleur;


  switch (couleur) {
    case estrouge:
// si rouge alors rotation antihoraire de 33 degres en divisant par 3
  Serial.println("counterclockwise");
  myStepper.step(stepsPerRevolution/3);
  delay(15000); // la camera filme la cible pendant 15 sec ok

   

      break;

    case estbleu:
      // faire quelque chose d'autre

      break;

case estjaune:
      // faire quelque chose d'autre

      break;

case estgris:
      // faire quelque chose d'autre

      break;

case estmauve:
      // faire quelque chose d'autre

      break;
  }

}

Il y a de l’idée (l’enum Est mieux en global)

N’y a-t-il pas d’autres états ? Quand le dolly ne bouge pas, arrive à un bout, avance ?

Dans quel état doit on tester la présence d’une des couleurs ?

Merci :slight_smile:
Hormis les actions définies par les couleurs, le dolly continue d'avancer lentement, dans un sens ou dans l'autre.

J'ai prévu que le dolly fasse marche arriere quand il arrive à la fin du rail grâce à un bumper switch monté dessus
Il y aura 2 bumper switch au total, un devant et un derriere, qui auront si je commence à comprendre le code, un nom différent.

Voici le code que j 'ai trouvé et modifié pour gérer les bumpers (j'ai enlevé la led qui ne me servira pas)

#include <Servo.h> // doublon 

const int bumperavant = 2; // switch bumper avant du dolly sur le pin 2
const int bumperarriere = 3;  // switch bumper arriere du dolly sur le pin 3
int pbavant = 0;          // A modofier ou supprimer ou ceonserver
int pbarriere = 0;         // A modofier ou supprimer ou conserver
Servo servoavantarriere;         // Definit le seul servo marche et arriere

void setup() { 
  servoavantarriere.attach(9);   // servo sur le pin D9

  // Set pin modes
  pinMode(bumperavant, INPUT);  
  pinMode(bumperarriere, INPUT); 
} 

void loop() { 
  forward();              // Start forward
  // Test bumper switches
  pbavant = digitalRead(bumperavant);  
  pbarriere = digitalRead(bumparriere);

  // si le switch arriere du dolly est active alors le dolly avance
  if (pbavant == HIGH) {
   reverse();
   delay(500);
  }

  // si le switch avant du dolly est active alors le dolly recule
  if (pbarriere == HIGH) {
   reverse();
   delay(500);  
  }
}

// Motion routines
void forward() {
  servoavantarriere.write(180); // chiffre a verifier
}

void reverse() {
  servoavantarriere.write(360);  // chiffre a verifier
}

void stopRobot() {
  servoavantarriere.write(90); // chiffre a verifier
}

Si on regarde le dolly comme système il a quelques états

  • a l’arrêt
  • en pause
  • en marche avant ou arrière
  • en train de traiter un ordre couleur

Cette machine à état reçoit comme événement un ordre de démarrage par l’humain sans doute, l’ordre du bumper avant ou arrière et la détection d’une couleur.

Ensuite il y a un sous système camera qui a ses ordres particuliers (pan / tilt / zoom / etc). Cette machine à état s’exécute soit en parallèle de la première quand l’événement couleur est rencontré (si vous voulez pouvoir zoomer doucement pendant qu’on avance par exemple) ou si vous voulez simplifier vous mettez en pause le premier système pendant qu’un événement couleur est effectué

Petite question - c’est pour faire du Time lapse sur une petite distance avec un objet proche ou un paysage très loin (ie focus stable) ou c’est vraiment pour un plateau avec des rails qui ne sont pas forcément rectilignes sur une grande distance ? Dans ce second cas l’orientation de l’axe la caméra et la mise au point seraient aussi à gérer - ce qui nécessitent d’instrumenter encore plus la caméra

Pour gérer les boutons et détecteurs de fin de course (bumper) qui sont comme des boutons, éventuellement utilisez la librairie de @bricoleau

La structure du code pourrait resembler un peu à cela (tapé ici donc y'a sans doute des bugs

// exemple Arduino Forum http://forum.arduino.cc/index.php?topic=603997.msg4099871#msg4099871
// J-M-L

#include <AccelStepper.h> // https://www.airspayce.com/mikem/arduino/AccelStepper/index.html
AccelStepper stepper; // config par défaut d'AccelStepper::FULL4WIRE (4 pins) sur 2, 3, 4, 5

#include <simpleBouton.h> // http://forum.arduino.cc/index.php?topic=375232.0
const uint8_t  pinBoutonDebut  = 6;
const uint8_t  pinBumperDebut  = 7;
const uint8_t  pinBumperFin  = 8;

//Cablage des boutons : pin---bouton---GND
simpleBouton boutonDebut(pinBoutonDebut);
simpleBouton bumperDebut(pinBumperDebut);
simpleBouton bumperFin(pinBumperFin);

enum : uint8_t {DOLLY_ARRET, DOLLY_PAUSE, DOLLY_AVANT, DOLLY_ARRIERE, DOLLY_CAMERA_ACTION} etatDolly = DOLLY_ARRET, etatDollyMemoire = DOLLY_ARRET;
enum ordre_t : uint8_t {ORDRE_AUCUN, ORDRE_ROUGE, ORDRE_VERT, ORDRE_BLEU} etatCommande = ORDRE_AUCUN;


void dollyMarcheAvant()
{
  // moteur en avant
  // ..
  etatDolly = DOLLY_AVANT;
}

void dollyMarcheArriere()
{
  // moteur en arrière
  // ..
  etatDolly = DOLLY_ARRIERE;
}

void dollyStop()
{
  stepper.stop();  // arret du moteur
  etatDolly = DOLLY_ARRET;
}

void dollyPause()
{
  stepper.stop();  // arret du moteur
  etatDolly = DOLLY_PAUSE;
}

void conditionsInitiales()
{
  dollyStop();
  etatCommande = ORDRE_AUCUN;
  etatDollyMemoire = DOLLY_ARRET;
  stepper.setMaxSpeed(100);
  stepper.setAcceleration(20);
}

void testerBoutons()
{
  // on met à jour l'état des boutons
  boutonDebut.actualiser();
  bumperDebut.actualiser();
  bumperFin.actualiser();

  // on teste s'il faut faire quelque chose
  if (boutonDebut.vientDEtreEnfonce()) {

    //======= APPUI DU BOUTON ==========
    // faudra être un peu plus précis que ça pour gérer la pause, ceci est un exemple
    if (etatDolly == DOLLY_ARRET) dollyMarcheAvant();
    else if (etatDolly == DOLLY_PAUSE) {
      if  (etatDollyMemoire == DOLLY_AVANT) dollyMarcheAvant();
      else dollyMarcheArriere();
    } else {
      etatDollyMemoire = etatDolly; // pour pouvoir remettre le bon état après
      dollyPause();
    }
    //==================================

  } else if (bumperDebut.vientDEtreEnfonce()) {

    //======= BUMPER DU DUBUT ==========
    dollyMarcheAvant();
    delay(10);  // éventuellement un petit delay() pour quitter l'appui du bumper
    //==================================

  } else if (bumperFin.vientDEtreEnfonce()) {

    //======= BUMPER DE FIN ==========
    dollyMarcheArriere();
    delay(10);  // éventuellement un petit delay() pour quitter l'appui du bumper
    //================================

  }
}

ordre_t testerCouleur()
{
  ordre_t ordre = ORDRE_AUCUN;
  // tester si on lit une couleur et affecter ordre, et changer etatDolly pour DOLLY_CAMERA_ACTION
  // ...
  if (ordre != ORDRE_AUCUN) {
    dollyPause(); // or arrête de bouger le temps de faire le changement sur la caméra
    etatDollyMemoire = etatDolly; // pour pouvoir remettre le bon état après exécution de l'ordre caméra
    etatDolly =  DOLLY_CAMERA_ACTION;
  }
  return ordre;
}

void setup()
{
  Serial.begin(115200);
  conditionsInitiales();
}

void loop()
{
  testerBoutons();
  ordre_t ordreEnCours = testerCouleur();

  switch (etatDolly) {
    case DOLLY_ARRET:
      break;
    case DOLLY_PAUSE:
      break;
    case DOLLY_AVANT:
      stepper.run(); // fait un pas si nécessaire
      break;
    case DOLLY_ARRIERE:
      stepper.run(); // fait un pas si nécessaire
      break;
    case DOLLY_CAMERA_ACTION:
      // faire ce qu'il faut (éventuellement en plusieurs tours de loop())
      // ...
      // une fois le boulot effectuer, remettre l'état à etatDollyMemoire
      break;
  }

  // ici on peut faire autre chose si ça ne prend pas trop de temps
  // ....
}

bien sûr faut rajouter tout ce qui concerne les moteurs et le pilotage de l'appareil photo / caméra et toute la logique applicative, gestion de mémoire des états et du timing etc.. donc y'a du boulot et sans doute dans certains états (par exemple quand on va en avant ou en arrière) le code sera factorisable (faire un pas moteur au bon moment si vous utilisez la librairie accelStepper par exemple)

:o alors ça c'est vraiment de l'assistance ! merci infiniment !

  • a l'arrêt
  • en pause
  • en marche avant ou arrière
  • en train de traiter un ordre couleur

Cette machine à état reçoit comme événement un ordre de démarrage par l'humain sans doute, l'ordre du bumper avant ou arrière et la détection d'une couleur.

Oui c'es exact, côté Arduino, j'ai prévu que :
2 bumpers
2 steppers pour la rotation de l'axe de la caméra et l'avance du dolly
un capteur RGB pour la gestion de la rotation.
un bouton on/off pour allumer le dolly avant le show
une batterie rechargeable avec suffisamment d'autonomie

Petite question - c'est pour faire du Time lapse sur une petite distance avec un objet proche ou un paysage très loin (ie focus stable) ou c'est vraiment pour un plateau avec des rails qui ne sont pas forcément rectilignes sur une grande distance ? Dans ce second cas l'orientation de l'axe la caméra et la mise au point seraient aussi à gérer - ce qui nécessitent d'instrumenter encore plus la caméra

Le dolly ne va pas servir à faire du time lapse, mais pour faire un travelling lent sur une scène pour filmer un groupe. Le dolly est autonome car alimenté avec sa propre batterie (je me renseigne sur la notion d'autonomie) et effectue des aller/retour sur le rail.
J'ai déjà retenu un moyen d'assemblage du rail qui permettra de garantir sa rectitude et horizontalité pour éviter notamment que l'image sursaute quand le dolly passe sur un nouveau rail.

Aucun contrôle de la camera n'est prévu car j'aimerai faire simple :

  • le smartphone ou camescope est simplement vissé, l’inclinaison fixe est simplement vérifiée avant le concert.
  • le démarrage de l'enregistrement et du dolly peut se faire quelques instants avant le show. Le dolly posé puis activé via les witch /On/Off commence à faire ses aller/retours et ce, peu importe la direction qu'il prendra. L'essentiel que les déclencheurs de bumper soient présents sur les rail en fin de course

OK donc vous aurez un smartphone ou une GoPro sur le dolly et l’appareil fera la mise au point en continu pour vous

Si le rail est rectiligne vous aurez sans doute (suivant la distance au centre de la scène) à régler L’orientation de la caméra. Il faudra réfléchir à comment vous décidez de faire cela.

Si le rail est rectiligne vous aurez sans doute (suivant la distance au centre de la scène) à régler L'orientation de la caméra. Il faudra réfléchir à comment vous décidez de faire cela.

Ce n'est pas prévu car le dolly aura pour mission de filmer les musiciens qui sont devant la scene d’où mon systeme de capteur et de poteaux pour gérer la rotation en face des sujets. L'idée est d'obtenir un joli travelling panoramique lent pour voir chaque musicien.

pano.png

Une fois le panoramique effectué la camera revient à la position 180degres et filme ce qui est visible en fond de scene

Ce soir je vérifie s'il est possible d'alimenter tout cela en autonomie via une ou 2 grandes batteries et ensuite je commande les pièces, car pour le moment je code "dans le vide" :slight_smile:

Je pense que j'ai suffisamment d'info pour me débrouiller.

Merci beaucoup !

pano.png

Bonjour
J'ai reçu les composants samedi et depuis j'ai ENORMEMENT appris!

Actuellement, j'arrive à coder un dolly avec 2 limit switches comme suit:

#include <AccelStepper.h>
#define FULLSTEP 4
#define HALFSTEP 8

//declare variables for the motor pins

int motorPin1 = 4;      // Blue   - 28BYJ48 pin 1
int motorPin2 = 5;      // Pink   - 28BYJ48 pin 2
int motorPin3 = 6;     // Yellow - 28BYJ48 pin 3
int motorPin4 = 7;     // Orange - 28BYJ48 pin 4

// Red    - 28BYJ48 pin 5 (VCC)

// The sequence 1-3-2-4 required for proper sequencing of 28BYJ48
//AccelStepper stepper2(FULLSTEP, motorPin1, motorPin3, motorPin2, motorPin4);
AccelStepper stepper1(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4);

int cwpin = 2;    //digital pin number for the cw button
int ccwpin = 3;   //digital pin number for the ccw button

void setup() {
  stepper1.setMaxSpeed(1000);
  stepper1.setAcceleration(50);
  stepper1.setMinPulseWidth(100);
  
 
  pinMode(cwpin, INPUT_PULLUP);
  pinMode(ccwpin, INPUT_PULLUP);

}

void loop() {

 if (digitalRead(cwpin) == LOW)  //  if the input is LOW (button pushed)

    { 
                                 delay(100); //pause de 10 secondes en fin de course 
                 CW();//rotates cw direction
            }

      

 if (digitalRead(ccwpin) == LOW){ //  if the input is LOW (button pushed)
        delay(100); //pause de 10 secondes en fin de course 
        CCW  ();//rotates ccw direction   
  
      }  

         
}

  void CW() {

    while (digitalRead(cwpin) == LOW)  
   
  {   
    stepper1.setSpeed(700);
       stepper1.runSpeed();
           }
  }

  void CCW() {

    while (digitalRead(ccwpin) == LOW)
   
     {
      stepper1.setSpeed(-700); // negative for ccw 
        stepper1.runSpeed();
           }
  }

   }

ça fonctionne bien, mais cela ne suffit par rapport à mon objectif.
Je vais tester le capteur RGB des que possible.

En revanche je peine pour faire tourner le 2eme stepper : j'aimerai tester la notion la rotation avec un angle définitif des que j'appuie sur un bouton.
Je sais coder cela, mais je ne sais pas l'inclure dans le code deja existant...

Une idée ?

Merci

Bonjour

Aprés 3 semaines d'apprentissage et de tatonnement, me voila au stade suivant:

Definition de 3 états : demarrage, aller (reculer), retour (avancer)
Ajout de 2 limit switches à chaque extrémité du parcours du dolly
Utilisation prévue d'un capteur d'obstacle pour gérer l'arret du dolly et la rotation de la camera.
C'est plus simple à implementer que le capteur de couleur prévu au départ

Le tout dans une machine à état assez rudimentaire :
le dolly change de sens quand le bouton est enfoncé (et non relâché, nuance que j'ai compris :slight_smile: )
Pour le moment je m'occupe seulement du comportement du stepper stepper_ar

Pouvez-vous m'indiquer ce qui coince dans ce code ?

Avec un immense merci !!!

#include <AccelStepper.h>
#include "simpleBouton.h" // http://forum.arduino.cc/index.php?topic=375232.0

// Define Constants
// Define step constants
#define FULLSTEP 4
#define HALFSTEP 8

#define motorPin1  8     // Blue   - 28BYJ48 pin 1
#define motorPin2  9     // Pink   - 28BYJ48 pin 2
#define motorPin3  10    // Yellow - 28BYJ48 pin 3
#define motorPin4  11    // Orange - 28BYJ48 pin 4

#define motorPin5  4     // Blue   - 28BYJ48 pin 1
#define motorPin6  5     // Pink   - 28BYJ48 pin 2
#define motorPin7  6     // Yellow - 28BYJ48 pin 3
#define motorPin8  7     // Orange - 28BYJ48 pin 4

// Define two motor objects
// The sequence 1-3-2-4 is required for proper sequencing of 28BYJ48
AccelStepper stepper_ar(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4);// moteur en charge de l'avance et recul du dolly
AccelStepper stepper_camera(HALFSTEP, motorPin5, motorPin7, motorPin6, motorPin8);//moteur pivotant la caméra, à coder plus tard 
 
simpleBouton bouton_aller(2);
simpleBouton bouton_retour(3);

enum State_enum {DEMARRAGE, ALLER, RETOUR};//etat du dolly stepper_ar
enum Sensors_enum {NONE, BUMPER_ALLER, BUMPER_RETOUR};//etats des 2 bumper limit swicht
 
void state_machine_run(uint8_t sensors);
void demarrage();
void aller();
void retour();
uint8_t read_IR();
uint8_t state = DEMARRAGE;

void setup() {

//Serial.begin(9600);

//Serial.begin(9600);

stepper_ar.setMaxSpeed(700.0);
stepper_ar.setAcceleration(400.0);
stepper_camera.setMaxSpeed(700.0);
stepper_camera.setAcceleration(400.0);  

}
 
void loop(){
state_machine_run(read_IR());

bouton_aller.actualiser();//limit switch 1
bouton_retour.actualiser();//limit switch 2

stepper_ar.run();
stepper_camera.run();
}
 
void state_machine_run(uint8_t sensors) 
{
  switch(state)
  {   
    case ALLER:
      if(sensors == BUMPER_RETOUR){
       aller();
        state = RETOUR;
      }
      break;
 
    case RETOUR:
      if(sensors == BUMPER_ALLER){
        retour();
        state = ALLER;
      }
      break;
  }
}
 
void demarrage()//demarrage du dolly
{
stepper_ar.moveTo(1000);//4096 = 2 tours
stepper_ar.setSpeed(400);
}

void aller()//trajet aller apres avoir activé le bouton_aller 
{
stepper_ar.moveTo(1000);//4096 = 2 tours
stepper_ar.setSpeed(400);
}
 
void retour()//trajet retour apres avoir activé le bouton_retour
{
stepper_ar.moveTo(-1000);//4096 = 2 tours
stepper_ar.setSpeed(-400);
}

uint8_t read_IR()
{
if (bouton_retour.vientDEtreRelache())aller();
if (bouton_aller.vientDEtreRelache())retour();
}