Raspberry Pi + Arduino : Système de Surveillance IoT Complet en Tunisie

Raspberry Pi + Arduino : Système de Surveillance IoT Complet en Tunisie

Guides Raspberry Pi

Raspberry Pi + Arduino : Système de Surveillance IoT Complet en Tunisie

Architecture hybride Pi + Arduino pour la surveillance IoT en Tunisie : OpenCV, PIR, Telegram, Home Assistant, ML face recognition. Code Python + Arduino complet.

5 avril 202616 min de lectureÉquipe Didactico

Sfax, mars 2026. Hamza, étudiant en 5ème année à l’INSAT, défend son PFE devant le jury. Son projet : un système de surveillance domotique complet pour la villa familiale, capable de détecter une intrusion, identifier les membres de la famille par reconnaissance faciale, déclencher une sirène, prévenir les voisins via Telegram, et tout journaliser dans un Home Assistant accessible depuis n’importe où dans le monde. Coût total des composants : moins de 350 dinars. Coût de l’équivalent commercial (Ring Pro + abonnement + capteurs Aqara + alarme Verisure) : plus de 4000 dinars. La différence ? Hamza a marié un Raspberry Pi 4 et un Arduino UNO dans une architecture hybride bien pensée. Voyons comment reproduire ce système chez vous, étape par étape.

Pourquoi pas un seul microcontrôleur ?

La question est légitime. Pourquoi compliquer avec 2 cartes au lieu d’utiliser un ESP32 unique, ou un Raspberry Pi seul ? Réponse : séparation des tâches selon les forces de chaque plateforme.

Forces du Raspberry Pi

  • Linux complet → OpenCV, Python, Docker, Home Assistant tournent nativement
  • Wi-Fi 5 + Bluetooth + Ethernet Gigabit
  • 4-8 Go de RAM pour traiter de la vidéo HD
  • Stockage SD/USB illimité pour archiver des vidéos
  • SSH, web server, accès distant — tout l’arsenal cloud-native

Faiblesses du Raspberry Pi

  • GPIO 3.3V uniquement (le 5V grille le SoC)
  • Pas de timer hardware déterministe (Linux n’est pas temps réel)
  • Boot 30-60 secondes (catastrophique pour une alarme qui doit démarrer en 100 ms)
  • Sensible aux coupures de courant (corruption SD)
  • Une seule interruption GPIO bloque potentiellement le système

Forces de l’Arduino UNO

  • Microcontrôleur ATmega328P pur — pas d’OS, démarrage instantané
  • Pins 5V tolérants → directement compatibles avec PIR, capteurs Hall, relais 5V
  • Interruptions hardware déterministes
  • Pas de risque de corruption à l’arrêt brutal
  • Consommation ultra-faible (~20 mA)

Faiblesses de l’Arduino

  • 2 Ko de SRAM — pas question d’OpenCV ou de TensorFlow
  • Pas de Wi-Fi natif
  • Pas de système de fichiers

La conclusion s’impose : Arduino fait le travail temps réel (lire PIR, déclencher sirène, gérer relais), Pi fait le travail intelligent (analyser la vidéo, notifier, archiver, exposer une API).

Architecture hybride : la division des tâches

Voici le schéma fonctionnel du système :

┌───────────────────────────────────────┐
│         RASPBERRY PI 4 (Linux)        │
│                                       │
│  Pi Camera v3 ──► OpenCV ──► Motion   │
│                       │       Detect  │
│                       ▼               │
│             Telegram Notify           │
│                       │               │
│             Home Assistant            │
│                       │               │
│             Flask Dashboard           │
└───────────────┬───────────────────────┘
                │ USB Serial 115200
                │ JSON messages
                ▼
┌───────────────────────────────────────┐
│         ARDUINO UNO (temps réel)      │
│                                       │
│  PIR HC-SR501 ──► Détection IR        │
│  Reed switch  ──► Porte ouverte ?     │
│  Buzzer       ◄── Alerte sonore       │
│  Relais 5V    ◄── Sirène 12V          │
│  LED RGB      ◄── État système        │
└───────────────────────────────────────┘

Le Pi est le « cerveau » et exécute la logique métier (algorithmes, notifications, web). L’Arduino est le « bras armé » qui interface avec le monde physique en temps réel.

