Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

WALTER : Un Robot Insecte Photovore Alimenté par Arduino

Composants et fournitures

SparkFun Arduino Pro Mini 328 - 5V/16MHz × 1
Capteur Ultrasonique HC-SR04 (Genérique) × 3
Photodiode × 4
Résistance 100k ohm × 4
Micro Servo MG90S à Engrenages Métalliques × 5
Batterie Portable pour Smartphone (2 Canaux : 1A et 2.1A) × 1

Outils et machines nécessaires

Applications et services en ligne

À propos de ce projet

[Veuillez excuser mon anglais]

J'aime beaucoup la configuration populaire des insectes Arduino à 2 servos sur YouTube. En les regardant, je me souviens toujours de ce que les passionnés de robotique BEAM faisaient bien avant que cette configuration ne devienne populaire. Ces férus de robotique analogique obtenaient de meilleurs résultats sur la démarche grâce à un meilleur angle entre les deux moteurs (microcore / bicore walker, etc.).

Cependant, à mon avis, aucun de ceux mentionnés ne semble plus vivant que VBug1.5 (aussi connu sous le nom de Walkman) créé par le fondateur de la robotique BEAM, Mark Tilden. Il utilise 5 moteurs, ce qui lui confère plus de manœuvrabilité.

Fabriquer un robot BEAM simple n'est pas difficile, mais construire quelque chose d'aussi complexe que le VBug1.5 pourrait être décourageant pour un novice en électronique comme moi. Alors, quand j'ai décidé de faire quelque chose comme les insectes de Tilden, j'ai dû me contenter de la plateforme Arduino, le choix le plus facile pour les non-ingénieurs (ou dans mon cas, honteusement, un ingénieur en herbe).

Résultat : j'ai créé Walter, un robot quadrupède Arduino à 4 pattes avec 5 servos. Vous vous demandez peut-être pourquoi je n'ai pas opté pour 8 ou 12 servos si je voulais un robot insecte réaliste. Eh bien, je cherchais la solution la plus simple pour obtenir le maximum de manœuvrabilité. Je parle d'utiliser beaucoup de colle au lieu de fabriquer des châssis.

COMPORTEMENTS

Comme beaucoup d'autres robots Arduino, Walter peut éviter les obstacles grâce aux capteurs ultrasoniques HC-SR04. Pour ajouter du caractère d'insecte, Walter est aussi un photovore, ce qui signifie qu'il est attiré par la lumière. Des photodiodes sont utilisées pour détecter la lumière. Des valeurs aléatoires sont générées dans le sketch Arduino pour que Walter décide quand il veut s'arrêter pour se reposer, et aussi pour changer aléatoirement sa vitesse de démarche (3 vitesses).

Au début, je voulais mettre des boutons tactiles sous chacun des pieds de Walter pour qu'il ait des capteurs de surface. Mais la batterie (une power bank pour smartphone) coûtait trop de poids aux servos. Je sais que les boutons tactiles pèsent presque rien, mais ironiquement, le poids du robot n'est pas suffisant pour appuyer sur les boutons retournés.

Je prévois de faire une version 2 de Walter avec des servos plus gros et d'inclure ces boutons comme capteurs de surface.

Code

WALTER.ino

/* WALTER - LE QUADRUPÈDE PHOTOVORE À 4 PATTES
Ce sketch Arduino est ma tentative de construire un robot quadrupède (4 pattes) à 5 servos nommé "WALTER".
Pour utiliser ce sketch, vous devrez peut-être modifier certaines valeurs pour votre convenance ou pour l'adapter à votre propre configuration matérielle.
Trouvez (Ctrl + F) ces marques pour rechercher facilement les valeurs qui pourraient devoir être changées :
- **** : Ces marques signifient qu'il s'agit des positions centrales des servos et qu'elles doivent être calibrées (positionnement des pattes de votre robot au repos).
- *** : Ces marques signifient l'affectation des broches Arduino (connexion capteurs & servos à l'Arduino). Référez-vous à ceci lors de la construction du robot.
- ** : Ces marques signifient que les valeurs peuvent être changées selon vos goûts (largeur de pas des pattes, combien tourner en détectant lumière/obstacle, etc). Laissez tel quel si vous ne savez pas ce que vous faites.
Vous pouvez utiliser ce sketch à vos risques.. et il est fourni tel quel.. heu.. De quoi parlent tous ces trucs de copyright que les gens mettent dans le code source publié ? L'essentiel est que je ne veux pas être tenu responsable si quelque chose de grave arrive en utilisant ce code. Amusez-vous bien !
Yohanes Martedi - 2015 */

