Infoforall

3 - MAKEBLOCK / Utilisation du capteur de distance et des conditions logiques SI

capteur ultrasons

Vous allez voir aujourd’hui l’une des bases de l’algorithme : Les instructions conditionnelles (à faire si la condition est vraie).

Nous allons également voir les types de variables suivantes : booléen, char, float et double.

En introduction, voilà le codage de différents test de conditions logiques entre deux variables A et B (ici des entiers) :

A = 50
B = 50
Symbole du testSignificationExempleResultat du test
==Est égal àA == B?
!=Est différent deA != B?
>Est supérieur àA > B?
>=Est supérieur ou égal àA >= B?
<Est inférieur àA < B?
<=Est inférieur ou égal àA <= B?

Chacun de ces tests ne peut donner normalement que deux résultats : true pour vrai ou false pour faux. Attention, contrairement à Python, on ne place pas de majuscule au début de la valeur.

1 - Le test logique SI

Commençons par voir comment choisir une action en fonction d’une entrée. C’est une action logique qu’on peut traduire en français par :

En françaisCodage Javascript
SI la première condition est vraie alorsif (condition_1) {
    Fait les actions 1    Instructions_1;
SINON SI la deuxième condition est vraie alors} else if (condition_2) {
    Fait les actions 2    Instructions_2;
SINON} else {
    Fait les actions 3    Instructions_3;
Fin du test}

On remarquera d’abord qu’on met des accolades [ { et }] après la condition de if, else if ou else. Cela permet à l’interpréteur de savoir quand commence la condition à tester (après le if, else if ou else) et quand la condition est définie (au } justement). Autre point important : c’est la tabulation (ou 4 espaces) qui permet de savoir qu’une instruction est rattachée au bloc. Contrairement à Python, il ne s'agit par contre que d'une convention visuelle de compréhension du code. La navigateur ne serait pas perdu si vous ne les placiez pas. Mais il faut le faire pour garantir que d'autres personnes puissent comprendre votre code. Dans Notepad++, on peut faire s'afficher les tabulations à l'aide du menu AFFICHAGE - SYMBOLES SPECIAUX - AFFICHER ESPACES ET TABULATIONS

A titre d'exemple, voici une animation qui vous propose deux boutons : GAUCHE permet d'aller à gauche et DROITE permet d'aller ... à droite.

Oui mais que faire si on demande d'aller à droite alors qu'on est déjà au bout du rectangle ? Il faut refuser d'avancer. Le script fait donc bien un choix logique IF en fonction de la position x du cercle au moment où le mouvement doit avoir lieu.

En françaisCodage Javascript
SI on peut encore aller à droite alorsif (x < xmax) {
    Autoriser le déplacement à droite    Autoriser_droite();
SINON SI on peut encore aller à gauche alors} else if (x > xmin) {
    Autoriser le déplacement à gauche    Autoriser_gauche();
Fin du test}


X actuelle = 250
X minimale = 150
X maximale = 350
avec un test X > XMIN valant
avec un test X < XMAX valant

Application : Faisons un petit programme qui permet d'afficher dans la console série l'action qu'on veut faire au robot en fonction de la valeur d'une variable choix.

void setup()

{

    // Ouverture du port série

    Serial.begin(9600);

    Serial.println("Debut du programme");

}


void loop()

{

    char choix = 'R';

    if (choix == 'A') {

        Serial.println("Faire avancer le robot");

    }

    else if (choix == 'R') {

        Serial.println("Faire reculer le robot");

    }

    else {

        Serial.println("Commande inconnue");

    }

    delay(3000);

}

Si on regarde la structure des instructions, on pourra alors aller dans un bloc et un seul bloc : dès qu'une des conditions est validée, on ne regarde plus les autres et on sort de la structure IF.

    if (choix == 'A') {

        Serial.println("Faire avancer le robot");

    }

    else if (choix == 'R') {

        Serial.println("Faire reculer le robot");

    }

    else {

        Serial.println("Commande inconnue");

    }

01° Tester le code et vérifier sa validité en changeant le contenu plusieurs fois de la variable choix.

02° Quel est le type de la variable choix ?

...CORRECTION...

char choix = 'R';

On voit qu'il ne s'agit pas d'un integer. C'est un nouveau type de variables : le caractère (A, B ...)