Composants et budget complet

Composant Référence Prix DT (Didactico)
Raspberry Pi 4 4GB RPi 4B 4GB 180 DT
Alim Pi USB-C 5V/3A Officielle 25 DT
microSD 64 Go classe A1 SanDisk Ultra 30 DT
Pi Camera v3 Module v3 Wide 90 DT
Arduino UNO R3 Officiel ou clone 35-65 DT
Câble USB-A vers USB-B Standard 5 DT
Capteur PIR HC-SR501 5V, portée 7m 8 DT
Capteur magnétique porte Reed switch 6 DT
Buzzer 5V passif Piézo 3 DT
Module relais 5V 1 canal SRD-05VDC 8 DT
Sirène 12V 110 dB Alarme classique 25 DT
Boîtier impression 3D PLA Bambu Lab A1 ~5 DT filament
TOTAL ~420 DT

Communication Pi ↔ Arduino

Deux protocoles dominants :

Option A : USB Serial 115200 baud (recommandé)

  • Simple : un câble USB-A vers USB-B, et c’est fini
  • Alimente l’Arduino (5V) en même temps
  • Le Pi voit l’Arduino comme /dev/ttyACM0 ou /dev/ttyUSB0
  • Pas de problème de niveaux logiques (l’USB s’occupe de tout)
  • Protocole : JSON ligne par ligne

Option B : I2C avec Pi en master

  • Plus rapide pour transactions courtes (1 ms vs 8 ms USB Serial)
  • Permet plusieurs Arduino sur le même bus
  • MAIS nécessite un convertisseur de niveau 3.3V ↔ 5V obligatoire
  • Complexité supplémentaire — réservez à l’option B aux cas spécifiques

Pour ce projet, on choisit l’option A USB Serial. Plus simple, plus robuste, suffisamment rapide.

Protocole JSON ligne par ligne

# Messages Arduino → Pi (1 ligne JSON par événement) :
{"type":"pir","value":1,"ts":12345}
{"type":"door","value":"open","ts":12350}
{"type":"heartbeat","uptime":3600}

# Messages Pi → Arduino :
{"cmd":"siren","state":"on","duration":30}
{"cmd":"led","color":"red"}
{"cmd":"buzzer","freq":440,"ms":200}

Code Arduino : capteurs et actionneurs temps réel

// surveillance-arduino.ino
#include <ArduinoJson.h>

const int PIR_PIN     = 2;   // Interruption hardware
const int DOOR_PIN    = 3;   // Reed switch (pull-up interne)
const int BUZZER_PIN  = 8;
const int RELAY_PIN   = 9;
const int LED_R       = 5;
const int LED_G       = 6;
const int LED_B       = 7;

volatile bool pirTriggered = false;
bool sirenActive   = false;
unsigned long sirenUntil = 0;
unsigned long lastHeartbeat = 0;

void pirISR() { pirTriggered = true; }

void setup() {
  Serial.begin(115200);
  pinMode(PIR_PIN, INPUT);
  pinMode(DOOR_PIN, INPUT_PULLUP);
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(LED_R, OUTPUT);
  pinMode(LED_G, OUTPUT);
  pinMode(LED_B, OUTPUT);

  attachInterrupt(digitalPinToInterrupt(PIR_PIN), pirISR, RISING);

  // LED verte = système OK
  digitalWrite(LED_G, HIGH);
}

void sendEvent(const char* type, const char* value) {
  StaticJsonDocument<128> doc;
  doc["type"]  = type;
  doc["value"] = value;
  doc["ts"]    = millis();
  serializeJson(doc, Serial);
  Serial.println();
}

void checkCommands() {
  if (Serial.available()) {
    StaticJsonDocument<256> doc;
    DeserializationError err = deserializeJson(doc, Serial);
    if (err) return;

    const char* cmd = doc["cmd"];
    if (strcmp(cmd, "siren") == 0) {
      const char* state = doc["state"];
      if (strcmp(state, "on") == 0) {
        int duration = doc["duration"] | 30;
        digitalWrite(RELAY_PIN, HIGH);
        sirenActive = true;
        sirenUntil  = millis() + duration * 1000UL;
        digitalWrite(LED_R, HIGH);
        digitalWrite(LED_G, LOW);
      } else {
        digitalWrite(RELAY_PIN, LOW);
        sirenActive = false;
        digitalWrite(LED_R, LOW);
        digitalWrite(LED_G, HIGH);
      }
    } else if (strcmp(cmd, "buzzer") == 0) {
      int freq = doc["freq"] | 440;
      int ms   = doc["ms"]   | 200;
      tone(BUZZER_PIN, freq, ms);
    }
  }
}