#include <Servo.h>

// ****Calibrer l'angle central des servos (en microsecondes car nous utiliserons la commande "xx.writeMicroseconds();"). Commencez avec 1500.
const int ANGLE_mid_Shaft = 1520;
const int ANGLE_mid_FLeft = 1550;
const int ANGLE_mid_FRight = 1570;
const int ANGLE_mid_BLeft = 1450;
const int ANGLE_mid_BRight = 1450;
const int ANGLE_sweep = 250; // **Définissez cette valeur (en microsecondes) pour déterminer la largeur du balayage des servos (largeur de pas des pattes). Valeur plus grande = angle de balayage plus large.
const int ANGLE_res = 10; // **Résolution du mouvement du servo (en microsecondes) au minimum à la largeur de bande morte par défaut du servo (plus haute résolution) ou plus (moins de résolution). Exemple : la bande morte du servo SG90 est de 10 microsecondes.
int sweepSPEED; // variable pour déterminer la vitesse de balayage des servos.
int sweepSPEED_Rand[3] = {4, 6, 8}; // **La vitesse du servo (vitesse de démarche) changera aléatoirement en 3 modes. Définissez la vitesse (en millisecondes) pour chaque mode. Valeur plus petite = plus rapide.
const int ANGLE_turnMAX = ANGLE_sweep * 1.5; // **Définissez cette valeur pour déterminer le maximum que le bot tournera vers la lumière. Valeur plus grande = virage plus grand.
const int ANGLE_turnNARROW = ANGLE_sweep * 0.25; // **Définissez cette valeur pour déterminer le maximum que le bot tournera en évitant des objets sur ses côtés dans un espace étroit. Valeur plus grande = virage plus grand.
const int SONAR_sum = 3; // Nombre de sonars utilisés.
const int PHOTO_sum = 4; // Nombre de photodiodes utilisées.
int PIN_trig[SONAR_sum] = {13, 11, 8}; // ***Broches Arduino connectées aux broches trigger des capteurs ultrasoniques ; {avant, gauche, droite}.
int PIN_ec[SONAR_sum] = {12, 10, 7}; // ***Broches Arduino connectées aux broches echo des capteurs ultrasoniques ; {avant, gauche, droite}.
int PIN_PHOTO[PHOTO_sum] = {2, 3, 1, 0}; // ***Broches d'entrée analogique Arduino connectées aux photodiodes ; {avant-gauche, avant-droite, arrière-gauche, arrière-droite}.
const int distRotate = 25; // **Distance minimale (en cm) entre le robot et l'obstacle avant que le robot ne l'évite en tournant.
const int distRetreat = 10; // **Distance minimale (en cm) avant que le robot ne recule.
const int distTurn = 20; // **Distance minimale (en cm) avant que le robot ne tourne pour éviter.
const int counter_gait_max = 8; // **Nombre de pas que le robot fera pour éviter l'obstacle (en tournant ou reculant).
// **Durée de repos et de marche (en millisecondes).
const int RUN_time = 25000;
const int REST_time = 3000;
// IDs pour les sonars :
int SONAR_id;
const int FRONT = 0;
const int LEFT = 1;
const int RIGHT = 2;
// IDs pour les photodiodes :
const int FRONT_LEFT = 0;
const int FRONT_RIGHT = 1;
const int BACK_LEFT = 2;
const int BACK_RIGHT = 3;
// Variables pour la lecture des photodiodes :
int PHOTO_Front_Left;
int PHOTO_Front_Right;
int PHOTO_Back_Left;
int PHOTO_Back_Right;
const int SONAR_TrigSig = 10; // Durée (en µs) du signal trigger nécessaire aux capteurs pour produire le son ultrasonique (déjà spécifié par les produits, ne pas changer cette valeur).
const unsigned long SONAR_MaxEc = 50000; // Durée maximale (en µs) du signal echo donné par les capteurs (déjà spécifié par les produits, ne pas changer cette valeur).
const float SOUND_speed = 0.034; // Vitesse du son dans l'air en cm/µs (déjà spécifié par la science, l'avatar Aang serait nécessaire pour faire de l'air bending si on voulait changer cette valeur).
int distance[SONAR_sum]; // Résultats du calcul de distance.
// Déclaration des servos :
Servo SERVO_shaft;
Servo SERVO_front_left;
Servo SERVO_front_right;
Servo SERVO_back_left;
Servo SERVO_back_right;
// Variables pour les angles de chaque servo :
int ANGLE_shaft = ANGLE_mid_Shaft;
int ANGLE_front_left = ANGLE_mid_FLeft;
int ANGLE_front_right = ANGLE_mid_FRight;
int ANGLE_back_left = ANGLE_mid_BLeft;
int ANGLE_back_right = ANGLE_mid_BRight;
// Manipulation d'angle pour le servo central (shaft).
const int ANGLE_max_Shaft = ANGLE_mid_Shaft + ANGLE_sweep;
const int ANGLE_min_Shaft = ANGLE_mid_Shaft - ANGLE_sweep;
int ANGLE_sweep_val;
// Variables pour enregistrer les angles actuels de chaque servo :
int ANGLE_shaft_record;
int ANGLE_front_left_record;
int ANGLE_front_right_record;
int ANGLE_back_left_record;
int ANGLE_back_right_record;
// Variables pour la correction des angles des servos selon la détection de lumière :
int LIGHT_left;
int LIGHT_right;
// Variables pour la correction des angles des servos selon la détection sonar :
int SONAR_left;
int SONAR_right;
// Drapeaux, compteurs, enregistrements que je ne sais jamais trop comment expliquer. :(
int ANGLE_prev;
int flag_shaft_reverse;
int flag_transition_rotate;
int flag_transition_start = 1;
int flag_rest = 0;
int flag_RUN_time = 0;
int rotate_random;
int counter_gait;

