Programmation moteurs pas à pas

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjour à tous! Une nouvelle fois je fais appel à vous pour me tirer d'affaire sur mon projet :) Alors voilà, on va y aller étape par étape:

  • le besoin : j'ai un coffre fort, la clé, l'autorisation de l'ouvrir (ben oui quand même), mais pas la combinaison. La serrure est une fichet bauche, soit trois cylindres de 20 chiffres chacuns (36° par clic). Donc 20x20x20 -> 8000 possibilités, autant dire que je cherche à automatiser la tâche… en plus c'est un bon challenge :D

  • le matériel : j'ai opté pour trois moteurs pas à pas NEMA, un par cylindre de combinaison. Un arduino Uno et deux shields de adafruit pour gérer les moteurs. Plus accessoirement un servomoteur pour tester la clé, après le servomoteur n'est pas indispensable)

  • la situation : après avoir un peu galéré à brancher mes moteurs… j'ai à peu près trouvé le moyen de sortir toutes mes combinaisons :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include <stdio.h>
#include <string.h>

int i=0 , j=0 , h=0;

main()
{
  for (i=0; i<220; i+=20)
  {
    for (j=0; j<220; j+=20)
    {
        for (h=0; h<220; h+=20)
        {printf("%d  %d   %d \n", i, j, h);
  }}}
}

20 par 20 parceque mes pas sont de 1.8° donc pour arriver à faire un clic à chaque fois, et vous vous en doutez, à la place de printf, ben je voudrais dire "moteur1/2/3".

  • Le problème : C'est la que le bât blesse… Je n'arrive pas à faire faire ce que je veux à mes moteurs. j'arrive bien à les faire tourner en utilisant la librairie d'exemples je peux bidouiller un peu pour qu'ils fassent plus ou moins de tours, plus ou moins vite, mais impossible d'utiliser ma formule, ni de leur imposer de faire x pas, un délais puis de nouveau x pas. Rien ne se passe

Voilà, j'en suis là, moins quelques cheveux, je vous joins le code que j'ai et qui ne marche pas, des suggestions?

Je vous mets le code que j'ai mis, vous constaterez que c'est plus ou moins l'exemple Accel_MultiStepper de la librairie remis à ma sauce.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// Shows how to run three Steppers at once with varying speeds
//
// Requires the Adafruit_Motorshield v2 library 
//   https://github.com/adafruit/Adafruit_Motor_Shield_V2_Library
// And AccelStepper with AFMotor support 
//   https://github.com/adafruit/AccelStepper

// This tutorial is for Adafruit Motorshield v2 only!
// Will not work with v1 shields

#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"
#include <stdio.h>
#include <string.h>

Adafruit_MotorShield AFMSbot(0x61); // Rightmost jumper closed
Adafruit_MotorShield AFMStop(0x60); // Default address, no jumpers

// Connect two steppers with 200 steps per revolution (1.8 degree)
// to the top shield
Adafruit_StepperMotor *myStepper1 = AFMStop.getStepper(200, 1);
Adafruit_StepperMotor *myStepper2 = AFMStop.getStepper(200, 2);

// Connect one stepper with 200 steps per revolution (1.8 degree)
// to the bottom shield
Adafruit_StepperMotor *myStepper3 = AFMSbot.getStepper(200, 1);

// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
// wrappers for the first motor!
void forwardstep1() {  
  myStepper1->onestep(FORWARD, SINGLE);
}
void backwardstep1() {  
  myStepper1->onestep(BACKWARD, SINGLE);
}
// wrappers for the second motor!
void forwardstep2() {  
  myStepper2->onestep(FORWARD, DOUBLE);
}
void backwardstep2() {  
  myStepper2->onestep(BACKWARD, DOUBLE);
}
// wrappers for the third motor!
void forwardstep3() {  
  myStepper3->onestep(FORWARD, INTERLEAVE);
}
void backwardstep3() {  
  myStepper3->onestep(BACKWARD, INTERLEAVE);
}

// Now we'll wrap the 3 steppers in an AccelStepper object
AccelStepper stepper1(forwardstep1, backwardstep1);
AccelStepper stepper2(forwardstep2, backwardstep2);
AccelStepper stepper3(forwardstep3, backwardstep3);

void setup()
{  
  AFMSbot.begin(); // Start the bottom shield
  AFMStop.begin(); // Start the top shield
   
  stepper1.setMaxSpeed(100.0);
  stepper1.setAcceleration(1000.0);

 
    
  stepper2.setMaxSpeed(100.0);
  stepper2.setAcceleration(1000.0);


  stepper3.setMaxSpeed(100.0);
  stepper3.setAcceleration(1000.0);
  
  
  int i=0 , j=0 , h=0;
  
  for (i=0; i<220; i+=20)
  {
    for (j=0; j<220; j+=20)
    {
        for (h=0; h<220; h+=20)
        {
            
            stepper1.move(i);
            stepper2.move(j);
            stepper3.move(h);
            delay(100);

  }}}
}

void loop()
{


}

Édité par Coyote

+0 -0

Cette réponse a aidé l'auteur du sujet

Rien ne bouge ? A mon avis c'est que tu declares des positions mais ne fait jamais de run()…

Bon il y a des trucs que je ne comprends pas… Si un cylindre fait 20 positions et 36 degres par clics ca veut dire un total de 720 degres soit trois tours pour faire toutes les positions ?

L'objectif de 220 dans les boucles for c'est pour quoi ? Il faudrait pas plutot aller a 400 ? (car 20 positions de 20 pas chacune) ?

Tu as essaye ces histoires de move en dehors du for ? Pourquoi pas utiliser "runToNewPosition" sinon ? L'avantage c'est que l'action est faite de suite et donc pas de run a appeler (mais c'est bloquant, mais ca t'arrange)

genre :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
int i=0 , j=0 , h=0;

for (i=0; i<220; i+=20) {
    stepper1.runToNewPosition(i);
    for (j=0; j<220; j+=20) {
        stepper2.runToNewPosition(j);
        for (h=0; h<220; h+=20) {
            stepper3.runToNewPosition(h);
            delay(100);
        }
    }
}

ZdS, le best du Zeste ! Tuto Arduino, blog, etc

+0 -0
Auteur du sujet

Si un cylindre fait 20 positions et 36 degres par clics ca veut dire un total de 720 degres soit trois tours pour faire toutes les positions ?>