void loop() {
  // 1. Capteur PIR (interruption ISR)
  if (pirTriggered) {
    pirTriggered = false;
    sendEvent("pir", "1");
  }

  // 2. Capteur porte (lecture polling - changement d'état)
  static int lastDoor = HIGH;
  int curDoor = digitalRead(DOOR_PIN);
  if (curDoor != lastDoor) {
    sendEvent("door", curDoor == LOW ? "open" : "closed");
    lastDoor = curDoor;
  }

  // 3. Timeout sirène automatique (sécurité)
  if (sirenActive && millis() > sirenUntil) {
    digitalWrite(RELAY_PIN, LOW);
    sirenActive = false;
    digitalWrite(LED_R, LOW);
    digitalWrite(LED_G, HIGH);
  }

  // 4. Heartbeat toutes les 30 s
  if (millis() - lastHeartbeat > 30000) {
    StaticJsonDocument<128> doc;
    doc["type"]   = "heartbeat";
    doc["uptime"] = millis() / 1000;
    serializeJson(doc, Serial);
    Serial.println();
    lastHeartbeat = millis();
  }

  // 5. Lire commandes du Pi
  checkCommands();
}

Code Python Pi : OpenCV, Telegram, Flask

Côté Pi, on a 3 tâches en parallèle (lancées via threads ou processus) :

  1. Lecture série Arduino et réaction aux événements
  2. Analyse vidéo OpenCV en continu (motion detection)
  3. Dashboard Flask exposant le live stream et l’historique

Lecture série + Telegram

# surveillance_pi.py
import serial
import json
import requests
import threading
import time
from datetime import datetime

TELEGRAM_TOKEN = "votre_bot_token"
TELEGRAM_CHAT  = "votre_chat_id"
SERIAL_PORT    = "/dev/ttyACM0"

ser = serial.Serial(SERIAL_PORT, 115200, timeout=1)
time.sleep(2)  # Reset Arduino

def notify_telegram(text, photo_path=None):
    """Envoie un message ou une photo via Telegram bot."""
    base = f"https://api.telegram.org/bot{TELEGRAM_TOKEN}"
    if photo_path:
        with open(photo_path, "rb") as f:
            requests.post(
                f"{base}/sendPhoto",
                data={"chat_id": TELEGRAM_CHAT, "caption": text},
                files={"photo": f},
                timeout=10
            )
    else:
        requests.post(
            f"{base}/sendMessage",
            data={"chat_id": TELEGRAM_CHAT, "text": text},
            timeout=10
        )

def send_arduino(cmd):
    """Envoie une commande JSON à l'Arduino."""
    ser.write((json.dumps(cmd) + "n").encode())

def listen_arduino():
    """Thread d'écoute série permanent."""
    while True:
        line = ser.readline().decode(errors="ignore").strip()
        if not line:
            continue
        try:
            event = json.loads(line)
        except json.JSONDecodeError:
            continue

        ts = datetime.now().strftime("%H:%M:%S")
        print(f"[{ts}] {event}")

        if event["type"] == "pir":
            # Mouvement détecté → capture photo et notify
            from camera import capture_snapshot
            snap = capture_snapshot()
            notify_telegram(f"🚨 Mouvement à {ts}", snap)
            # Déclenche sirène 30 s
            send_arduino({"cmd": "siren", "state": "on", "duration": 30})
        elif event["type"] == "door" and event["value"] == "open":
            notify_telegram(f"🚪 Porte ouverte à {ts}")

if __name__ == "__main__":
    threading.Thread(target=listen_arduino, daemon=True).start()
    while True:
        time.sleep(60)

Détection de mouvement OpenCV (camera.py)

# camera.py
import cv2
import numpy as np
from picamera2 import Picamera2
from datetime import datetime

picam = Picamera2()
config = picam.create_video_configuration(main={"size": (1280, 720)})
picam.configure(config)
picam.start()