void setup() {
  // Serial.begin(9600); // Serial.. pour vérification & débogage..
  SERVO_shaft.attach(2); // ***Broche de signal du servo horizontal (shaft) sur Arduino.
  SERVO_front_left.attach(4); // ***Broche de signal du servo avant-gauche sur Arduino.
  SERVO_front_right.attach(3); // ***Broche de signal du servo avant-droite sur Arduino.
  SERVO_back_left.attach(6); // ***Broche de signal du servo arrière-gauche sur Arduino.
  SERVO_back_right.attach(5); // ***Broche de signal du servo arrière-droite sur Arduino.
  // Mettre les servos à leurs angles centraux.
  SERVO_shaft.writeMicroseconds(ANGLE_mid_Shaft);
  SERVO_front_left.writeMicroseconds(ANGLE_mid_FLeft);
  SERVO_front_right.writeMicroseconds(ANGLE_mid_FRight);
  SERVO_back_left.writeMicroseconds(ANGLE_mid_BLeft);
  SERVO_back_right.writeMicroseconds(ANGLE_mid_BRight);
  // Configuration des broches pour les sonars, pinMode et valeur.
  for(SONAR_id = 0; SONAR_id < SONAR_sum; SONAR_id++) {
    pinMode(PIN_trig[SONAR_id], OUTPUT);
    pinMode(PIN_ec[SONAR_id], INPUT);
    digitalWrite(PIN_trig[SONAR_id], LOW);
  }
  randomSeed(analogRead(5)); // Utilisation de la broche analogique 5 pour générer des valeurs aléatoires utilisées plus tard.
  SONAR_READ_ALL(); // Lecture sonar initiale avant de faire quoi que ce soit,
  SONAR_READ_ALL(); // et en fait j'oublie pourquoi je dois l'appeler deux fois la première fois. Mais croyez-moi, c'est nécessaire.
  START(); // Cette fonction s'assure quelles pattes sont levées aléatoirement au premier pas.
  delay(3000); // **dum.. daa.. dum..
}

void loop() {
  int state = random(0,2);
  if(state == 0) {
    REST();
  } else {
    int randomSPEED = random(0,3);
    sweepSPEED = sweepSPEED_Rand[randomSPEED];
    RUN();
    flag_rest = 0;
  }
}

void REST() {
  if(flag_rest == 0) {
    TRANSITION_GAIT();
    flag_rest = 1;
  }
  delay(REST_time);
}

void RUN() {
  unsigned long TIMER_state = millis();
  while((millis() - TIMER_state) <= RUN_time) {
    if(distance[FRONT] > distRotate) {
      flag_RUN_time = 0;
      while(flag_RUN_time == 0) {
        FORWARD();
      }
    }
    while(distance[FRONT] > distRetreat && distance[FRONT] <= distRotate) {
      while(distance[LEFT] > distance[RIGHT]) {
        ROTATE_LEFT_AVOID();
        break;
      }
      while(distance[LEFT] < distance[RIGHT]) {
        ROTATE_RIGHT_AVOID();
        break;
      }
      while(distance[LEFT] == distance[RIGHT]) {
        ROTATE_RANDOM_AVOID();
        break;
      }
    }
    while(distance[FRONT] <= distRetreat) {
      RETREAT_AVOID();
    }
  }
}