On remarquera qu'on doit transmettre la 'valeur' du caractère en l'entourant de guillemets simples.

Remarque :Dans beaucoup de langages, on peut délimiter les caractères uniques (type char) et les chaînes de caractères (string) avec des guillemets simples ou doubles ( " ou ' ). Ce n'est pas le cas avec C : si c'est un caractère simple (variable de type char), il faut utiliser les guillemets simples.

03° Rajouter quelques tests pour gérer également les demandes de rotation à droite et à gauche.

...CORRECTION...

void setup()

{

    // Ouverture du port série

    Serial.begin(9600);

    Serial.println("Debut du programme");

}


void loop()

{

    char choix = 'R';

    if (choix == 'A') {

        Serial.println("Faire avancer le robot");

    }

    else if (choix == 'R') {

        Serial.println("Faire reculer le robot");

    }

    else if (choix == 'G') {

        Serial.println("Tourner à gauche");

    }

    else if (choix == 'D') {

        Serial.println("Tourner à droite");

    }

    else {

        Serial.println("Commande inconnue");

    }

    delay(3000);

}

Remarque : on peut exécuter plusieurs instructions dans le if ou le else if ou le else. On peut même imbriquer un bloc if dans un if.

Le code suivant rajoute une nouvelle variable inversion qui est un booléen : un type de variable ne pouvant valoir que true ou false. Si cette variable contient vraie, on veut inverser l'instruction normalement demandée.

04° Tester ce nouveau code :

void setup()

{

    // Ouverture du port série

    Serial.begin(9600);

    Serial.println("Debut du programme");

}


void loop()

{

    char choix = 'R';

    bool inversion = false;

    if (choix == 'A') {

        if (!inversion) {

            Serial.print("Faire avancer le robot");

        }

        else {

            Serial.print("Faire reculer le robot (on inverse)");

        }

    }

    else if (choix == 'R') {

        Serial.println("Faire reculer le robot");

    }

    else if (choix == 'G') {

        Serial.println("Tourner à gauche");

    }

    else if (choix == 'D') {

        Serial.println("Tourner à droite");

    }

    else {

        Serial.println("Commande inconnue");

    }

    delay(3000);

}

Pour inverser un booléen, on utilise le point d'exclamation : ainsi  !inversion  va renvoyer l'inverse du booléen  inversion .

05° Que devrait afficher le programme ? Tester pour vérifier votre réponse.

C'est un peu lourd de devoir à chaque fois téléverser juste pour changer le caractère. Heureusement, on peut faire mieux : on peut envoyer un caractère à l'Arduino via la liaison série : votre Moniteur série possède une zone où l'utilisateur peut taper des choses, juste au dessus de la zone d'affichage.

Pour afficher des choses dans le moniteur série, il faut écrire ceci :

    Serial.println("Commande inconnue");

Pour lire ce qu'on vient de taper, vous pouvez noter cela tout simplement :

    char choix = Serial.read();

06° Utiliser le code ci-dessous pour tenter de contrôler l'affichage sur la console en fonction de ce que vous tapez dans la console :

void setup()

{

    // Ouverture du port série

    Serial.begin(9600);

    Serial.println("Debut du programme");

}


void loop()

{

    char choix = Serial.read();

    bool inversion = false;

    if (choix == 'A') {

        if (!inversion) {

            Serial.print("Faire avancer le robot");

        }

        else {

            Serial.print("Faire reculer le robot (on inverse)");

        }

    }

    else if (choix == 'R') {

        Serial.println("Faire reculer le robot");

    }

    else if (choix == 'G') {

        Serial.println("Tourner à gauche");

    }

    else if (choix == 'D') {

        Serial.println("Tourner à droite");

    }

    else {

        Serial.println("Commande inconnue");

    }

    delay(3000);

}

Il reste à tester des conditions doubles. Une condition renvoie un booléen qui est true (True en Python, avec un T majuscule) ou false.On peut tester plusieurs conditions à la fois à l’aide des codages suivants :

TEST LOGIQUEEn FrançaisEn Python
andcode ETA && B : Renvoie true si les deux conditions A et B sont true.
orcode OUA || B : Renvoie true si l'une deux conditions au moins est true.
notcode NON!A : Renvoie true si A == false et renvoie false si A == true.

Pour obtenir |, il faut taper ALT GR + 6 sur votre clavier. C'est l'un des symboles de la touche 6.

Plutôt que de faire un test IF imbriqué dans un IF, on aurait ainsi pu faire cela :

    if (choix == 'A' && !inversion ) {

        Serial.print("Faire avancer le robot");

    }

    else if (choix == 'A' && inversion ) {

        Serial.print("Faire reculer le robot (on inverse)");

    }

07° Modifier une dernière fois votre code pour avoir uniquement des tests doubles.

2 - Le capteur à ultrasons

capteur ultrasons

Le principe de base est simple : l'émetteur d'ultrasons émet des ondes qui se propagent à la vitesse du son. On active un chronomètre interne.

Les ondes sont ensuite réfléchies sur les obstacles et reviennent vers le capteur d'ultrasons. On arrête alors le chronomètre.

Sachant que 2d = v.t et connaissant la durée t entre émission et réception et en estimant la vitesse du son, on parvient à calculer la distance d théorique.

Nous allons maintenant voir comment utiliser ce capteur avec Makeblock.

08° Ouvrir le fichier d'exemple de Makeblock nommé UltrasonicSensorTest : Fichier > Exemples > ; MakeBlockDrive > Me_UltrasonicSensor.

/**

* \par Copyright (C), 2012-2016, MakeBlock

     * @fileUltrasonicSensorTest.ino

     * @authorMakeBlock

> * @version V1.0.0

     * @date2015/09/01

     * @briefDescription: this file is sample code for Me ultrasonic sensor module.

*

* Function List:

* 1. double MeUltrasonicSensor::distanceCm(uint16_t MAXcm)

*

* \par History:

*

* Mark Yan2015/09/01 1.0.0 rebuild the old lib

*

> */

#include "MeOrion.h"


MeUltrasonicSensor ultraSensor(PORT_7); /* Ultrasonic module can ONLY be connected to port 3, 4, 6, 7, 8 of base shield. */


void setup()

{

    Serial.begin(9600);

}


void loop()

{

    Serial.print("Distance : ");

    Serial.print(ultraSensor.distanceCm() );

    Serial.println(" cm");

    delay(100); /* the minimal measure interval is 100 milliseconds */

}

09° Lancer le programme et faire quelques tests pour vous persuader de sa validité.

Nous avons vu pour l'instant plusieurs types de variables :

Il reste encore à traiter le cas des nombres à virgules. On les nomme nombres à virgule flottante en informatique.

Sans rentrer dans les détails, le type de base est le type float. Mais attention, on ne stocke pas nécessairement exactement la valeur, mais plutôt une valeur approchée.

Si vous voulez plus de précision sur le stockage de la valeur, vous pouvez utiliser le type double, qui est justement le type renvoyé par la méthode distanceCm.

10° Stocker la distance détectée dans une variable de type double.

11° Adapter le programme pour qu'il puisse afficher la distance à partir de votre variable et pas directement à l'aide de ultraSensor.distanceCm.

3 - Quelques petits défis

Vous allez maintenant pouvoir utiliser vos nouvelles connaissances pour faire des choses bien sympathiques.

12° Créer un programme qui lance le robot en marche avant. On stoppe à 40 cm d'un obstacle.

13° Modifier le programme : on diminue la vitesse à partir de 40cm mais on stoppe à 15 cm de l'obstacle.

14° Modifier le programme : on fait un rotation de 90° vers la droite une fois qu'on a stoppé face à un obstacle.

15° Modifier le programme : si on recontre un obstacle à 15cm également après rotation, on tourne pour faire demi-tour. Dans le deux cas, on repart en marche avant.

16° Modifier le programme : si on ne peut aller ni à droite, ni à gauche, on fait simplement demi-tour.

17° Modifier le programme : si le robot ne peut aller ni à gauche, ni à droite, il doit tourner jusqu'à trouver un chemin possible où il n'y a pas d'obstacle à moins de 40 cm.

FINAL° Test du labyrinthe : votre robot doit être capable de sortir du chemin créé pour lui dans la salle. Vous avez le droit d'utiliser les tables et de créer des chemins de plus en plus complexes.

Il reste beaucoup, beaucoup de possibilités. Mais nous n'avons pas encore vu tous les tests. Par exemple, il n'est pas possible de réaliser une chose très simple pour un humain : se diriger vers l'objet le plus proche ! Mais dans quelques heures, vous devriez être en mesure de faire cela...