Servomoteurs démarrés aléatoirement

Bonjour,
J'ai comme projet un placard comprenant de nombreuses portes qui s'ouvriraient de manière aléatoire.
Une porte s'ouvre, reste ouverte quelques secondes, puis se ferme et une autre s'ouvre, ainsi de suite.
Les Servomoteurs seraient choisis par la fonction Random.
Je découvre Arduino et l'essai de programme ci-joint doit comporter des erreurs de conception, car rien ne se passe.
Pouvez-vous m'éclairer sur ce sujet, merci.

#include <Servo.h>

Servo myservo;

int data;
int pos = 0;`Texte préformaté`

void setup()
{
Serial.begin(9600);
myservo.attach(data);

}

void loop()
{

data = random(6,11);

Serial.println(data);
delay(1000);

for (pos = 0; pos <= 180; pos += 1)
myservo.write(pos);

delay(10);

for (pos = 180; pos >= 0; pos -= 1)
myservo.write(pos);

delay(10);
}

Modifiez la ligne de configuration :

myservo.attach(data);

à l'intérieur de la loop

void loop() {
data = random(6,11);
myservo.attach(data);

Lorsque tu fais ça dans setup()

tu n'as encore pas donné de valeur à data comme c'est une variable globale elle vaut 0.

Dans loop cette affectation ne va pas changer le servo utilisé.

Ta boucle s'exécute à toute vitesse car le delay() n'est pas dans la boucle. Il manque des accolades.

Il faudrait faire

for (pos = 0; pos <= 180; pos += 1){
  myservo.write(pos);
  delay(10);
}

Il est préférable d'attacher les servos une bonne fois pour toute dans le setup() et de ne plus les détacher pour éviter des mouvements aléatoires lorsqu'on les rattache.
Si les servos doivent fonctionner sur une zone limitée de leur course, il est prudent de fournir les valeurs min et max dans attach(). voir ici:
https://www.arduino.cc/reference/en/libraries/servo/attach/

Personnellement je ferais un truc dans ce genre là (pas testé):

#include <Servo.h>

// On suppose que les servos sont au nombre de 6 branchés de la pin D6 à D11
Servo mesServos[6];

void setup() {
  for (byte i = 0; i<5; i++){
    mesServos[i].attach(i + 6);
  }
  randomSeed(analogRead(A0) + micros()); // un semblant de hasard pour ne pas avoir toujours la même séquence

}

void bougeServo (Servo unServo){
  for (int pos =  0; pos <= 180; pos += 1){
    unServo.write(pos);
    delay(10);
  }
  for (int pos = 180; pos >= 0; pos -= 1){
    unServo.write(pos);
    delay(10);
  }
}

void loop() {
  int data = random(6,11);

  Serial.println(data);
  delay(1000);

  bougeServo(mesServos[data]);

}
1 Like

Bonjour,
merci messieurs pour l'attention apporté à mes difficultés de codage pour faire fonctionner les servomoteurs en aléatoire.
Je suis allé sur Tinkercad essayer le code proposé, mais au démarrage de la simulation, j'ai quelques messages d'alerte concernant "bougeServo" et aussi de déclaration manquante de "Servo".
Je vous transmets le lien pour votre précieux aide, merci d'avance.

Bonjour,

Apparemment il y a un bug dans tinkercad. Le compilateur ne reconnait pas la class Servo dans la déclaration de bougeServo().
En précisant explicitement que c'est une class, ça semble fonctionner:
void bougeServo(class Servo unServo){

Remarque:
Il y a un bug ici
int data = random(6, 11);
ce doit être
int data = random(0, 6);

1 Like

Bonjour chers soutiens,
Grâce à votre aide, je suis enfin arrivé à faire fonctionner 6 servomoteurs en aléatoire sur une carte Arduino Uno.
Et aussi avec Module d'extension de capteur NANO e/s IO, pour Arduino UNO R3 Nano V3.0 3.0 c !
Encore merci et à bientôt pour votre aide précieuse.

Bonjour,
je reviens vers vous, car je ne suis pas au bout de ma programmation.

1/ je souhaiterais avoir un délai entre les étapes d'ouverture et de fermeture des servomoteurs. J'ai tenté ce programme, mais j'ai un message d'erreur.

Servomoteurs_al_atoire_temporisation.ino (1,3 Ko)

2/ Là dans les essais, je suis avec 6 servomoteurs, mais dans mon projet, c'est 20 (ou 40) commandés par un seul programme... Comment ça se passe pour attribuer 20 services ou plus ?

Merci pour votre aide.

Bonsoir 42david

Il faudrait t'orienter du côté du PCA9685


Tu peux les chaîner et ça te simplifiera le câblage.

Cordialement
jpbbricole

1 Like

Bonjour 42david

Essaies ce programme,
ARDFR_42david_Servo.ino (1.5 KB)

une des modifications apportée est la mise en tableau des pin des servo (mesServoPin[]), ainsi, il ne sera plus nécessaire que ces pin soient contiguës, tu pourras les "piquer" n'importe où dans les pin disponibles. Avec ce tableau, l'extension de ton programme sera plus aisée.
Ainsi, pour étendre le nombre de servo, il suffit d'en mettre le port dans le tableau mesServoPin[].
J'ai ajouté quelques variables pour te faciliter le travail.

Au départ, tout les servo sont mis sur fermé

	for (byte s = 0; s < ServoNombre; s++)
	{
		mesServos[s].attach(mesServoPin[s]);     // Initialisation du servo s
		mesServos[s].write(pos_ferme);;     // Servo s sur fermeture
	}

A+
Cordialement
jpbbricole

1 Like

Merci Jpbbricole, les servomoteurs fonctionnent aux petits oignons !

Bonjour 42david

Super!

Su tu passes au PCA9685, dis le moi, je te donnerai un coup de main si nécessaire.

Cordialement
jpbbricole

Bonjour,
mon projet fonctionne grâce à vos soutiens . Actuellement les servomoteurs sont raccordés sur un module pour Nano Arduinode de 13 servomoteurs.
Je voudrais passer au PCA9685 comme encouragé. Je me pose la question fatidique, en plus de nouvelle bibliothèque pour prendre en charge le PCA9685 faut-il changer le code pour le programme
ARDFR_42david_Servo.ino (1.5 KB)
-Est-ce que je pourrais utiliser une source de type courante :Transformateur d'alimentation secteur 5V-15V 3 A.
Merci pour vos lumières,
Cordialement David

Bonsoir 42david

Oui, en le réglant sur 5V :wink: et tu le connectes sur les bornes du PCA9685
image
Je de donne la version PCA9685, tu verra, le fond du code ne change pas beaucoup, tu peux chaîner les PCA en indiquant leur adresse en soudant les ponts idoines.
image
Le premier PCA (No. 0) n'a pas de pont, le 2ème (No. 1) a A0 de soudé le 3ème (No.2) a A1 de soudé et ainsi de suite (c'est du comptage binaire)
Tu peux chaîner 64 PCA9685, de quoi voire venir!

Le reste des explications sont dans le programme.

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>     // https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library

// Ce tableau contient les pin des hub utilisées, le 2ème hub a A0 ponté
// La numérotation débute à 0 (hub 0) le hub 1 débute à 16 et ainsi de suite, 
const int mesServoPin[] = {3, 11, 16, 27};
const int ServoNombre = sizeof(mesServoPin)/sizeof(mesServoPin[0]);

Adafruit_PWMServoDriver servoHub[] =
{
	Adafruit_PWMServoDriver(0x40),     // Servos de 0-15
	Adafruit_PWMServoDriver(0x41),     // Servos de 16-31
};
const int servoHubNombre = sizeof(servoHub) / sizeof(servoHub[0]);

//-------------------------------------A régler en fonction des servo utilisés
const word servoPulseMin =  125;     // Impulsion minimum
const word servoPulseMax =  575;     // Impulsion maximum

int pos = 0;
int pos_ferme =5;
int pos_ouverte = 120;
int servoHazard = 0;
int pos_ferme_Delay = 30;
int pos_ouverte_Delay = 30;

void setup()
{
	Serial.begin(9600);
	//--------------------------------- Initialisation hub servo
	for (int h = 0; h < servoHubNombre; h ++)
	{
		servoHub[h].begin();
		servoHub[h].setPWMFreq(60);  // Analog servos run at ~60 Hz updates

		servoHub[h].setPWMFreq(60);  // Analog servos run at ~60 Hz updates
	}

	randomSeed(analogRead(A0) + micros()); // un semblant de hasard pour ne pas avoir toujours la même séquence
}


void loop()
{
	servoHazard = mesServoPin[random(0,ServoNombre)];     // Choix d'un servo "au hazard"

	servoOuverture(servoHazard);
	delay(1500);     //temporisation entre l'ouverture et la fermeture
	servoFermeture(servoHazard);
	delay(3000);     //temporisation avant le servo suivant
}

void servoOuverture(int servoNum)
{
	Serial.println("Servo : Ouvrir servo " + String(servoNum));

	for (int pos = pos_ferme ;pos <=pos_ouverte; pos++)
	{
		servoMouvement(servoNum, pos);

		delay(pos_ouverte_Delay);
	}
}

void servoFermeture(int servoNum)
{
	Serial.println("Servo : Fermer " + String(servoNum));

	for (int pos = pos_ouverte; pos >= pos_ferme; pos--)
	{
		servoMouvement(servoNum, pos);

		delay(pos_ouverte_Delay);
	}
}

void servoMouvement(int servoNum, int servoPosition)
{
	//Serial.print("\tServo HUB: " + String(servoNum / 16));
	//Serial.println("\tSlot : " + String(servoNum % 16));

    servoHub[servoNum / 16].setPWM(servoNum % 16, 0, angleToPulse(servoPosition));
}

word angleToPulse(int angle)
{
	return map(angle,0, 180, servoPulseMin, servoPulseMax);     // map angle of 0 to 180 to Servo min and Servo max
}

En principe tu n'as que ça à régler:

//-------------------------------------A régler en fonction des servo utilisés
const word servoPulseMin =  125;     // Impulsion minimum
const word servoPulseMax =  575;     // Impulsion maximum

Amuses toi bien et pose les bonnes questions :wink:

A+
Cordialement
jpbbricole

Bonjour,
Merci pour ton aide précieuse. Ma carte Nano ne repond plus sur mon projet de portes et le PCA9685 devrait être la solution:

  • Bibliothèque adafruit ok
  • Modification imputions 1500/2500 pour servomoteur DS3115
  • Programme téléversé sur carte Uno ok
  • Branchement GND SCL SDA et VCC avec leur vis à vis
  • Le courant passe
  • Le moteur d'essai ne fonctionne pas !
  • Essai sur un autre carte PCA9685, vérification moteur, rien ne bouge.

Bonjour 42david

Mets ton programme en ligne.

PS: Fais un test pour contrôler si ton Arduino "voit" ton PCA9685, charges ce programme, un scanner i2C, et, avec ton moniteur série à 9600 tu dois voir:

Scanning...
I2C device found at address 0x40  !
I2C device found at address 0x70  !
done

Preuve que ton bus i2C fonctionne.

Cordialement
jpbbricole

Bonjour jbbbricole

la réponse au scanner de la carte PCA9685 est correcte :
I2C device found at address 0x40 !
done

Voici le programme qui a tout pour fonctionner. Les étapes de fermeture et d'ouverture sont bien indiquées dans l'exécution. Pourtant quand le programme tombe sur la broche où se trouve le servomoteur pour le test, rien ne se passe.

PCA9685.ino (2,8 Ko)

Cordialement,
David

Bonjour 42david

J'ai essayé le programme mais avec mes valeurs, ça fonctionne

const word servoPulseMin =  125;     // Impulsion minimum
const word servoPulseMax =  575;     // Impulsion maximum

Tes paramètres:

const word servoPulseMin =1500;     // Impulsion minimum
const word servoPulseMax =2500;     // Impulsion maximum

me semblent 10* trop hauts.

Une toute belle journée
Cordialement

Bonjour jpbbricole,
La solution pour que le courant passe a été de rajouter un cinquième fil reliant la carte Uno à la carte PCA9685 de la broche Vin à V+.
Le programme est au top, mais il y a un bug. Au bout de cinq, dix minutes, le programme cafouille et s'arrête. Est-ce dû à des interférences, car les câbles sont asses proches ou dois-je rehausser les impulsions... ou autre chose.
Cordialement,
David

Bonjour David

Ca "sent" le composant qui chauffe!
Avec quoi alimentes tu tes servo (bornier à vis) et comment est alimenté l'Arduino.

???
Regardes ici pour le câblage.

Cordialement
jpbbricole

Le courant vient de l'alimentation de la carte Uno qui est relié à un transformateur de type smartphone de 5v- 2 A.
Si je ne rajoute pas ce cinquième fil (vin/v+) je n'ai que 1v en sortie.