/*________________________________________________________________________________________
########################################## GAIT ########################################*/
/*=================================== MOUVEMENT SHAFT ===================================*/
void SHAFT() {
  unsigned long TIMER_servo = millis();
  while((millis() - TIMER_servo) <= sweepSPEED) {
    while(ANGLE_shaft == ANGLE_mid_Shaft) {
      counter_gait++;
      SONAR_READ_ALL();
      LIGHT_COMPARE_EXECUTE();
      SIDE_AVOID();
      flag_RUN_time = 1;
      break;
    }
  }
  if(ANGLE_prev < ANGLE_shaft && ANGLE_shaft < ANGLE_max_Shaft) {
    ANGLE_prev = ANGLE_shaft;
    ANGLE_shaft += ANGLE_res;
  } else if(ANGLE_shaft >= ANGLE_max_Shaft) {
    ANGLE_prev = ANGLE_shaft;
    ANGLE_shaft -= ANGLE_res;
  } else if(ANGLE_prev > ANGLE_shaft && ANGLE_shaft > ANGLE_min_Shaft) {
    ANGLE_prev = ANGLE_shaft;
    ANGLE_shaft -= ANGLE_res;
  } else if(ANGLE_shaft <= ANGLE_min_Shaft) {
    ANGLE_prev = ANGLE_shaft;
    ANGLE_shaft += ANGLE_res;
  }
  SERVO_shaft.writeMicroseconds(ANGLE_shaft);
}

void SHAFT_REVERSE() {
  if(ANGLE_prev < ANGLE_shaft) {
    ANGLE_prev = ANGLE_shaft + 1;
  } else if(ANGLE_prev > ANGLE_shaft) {
    ANGLE_prev = ANGLE_shaft - 1;
  }
}
/*================================ FIN MOUVEMENT SHAFT ================================*/
/*===================================== TRANSITION =====================================*/
void TRANSITION_GAIT() {
  ANGLE_front_left_record = ANGLE_front_left;
  ANGLE_front_right_record = ANGLE_front_right;
  ANGLE_back_left_record = ANGLE_back_left;
  ANGLE_back_right_record = ANGLE_back_right;
  ANGLE_shaft_record = ANGLE_shaft;
  int flag = HIGH;
  int counter = 0;
  while(flag == HIGH) {
    SHAFT();
    LIGHT_left = 0;
    LIGHT_right = 0;
    counter++;
    ANGLE_front_left = map(counter, 1, ((ANGLE_sweep * 2) / ANGLE_res), ANGLE_front_left_record, ANGLE_mid_FLeft);
    ANGLE_front_right = map(counter, 1, ((ANGLE_sweep * 2) / ANGLE_res), ANGLE_front_right_record, ANGLE_mid_FRight);
    ANGLE_back_left = map(counter, 1, ((ANGLE_sweep * 2) / ANGLE_res), ANGLE_back_left_record, ANGLE_mid_BLeft);
    ANGLE_back_right = map(counter, 1, ((ANGLE_sweep * 2) / ANGLE_res), ANGLE_back_right_record, ANGLE_mid_BRight);
    SERVO_shaft.writeMicroseconds(ANGLE_shaft);
    SERVO_front_left.writeMicroseconds(ANGLE_front_left);
    SERVO_front_right.writeMicroseconds(ANGLE_front_right);
    SERVO_back_left.writeMicroseconds(ANGLE_back_left);
    SERVO_back_right.writeMicroseconds(ANGLE_back_right);
    if(counter == ((ANGLE_sweep * 2) / ANGLE_res)) {
      flag = LOW;
      START();
      flag_transition_rotate = 0;
    }
  }
}

void TRANSITION_START() {
  if(ANGLE_shaft == ANGLE_mid_Shaft || (ANGLE_shaft > ANGLE_mid_Shaft && ANGLE_shaft > ANGLE_prev) || (ANGLE_shaft < ANGLE_mid_Shaft && ANGLE_shaft < ANGLE_prev)) {
    ANGLE_sweep_val = 0;
  } else {
    flag_transition_start = 0;
  }
}

void START() {
  ANGLE_prev = random((ANGLE_shaft), (ANGLE_shaft + 2));
  if(ANGLE_prev == ANGLE_shaft) {
    ANGLE_prev -= 1;
  }
  flag_transition_start = 1;
}

