Bateau autonome Coller aux parois d'une piscine 1/2

Oui c'est cela.
c'est vrai qu'un dessin vaux mieux qu'un long discours :slight_smile:

voici mon essai

void loop() {
  
  if ((millis() - startMillis >= 0 * 60 * 1000L)&& (millis() - startMillis < 10 * 60 * 1000L)) 
{ // < entre 0 et 10 minutes dès le départ le bateau bouge aléatoirement
    startMillis = millis();
aleatoire();
  }

 if ((millis() - startMillis >= 10 * 60 * 1000L)&& (millis() - startMillis < 20 * 60 * 1000L)) 
{ // vrai si 10mn<  millis <20 minutes, on lance bordure
      startMillis = millis();
      bordures();
    }
else 
 { // faux si  millis< 10 minutes donc on retourne dans aléatoire en attendant de dépasser 20 mn
      startMillis = millis();
      aleatoire();
    }


 if ((millis() - startMillis > 20 * 60 * 1000L)) // millis est > à 20 mn
{ startMillis = millis(); // le cycle est terminé, temps initial mis à jour
    }


ultrasons ();
delay (100);
}

Une question basique

Ce ne serait pas plus simple en utilisant deux tempo par 2 rheostat ?
on pourrait ainsi changer les temps sans reprogrammer ?

ce n'est juste qu' une question.

Maintenant, en oubliant la première branche de gauche, on voit ceci :

  • de 0 à 10 minutes : aléatoire
  • de 10 à 20 minutes : bordure
  • au delà de 20 minutes : aléatoire puis bordure (en boucle)

Je n'ai pas précisé mais dans le troisième cas on a aléatoire immédiatement suivi de bordure. Pour l'Arduino, "immédiatement" signifie qu'on en voit rien, ça va trop vite pour nous. Donc le troisième point est pratiquement équivalent à bordure uniquement.

C'est pourquoi je posais cette question, car ça me parait bizarre.

Je te propose ça :

  • la variable startMillis doit être globale, pour l'accéder dans la loop ET le setup
  • tu l'initialises dans le setup : startMillis = millis();
  • puis la loop :
void loop () {
  long tempsEcoule = millis() - startMillis;
  if (tempsEcoule < 10000) aleatoire();
  else if (tempsEcoule < 20000) bordure();
  else startMillis = millis();
}

Je pense que ça ça fera "aleatoire" pendant 10 minutes, puis "bordure" pendant 10 minutes, et reviendra au début ("aleatoire" pendant 10 minutes, puis "bordure" pendant 10 minutes, etc).

C'est tout simple : tu peux le tester avec des valeurs de temporisation plus courtes (genre 60 et 120 au lieu de 10000 et 20000) et voir si ça marche. Ensuite, tu peux le complexifier comme tu veux.

Comment gères-tu la distance ? Ça n’apparaît pas dans ton diagramme .

Je pensais que la distance était gérée par les ultrasons !? avec if cm < 15 cm dans
les fonctions aléatoires et ultrasons

dans la fonction bordure j'utiliserai cela
if( (buttonState==HIGH) && (cm<=15) ) ... // contact ET ultrason, le bateau met en route le moteur coté bord pour s'en écarter un peu
Puis
if( (buttonState==HIGH) && !(cm<=15) ) ... // contact sans ultrason le bateau met en route le moteur coté inverse du bord pour se plaquer contre ce bord
mais je mets cm< 5cm
C'est possible de passer de 15 à 5 cm de détection dans cette fonction ?

PS : erreur dans la console
exit status 1
'bordure' was not declared in this scope

PS bis : mon code était presque bon :slight_smile:

/*
  This code corresponds to a floating boat with rudimentary sensing capabilities -
  step by step instructions and images are at levinegabriella.com/teaching
  It includes an parallax ultrasonic rangefinder : see data sheet
  http://www.arduino.cc/en/Tutorial/Ping
  which allows the boat to turn away from obstacles ahead.
  It also includes two reed switches so if it hits barriers from the side, it
  turns around away from the wall
  created 2011 by gabriella levine
*/


