Au cours de l’année, nous avons travaillé sur un projet de canard télécommandé, pour cela nous avons utilisé ce matériel :
Pour relier tout ce système nous avons soudé tous les câbles nécessaires au bon fonctionnement du système.
L'objectif sera de créer un serveur sur la carte raspberry pour recevoir le flux vidéo de la caméra, l'encoder et l'envoyer sur un site web. De plus depuis ce site web nous devrions pouvoir diriger le canard. Pour que le canard puisse se déplacer nous allons utilisé des propolseurs.
2 | Pile 9V | |
2 | Propulseur miniature submersible | amazone réf. B07WY4MDYZ |
1 | Une carte raspberry pi4 | kubii réf. PI5 |
1 | Mini caméra filaire | okdo réf. 2020456 |
1 | Batterie externe | keja 78290 |
4 | Relais | iduino ME108 |
1 | Haut parleur | sl-200 (action) |
Nombre | Materiels | Réference |
---|
![]() |
![]() |
![]() |
![]() |
![]() |
|
![]() |
![]() |
![]() |
![]() |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <style> body { background-image:url(fondécran.jpg); background-repeat: no-repeat; background-size: cover; } svg { width: 130px; height: 130px; margin: 15px 15px 15px 15px; position: relative; top: -500px; left: 900px; } h1 { font-size: 48px; font-family: Gotham, Tahoma, Fantasy; color: #fdf1b8 ; position: relative; left: 683px; } iframe { border: thick double #fdf1b8; position: relative; top: -10px; left: 150px; } #rec { position: relativ; top: -360px; left: 90px; width: 120px; height: 120px; } #off { position: relativ; top: -360px; left:850px; width: 120px; heigt: 120px; } </style> <script> ordre=function (val) { var xhr=new XMLHttpRequest(); xhr.open("GET", val, true); xhr.send(null); }; </script> <title> CANARD ESPION </title> </head> <body> <h1>CANARD ESPION</h1> <iframe src="http://192.168.42.191:8000" width="660" height="500" ></iframe> <br> <svg></svg> <svg onclick="ordre('A1');" viewBox="0 0 24 24" fill="none" stroke="#fdf1b8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M16 12l-4-4-4 4M12 16V9"/></svg> <br> <svg onclick="ordre('G1');" viewBox="0 0 24 24" fill="none" stroke="#fdf1b8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 8l-4 4 4 4M16 12H9"/></svg> <svg onclick="ordre('A0');" viewBox="0 0 24 24" fill="none" stroke="#fdf1b8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><rect x="9" y="9" width="6" height="6"></rect></svg> <svg onclick="ordre('D1');" viewBox="0 0 24 24" fill="none" stroke="#fdf1b8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 8l4 4-4 4M8 12h7"/></svg> <br> <svg></svg> <svg onclick="ordre('A-1');" viewBox="0 0 24 24" fill="none" stroke="#fdf1b8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10"/><path d="M16 12l-4 4-4-4M12 8v7"/></svg> <svg id="rec" onclick="ordre('rec');" viewBox="0 0 24 24" fill="none" stroke="#fdf1b8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><polygon points="10 8 16 12 10 16 10 8"></polygon></svg> <svg id="off" onclick="ordre('off');" viewBox="0 0 24 24" fill="none" stroke="#fdf1b8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18.36 6.64a9 9 0 1 1-12.73 0"></path><line x1="12" y1="2" x2="12" y2="12"></line></svg> </body> </html>
marche.sh #!/bin/bash ./camera.py 1>/dev/null 2>/dev/null & sleep 15 ./serveur.py 1>/dev/null 2>/dev/null &
stop.sh #!/bin/bash killall camera.py killall serveur.py
#!/usr/bin/python3 import io import logging import socketserver from http import server from threading import Condition from picamera2 import Picamera2 from picamera2.encoders import JpegEncoder from picamera2.outputs import FileOutput # HTML page for the MJPEG streaming demo PAGE = """\ <!DOCTYPE html > <html > <img src="stream.mjpg" width="640" height="480" > </html > """ # Class to handle streaming output class StreamingOutput(io.BufferedIOBase): def __init__(self): self.frame = None self.condition = Condition() def write(self, buf): with self.condition: self.frame = buf self.condition.notify_all() # Class to handle HTTP requests class StreamingHandler(server.BaseHTTPRequestHandler): def do_GET(self): if self.path == '/': # Redirect root path to index.html self.send_response(301) self.send_header('Location', '/index.html') self.end_headers() elif self.path == '/index.html': # Serve the HTML page content = PAGE.encode('utf-8') self.send_response(200) self.send_header('Content-Type', 'text/html') self.send_header('Content-Length', len(content)) self.end_headers() self.wfile.write(content) elif self.path == '/stream.mjpg': # Set up MJPEG streaming self.send_response(200) self.send_header('Age', 0) self.send_header('Cache-Control', 'no-cache, private') self.send_header('Pragma', 'no-cache') self.send_header('Content-Type', 'multipart/x-mixed-replace; boundary=FRAME') self.end_headers() try: while True: with output.condition: output.condition.wait() frame = output.frame self.wfile.write(b'--FRAME\r\n') self.send_header('Content-Type', 'image/jpeg') self.send_header('Content-Length', len(frame)) self.end_headers() self.wfile.write(frame) self.wfile.write(b'\r\n') except Exception as e: logging.warning( 'Removed streaming client %s: %s', self.client_address, str(e)) else: # Handle 404 Not Found self.send_error(404) self.end_headers() # Class to handle streaming server class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer): allow_reuse_address = True daemon_threads = True # Create Picamera2 instance and configure it picam2 = Picamera2() picam2.configure(picam2.create_video_configuration(main={"size": (640, 480)})) output = StreamingOutput() picam2.start_recording(JpegEncoder(), FileOutput(output)) try: # Set up and start the streaming server address = ('', 8000) server = StreamingServer(address, StreamingHandler) server.serve_forever() finally: # Stop recording when the script is interrupted picam2.stop_recording()
serveur.py #!/usr/bin/python3 import RPi.GPIO as GPIO import http.server import os from picamera2 import Picamera2 import subprocess import time import sys time.sleep(15) # Configuration des GPIO pour contrôler les moteurs GPIO.setwarnings(False) # Désactiver les avertissements GPIO.setmode(GPIO.BCM) GPIO.setup(22, GPIO.OUT) GPIO.setup(23, GPIO.OUT) GPIO.setup(24, GPIO.OUT) GPIO.setup(25, GPIO.OUT) # Serveur Web sur le port 5555 class rep(http.server.SimpleHTTPRequestHandler): def do_GET(self): if self.path == '/A1': GPIO.output(23, GPIO.HIGH) GPIO.output(22, GPIO.LOW) GPIO.output(24, GPIO.HIGH) GPIO.output(25, GPIO.LOW) elif self.path == '/G1': GPIO.output(23, GPIO.HIGH) GPIO.output(22, GPIO.LOW) GPIO.output(24, GPIO.LOW) GPIO.output(25, GPIO.LOW) elif self.path == '/A0': GPIO.output(23, GPIO.LOW) GPIO.output(22, GPIO.LOW) GPIO.output(24, GPIO.LOW) GPIO.output(25, GPIO.LOW) elif self.path == '/D1': GPIO.output(22, GPIO.LOW) GPIO.output(23, GPIO.LOW) GPIO.output(24, GPIO.HIGH) GPIO.output(25, GPIO.LOW) elif self.path == '/A-1': GPIO.output(23, GPIO.LOW) GPIO.output(22, GPIO.HIGH) GPIO.output(24, GPIO.LOW) GPIO.output(25, GPIO.HIGH) elif self.path == '/rec': os.system('mpg123 /home/eric/son_canard.mp3') elif self.path == '/off': os.system('sudo reboot') else: super().do_GET() adr = ("", 5555) http.server.HTTPServer(adr, rep).serve_forever() Utiliser crontab Une autre méthode est d'utiliser cron, un planificateur de tâches Unix. Vous pouvez ajouter une tâche cron pour exécuter votre script au démarrage. Éditez la crontab pour l'utilisateur pi : sh Copier le code crontab -e Ajoutez la ligne suivante à la fin du fichier : @reboot /home/pi/monscript.sh Enregistrez et quittez l'éditeur : Si vous utilisez nano, appuyez sur Ctrl+X, puis Y et Enter.
Donc le canard n'a pas explosé.