synchroniser moteur PaP avec capteur ultrason (projet robotique)

Bonjour,

Je souhaite réaliser un robot à 2 roues qui évite les obstacles comme on peut le voir dans beaucoup de projet. Rien de très compliqué… normalement.
J'ai suivi le Mooc arduino sur open class room avec succès.

Vous trouverez ici la base sur laquelle je m'appuie

Je viens demander de l'aide par rapport à la partie programmation.
Je souhaite écrire un code qui permettent aux moteurs de bouger en fonction des informations donnés par le capteur ultrason.

Mon problème concerne donc la synchronisation entre le capteur ultrason et les moteurs pas à pas. J'ai essayé d'utiliser la librairie stepper.h ainsi que <accel.stepper.h.> Je sens que je touche du doigt la solution mais j'ai besoin d'aide.

Je n'ai peut être pas pris les bons moteurs ?

Existe-t-il des moteurs qui me faciliteraient la tâche comme ceci ?:

Ou ceci:

J'utilise la version 1.8.5 de l'IDE Arduino.

Je suis sur windows 10 64bits

Mon matériel:

Carte arduino UNO
Breadboard classique
Moteurs Pas à Pas
Motor Drive Shield Expansion
Module Ultrason de Capteur de Distance

Merci d'avance pour votre aide.
PS: Je n'ai pas vu d'endroit pour "se présenter" si j'ai mal fait qqchose, merci de me l'indiquer gentiment et je corrigerai ça dans les meilleurs délais.

Je souhaite écrire un code qui permettent aux moteurs de bouger en fonction des informations donnés par le capteur ultrason. Mon problème concerne donc la synchronisation entre le capteur ultrason et les moteurs pas à pas. J'ai essayé d'utiliser la librairie stepper.h ainsi que <accel.stepper.h.> Je sens que je touche du doigt la solution mais j'ai besoin d'aide.

Mais quel est votre soucis vraiment?

Hmmm...

Synchroniser un capteur ultrasons avec des moteurs?

On récupère un signal (une distance) et de là, on dit quoi faire aux moteurs...

J'ai pas compris le problème, si les moteurs vont, alors ils fonctionnent :smiley:

On peut en savoir davantage?

Merci de vos réponses :slight_smile:

Eh bien, oui, le capteur me renvoie une valeur, que je déchiffre pour évaluer la distance, mon soucis, c'est de faire arrêter les moteurs (c'est les moteurs pas à pas commandé par la Carte Pilot ULN2003) et les faire changer de direction pour faire reculer les moteur à 90° dans un angle et ensuite de reprendre sa course.

Mon soucis, c'"est que les moteurs n'avancent plus que très lentement, surement parce que mon programme envoie et reçoit les valeurs au capteur qui ralentissent du coup l'avancée des moteurs :confused:

Je sais qu'il y a deux bibliothèques pour les moteurs, et

Avec le premier, impossible de lancer les deux moteurs en même temps, avec le deuxième oui, mais il est hyper complexe (enfin pour moi) x)

Si vous pouviez éclairer ma lanterne je vous serez très reconnaissant ^^

Avec stepper, on lance les moteurs l'un après l'autre avec une fraction de seconde de décalage, l'autre je connais même pas ^^

Je construis un robot line follower en ce moment, je vais lui apprendre à éviter les obstacles avec un HC-SR04 monté sur servo (pour regarder sur les côtés)

Je vais le faire ralentir en fonction de la distance, ça évite d'arriver à fond sur un obstacle et freiner comme une brute pour finir par percuter un chien qui dort encore en plein passage. Bon sang couché panier !
A une certaine distance de l'objet à contourner, on est à l'arrêt complet. De là, on fait un pivot (à gauche ou à droite, question de convictions), ou alors on "regarde" des deux côtés pour vérifier qu'il n'y ait rien et qu'on peut pivoter.
Une fois parallèle à l'objet, on avance jusqu'à avoir dépassé l'objet, on se remet perpendiculaire, on avance jusqu'à ne plus voir l'objet, c'est évité. Est-ce qu'on évite juste, ou est-ce qu'on contourne?