prev_frame = None

def capture_snapshot():
    """Capture une photo et retourne le chemin."""
    path = f"/tmp/snap_{datetime.now().strftime('%Y%m%d_%H%M%S')}.jpg"
    frame = picam.capture_array()
    cv2.imwrite(path, frame)
    return path

def detect_motion():
    """Boucle OpenCV de détection de mouvement (différence frames)."""
    global prev_frame
    while True:
        frame = picam.capture_array()
        gray  = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
        gray  = cv2.GaussianBlur(gray, (21, 21), 0)

        if prev_frame is None:
            prev_frame = gray
            continue

        delta  = cv2.absdiff(prev_frame, gray)
        thresh = cv2.threshold(delta, 25, 255, cv2.THRESH_BINARY)[1]
        thresh = cv2.dilate(thresh, None, iterations=2)
        contours, _ = cv2.findContours(
            thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

        for c in contours:
            if cv2.contourArea(c) < 5000:  # Ignore petits mouvements
                continue
            # Mouvement significatif détecté
            snap = capture_snapshot()
            from surveillance_pi import notify_telegram
            notify_telegram("📹 Mouvement caméra", snap)
            break

        prev_frame = gray

Dashboard Flask

# dashboard.py
from flask import Flask, Response, render_template_string
import cv2

app = Flask(__name__)

HTML = """
<h1>🏠 Surveillance Didactico</h1>
<img src="/stream" width="800">
<p>Statut Arduino : {{ status }}</p>
"""

@app.route("/")
def index():
    return render_template_string(HTML, status="OK")

def generate_stream():
    from camera import picam
    while True:
        frame = picam.capture_array()
        _, jpg = cv2.imencode(".jpg", frame)
        yield (b"--framernContent-Type: image/jpegrnrn" +
               jpg.tobytes() + b"rn")

@app.route("/stream")
def stream():
    return Response(generate_stream(),
                    mimetype="multipart/x-mixed-replace; boundary=frame")

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, threaded=True)

Enregistrement vidéo segmenté

Plutôt qu’un seul énorme fichier vidéo, on découpe en segments de 10 minutes via ffmpeg. Stockage sur SD interne ou disque USB.

# Capture continue segmentée avec libcamera + ffmpeg
libcamera-vid -t 0 --inline --width 1280 --height 720 
  --framerate 25 --codec h264 -o - | 
ffmpeg -i - -c copy -f segment -segment_time 600 
  -reset_timestamps 1 -strftime 1 
  /mnt/usb/cam/cam-%Y%m%d-%H%M%S.mp4

# Nettoyage automatique des vidéos > 14 jours :
find /mnt/usb/cam/ -name "*.mp4" -mtime +14 -delete
# Ajouter au crontab :
0 3 * * * find /mnt/usb/cam/ -name "*.mp4" -mtime +14 -delete

Accès distant : SSH, ngrok, IPv6

Trois options pour accéder à votre Pi depuis l’extérieur :

1. ngrok (le plus simple)

# Installation :
curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | 
  sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null
echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | 
  sudo tee /etc/apt/sources.list.d/ngrok.list
sudo apt update && sudo apt install ngrok
ngrok config add-authtoken VOTRE_TOKEN

# Exposer le dashboard Flask :
ngrok http 5000
# → https://xxxx.ngrok-free.app accessible depuis n'importe où

2. IPv6 natif (Topnet, Orange Tunisie)

Si votre FAI fournit du IPv6 natif (Topnet le fait depuis 2022), chaque appareil de votre maison a une IP publique unique IPv6 directement joignable. Ouvrez les bons ports dans le firewall :

sudo ufw allow 22/tcp           # SSH
sudo ufw allow 5000/tcp         # Flask dashboard
sudo ufw enable

# Trouver votre IPv6 :
ip -6 addr show wlan0 | grep global

3. WireGuard VPN (le plus sécurisé)

Monter un VPN WireGuard sur le Pi, et se connecter depuis le téléphone. Aucun port ouvert vers Internet, traffic chiffré point-à-point. Tutoriel complet sur le wiki WireGuard.

Intégration Home Assistant

En bonus, on peut faire remonter tous les événements PIR/porte/sirène dans Home Assistant via MQTT :