int ROTATE_RANDOM() {
  return random(0, 2);
}
/*================================== FIN TRANSITION ==================================*/
/*======================================== MARCHE ========================================*/
void FORWARD() {
  while(flag_transition_rotate == 2) {
    TRANSITION_GAIT();
  }
  flag_transition_rotate = 1;
  while(flag_shaft_reverse == 0) {
    SHAFT_REVERSE();
    break;
  }
  flag_shaft_reverse = 1;
  while(flag_transition_start == 1) {
    SHAFT();
    TRANSITION_START();
    WALK();
  }
  SHAFT();
  ANGLE_sweep_val = ANGLE_sweep;
  WALK();
}

void RETREAT() {
  while(flag_transition_rotate == 2) {
    TRANSITION_GAIT();
  }
  flag_transition_rotate = 1;
  while(flag_shaft_reverse == 1) {
    SHAFT_REVERSE();
    break;
  }
  flag_shaft_reverse = 0;
  while(flag_transition_start == 1) {
    SHAFT();
    LIGHT_left = 0;
    LIGHT_right = 0;
    TRANSITION_START();
    WALK();
  }
  SHAFT();
  LIGHT_left = 0;
  LIGHT_right = 0;
  ANGLE_sweep_val = (ANGLE_sweep * -1);
  WALK();
}

void WALK() {
  if(ANGLE_shaft >= ANGLE_mid_Shaft && ANGLE_prev < ANGLE_shaft) {
    ANGLE_front_left = map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_max_Shaft, ((ANGLE_mid_FLeft - ANGLE_sweep_val) + LIGHT_left + SONAR_left), ANGLE_mid_FLeft);
    ANGLE_front_right = map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_max_Shaft, ((ANGLE_mid_FRight - ANGLE_sweep_val) - LIGHT_right - SONAR_right), ANGLE_mid_FRight);
    ANGLE_back_left = map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_max_Shaft, ((ANGLE_mid_BLeft + ANGLE_sweep_val) - LIGHT_left - SONAR_left), ANGLE_mid_BLeft);
    ANGLE_back_right = map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_max_Shaft, ((ANGLE_mid_BRight + ANGLE_sweep_val) + LIGHT_right + SONAR_right), ANGLE_mid_BRight);
  } else if(ANGLE_shaft >= ANGLE_mid_Shaft && ANGLE_prev > ANGLE_shaft) {
    ANGLE_front_left = map(ANGLE_shaft, ANGLE_max_Shaft, ANGLE_mid_Shaft, ANGLE_mid_FLeft, ((ANGLE_mid_FLeft + ANGLE_sweep_val) - LIGHT_left - SONAR_left));
    ANGLE_front_right = map(ANGLE_shaft, ANGLE_max_Shaft, ANGLE_mid_Shaft, ANGLE_mid_FRight, ((ANGLE_mid_FRight + ANGLE_sweep_val) + LIGHT_right + SONAR_right));
    ANGLE_back_left = map(ANGLE_shaft, ANGLE_max_Shaft, ANGLE_mid_Shaft, ANGLE_mid_BLeft, ((ANGLE_mid_BLeft - ANGLE_sweep_val) + LIGHT_left + SONAR_left));
    ANGLE_back_right = map(ANGLE_shaft, ANGLE_max_Shaft, ANGLE_mid_Shaft, ANGLE_mid_BRight, ((ANGLE_mid_BRight - ANGLE_sweep_val) - LIGHT_right - SONAR_right));
  } else if(ANGLE_shaft < ANGLE_mid_Shaft && ANGLE_prev > ANGLE_shaft) {
    ANGLE_front_left = map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_min_Shaft, ((ANGLE_mid_FLeft + ANGLE_sweep_val) - LIGHT_left - SONAR_left), ANGLE_mid_FLeft);
    ANGLE_front_right = map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_min_Shaft, ((ANGLE_mid_FRight + ANGLE_sweep_val) + LIGHT_right + SONAR_right), ANGLE_mid_FRight);
    ANGLE_back_left = map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_min_Shaft, ((ANGLE_mid_BLeft - ANGLE_sweep_val) + LIGHT_left + SONAR_left), ANGLE_mid_BLeft);
    ANGLE_back_right = map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_min_Shaft, ((ANGLE_mid_BRight - ANGLE_sweep_val) - LIGHT_right - SONAR_right), ANGLE_mid_BRight);
  } else if(ANGLE_shaft < ANGLE_mid_Shaft && ANGLE_prev < ANGLE_shaft) {
    ANGLE_front_left = map(ANGLE_shaft, ANGLE_min_Shaft, ANGLE_mid_Shaft, ANGLE_mid_FLeft, ((ANGLE_mid_FLeft - ANGLE_sweep_val) + LIGHT_left + SONAR_left));
    ANGLE_front_right = map(ANGLE_shaft, ANGLE_min_Shaft, ANGLE_mid_Shaft, ANGLE_mid_FRight, ((ANGLE_mid_FRight - ANGLE_sweep_val) - LIGHT_right - SONAR_right));
    ANGLE_back_left = map(ANGLE_shaft, ANGLE_min_Shaft, ANGLE_mid_Shaft, ANGLE_mid_BLeft, ((ANGLE_mid_BLeft + ANGLE_sweep_val) - LIGHT_left - SONAR_left));
    ANGLE_back_right = map(ANGLE_shaft, ANGLE_min_Shaft, ANGLE_mid_Shaft, ANGLE_mid_BRight, ((ANGLE_mid_BRight + ANGLE_sweep_val) + LIGHT_right + SONAR_right));
  }
  SERVO_front_left.writeMicroseconds(ANGLE_front_left);
  SERVO_front_right.writeMicroseconds(ANGLE_front_right);
  SERVO_back_left.writeMicroseconds(ANGLE_back_left);
  SERVO_back_right.writeMicroseconds(ANGLE_back_right);
}
/*===================================== FIN MARCHE =====================================*/
/*======================================= ROTATION =======================================*/
void ROTATE_LEFT() {
  while(flag_transition_rotate == 1) {
    TRANSITION_GAIT();
  }
  flag_transition_rotate = 2;
  while(flag_shaft_reverse == 2) {
    SHAFT_REVERSE();
    break;
  }
  flag_shaft_reverse = 3;
  while(flag_transition_start == 1) {
    SHAFT();
    LIGHT_left = 0;
    LIGHT_right = 0;
    TRANSITION_START();
    ROTATE();
  }
  SHAFT();
  LIGHT_left = 0;
  LIGHT_right = 0;
  ANGLE_sweep_val = ANGLE_sweep;
  ROTATE();
}