/*
  En C/C++ un ET logique se note &&. Un OU logique se note ||. La négation se note !. Donc cela ressemblera à :
  if( (buttonState==HIGH) && (cm<=15) ) ... // contact ET ultrason
  if( (buttonState==HIGH) && !(cm<=15) ) ... // contact sans ultrason
  Remarque : pour le dernier cas on peut écrire if( (buttonState==HIGHT) && (cm>15) ) ... // contact sans ultrason
*/

// constants
// set pin numbers:
const int pingPin = 7;
const int DetecteurPin1 = 2; // the number of the pushbutton pin  Le numéro de l'épingle à commande automatique(presse-bouton)
const int DetecteurPin2 = 4;
const int moteur1 = 3; // the number of the motor pin    le (numéro l'épingle du moteur
const int moteur2 = 11;
//
//**************************************************************************************************
const int pompe = 10; // declaration pompe au pin 10 ********************************************
//**************************************************************************************************

// variables
int BtnContact = 0; // variable for reading the pushbutton status     variable pour lire le statut du 1er bouton de contact
int BtnContact1 = 0; //

// Variable globale pour faire le décompte du temps
unsigned long startMillis; // à 0 par défaut
long cm = 0;


//variable pour lire le statut du 2 ieme bouton de contact
void setup() {
  //begin serial
  Serial.begin(9600);
  // initialise  les pin moteurs à OUTPUT, soit éteint
  pinMode(moteur1, OUTPUT);
  pinMode(moteur2, OUTPUT);
  // initialise les boutons contact pins à INPUT, soit actif:
  pinMode(DetecteurPin1, INPUT);
  pinMode(DetecteurPin2, INPUT);

  //**************************************************************************************************
  // initialize the pump pins as output:   au démarrage la pompe ne marche pas ***********************
  pinMode(pompe, OUTPUT);
  // *************************************************************************************************
  //
}
void loop() {
   // dès le départ le bateau bouge aléatoirement
  long tempsEcoule = millis() - startMillis;
  if (tempsEcoule < 10000) aleatoire();
  else if (tempsEcoule < 20000) bordure();
  else startMillis = millis();
  ultrasons ();
delay (100);
}





//******
//******
//******

void button() {
  // vérifie si les boutoncontact sont actifs(HIGH), si oui le moteur passe à actif(HIGH) ou éteint(LOW) selon le programme
  if (BtnContact1 == HIGH) {
    // turn LED on:
    digitalWrite(moteur1, LOW);
    //
    //**************************************************************************************************
    // si le bouton touche le bord la pompe fonctionne *************************************************
    digitalWrite(pompe, HIGH);
    //**************************************************************************************************
  }
  else {
    // turn LED off:
    digitalWrite(moteur1, HIGH);
    //
    //**************************************************************************************************
    // sinon pas de contact la pompe stoppe ************************************************************
    digitalWrite(pompe, LOW);
    //**************************************************************************************************
  }
  if (BtnContact == HIGH) {
    // turn LED on:
    digitalWrite(moteur2, LOW);
    //
    //**************************************************************************************************
    // si le bouton touche le bord la pompe fonctionne *************************************************
    digitalWrite(pompe, HIGH);
    //**************************************************************************************************
  }
  else {
    // turn LED off:
    digitalWrite(moteur2, HIGH);
    //
    //**************************************************************************************************
    // sinon pas de contact la pompe stoppe ************************************************************
    digitalWrite(pompe, LOW);
    //**************************************************************************************************
  }
}


void ultrasons() {

  // establish variables for duration of the ping,
  // and the distance result in inches and centimeters:
  long duration, inches, cm;
  // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
  // Give a short LOW pulse beforehand to ensure a clean HIGH pulse.
  //Le PING))) est déclenché par un contact de 2 ou plusieurs micro-secondes.
  //Donnez une impulsion ETEINT courte à l'avance pour assurer une impulsion MARCHE propre
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);
  /*
    le même pin est utilisé pour lire le signal du PING))) : impulsion
    dont la durée est le temps (en micro-secondes) de l'émission
    du Ping à la réception de son écho sur un objet.
  */
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);
  cm = microsecondsToCentimeters(duration);

}

