.. note::
Bonjour, bienvenue dans la communauté des passionnés de Raspberry Pi, Arduino et ESP32 sur Facebook ! Explorez plus en profondeur l'univers du Raspberry Pi, Arduino et ESP32 avec d'autres passionnés.
**Pourquoi rejoindre ?**
- **Support d'experts** : Résolvez vos problèmes après-vente et défis techniques grâce à l'aide de notre communauté et de notre équipe.
- **Apprendre et partager** : Échangez des astuces et des tutoriels pour perfectionner vos compétences.
- **Aperçus exclusifs** : Accédez en avant-première aux annonces de nouveaux produits et obtenez des aperçus exclusifs.
- **Réductions spéciales** : Profitez de réductions exclusives sur nos produits les plus récents.
- **Promotions et concours festifs** : Participez à des concours et des promotions spéciales pendant les fêtes.
👉 Prêt à explorer et à créer avec nous ? Cliquez sur [|link_sf_facebook|] et rejoignez-nous dès aujourd'hui !
.. _py_avoid:
4. Évitement d'Obstacle
=========================
Dans ce projet, PiCrawler utilise un module ultrasonique pour détecter les obstacles
devant lui. Lorsque PiCrawler détecte un obstacle, il envoie un signal et cherche une
autre direction pour continuer à avancer.
.. .. image:: img/avoid1.png
**Exécuter le Code**
.. raw:: html
.. code-block::
cd ~/picrawler/examples
sudo python3 4_avoid.py
Au démarrage du programme, le PiCrawler se met debout.
Il mesure en continu la distance à l’aide du capteur ultrasonique
et affiche la valeur dans le terminal.
Si un obstacle est détecté à moins de 15 cm :
- Un son d’avertissement est joué.
- Le robot effectue un petit virage à gauche.
Si le chemin est dégagé :
- Le robot avance.
Le robot continue d’éviter les obstacles automatiquement jusqu’à ce que vous appuyiez sur Ctrl+C.
Avant de quitter, il se rassoit en toute sécurité.
**Code**
.. note::
Vous pouvez **Modifier/Réinitialiser/Copier/Exécuter/Arrêter** le code ci-dessous. Mais avant cela, vous devez vous rendre dans le répertoire du code source, tel que ``picrawler\examples``. Après avoir modifié le code, vous pouvez l'exécuter directement pour voir l'effet.
.. raw:: html
.. code-block:: python
from picrawler import Picrawler
from robot_hat import Music, Ultrasonic, Pin
import time
import signal
music = Music()
crawler = Picrawler()
sonar = Ultrasonic(Pin("D2"), Pin("D3")) # Ultrasonic trigger/echo pins
music.music_set_volume(100) # Set speaker volume
alert_distance = 15 # Obstacle warning distance (cm)
speed = 80 # Movement speed
# ----------------------------
# Add hardware timeout to sonar.read()
# Prevent program from freezing
# ----------------------------
class Timeout(Exception):
pass
def _alarm_handler(signum, frame):
raise Timeout()
signal.signal(signal.SIGALRM, _alarm_handler)
# Read distance once with timeout protection
def safe_read_once(timeout_s=1):
try:
signal.alarm(timeout_s)
d = sonar.read()
signal.alarm(0)
return d
except Timeout:
signal.alarm(0)
return None
except Exception:
signal.alarm(0)
return None
# Read multiple times and return median value (anti-noise)
def read_distance_filtered(n=5, gap=0.03, timeout_s=1):
vals = []
for _ in range(n):
d = safe_read_once(timeout_s=timeout_s)
if d is not None and d > 0:
vals.append(d)
time.sleep(gap)
if not vals:
return None
vals.sort()
return vals[len(vals)//2] # Median filter
def main():
distance = read_distance_filtered(n=5, gap=0.03, timeout_s=1)
print("distance:", distance)
if distance is None:
time.sleep(0.15) # Wait if read failed
return
if distance <= alert_distance:
# Obstacle detected → play sound and turn
try:
music.sound_play_threading('./sounds/sign.wav', volume=100)
except Exception as e:
print("sound error:", e)
crawler.do_action('turn left angle', 1, speed)
time.sleep(0.5) # Quiet window after movement
else:
# Path clear → move forward
crawler.do_action('forward', 1, speed)
time.sleep(0.4)
if __name__ == "__main__":
try:
crawler.do_step('stand', 40) # Stand before starting
time.sleep(1.0)
while True:
main()
except KeyboardInterrupt:
print("\nStop.")
finally:
try:
crawler.do_step('sit', 40) # Sit before exit
time.sleep(1.0)
except Exception:
pass
**Comment ça fonctionne ?**
#. Bloc d'initialisation
.. code-block:: python
music = Music()
crawler = Picrawler()
sonar = Ultrasonic(Pin("D2"), Pin("D3"))
music.music_set_volume(100)
alert_distance = 15
speed = 80
Ce bloc initialise les trois modules principaux :
- ``music`` : contrôle la lecture du son.
- ``crawler`` : contrôle les mouvements du PiCrawler.
- ``sonar`` : lit la distance à l’aide du capteur ultrasonique.
Il définit également le volume du haut-parleur, le seuil de détection d’obstacle (en cm)
et la vitesse de déplacement.
#. Bloc de configuration du timeout (empêche ``sonar.read()`` de se bloquer)
.. code-block:: python
class Timeout(Exception):
pass
def _alarm_handler(signum, frame):
raise Timeout()
signal.signal(signal.SIGALRM, _alarm_handler)
Le pilote du capteur ultrasonique peut se bloquer en attendant le signal d’écho.
Ce bloc installe un gestionnaire de signal afin que le programme puisse interrompre
un appel ``sonar.read()`` bloqué et continuer à fonctionner.
#. Fonction : safe_read_once()
.. code-block:: python
def safe_read_once(timeout_s=1):
try:
signal.alarm(timeout_s)
d = sonar.read()
signal.alarm(0)
return d
except Timeout:
signal.alarm(0)
return None
except Exception:
signal.alarm(0)
return None
Cette fonction lit une fois la distance ultrasonique avec une protection de timeout.
- Si la lecture réussit, elle renvoie la valeur de distance.
- Si un timeout se produit ou si une erreur survient, elle renvoie ``None`` au lieu de bloquer le programme.
#. Fonction : read_distance_filtered()
.. code-block:: python
def read_distance_filtered(n=5, gap=0.03, timeout_s=1):
vals = []
for _ in range(n):
d = safe_read_once(timeout_s=timeout_s)
if d is not None and d > 0:
vals.append(d)
time.sleep(gap)
if not vals:
return None
vals.sort()
return vals[len(vals)//2]
Cette fonction améliore la fiabilité en lisant plusieurs échantillons :
- Les valeurs invalides (``None`` ou ``<= 0``) sont ignorées.
- Les valeurs restantes sont triées.
- La valeur médiane est renvoyée afin de réduire le bruit des mesures.
#. Fonction : main() (décision principale et action)
.. code-block:: python
def main():
distance = read_distance_filtered(...)
if distance is None:
return
if distance <= alert_distance:
music.sound_play_threading(...)
crawler.do_action('turn left angle', 1, speed)
else:
crawler.do_action('forward', 1, speed)
Voici la logique principale de contrôle :
- Lit une valeur de distance filtrée.
- Si la lecture échoue, ce cycle est ignoré.
- Si un obstacle est plus proche que ``alert_distance``, le robot joue un son d’avertissement et tourne à gauche.
- Sinon, il avance.
#. Bloc d’entrée du programme (boucle continue + arrêt sécurisé)
.. code-block:: python
if __name__ == "__main__":
try:
crawler.do_step('stand', 40)
while True:
main()
except KeyboardInterrupt:
print("\nStop.")
finally:
crawler.do_step('sit', 40)
Ce bloc contrôle le flux global du programme :
- Le robot se met debout avant de commencer.
- Le programme exécute ``main()`` en boucle infinie.
- Appuyer sur Ctrl+C arrête la boucle.
- Le robot se remet en position assise avant la fin du programme.