# config Home Assistant - configuration.yaml
mqtt:
  binary_sensor:
    - name: "PIR Entrée"
      state_topic: "didactico/pir"
      payload_on: "1"
      payload_off: "0"
      device_class: motion
    - name: "Porte Entrée"
      state_topic: "didactico/door"
      payload_on: "open"
      payload_off: "closed"
      device_class: door
  switch:
    - name: "Sirène"
      command_topic: "didactico/siren/set"
      state_topic: "didactico/siren/state"
      payload_on: "on"
      payload_off: "off"

# Automation HA : siren + lumière rouge si mouvement la nuit
automation:
  - alias: "Intrusion nocturne"
    trigger:
      platform: state
      entity_id: binary_sensor.pir_entree
      to: "on"
    condition:
      condition: time
      after: "23:00:00"
      before: "06:00:00"
    action:
      - service: switch.turn_on
        entity_id: switch.sirene
      - service: light.turn_on
        data:
          entity_id: light.salon
          color_name: red

ML face recognition pour la famille

Pour éviter les fausses alarmes (la famille rentre du travail), on ajoute de la reconnaissance faciale. La librairie face_recognition (basée sur dlib) tourne en CPU sur Pi 4.

# Installation (long, ~30 min sur Pi 4) :
sudo apt install -y cmake libopenblas-dev liblapack-dev
pip3 install face_recognition opencv-python

# Apprentissage des visages :
mkdir -p /home/didactico/faces/{papa,maman,hamza,sara}
# Mettre 3-5 photos par personne dans chaque dossier

# encode_faces.py
import face_recognition
import os
import pickle

known = {"encodings": [], "names": []}
for person in os.listdir("/home/didactico/faces"):
    for f in os.listdir(f"/home/didactico/faces/{person}"):
        img = face_recognition.load_image_file(
            f"/home/didactico/faces/{person}/{f}")
        encs = face_recognition.face_encodings(img)
        if encs:
            known["encodings"].append(encs[0])
            known["names"].append(person)

with open("faces.pkl", "wb") as f:
    pickle.dump(known, f)

# Reconnaissance live :
import pickle
import face_recognition
import cv2

with open("faces.pkl", "rb") as f:
    known = pickle.load(f)

def identify(frame):
    rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    locations = face_recognition.face_locations(rgb)
    encodings = face_recognition.face_encodings(rgb, locations)
    names = []
    for enc in encodings:
        matches = face_recognition.compare_faces(
            known["encodings"], enc, tolerance=0.5)
        name = "INCONNU"
        if True in matches:
            idx = matches.index(True)
            name = known["names"][idx]
        names.append(name)
    return names

# Dans la boucle de détection :
names = identify(frame)
if "INCONNU" in names:
    notify_telegram(f"⚠️ Visage inconnu détecté !")
    send_arduino({"cmd": "siren", "state": "on", "duration": 60})
else:
    notify_telegram(f"👋 {', '.join(names)} rentre à la maison")

Sécurité réseau et hardening

⚠️ Sécurité critique Un système de surveillance mal sécurisé est pire que pas de système : un attaquant peut désactiver vos alarmes et regarder vos vidéos. Appliquez impérativement les mesures ci-dessous.

Checklist hardening Pi

  • Changer le mot de passe par défaut (pi/raspberry est interdit en 2026)
  • Authentification SSH par clé uniquement (désactiver password) :
    # Sur votre PC :
    ssh-keygen -t ed25519 -f ~/.ssh/dida_pi
    ssh-copy-id -i ~/.ssh/dida_pi.pub didactico@pi.local
    
    # Sur le Pi, /etc/ssh/sshd_config :
    PasswordAuthentication no
    PermitRootLogin no
    PubkeyAuthentication yes
    sudo systemctl restart ssh
  • fail2ban pour bloquer les attaques bruteforce :
    sudo apt install -y fail2ban
    sudo nano /etc/fail2ban/jail.local
    # Ajouter :
    #   [sshd]
    #   enabled = true
    #   maxretry = 3
    #   bantime = 3600
    sudo systemctl enable --now fail2ban
  • HTTPS sur le dashboard Flask (Let’s Encrypt via nginx + certbot)
  • Updates automatiques (unattended-upgrades) :
    sudo apt install -y unattended-upgrades
    sudo dpkg-reconfigure unattended-upgrades
  • Backup quotidien de la SD (image disque vers NAS ou cloud chiffré)