void aleatoire() {

  if (cm <= 15) {
    //digitalWrite(moteur, LOW);
    digitalWrite(moteur2, LOW);
    //
    //**************************************************************************************************
    // à moins de 15 cm la pompe fonctionne ************************************************************
    digitalWrite(pompe, HIGH);
    //**************************************************************************************************
  }
  else {
    //digitalWrite(moteur, HIGH);
    digitalWrite(moteur2, HIGH);
    //
    //**************************************************************************************************
    // sinon à plus de 15 cm la pompe stoppe ***********************************************************
    digitalWrite(pompe, LOW);
    //**************************************************************************************************
    button();
  }
}

void bordures() {
  /*
    En C/C++ un ET logique se note &&. Un OU logique se note ||. La négation se note !. Donc cela ressemblera à :
    if( (buttonState==HIGH) && (cm<=5) ) ... // contact ET ultrason
    if( (buttonState==HIGH) && !(cm<=5) ) ... // contact sans ultrason
    Remarque : pour le dernier cas on peut écrire if( (buttonState==HIGHT) && (cm>5) ) ... // contact sans ultrason
  */
}



//******
//******
//******

long microsecondsToCentimeters(long microseconds)
{
  /*
    La vitesse du son est 340 m/s ou 29 micro-secondes par centimètre.
    Le tintement voyage d'et en arrière, ainsi trouver la distance de le
    L'objet nous prenons la moitié de la distance a voyagé.
  */
  return microseconds / 29 / 2;
}

ArduinoFree:
Je pensais que la distance était gérée par les ultrasons !? avec if cm < 15 cm dans les fonctions aléatoires et ultrasons

OK, ça n'apparaissait pas dans ton diagramme, d'où ma question

dans la fonction bordure j'utiliserai cela
if( (buttonState==HIGH) && (cm<=15) ) ... // contact ET ultrason, le bateau met en route le moteur coté bord pour s'en écarter un peu
Puis
if( (buttonState==HIGH) && !(cm<=15) ) ... // contact sans ultrason le bateau met en route le moteur coté inverse du bord pour se plaquer contre ce bord
mais je mets cm< 5cm
C'est possible de passer de 15 à 5 cm de détection dans cette fonction ?

Oui, il suffit de tester, mais a priori OK

ArduinoFree:
PS : erreur dans la console
exit status 1
'bordure' was not declared in this scope

PS bis : mon code était presque bon :slight_smile:

c'est de ma faute, ta fonction s'appelle bordures() avec un 's' : change l'appel dans la loop.

Dernier point, tu devrais mettre l'appel à ultrasons() avant le test de la loop, donc en première ligne. Ça initialisera la distance.

Voilou

void loop() {
  // dès le départ le bateau bouge aléatoirement et la fonction ultrasons est lancée
  ultrasons ();
  long tempsEcoule = millis() - startMillis;
  if (tempsEcoule < 10000) aleatoire();
  else if (tempsEcoule < 20000) bordures();
  else startMillis = millis();
  
delay (100);
}

Merci pour vos aides

Je vais maintenant coder la partie bordures et je reviens vous voir.
ensuite Attendre 2 à 3 semaines pour recevior tous les élément pour faire le montage :frowning: :frowning:

OK, bonne continuation ! :slight_smile:

Bien joué à tous les 2 :clap: ! Si tu reçois l'arduino et la plaque d'essais rapidement tu pourras peut-être "simuler" l'ensemble avec 2 leds et 2 résistances de 220 Ohms (pour les moteurs) et 3 interrupteurs (les 2 contacts+le détecteur ultrason).

A+

Unr question sur les moteurs électriques et mettre en pause après 1 heure de fonctionnement

Actuellement le code fait tourner en permanence les 2 moteurs électriques.
Ne risquent ils pas de chauffer ?

C'est pour cela que je pensais faire une tempo : le cycle tourne pendant 1 heure puis pause 15 mn
par une fonction nommée 'pause'

Mais la fonction millis remet le compteur temps à 0 au bout de 20 mn non ?
Par contre je ne sais pas où mettre la durée de 15 mn pour pause ().

dois-je créé une autre variable de temps ?
long tempsEcouleAvantPause = millis() - startMillis;