void ROTATE_RIGHT() {
  while(flag_transition_rotate == 1) {
    TRANSITION_GAIT();
  }
  flag_transition_rotate = 2;
  while(flag_shaft_reverse == 3) {
    SHAFT_REVERSE();
    break;
  }
  flag_shaft_reverse = 2;
  while(flag_transition_start == 1) {
    SHAFT();
    LIGHT_left = 0;
    LIGHT_right = 0;
    TRANSITION_START();
    ROTATE();
  }
  SHAFT();
  LIGHT_left = 0;
  LIGHT_right = 0;
  ANGLE_sweep_val = (ANGLE_sweep * -1);
  ROTATE();
}

void ROTATE() {
  if(ANGLE_shaft >= ANGLE_mid_Shaft && ANGLE_prev < ANGLE_shaft) {
    ANGLE_front_left = map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_max_Shaft, (ANGLE_mid_FLeft + ANGLE_sweep_val), ANGLE_mid_FLeft);
    ANGLE_front_right = map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_max_Shaft, (ANGLE_mid_FRight - ANGLE_sweep_val), ANGLE_mid_FRight);
    ANGLE_back_left = map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_max_Shaft, (ANGLE_mid_BLeft - ANGLE_sweep_val), ANGLE_mid_BLeft);
    ANGLE_back_right = map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_max_Shaft, (ANGLE_mid_BRight + ANGLE_sweep_val), ANGLE_mid_BRight);
  } else if(ANGLE_shaft >= ANGLE_mid_Shaft && ANGLE_prev > ANGLE_shaft) {
    ANGLE_front_left = map(ANGLE_shaft, ANGLE_max_Shaft, ANGLE_mid_Shaft, ANGLE_mid_FLeft, (ANGLE_mid_FLeft - ANGLE_sweep_val));
    ANGLE_front_right = map(ANGLE_shaft, ANGLE_max_Shaft, ANGLE_mid_Shaft, ANGLE_mid_FRight, (ANGLE_mid_FRight + ANGLE_sweep_val));
    ANGLE_back_left = map(ANGLE_shaft, ANGLE_max_Shaft, ANGLE_mid_Shaft, ANGLE_mid_BLeft, (ANGLE_mid_BLeft + ANGLE_sweep_val));
    ANGLE_back_right = map(ANGLE_shaft, ANGLE_max_Shaft, ANGLE_mid_Shaft, ANGLE_mid_BRight, (ANGLE_mid_BRight - ANGLE_sweep_val));
  } else if(ANGLE_shaft < ANGLE_mid_Shaft && ANGLE_prev > ANGLE_shaft) {
    ANGLE_front_left = map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_min_Shaft, (ANGLE_mid_FLeft - ANGLE_sweep_val), ANGLE_mid_FLeft);
    ANGLE_front_right = map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_min_Shaft, (ANGLE_mid_FRight + ANGLE_sweep_val), ANGLE_mid_FRight);
    ANGLE_back_left = map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_min_Shaft, (ANGLE_mid_BLeft + ANGLE_sweep_val), ANGLE_mid_BLeft);
    ANGLE_back_right = map(ANGLE_shaft, ANGLE_mid_Shaft, ANGLE_min_Shaft, (ANGLE_mid_BRight - ANGLE_sweep_val), ANGLE_mid_BRight);
  } else if(ANGLE_shaft < ANGLE_mid_Shaft && ANGLE_prev < ANGLE_shaft) {
    ANGLE_front_left = map(ANGLE_shaft, ANGLE_min_Shaft, ANGLE_mid_Shaft, ANGLE_mid_FLeft, (ANGLE_mid_FLeft + ANGLE_sweep_val));
    ANGLE_front_right = map(ANGLE_shaft, ANGLE_min_Shaft, ANGLE_mid_Shaft, ANGLE_mid_FRight, (ANGLE_mid_FRight - ANGLE_sweep_val));
    ANGLE_back_left = map(ANGLE_shaft, ANGLE_min_Shaft, ANGLE_mid_Shaft, ANGLE_mid_BLeft, (ANGLE_mid_BLeft - ANGLE_sweep_val));
    ANGLE_back_right = map(ANGLE_shaft, ANGLE_min_Shaft, ANGLE_mid_Shaft, ANGLE_mid_BRight, (ANGLE_mid_BRight + ANGLE_sweep_val));
  }
  SERVO_front_left.writeMicroseconds(ANGLE_front_left);
  SERVO_front_right.writeMicroseconds(ANGLE_front_right);
  SERVO_back_left.writeMicroseconds(ANGLE_back_left);
  SERVO_back_right.writeMicroseconds(ANGLE_back_right);
}
/*==================================== FIN ROTATION ====================================*/
/*_________________________________________________________________________________________
/*##################################### FIN GAIT #####################################*/
/*================================= LECTURE ULTRASONIQUE =================================*/
void SONAR_READ_ALL() {
  for(SONAR_id = 0; SONAR_id < SONAR_sum; SONAR_id++) {
    distance[SONAR_id] = int(SONAR_READ(SONAR_id));
  }
}