📹
SYSTÈME COMPLET

Raspberry Pi 4 + Arduino UNO

Le combo parfait pour vos projets de surveillance, domotique et PFE IoT. Tous les composants disponibles chez Didactico Sfax avec livraison 24-48h partout en Tunisie.

Voir Pi + Arduino →

FAQ Pi + Arduino surveillance

Pourquoi un Arduino quand un ESP32 ferait les deux à la fois ?

Un ESP32 est plus puissant qu’un UNO, mais il reste limité (520 Ko RAM, pas de Linux). Pour la vision OpenCV, le ML face recognition et Home Assistant, il faut absolument un Pi. L’Arduino sert juste à offloader le temps réel critique (PIR, sirène, watchdog). Vous pouvez remplacer l’Arduino UNO par un ESP32 si vous voulez ajouter du WiFi/MQTT direct côté capteurs.

Quelle distance maximum entre Pi et Arduino en USB ?

Câble USB standard : 5 mètres. Au-delà, prévoyez un répéteur actif USB (~30 DT) ou passez en RS485 différentiel (compatible jusqu’à 100 m, mais demande des modules MAX485 sur les 2 cartes).

Le PIR HC-SR501 a-t-il beaucoup de faux positifs ?

Le HC-SR501 est sensible aux courants d’air chauds, aux insectes, à la lumière directe du soleil. Réglez les 2 potentiomètres (sensibilité et délai), positionnez-le à l’abri du soleil direct, et combinez toujours avec une confirmation vidéo avant de déclencher la sirène. Pour un cas critique (banque, bijouterie), passez sur un capteur PIR dual avec compensation thermique.

Combien de FPS en détection de mouvement OpenCV sur Pi 4 ?

Avec une caméra 1280×720, 15-25 FPS sans accélération GPU, parfait pour la surveillance. Pour de la reconnaissance faciale temps réel, ça tombe à 2-5 FPS — suffisant pour un usage domestique mais pas en streaming live. Si vous voulez plus, passez sur un Pi 5 ou un mini-PC x86 avec Coral USB.

La caméra Pi v3 voit-elle dans le noir ?

Non, c’est une caméra couleur sans IR. Pour la vision nocturne, prenez la Pi NoIR Camera (sans filtre infrarouge) + un projecteur IR 850 nm. Comptez 130-180 DT supplémentaires.

Stocker les vidéos en cloud plutôt que sur SD ?

Oui, plusieurs options : Backblaze B2 (~6 dollars/To/mois), AWS S3 Glacier Deep Archive (~1 dollar/To/mois), ou self-hosted MinIO sur un VPS Hetzner (~5 euros/mois pour 80 Go). Configurez rclone sur le Pi pour synchroniser /mnt/usb/cam toutes les heures.

Le système consomme combien d’électricité ?

Pi 4 (~5W) + Arduino UNO (~0.5W) + Pi Camera (~0.5W) + sirène en veille (négligeable) = environ 6W en moyenne, soit ~0.144 kWh/jour. À 250 millimes le kWh STEG, ça représente moins de 1.1 DT par mois.

Conclusion

L’architecture hybride Raspberry Pi + Arduino n’est pas un compromis bâtard : c’est la séparation idéale des préoccupations en IoT moderne. Le Pi orchestre, le Arduino agit. Cette répartition vous permet d’obtenir un système de surveillance de niveau commercial pour le prix d’une soirée pizza, tout en gardant le contrôle total sur vos données (pas de cloud propriétaire, pas d’abonnement mensuel, pas de fuite vers des serveurs étrangers).

Pour les étudiants de l’INSAT, ENIT, ISBS et ISET, ce projet constitue une base solide de PFE qui peut s’étendre vers l’IA embarquée (TensorFlow Lite sur Pi), la sécurité offensive (pentest WiFi avec le même matériel), ou l’IoT industriel (passerelle LoRaWAN). Tous les composants sont en stock chez Didactico Sfax avec livraison 24-48h partout en Tunisie.

Pour aller plus loin, consultez nos guides Raspberry Pi Zero et 5 projets Raspberry Pi débutants.