void loop() {
  // dès le départ le bateau bouge aléatoirement et la fonction ultrasons est lancée
  ultrasons ();
  long tempsEcoule = millis() - startMillis;
  if (tempsEcoule < 10000) aleatoire();
  else if (tempsEcoule < 20000) bordures();
  else if (tempsEcouleAvantPause < 60000) pause(); // après 60 mn de fonctionnement mise en pause
  else startMillis = millis();
  
delay (100);
}

void pause () {
digitalWrite(moteur1, LOW);
digitalWrite(moteur2, LOW);
}
}

Ça dépend de ce que tu appelles une pause. Si pendant la pause le bateau ne doit vraiment rien faire, tu peux mettre un delay (ou plusieurs les uns à la suite des autres, le tout dans une fonction, maintenant tu connais bien ça) mais si le bateau doit réagir à une mesure capteur, il faut faire une boucle avec millis en surveillant le capteur.

Le bateau ne doit rien faire donc delay.

void loop() {
  // dès le départ le bateau bouge aléatoirement et la fonction ultrasons est lancée
  ultrasons ();
  long tempsEcoule = millis() - startMillis;
  if (tempsEcoule < 10000) aleatoire();
  else if (tempsEcoule < 20000) bordures();
  else if (tempsEcouleAvantPause < 60000) pause(); // après 60 mn de fonctionnement mise en pause
  else startMillis = millis();
  
delay (100);
}

void pause () {
delay (900 000);  //    15 mn soit  15 *60*1000(milli secondes)
}
}

Je pense que tu devrais ajouter un startMillis = millis(); après le delay

Je ne comprends pas mon erreur

expected ')' before numeric constant au niveau du Delay de 'pause'

void loop() {
  // dès le départ le bateau bouge aléatoirement et la fonction ultrasons est lancée
  ultrasons ();
  long tempsEcoule = millis() - startMillis;
  long tempsEcouleAvantPause = millis() - startMillis;
  if (tempsEcoule < 10000) aleatoire();
  else if (tempsEcoule < 20000) bordures();
  else if (tempsEcouleAvantPause < 60000) pause(); // après 60 mn de fonctionnement mise en pause
  else startMillis = millis();

  delay (100);
}

void pause () {
  delay (900 000);  //    15 mn soit  15 *60*1000(milli secondes)
  startMillis = millis();
}

Pas d'espace entre 900 & 000

Merci

J'ai ma fonction bordure mais avec cette erreur

expected identifier before '(' token à la ligne
if ( BtnContact2) && (cm <= 5)) { //contact ET ultrason : le bateau est dans un angle ou arrondi détecté par ultrasons

Je ne comprends pas car les parenthèses, accolades me semblent bonnes ?

void bordures() {
  /*
    En C/C++ un ET logique se note &&. Un OU logique se note ||. La négation se note !. Donc cela ressemblera à :
    if( (buttonState==HIGH) && (cm<=5) ) ... // contact ET ultrason
    if( (buttonState==HIGH) && !(cm<=5) ) ... // contact sans ultrason
    Remarque : pour le dernier cas on peut écrire if( (buttonState==HIGHT) && (cm>5) ) ... // contact sans ultrason
  */

  if ( BtnContact1) && (cm <= 5)) { // contact ET ultrason : le bateau est dans un angle ou arrondi détecté par ultrasons
    digitalWrite(moteur1, LOW);
    digitalWrite(moteur2, HIGH);
    //  la pompe fonctionne ************************************************************
    digitalWrite(pompe, HIGH);
  }

  if ( BtnContact2) && (cm <= 5)) { //contact ET ultrason : le bateau est dans un angle ou arrondi détecté par ultrasons
  digitalWrite(moteur1, HIGH);
    digitalWrite(moteur2, LOW);
    //  la pompe fonctionne ************************************************************
    digitalWrite(pompe, HIGH);
  }

  if ( BtnContact1) && !(cm <= 5)) { //contact SANS ultrason : le bateau est collé à un bord et le suit
  digitalWrite(moteur1, HIGH);
    digitalWrite(moteur2, LOW);
    //  la pompe fonctionne ************************************************************
    digitalWrite(pompe, HIGH);
  }

  if ( BtnContact2) && !(cm <= 5)) { //contact SANS ultrason : le bateau est collé à un bord et le suit
  digitalWrite(moteur1, LOW);
    digitalWrite(moteur2, HIGH);
    //  la pompe fonctionne ************************************************************
    digitalWrite(pompe, HIGH);
  }
  button();
}

Non, vérifie mieux, il y des erreurs. En fait seuls les deux premiers tests sont bons :slight_smile:
Il te manque des ( au début

Effectivement j'ai oublié la double parenthèse à chaque if :frowning:

void bordures() {
  /*
    En C/C++ un ET logique se note &&. Un OU logique se note ||. La négation se note !. Donc cela ressemblera à :
    if( (buttonState==HIGH) && (cm<=5) ) ... // contact ET ultrason
    if( (buttonState==HIGH) && !(cm<=5) ) ... // contact sans ultrason
    Remarque : pour le dernier cas on peut écrire if( (buttonState==HIGHT) && (cm>5) ) ... // contact sans ultrason
  */

  if ( (BtnContact1) && (cm <= 5)) { // contact ET ultrason : le bateau est dans un angle ou arrondi détecté par ultrasons
    digitalWrite(moteur1, LOW);
    digitalWrite(moteur2, HIGH);
    //  la pompe fonctionne ************************************************************
    digitalWrite(pompe, HIGH);
  }

  if ( (BtnContact2) && (cm <= 5)) { //contact ET ultrason : le bateau est dans un angle ou arrondi détecté par ultrasons
  digitalWrite(moteur1, HIGH);
    digitalWrite(moteur2, LOW);
    //  la pompe fonctionne ************************************************************
    digitalWrite(pompe, HIGH);
  }

  if ( (BtnContact1) && !(cm <= 5)) { //contact SANS ultrason : le bateau est collé à un bord et le suit
  digitalWrite(moteur1, HIGH);
    digitalWrite(moteur2, LOW);
    //  la pompe fonctionne ************************************************************
    digitalWrite(pompe, HIGH);
  }

  if ( (BtnContact2) && !(cm <= 5)) { //contact SANS ultrason : le bateau est collé à un bord et le suit
  digitalWrite(moteur1, LOW);
    digitalWrite(moteur2, HIGH);
    //  la pompe fonctionne ************************************************************
    digitalWrite(pompe, HIGH);
  }
  button();
}

Ok ça compile ?
Quand le compilateur t'indique des erreurs, il te donne aussi le numéro des lignes concernées dans le code. Ça aide à les trouver. Pense à les copier dans tes messages si tu as encore des problèmes, ça nous aide aussi.

C'est quoi la fonction button()?

Oui ça complie

La fonction button est celle qui déclenche les moteurs
si btncontact1 alors moteur1 et pas moteur2
si btncontact2 alors moteur2 et pas moteur1

Une question de présentation.
avec d'autre code, les consoles indique le numéro de ligne du code.
Arduino ne le fait pas ?
du style

001 void ....() {
002 ......
003 }

void button() {
  // moteur et Btncontact sont opposes
  // vérifie si les boutoncontact sont actifs(HIGH), si oui le moteur passe à actif(HIGH) ou éteint(LOW) selon le programme
  if (BtnContact1 == HIGH) {
    // turn LED on:
    digitalWrite(moteur1, LOW);
    //
    //**************************************************************************************************
    // si le bouton touche le bord la pompe fonctionne *************************************************
    digitalWrite(pompe, HIGH);
    //**************************************************************************************************
  }
  else {
    // turn LED off:
    digitalWrite(moteur1, HIGH);
    //
    //**************************************************************************************************
    // sinon pas de contact la pompe stoppe ************************************************************
    digitalWrite(pompe, LOW);
    //**************************************************************************************************
  }
  if (BtnContact2 == HIGH) {
    // turn LED on:
    digitalWrite(moteur2, LOW);
    //
    //**************************************************************************************************
    // si le bouton touche le bord la pompe fonctionne *************************************************
    digitalWrite(pompe, HIGH);
    //**************************************************************************************************
  }
  else {
    // turn LED off:
    digitalWrite(moteur2, HIGH);
    //
    //**************************************************************************************************
    // sinon pas de contact la pompe stoppe ************************************************************
    digitalWrite(pompe, LOW);
    //**************************************************************************************************
  }
}

Non l ne les affiche pas mais si tu cliques sur une ligne de code dans l'IDE le numéro apparaît en bas (bien caché c'est vrai)