Ce que fait le moteur en fonction du retour du capteur, il n'y a que toi qui puisse le définir. Il faut essayer à la maison. En fonction du revêtement, ça va patiner plus ou moins.
La précision de l'évitement dépend de ce qu'on veut obtenir et du mal qu'on se donne. Le mien utilisera d'autres capteurs pour être précis et prendre en compte le patinage, mais ma maman veut pas que je dise comment.

C'est un robot pour le tournoi de Nîmes? pour embêter le chien? Épater les filles geeks?

Sois bien sûr que tu maîtrises bien les rotations, c'est pas facile à régler, le mien conduit comme un ivrogne. je dois donc être certain qu'il suivra parfaitement une ligne. SI le tient roule au pif et évite ce qu'il rencontre, observe sur les vidéos le comportement des machines, on en déduit les finesses (ou pas) de programmation. Pis c'est mieux que Joséphine Ange Gardien à regarder.

C'est sûr que j'ai un peu de mal avec les rotations xD

Et oui, c'est un projet très intéressant ! D'ailleurs, j'aimerai "upgrader" mon robot dans le futur pour qu'il fasse ça aussi, mais pour l'instant, je pense que le problème c'est qu'entre faire avancer le moteur d'un pas, et de prendre l'information sur le capteur, il se passe bien plus qu'une fraction de seconde :confused: surtout que c'est deux moteurs !

Est ce que ton programme utilisant un servo-moteur serait le même pour un moteur pas à pas ?

Comment fais tu pour à la fois envoyer et recevoir les informations au capteurs et faire tourner les moteurs sans les ralentir voir les bloquer ?

Merci de ton aide ^^

Je reçois les infos de 5 capteurs.
Je les traite pour avoir un signal compréhensible.
Je détermine les cas de figure possibles.
Je dis aux moteurs leur sens de rotation et leur vitesse.

pour l'instant, des valeurs renvoyées par mes capteurs je fais un seul code binaire genre: B00000
Ensuite, je traite dans un switch/case.

Ca c'est pour suivre une ligne, et j'en suis là.

Pour l'évitement:
Envoyer impulsion sur le module ultrasons
Lire le retour.
Evaluer la distance.
Commander les moteurs. (freiner ou pas)

Si on a freiné, les moteurs finissent à l'arrêt.
Commander le servo, 90° à gauche
envoi Pulse
lecture Signal
commander les moteurs 90 gauche si la voie est libre
sinon, 180 droite
envoi
lecture
commander les moteurs.

Plein de vidéos de ce type de bestiole. C'est pas le plus compliqué.
Attention à l'emplacement du HCSR04 (j'imagine que c'est celui la), trop bas, il est embêté par le sol, des mouvements trop rapides et le signal est inutilisable.
Il y a des temps de réponse et de positionnement à respecter. J'ai fait un post là-dessus, en le retrouvant tu auras du code et une problématique.

Comment fais tu pendant l’émission et la réception des données du capteur, faire avancer tes moteurs? Pour les pas à pas, ils sont obligés de finir le nombre de pas que je leur ai demandé de faire.

Pendant ce temps le programme est bloqué sur ça, et quand c'est fini, les moteurs s'arrêtent, ensuite émission, réception de la distance par le capteur, et ensuite je commande au moteur ce que je veux.

En gros je suis obligé de faire par exemple 2000 pas, arrêt des moteurs, lecture du capteur, relance des moteurs pour 2000 pas si tout va bien. Enfin, je suis obligé, dans la limite de ou j'ai vraiment pas pigé quelque chose :confused: et je voudrais lire pendant l'avancement des moteurs, pas les obliger à s'arrêter.

Rumpel:
Comment fais tu pendant l’émission et la réception des données du capteur, faire avancer tes moteurs? Pour les pas à pas, ils sont obligés de finir le nombre de pas que je leur ai demandé de faire.

Pendant ce temps le programme est bloqué sur ça, et quand c'est fini, les moteurs s'arrêtent, ensuite émission, réception de la distance par le capteur, et ensuite je commande au moteur ce que je veux.

En gros je suis obligé de faire par exemple 2000 pas, arrêt des moteurs, lecture du capteur, relance des moteurs pour 2000 pas si tout va bien. Enfin, je suis obligé, dans la limite de ou j'ai vraiment pas pigé quelque chose :confused: et je voudrais lire pendant l'avancement des moteurs, pas les obliger à s'arrêter.

la librairie AccelStepper est non bloquante sinon il faut dire à vos moteurs de faire un pas tous les deltaT et vous gérez vous même ainsi la vitesse. pendant que le microprocesseur attend le prochain deltaT il a le temps de faire autre chose

J'utilise des moteurs à balais de noob. :smiley:

Et quelle fonction il faudrait utiliser de cette librairie ? Si je ne me trompe pas il faut définir la vitesse max et la vitesse, et ensuite lancer le moteur ?

" stepperX.setMaxSpeed(600.0);
stepperX.setSpeed(600.0);

stepperx.run(); "

Mais quand le proramme arrive sur le .run, il l'utilise complètement, et sortir de cette fonction pour en utiliser une autre revient au même problème :confused:

(à moins que c'est mon programme de lecture et d’émission pour le capteur qui est trop "long"?)

hmmm, j'arrive pas vraiment à identifier pleinement le problème :confused:

faut lire la doc...

AccelStepper significantly improves on the standard Arduino Stepper library in several ways:

Supports acceleration and deceleration
Supports multiple simultaneous steppers, with independent concurrent stepping on each stepper
API functions never delay() or block
Supports 2, 3 and 4 wire steppers, plus 3 and 4 wire half steppers.
Supports alternate stepping functions to enable support of AFMotor (GitHub - adafruit/Adafruit-Motor-Shield-library: Adafruit Motor shield V1 firmware with basic Microstepping support. Works with all Arduinos and the Mega)
Supports stepper drivers such as the Sparkfun EasyDriver (based on 3967 driver chip)
Very slow speeds are supported
Extensive API
Subclass support

la fonction run() est non bloquante, il suffit de l'appeler souvent et elle effectue au plus 1 pas - en fonction des consignes données.

mais c'est vrai qu'on utilise plus souvent des moteurs normaux à qui on dit simplement "tourne dans un sens ou dans l'autre" pour faire un petit véhicule qui se déplace - les pas n'étant pas super précis pour savoir où vous êtes de toutes façon puisque suivant le sol votre roue peut patiner un peu etc...

Je suis retourné sur ton lien

Composants électroniques

1 carte Arduino UNO
1 shield E/S gravity
1 capteur de distance infrarouge
2 capteurs de niveau de gris (ligne)
2 servomoteurs à rotation continue + roues

Carte Uno, ok...
Shield... perso, j'ai un ptotoshield sur Uno, après je passe tout sur nano, pas besoin de shield
Capteur IR ... la portée est naze
Capteurs niveau de gris: je découvre, à voir la précision du truc, le module a l'air large, l'émission de la led aussi, si on en met plusieurs côte à côte, pas sur que ça fonctionne.
Servos: alors là, je comprends pas l'intérêt, c'est un moteur démultiplié. Un servo sans retour de position, ça sert à quoi? Par contre à installer ça va bien, un peu de colle et hop. Je n'ai jamais joué avec ces machins, c'est peut-être bien, peut-être pas.

Je n'utilise pas de pàp, j'ai deux moteurs tout simples, je les commande directement via la carte de puissance.

 //vitesse élevée
  analogWrite(E1, 200);
  analogWrite(E2, 200);
  //marche avant
  digitalWrite(I1, HIGH);
  digitalWrite(I2, LOW);
  digitalWrite(I3, HIGH);
  digitalWrite(I4, LOW);

au fait pour le capteur à ultra-son c'est pas mal d'envisager d'utiliser NewPing

trois points que je trouve importants dans la liste des fonctionnalités

...
Ping sensors consistently and reliably at up to 30 times per second.
Timer interrupt method for event-driven sketches.
Built-in digital filter method ping_median() for easy error correction.
Uses port registers when accessing pins for faster execution and smaller code size.
Allows setting of a maximum distance where pings beyond that distance are read as no ping "clear".
...

le dernier point est important, s'il n'y a rien devant vous à 1m par exemple (ou 50cm - vous décidez) pas la peine d'attendre le retour du signal à ultrason vous pouvez continuer d'avancer

J-M-L:
au fait pour le capteur à ultra-son c'est pas mal d'envisager d'utiliser

En effet, pas mal du tout :wink:
grapille des idées

Merci beaucoup pour NewPing ! c’était ça le gros problème que j'avais, il mettais environ 1 sec a récupérer le ping et ça stoppais tout mon programme, maintenant je suis en train d'apprendre a utiliser AccelStepper :'D

Je vous tiens au courant quand j'aurai réussi ^^ merci encore pour votre aide :slight_smile:

Cool - tenez nous au courant!

Salut !

je reviens après avoir avancé sur mon programme, mais je bloque pour changer de direction les moteurs et de maintenir les tours (en pas) à effectuer.

Le programme pour le capteur

#include <NewPing.h>

#define ECHO_PIN 12 // broche Echo sur D11
#define TRIGGER_PIN 13 // broche Trigger sur D12

#define MAX_DISTANCE 100

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);