Chaque cylindre fait 20 position en 2 tours (oui je n'avais pas précisé ^^), soit 36° par clic.

L'objectif de 220 dans les boucles for c'est pour quoi ? Il faudrait pas plutot aller a 400 ? (car 20 positions de 20 pas chacune) ?

Ben la tu as carrément raison, faut aller jusqu'à 400

Pourquoi pas utiliser "runToNewPosition" sinon ?

J'ai essayé la plupart des fonctions, mais pas celle-ci, je test ce soir, et je vous tiens au courant.

+0 -0
Auteur du sujet

Hello juste pour vous tenir au courant sur l'avancement de mon projet.. J'ai ajouté plusieurs éléments : - Pour stopper le programme une fois que la bonne combinaison a été trouvée, j'ai ajouté un bouton poussoir, si le servo arrive a tourner la clé il cliquera sur le bouton. - Pour connaitre la combinaison en cours et une fois fini la bonne combinaison un petit LCD de 16x2. - Pour le fun une led rouge tant que la combi n'est pas ok et vert quand c'est tout bon :)

Voici le schéma du montage (hors moteurs PAP): schema-montage

Et le code utilisé :

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"
#include <stdio.h>
#include <string.h>
#include <Servo.h>
#include <LiquidCrystal.h>
//         ---------------------------------------Bouton
const int buttonPin = 7;
const int ledPinRouge =  8;
const int ledPinVerte = 9;
int buttonState = 0;

//         ---------------------------------------Servo
Servo myservo;
int pos = 0;
//         ---------------------------------------Lcd
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

//         ---------------------------------------MotorShield
Adafruit_MotorShield AFMSbot(0x61); // Declaration des deux shields
Adafruit_MotorShield AFMStop(0x60);

Adafruit_StepperMotor *myStepper1 = AFMStop.getStepper(200, 1);  // Connexion des trois moteurs PAP 200pas par tour
Adafruit_StepperMotor *myStepper2 = AFMStop.getStepper(200, 2);  
Adafruit_StepperMotor *myStepper3 = AFMSbot.getStepper(200, 1);

// Choix de mouvement  DOUBLE INTERLEAVE ou MICROSTEP
void forwardstep1() {  myStepper1->onestep(FORWARD, SINGLE); }
void backwardstep1() {  myStepper1->onestep(BACKWARD, SINGLE);}
void forwardstep2() {  myStepper2->onestep(FORWARD, DOUBLE);}
void backwardstep2() {  myStepper2->onestep(BACKWARD, DOUBLE);}
void forwardstep3() {  myStepper3->onestep(FORWARD, INTERLEAVE);}
void backwardstep3() {    myStepper3->onestep(BACKWARD, INTERLEAVE);}

// Now we'll wrap the 3 steppers in an AccelStepper object
AccelStepper stepper1(forwardstep1, backwardstep1);
AccelStepper stepper2(forwardstep2, backwardstep2);
AccelStepper stepper3(forwardstep3, backwardstep3);

void setup()
{  
//-----------------------------Servo
  myservo.attach(0);
 
//-----------------------------lcd
lcd.begin(16, 2);

//-----------------------------Bouton
  pinMode(ledPinRouge, OUTPUT);
  pinMode(ledPinVerte, OUTPUT);
  pinMode(buttonPin, INPUT);
  buttonState = digitalRead(buttonPin);

//-----------------------------Shield
  AFMSbot.begin(); // Start the bottom shield
  AFMStop.begin(); // Start the top shield

  stepper1.setMaxSpeed(100.0);
  stepper1.setAcceleration(1000.0);

  stepper2.setMaxSpeed(100.0);
  stepper2.setAcceleration(1000.0);

  stepper3.setMaxSpeed(100.0);
  stepper3.setAcceleration(1000.0);

//--------------------Algo parametres et c est parti
int i=-20 , j=0 , k=0 , l=0 , m=-20;
while ( i < 420 )
    {
     buttonState = digitalRead(buttonPin);if (buttonState == HIGH){break;}
//----------------Bouton

digitalWrite(ledPinVerte, LOW);  //Led verte eteinte
        digitalWrite(ledPinRouge, HIGH); //Led rouge allumee
//----------------Calcul
     i += 20 ;
     j = -20;
     while ( j < 420 )
        {
     buttonState = digitalRead(buttonPin);if (buttonState == HIGH){break;}
        j += 20;
        m += 20;
        k = 0;
        while ( k < 420)
            {
              lcd.clear();
            buttonState = digitalRead(buttonPin);
            stepper1.runToNewPosition(i);
            stepper2.runToNewPosition(m);
            stepper3.runToNewPosition(l);
            lcd.print("M1:"); lcd.print(   (i%400)/20, DEC);lcd.print(" M2:");lcd.print((m%400)/20, DEC);lcd.print(" M3:");lcd.print((l%400)/20, DEC);
             if (buttonState == HIGH){break;}
             

//----------------------Servo
for(pos = 0; pos < 180; pos += 1)  // test de 0 a 180degrees
  {                                   
    myservo.write(pos);              // va en position de la variable 'pos'
    delay(15);                       // 15ms pour rejoindre la position
  }
            
            k += 20;
            l += 20;
             }}}

}

void loop()
{
         digitalWrite(ledPinVerte, HIGH);  //Led verte allumee
         digitalWrite(ledPinRouge, LOW);   //Led rouge eteinte

}

+0 -0

Je sais que le sujet est résolu mais j'aimerais juste faire remarquer que ton indentation est pas terrible. Là c'est un tout petit programme, pour l'instant. Mais dès que ça devient conséquent, une bonne indentation permet de lire avec beaucoup plus de facilité.

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte