Arduino UNO : Problème de code

Bonjour à tous,

Je suis débutant en arduino, et j'ai un moteur à faire tourner à une certaine vitesse en fonction d'une condition angulaire (récupérer grâce à un gyromètre) pour faire un gyroscope (Vmax si <-15 ou >15 sinon Vmin). Or, mon support+gyromètre+moteur oscillent autour de ces valeurs la, donc ma condition devient vraie, puis fausse, puis vraie, ect. J'aimerais donc que lorsque la condition devient vraie une fois, le moteur puisse tourner pendant 5 secondes par exemple à Vmax, avant de refaire ma boucle if. J'ai donc rajouté un Delay(5000), or mon système détecte bien l'angle et V=Vmax mais le moteur ne ralentit pas au bout des 5 secondes, et continue de tourner à Vmax sans s'arrêter.
Est-ce-que quelqu'un pourrait m'aider ?
Je ne vois vraiment pas comment faire.
Merci de votre aide.

Voici la partie de code :

if(mpu6050.getAngleY()< -15 or mpu6050.getAngleY()> 15) { //Boucle if avec condition angulaire
esc.writeMicroseconds(1500); // Si oui, alors v=Vmax
delay(5000); //Délai de 5 secondes
}

else {
esc.writeMicroseconds(1050); //Sinon, v=Vmin

}

'or' s'écrit || en C

if(mpu6050.getAngleY()< -15 || mpu6050.getAngleY()> 15)  {

C’est aussi du C ou C++ (représentation alternative)

Il en existe toute une liste

[b]Primary Alternative[/b]
&& and
&= and_eq
& bitand
| bitor
~ compl
! not
!= not_eq
|| or
|= or_eq
^ xor
^= xor_eq
{ <%
} %>
[ <:
] :>
# %:
## %:%:

Alors c'est peut-être la différence entre 1500 et 1050 qui est trop faible pour que tu voies quelque chose

Je ne connais pas le mpu6050 et je ne visualise pas le montage (ni la bibliotheque utilisée pour écrire "esc.writeMicroseconds(1500);"). Le gyroscope tourne-t-il avec le moteur ?

D'après ce que je vois, tu récupères la position angulaire du gyroscope et fais tourner le moteur. Je vois deux raison pour que le moteur continue à tourner :

  1. La vitesse du moteur est trop élevée pour qu'il arrive à s'arrêter instantanément. Il y aurait un retard à l'arrêt mais il ne tournerait pas de manière continue.

  2. La condition "(mpu6050.getAngleY()< -15 or mpu6050.getAngleY()> 15)" reste vrai malgré la rotation du moteur.

Essaie d'afficher la valeur de l'angle du gyroscope après avoir fait tourner le moteur :

if(mpu6050.getAngleY()< -15 or mpu6050.getAngleY()> 15)  {       //Boucle if avec condition angulaire
     esc.writeMicroseconds(1500);                                                 // Si oui, alors v=Vmax
         delay(5000);  //Délai de 5 secondes
     Serial.println(mpu6050.getAngleY());  //affichage de l'angle 5s après le départ du moteur                                      
}

   
else  {
     esc.writeMicroseconds(1050);                                    //Sinon,  v=Vmin
     
}

Bon, je ne sais pas si vous avez un sens de l'humour un peu spécial ou si vous êtes réellement ennuyé:

un gyroscope type MPU6050 sort une vitesse de rotation et, pour pouvoir avoir un angle, il faut integrer cette vitesse (de préférence avec des pas de temps petits).
Normalement, votre librairie (inconnue, car vous ne fournissez pas sa référence) peut intégrer avec des pas de temps tout petits ... à condition que ce soit prévu expressément et que vous lui laissiez le temps.
Si elle n'utilise pas d'interruption, elle va donc s'executer dans le fil principal, qui contient
delay(5000)
Delay étant bloquant, il y aura donc 5 secondes où elle sera incapable d'intégrer... et ce sont les 5 secondes les plus utiles...
A noter que certaine librairie
(celle que j'ai lue; si c'est la même que la votre, lier serait redondant; si ce n'est pas la même, lier serait une source de confusion)
pour MPU6050 a une fonction "update" qui permet, si elle est activée assez souvent, de mettre à jour les angles. Son appel est fortement recommandé avant getAngleXXXXX.

Ça pourrait être cette bibliothèque : MPU6050_tockn, je n'en trouve aucune autre qui dispose de la méthode getAngleY()

Il faut appeler la méthode update() dans la loop pour pouvoir calculer les angles.

Merci de vos réponses.
Il s'agit d'un stabilisateur pour bateau, dont seul le moteur avec volant d'inertie tourne (cf système : seakeeper.com). Le gyroscope (MPU) est fixé à l'horizontale par rapport au bateau et c'est en récupérant les données du gyroscope, que j'ai pu définir la condition angulaire que je veux (à savoir +15° et -15°). J'aimerais que mon moteur ne soit jamais à l'arrêt (donc soit à Vmin soit à Vmax).
Pour la question du temps, mon bateau se stabilise assez vite naturellement (<7 secondes), c'est pour cela que j'ai besoin d'une réponse quasi instantanée du moteur d'où les 5 secondes. Mon problème vient notamment du fait que ma condition reste vraie par moment, d'où le fait que j'ai utilisé delay()

Voici le code complet du système (la partie données gyroscope étant optionnelle, mais permet de voir la réaction du bateau) :

#include <MPU6050_tockn.h>
#include <Wire.h>
#include <Servo.h>

//VARIABLE MOTEUR//

Servo esc;

MPU6050 mpu6050(Wire);

long timer = 0;

void setup(){

esc.attach(9); // Pin sur lequel est connecté le hacheur (fil jaune)
esc.writeMicroseconds(1000); // Initialise la vitesse de rotation à 0
Serial.begin(9600); // Initialise la communication série à 9600 bits/s

Serial.begin(9600);
Wire.begin();
mpu6050.begin();
mpu6050.calcGyroOffsets(true);

esc.writeMicroseconds(1050); //Initialise la vitesse de rotation de base à Vmin
}

void loop(){

if(mpu6050.getAngleY()< -15 or mpu6050.getAngleY()> 15) {
esc.writeMicroseconds(1500);
delay(5000);
}

else {
esc.writeMicroseconds(1050);

}

mpu6050.update();

if(millis() - timer > 1000){ //Boucle permettant de récupérer les données du gyroscope toute les 1 secondes

Serial.println("=======================================================");
Serial.print("temp : ");Serial.println(mpu6050.getTemp());
Serial.print("accX : ");Serial.print(mpu6050.getAccX());
Serial.print("\taccY : ");Serial.print(mpu6050.getAccY());
Serial.print("\taccZ : ");Serial.println(mpu6050.getAccZ());

Serial.print("gyroX : ");Serial.print(mpu6050.getGyroX());
Serial.print("\tgyroY : ");Serial.print(mpu6050.getGyroY());
Serial.print("\tgyroZ : ");Serial.println(mpu6050.getGyroZ());

Serial.print("accAngleX : ");Serial.print(mpu6050.getAccAngleX());
Serial.print("\taccAngleY : ");Serial.println(mpu6050.getAccAngleY());

Serial.print("gyroAngleX : ");Serial.print(mpu6050.getGyroAngleX());
Serial.print("\tgyroAngleY : ");Serial.print(mpu6050.getGyroAngleY());
Serial.print("\tgyroAngleZ : ");Serial.println(mpu6050.getGyroAngleZ());

Serial.print("angleX : ");Serial.print(mpu6050.getAngleX());
Serial.print("\tangleY : ");Serial.print(mpu6050.getAngleY());
Serial.print("\tangleZ : ");Serial.println(mpu6050.getAngleZ());
Serial.println("=======================================================\n");
timer = millis();

}
}

Donc quand vous êtes dans le délai de 5s, vous n’appelez plus mpu6050.update();

Avez vous un lien vers votre carte ?

Il ne faut généralement pas appeler délai, utiliser millis() et/ou la programmation par machine à états (cf mon tuto éventuellement)

====
corrigez votre post ci dessus et rajoutez les code tags autour du code:
[code]`` [color=blue]// votre code ici[/color] ``[/code].

ça doit ressembler à cela:// votre code ici
(faites aussi ctrl-T (PC) or cmd-T (Mac) dans l’IDE avant de copier le code pour qu’il soit indenté correctement)

Voici votre code formatté -par astyle-, emballé pour les utilisateurs de "smart" "phones" et avec des commentaires de mon cru (3)

#include <MPU6050_tockn.h>
#include <Wire.h>
#include  <Servo.h>

//VARIABLE MOTEUR//

Servo esc;

MPU6050 mpu6050(Wire);

long timer = 0;

void setup() {

    esc.attach(9); // Pin sur lequel est connecté le hacheur (fil jaune)
    esc.writeMicroseconds(1000);  // Initialise la vitesse de rotation à 0
    Serial.begin(115200); // Initialise la communication série à 115200 bits/s (9600 peut générer des blocages, buggant la liaison de debugging

    Serial.begin(9600); // NON NON

    Wire.begin();
    mpu6050.begin();
    mpu6050.calcGyroOffsets(true);

    esc.writeMicroseconds(1050);  //Initialise la vitesse de rotation de base à Vmin
}

void loop() {

    if (mpu6050.getAngleY()< -15 or mpu6050.getAngleY()> 15)  {
        esc.writeMicroseconds(1500);
        delay(5000); // c'est là ligne très criticable
    }   else  {
        esc.writeMicroseconds(1050);
 }

    mpu6050.update();

    if(millis() - timer > 1000) {              //Boucle permettant de récupérer les données du gyroscope toute les 1 secondes

        Serial.println("=======================================================");
        Serial.print("temp : ");
        Serial.println(mpu6050.getTemp());
        Serial.print("accX : ");
        Serial.print(mpu6050.getAccX());
        Serial.print("\taccY : ");
        Serial.print(mpu6050.getAccY());
        Serial.print("\taccZ : ");
        Serial.println(mpu6050.getAccZ());

        Serial.print("gyroX : ");
        Serial.print(mpu6050.getGyroX());        Serial.print("\tgyroY : ");
        Serial.print(mpu6050.getGyroY());
        Serial.print("\tgyroZ : ");
        Serial.println(mpu6050.getGyroZ());

        Serial.print("accAngleX : ");
        Serial.print(mpu6050.getAccAngleX());
        Serial.print("\taccAngleY : ");
        Serial.println(mpu6050.getAccAngleY());

        Serial.print("gyroAngleX : ");
        Serial.print(mpu6050.getGyroAngleX());
        Serial.print("\tgyroAngleY : ");
        Serial.print(mpu6050.getGyroAngleY());
        Serial.print("\tgyroAngleZ : ");
        Serial.println(mpu6050.getGyroAngleZ());
        Serial.print("angleX : ");
        Serial.print(mpu6050.getAngleX());
        Serial.print("\tangleY : ");
        Serial.print(mpu6050.getAngleY());
        Serial.print("\tangleZ : ");
        Serial.println(mpu6050.getAngleZ());
        Serial.println("=======================================================\n");
        timer = millis();

    }
}

a) vu la taille de vos impressions (vont crer un goulot d'etranglement), passez en 115200 bauds.
b) le delay (5000) bloque complètement le programme (et rend toute evolution délicate, pour être très optimiste: si vous rajoutez un feu clignotant à votre bateau, je vous garantis des souffrances atroces)
Pour éviter de telles horreurs, vous devriez commencer par lire l'exemple minimaliste blinkWithoutDelay quiest dans votre IDE -20 lignes au grand maximum, commentaires sensés inclus-
Ceet exemple minimaliste est, IIRC, un prerequis pour la lecture de l'excellent tutorial de JML, qu'il a eu bien raison de citer en post précedent .

Autant déclarer la variable timer en 'unsigned long', ça ne peut pas faire de mal

Ensuite, en effet les différents delay font que l'intégration qui permet de calculer l'angle se perd, car l'update n'est pas fait assez régulièrement.

Une machine à états est une bonne solution pour ce genre de projet. Si tu ne veux pas te lancer dans un changement de code trop complexe, il suffit de créer une variable 'vitesse' qui prendrait les valeurs 1050 ou 1500 selon la valeur d'angle que fournit le MPU.

Si je comprends bien, tu veux juste respecter une temporisation de 5 secondes après un changement de vitesse pour laisser le temps au moteur de se stabiliser ? Dans ce cas, tu crées un booléen (par exemple vitesseChange) qui sera à true immédiatement après un changement de vitesse et qui pilotera une temporisation de 5 secondes avant de revenir à false. Si le booléen est true, alors tu interdis un nouveau changement de vitesse.

Bon, il n'y a qu'un delay explicite (mais enorme: 5 seconde) dans le code de Monsieur ADjar.

La librairie fournie (et, en passant, merci de m'avoir épargné de rechercher dans github et le ouaibe toutes ses éventuelles moutures de cette librairie) n'utilise que deux fois des delays bloquants, au demarrage, ce qui n'est pas gênant.
Reste un delay implicite: transmettre, toutes les secondes, 300 caractères à 9600 bauds prend 0.3 secondes (300 millisecondes) et c'est déjà beaucoup.... 30 millisecondes serait mieux (et je n'ai estimé "que" les temps de transmission du texte fixe, pas celui des valeurs!)
En 5 secondes, la vitesse de rotation du moteur a pu fluctuer sans aucun contrôle.

La seconde solution (avoir un booleen qui indique si on est en train de changer de vitesse ou pas; si on est en train de changer de vitesse, on se contente de mettre à jour les positions, sans chercher à contrôler quoi que ce soit) ne nécessite pas des changements de code énormes.