float SONAR_READ(int index) {
  float SONAR_distance;
  digitalWrite(PIN_trig[index], HIGH);
  delayMicroseconds(SONAR_TrigSig);
  digitalWrite(PIN_trig[index], LOW);
  float SONAR_EcInterval = float(pulseIn(PIN_ec[index], HIGH, SONAR_MaxEc));
  while(SONAR_EcInterval > 0.0) {
    SONAR_distance = SONAR_EcInterval * (SOUND_speed / 2.0);
    break;
  }
  while(SONAR_EcInterval == 0.0) {
    SONAR_distance = 501.0;
    break;
  }
  return SONAR_distance;
}
/*============================= FIN LECTURE ULTRASONIQUE =============================*/
/*==================================== DÉTECTION LUMIÈRE ====================================*/
void LIGHT_COMPARE_EXECUTE() {
  PHOTO_Front_Left = analogRead(PIN_PHOTO[FRONT_LEFT]);
  PHOTO_Front_Right = analogRead(PIN_PHOTO[FRONT_RIGHT]);
  PHOTO_Back_Left = analogRead(PIN_PHOTO[BACK_LEFT]);
  PHOTO_Back_Right = analogRead(PIN_PHOTO[BACK_RIGHT]);
  if((PHOTO_Front_Left + PHOTO_Front_Right) >= (PHOTO_Back_Left + PHOTO_Back_Right)) {
    int LIGHT_Sensitivity = 50;
    if(LIGHT_COMPARE() > LIGHT_Sensitivity) {
      LIGHT_left = LIGHT_COMPARE();
      LIGHT_right = 0;
    } else if(LIGHT_COMPARE() < -LIGHT_Sensitivity) {
      LIGHT_left = 0;
      LIGHT_right = LIGHT_COMPARE();
    } else {
      LIGHT_left = 0;
      LIGHT_right = 0;
    }
  } else {
    if(PHOTO_Back_Left > PHOTO_Back_Right) {
      LIGHT_right = 0;
      LIGHT_left = ANGLE_turnMAX;
    } else if(PHOTO_Back_Left < PHOTO_Back_Right) {
      LIGHT_right = -ANGLE_turnMAX;
      LIGHT_left = 0;
    } else {
      int RANDOM_back_light = random(0,2);
      if(RANDOM_back_light == 0) {
        LIGHT_right = 0;
        LIGHT_left = ANGLE_turnMAX;
      } else if(RANDOM_back_light == 1) {
        LIGHT_right = -ANGLE_turnMAX;
        LIGHT_left = 0;
      }
    }
  }
}

int LIGHT_COMPARE() {
  int LIGHT_rate;
  if(PHOTO_Front_Left > PHOTO_Front_Right) {
    LIGHT_rate = PHOTO_Front_Left;
  } else if(PHOTO_Front_Right > PHOTO_Front_Left) {
    LIGHT_rate = PHOTO_Front_Right;
  } else {
    LIGHT_rate = PHOTO_Front_Right;
  }
  int LIGHT_compareRAW = PHOTO_Front_Left - PHOTO_Front_Right;
  LIGHT_compareRAW = map(LIGHT_compareRAW, -LIGHT_rate, LIGHT_rate, -ANGLE_turnMAX, ANGLE_turnMAX);
  return LIGHT_compareRAW;
}
/*================================= FIN DÉTECTION LUMIÈRE =================================*/
/*====================================== COMPORTEMENT ======================================*/
void RETREAT_AVOID() {
  counter_gait = 0;
  while(counter_gait <= counter_gait_max) {
    RETREAT();
  }
}

void ROTATE_LEFT_AVOID() {
  counter_gait = 0;
  rotate_random = 2;
  while(counter_gait <= counter_gait_max) {
    ROTATE_LEFT();
  }
}

void ROTATE_RIGHT_AVOID() {
  counter_gait = 0;
  rotate_random = 2;
  while(counter_gait <= counter_gait_max) {
    ROTATE_RIGHT();
  }
}

void ROTATE_RANDOM_AVOID() {
  rotate_random = ROTATE_RANDOM();
  while(rotate_random == 0) {
    ROTATE_LEFT_AVOID();
  }
  while(rotate_random == 1) {
    ROTATE_RIGHT_AVOID();
  }
}

void SIDE_AVOID() {
  if(distance[LEFT] <= distTurn && distance[RIGHT] > distTurn) {
    LIGHT_left = 0;
    LIGHT_right = 0;
    SONAR_left = 0;
    SONAR_right = -(map(distance[LEFT], 0, distTurn, ANGLE_turnMAX, 0));
  } else if(distance[RIGHT] <= distTurn && distance[LEFT] > distTurn) {
    LIGHT_left = 0;
    LIGHT_right = 0;
    SONAR_right = 0;
    SONAR_left = map(distance[RIGHT], 0, distTurn, ANGLE_turnMAX, 0);
  } else if(distance[LEFT] <= distTurn && distance[RIGHT] <= distTurn) {
    LIGHT_left = 0;
    LIGHT_right = 0;
    if(distance[LEFT] < distance[RIGHT]) {
      SONAR_left = 0;
      SONAR_right = -(map(distance[LEFT], 0, distTurn, ANGLE_turnNARROW, 0));
    } else if(distance[RIGHT] < distance[LEFT]) {
      SONAR_right = 0;
      SONAR_left = map(distance[RIGHT], 0, distTurn, ANGLE_turnNARROW, 0));
    }
  } else {
    SONAR_right = 0;
    SONAR_left = 0;
  }
}
/*================================== FIN COMPORTEMENT ==================================*/

Schémas

Schéma de câblage disponible dans le dépôt du projet.

Processus de fabrication

  1. Dé numérique Arduino sur écran LCD 16x2 – Générateur aléatoire à bouton poussoir
  2. Construire un Iron Man animé avec Arduino : capteurs, sons et relais
  3. Find Me : Localisateur d'objets intelligent avec Arduino et Bluetooth
  4. Construire un bras robotique 3D fonctionnel piloté par Arduino – Guide pas à pas
  5. Mesurer la masse de la Terre avec Arduino : Guide DIY étape par étape
  6. Contrôleur d'humidificateur DIY avec Arduino et relais – Installation haute tension sécurisée
  7. Jeu Pong sur Matrice NeoPixel avec Arduino Nano
  8. Volant Joystick Arduino Personnalisé pour Jeux Vidéo
  9. Health Band : Bracelet intelligent fiable d'assistance pour personnes âgées