unsigned int pingSpeed = 200; // période d'envoi du "ping". Une période de 50 millisecondes correspond à 20 "pings" par seconde.
unsigned long pingTimer; // timer, pour le prochain "ping".

void setup(){
Serial.begin(115200); // moniteur Série à 115200 bauds pour afficher les résultats.
pingTimer = millis();

}
void loop(){
if (millis() >= pingTimer) { // pingSpeed milliseconds since last ping, do another ping.
pingTimer += pingSpeed; // Set the next ping time.
sonar.ping_timer(echoCheck); // Send out the ping, calls "echoCheck" function every 24uS where you can check the ping status.
}
// Do other stuff here, really. Think of it as multi-tasking.
}

void echoCheck() { // Timer2 interrupt calls this function every 24uS where you can check the ping status.
// Don't do anything here!
if (sonar.check_timer()) { // This is how you check to see if the ping was received.
// Here's where you can add code.
Serial.print("Ping: ");
Serial.print(sonar.ping_result / US_ROUNDTRIP_CM); // Ping returned, uS result in ping_result, convert to cm with US_ROUNDTRIP_CM.
Serial.println("cm");
}
// Don't do anything here!
}

Celui qui fais la marche arrière avec un moteur (juste avec un bouton)

#include <AccelStepper.h>
// Define a stepper and the pins it will use
AccelStepper stepper(4, 8,10,9,11); // Defaults to AccelStepper::FULL4WIRE (4 pins) on 2, 3, 4, 5
// This defines the analog input pin for reading the control voltage
// Tested with a 10k linear pot between 5v and GND
int btn=7;
int val1=0;
void setup()
{
Serial.begin(9600);
stepper.setMaxSpeed(600);
}
void loop()
{
val1=digitalRead(btn);
Serial.print(val1);

if(val1==0){
stepper.runSpeed();
stepper.setSpeed(500);
}
if(val1==1){
stepper.setCurrentPosition(0);
stepper.setSpeed(500);
stepper.setAcceleration(500);
stepper.runToNewPosition(-1000);
}
}

Les deux marchent très bien séparément mais je n'arrive pas à les mettre en commun (je laisse la commande avec le bouton pour tester plus efficacement) au lieu de changer de direction, il s'arrette et ne bouge plus du tout

#include <NewPing.h>
#include <AccelStepper.h>

#define ECHO_PIN 12 // broche Echo sur D11
#define TRIGGER_PIN 13 // broche Trigger sur D12

#define MAX_DISTANCE 100

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
AccelStepper stepper(4, 8,10,9,11);

unsigned int pingSpeed = 200;
unsigned long pingTimer;
int btn=7;
int val1=0;
void setup(){
pinMode(7,INPUT);
stepper.setMaxSpeed(800);
stepper.setSpeed(500);
Serial.begin(115200);
pingTimer = millis();

}
void loop(){
if (millis() >= pingTimer) {
pingTimer += pingSpeed;
sonar.ping_timer(echoCheck);
}
stepper.runSpeed();
stepper.setSpeed(500);
}

void echoCheck() {
// Don't do anything here!
if (sonar.check_timer()) {
stepper.runSpeed();
val1=digitalRead(btn);
Serial.print(val1);
if(val1==1){
stepper.setCurrentPosition(0);
stepper.setSpeed(500);
stepper.setAcceleration(500);
stepper.runToNewPosition(-1000);
}
stepper.runSpeed();
stepper.setSpeed(500);

Serial.print("Ping: ");
Serial.print(sonar.ping_result / US_ROUNDTRIP_CM);
Serial.println("cm");
}
// Don't do anything here!
}

Si vous avez des idées ou autre, je suis preneur, merci de votre aide :slight_smile: