Outils pour utilisateurs

Outils du site


failomaton

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
failomaton [2023/11/16 20:28] – [Failomaton] Mushussufailomaton [2024/05/18 13:09] (Version actuelle) – [Caméra] Mushussu
Ligne 1: Ligne 1:
 ====== Failomaton ====== ====== Failomaton ======
 Le projet est de réaliser un photomaton qui vous rate le portrait consciencieusement. Un bijou de technologie pour un résultat décevant. Le projet est de réaliser un photomaton qui vous rate le portrait consciencieusement. Un bijou de technologie pour un résultat décevant.
 +
 +{{ :failomatonbeta1.mp4 |Version de test}}
 +
 +
 +==== A faire ====
 +* Un bouton de redémarrage du programme
 +* La gestion du manque de papier
 +* Monnayeur
 +===== Conception du distributeur de photos =====
 +{{:pieces_2d.png?200|Pièces 2D}}
 +
 +<code cpp>
 +
 +$fn = 200;
 +
 +// Épaisseur CP 10mm
 +
 +cote();
 +translate([350, 145]) rotate(180) cote();
 +translate([290, 165]) rotate(90) support();
 +
 +translate([305, 155]) rotate(90) mirror([0, 1, 0]) glissiere();
 +translate([330, 470]) rotate(180) glissiere();
 +
 +translate([15, 600]) rotate(-90) trapeze();
 +translate([123, 558]) mirror([0, 1, 0]) trapeze();
 +
 +// Épaisseur CP 15mm
 +
 +translate([-120, 50]) renfort1();
 +translate([-10, 50]) mirror([1, 0, 0]) renfort1();
 +
 +translate([-260, 0]) rotate(-30) ecarteur();
 +translate([-30, 30]) rotate(150) ecarteur();
 +
 +module cote() {
 +    difference() {
 +        union() {
 +            square([290, 150]);
 +            translate([90, -10]) square([30, 10]);
 +        }
 +        square([55, 6]); // Encoche rabat
 +        translate([290, 0]) rotate(-30) translate([-400, 0]) square([400, 200]);
 +        translate([0, 80]) rotate(-30) translate([-100, 0]) square([100, 100]);
 +        translate([265, 0]) rotate(-30) square([100, 100]); // Petite pointe
 +        translate([0, 80]) rotate(-30) translate([-100, 0]) square([100, 100]); 
 +        // Encoches glissieres
 +        translate([290,0]) rotate(-30) translate([-131.6, -10]) square([50, 11]); 
 +        translate([290,0]) rotate(-30) translate([-231.6, -10]) square([50, 11]);
 +    }
 +}
 +
 +module support() {
 +    difference() {
 +        square([236, 290]);
 +        translate([49.9, 34.9]) square([10.2, 30.2]);
 +        translate([175.9, 34.9]) square([10.2, 30.2]);
 +        translate([16.9, 84.9]) square([16.2,15.2]);
 +        translate([202.9, 84.9]) square([16.2,15.2]);
 +    }
 +}
 +
 +module glissiere() {
 +    difference() {
 +        square([331.6, 60]);
 +        square([60.1, 10]);
 +        translate([109.9, 0]) square([50.2, 10]);
 +        translate([209.9, 0]) square([150, 35]);
 +    }
 +}
 +
 +module trapeze() {
 +    difference() {
 +        square([135 * cos(30) + 40, 135 * sin(30)]);
 +        rotate(30) square([200, 200]);
 +        translate([0, 2]) difference() {
 +            translate([0, 58]) resize([320, 116]) circle(d=100);
 +            translate([0, 58]) resize([315.3, 111.5]) circle(d=100);
 +            translate([0, 58]) square([200, 100]);
 +        }
 +    }
 +    difference() {
 +        rotate(30) translate([-20, 0]) square([200, 30]);
 +        translate([0, 135 * sin(30)]) square([200, 100]);
 +    }
 +    translate([135 * cos(30) + 39.9,0]) square([0.1, 135 * sin(30)]); // Fil pour créer une poche pour la CNC
 +}
 +
 +module ecarteur() {
 +    difference() {
 +        rotate(30) translate([-20, 0]) square([200, 30]);
 +        translate([0, 135 * sin(30)]) square([200, 100]);
 +    }  
 +}
 +
 +module renfort1() {
 +    difference() {
 +        square([49.9, 50]);
 +        translate([-15, 0]) rotate(45) square([100, 100]);
 +    }
 +    translate([17, -10]) square([16, 10]);
 +}
 +</code>
 ===== Installation de ImageMagick ===== ===== Installation de ImageMagick =====
 Installation du paquet Installation du paquet
Ligne 73: Ligne 176:
 Éditer le fichier de configuration de CUPS : Éditer le fichier de configuration de CUPS :
   sudo nano /etc/cups/cupsd.conf   sudo nano /etc/cups/cupsd.conf
 +Ajouter les ligne. suivantes au début du fichier :
 +  # Efface l'historiq<ue des tâches 
 +  PreserveJobHistory No
 Modifier la section suivante : Modifier la section suivante :
   # Only listen for connections from the local machine.   # Only listen for connections from the local machine.
Ligne 156: Ligne 262:
 Pour imprimer une photo Pour imprimer une photo
   lp -d Canon_SELPHY_CP1300 photo1.jpg   lp -d Canon_SELPHY_CP1300 photo1.jpg
 +===== Installation complémentaire =====
 +==== Reconnaissance de la clef ====
 +Nous souhaitons mettre les fichiers audios sur une clef USB, afin que leurs modifications soient plus aisées et que les photos prises soient aussi sauvegardées sur la clef.
 +
 +Les clefs sont gérées par des fichiers situés dans le répertoire /dev. Afin de connaitre le nom du fichier. Avant d'insérer la clef, tapez :
 +  ls /dev
 +Une fois insérée tapez de nouveau :
 +  ls /dev
 +Vous noterez des noms qui apparaîssent du style sdX et sdX Y. X prenant la forme d'une lettre (a, b, c, d, …) et Y d'un chiffre indiquant le numéro de partition de la clef.
 +
 +Ici, apparaissent sda et sda 1
 +==== Montage de la clef ====
 +Avant de procéder au montage proprement dit, il faut créer un répertoire qui permettra de naviguer dedans.
 +  mkdir /media/usb
 +Ensuite ouvrir le fichier mtab
 +  sudo nano /etc/mtab
 +Observer le fichier aucune ligne ne doit commencer par : /dev/sda1 /media/usb
 +Ctrl + X pour quitter
 +Monter le la partition de la clef :
 +  sudo mount -t vfat /dev/sda1 /media/usb -o rw,users,umask=0
 +Ouvrez de nouveau mtab
 +  sudo nano /etc/mtab
 +La dernière ligne commence par : /dev/sda1 /media/usb
 +Copier cette ligne
 +Ctrl + x pour quitter
 +Ouvrez le fichier fstab
 +  sudo nano /etc/fstab
 +Coller la ligne à la fin du fichier. Ctrl + o, Ctrl + x pour enregistrer et quitter
 +  sudo reboot
 +Pour que tout soit bien intégrer.
 +
 +
 ===== Code ===== ===== Code =====
 +A tester :
 +  cat file.wav > /dev/audio
 ==== Fichier de configuration de la caméra ==== ==== Fichier de configuration de la caméra ====
 Placer un fichier config.txt dans le répertoire où est placé le fichier en C Placer un fichier config.txt dans le répertoire où est placé le fichier en C
Ligne 166: Ligne 306:
 ==== Code C pour la Raspberry Pi ==== ==== Code C pour la Raspberry Pi ====
 <code c> <code c>
-// gcc -Wall -o test test.c -lwiringPi+// g++ -Wall -o test `cups-config --cflags` test.c `cups-config --libs` -lwiringPi
  
 #include <dirent.h> #include <dirent.h>
Ligne 174: Ligne 314:
 #include <string.h> #include <string.h>
 #include <signal.h> #include <signal.h>
 +#include <sys/types.h>
 #include <time.h> #include <time.h>
 #include <stdlib.h> #include <stdlib.h>
 +#include <sys/wait.h>
 +#include <cups/cups.h>
 +
 +#include <string>
 +#include <iostream>
 +
 +#define boutonPhoto 26 // Fil rouge
 +#define vibrationArduino 27 // Fil vert
 +#define declenchementArduino 28 // Fil jaune
 +#define monnayeur 29 // Fil blanc
  
 int nbPhotos = 0; int nbPhotos = 0;
 time_t compteurTemps; time_t compteurTemps;
 +static pid_t pidAttente = 0;
 +static pid_t pidProcedure = 0;
 +static pid_t pidPhoto = 0;
 +static pid_t pidAssistance = 0;
 +
 +int attente = 0;
 +int procedure = 0;
  
 void reverse(char s[]) void reverse(char s[])
Ligne 190: Ligne 348:
          s[j] = c;          s[j] = c;
      }      }
- +} 
 void itoa(int n, char s[]) void itoa(int n, char s[])
  {  {
Ligne 205: Ligne 364:
      s[i] = '\0';      s[i] = '\0';
      reverse(s);      reverse(s);
-+}
  
 void photo() { void photo() {
     time_t temps = time(NULL);     time_t temps = time(NULL);
-    if (difftime(temps, compteurTemps) > 3) // Permet d'éliminer les rebonds de l'interrupteur+    if (difftime(temps, compteurTemps) > 5) // Permet d'éliminer les rebonds de l'interrupteur
     {     {
         compteurTemps = temps;         compteurTemps = temps;
-        char buffer [6]; +        if (procedure == 0) { 
-        itoa(nbPhotos, buffer); +            procedure = 1; 
-        char src[40] = "/home/pi/Photos/photo_"+            kill(pidAttente, SIGTERM); 
-        strcat(src, buffer); +            printf("Procedure\n"); 
-        strcat(src, ".jpg"); +            if((pidProcedure = fork()) == 0) 
-        printf("%s\n",src); +            { 
-        nbPhotos++; +                execl("/usr/bin/mplayer", 
-        digitalWrite(26, HIGH); +                    "/usr/bin/mplayer", 
-        static pid_t pid = 0; +                    "-really-quiet", 
-        if ((pid = fork()) == 0) +                    "-loop", "0", 
-           +                    "/media/usb/Audio/Procedure.wav", 
-            // libcamera-jpeg --roi 0.25,0.25,0.5,0.-/home/pi/Photos/hghgh.jpg -t 2 +                    NULL); 
-            execl("/usr/bin/libcamera-jpeg", "", "-o", src, "-t", "2", NULL);+            } 
 +            sleep(13); 
 +                digitalWrite(vibrationArduino, HIGH); 
 +            sleep(1); 
 +                digitalWrite(vibrationArduino, LOW); 
 +         } else { 
 +            kill(pidProcedure, SIGTERM); 
 +            printf("Photo\n"); 
 +            if((pidPhoto = fork()) == 0) 
 +            { 
 +                execl("/usr/bin/mplayer", 
 +                    "/usr/bin/mplayer", 
 +                    "-really-quiet", 
 +                    "-loop", "0", 
 +                    "/media/usb/Audio/Photo.wav", 
 +                    NULL); 
 +            } 
 +            sleep(5); 
 +            char buffer [6]; 
 +            itoa(nbPhotos, buffer); 
 +            char src[40] = "/media/usb/Photos/photo_"
 +            strcat(src, buffer); 
 +            strcat(src, ".jpg"); 
 +            printf("%s\n",src); 
 +            nbPhotos++; 
 +            digitalWrite(declenchementArduino, HIGH); 
 +            static pid_t pid = 0; 
 +            if ((pid = fork()) == 0) 
 +            
 +                // libcamera-jpeg -o photo_0.jpg -c config.txt 
 +                execl("/usr/bin/libcamera-jpeg", 
 +                    "", 
 +                    "-o", src, 
 + "--shutter", "800000", 
 +                    "-c", "config.txt", 
 +                    NULL); 
 +            } 
 +            sleep(1); 
 +            digitalWrite(declenchementArduino, LOW); 
 +            FILE * fichier ; 
 +            do 
 +            { 
 +                fichier = fopen(src, "r"); 
 +            } while  (fichier == NULL); 
 +            fclose(fichier); 
 +            static pid_t pid1 = 0
 +            if ((pid1 = fork()) == 0) 
 +            { 
 +                // convert -crop 3836x2592+386+0 -rotate -90 Photos/photo_0.jpg Photos/photo1.jpg 
 +                execl( 
 +                    "/usr/bin/convert", 
 +                    "", 
 +                    "-crop", 
 +                    "3836x2592+386+0", 
 +                    "-rotate", "90", 
 +                    src, src, 
 +                    NULL); 
 +            } 
 +            sleep(2); 
 +            //const char *filename = "photo.jpg"; 
 + 
 +            // Impression de la photo 
 +            http_t *http; 
 +            ipp_t *request, *response; 
 + 
 +            static const char * const requested_attributes[] = 
 +            { 
 +                "printer-description", 
 +                "job-template", 
 +                "media-col-database" 
 +            }; 
 +            http = httpConnect2("localhost", 631, NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL); 
 + 
 +            request = ippNewRequest(IPP_OP_PRINT_JOB); 
 +            ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, "ipp://localhost/printers/Canon_SELPHY_CP1300"); 
 +            ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, "pi"); 
 +            ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", NULL, "image/jpeg"); 
 +            ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "media", NULL, "jpn_hagaki_100x148mm"); 
 +            ippDelete(cupsDoFileRequest(http, request, "/ipp/print", src)); 
 +            sleep(17); 
 +            kill(pidPhoto, SIGTERM); 
 + 
 +            // Test si il manque du papier 
 +            ipp_attribute_t *attr; 
 +            char value[2048]; 
 +            // Procedure 
 +            uint8_t erreur; 
 +            uint8_t assistance = 0; 
 +            do { 
 +                erreur = 0; 
 +                request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); 
 +                ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, "ipp://localhost/printers/Canon_SELPHY_CP1300"); 
 +                ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", NULL, "image/pwg-raster"); 
 +                ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(requested_attributes) / sizeof(requested_attributes[0])), NULL, requested_attributes); 
 + 
 +                response = cupsDoRequest(http, request, "/ipp/print"); 
 +                for (attr = ippFirstAttribute(response); attr; attr = ippNextAttribute(response)) 
 +                { 
 +                    if (strcmp(ippGetName(attr), "printer-state-reasons") == 0) 
 +                    { 
 +                        ippAttributeString(attr, value, sizeof(value)); 
 +                        std::string valeur(value); 
 +                        std::size_t erreurCartouche = valeur.find("marker-supply-empty-error"); 
 +                        std::size_t erreurPapier = valeur.find("media-empty-error"); 
 +                        if (erreurCartouche <= 2048) 
 +                        { 
 +                            // Plus d'encre 
 +                            erreur = 1; 
 +                            if (assistance == 0) { 
 +                                printf("Assistance\n"); 
 + 
 +                                assistance = 1; 
 +                                if((pidAssistance = fork()) == 0) 
 +                                { 
 +                                    execl("/usr/bin/mplayer", 
 +                                    "/usr/bin/mplayer", 
 +                                    "-really-quiet", 
 +                                    "-loop", "0", 
 +                                    "/media/usb/Audio/AssistanceCartouche.wav", 
 +                                    NULL); 
 +                                } 
 +                            } 
 +                        } 
 +                        if (erreurPapier <= 2048) 
 +                        { 
 +                            // Plus de papier 
 +                            erreur = 2
 +                            if (assistance == 0) { 
 +                                printf("Assistance\n"); 
 + 
 +                                assistance = 1; 
 + 
 +                                if((pidAssistance = fork()) == 0) 
 +                                { 
 +                                    execl("/usr/bin/mplayer", 
 +                                    "/usr/bin/mplayer", 
 +                                    "-really-quiet", 
 +                                    "-loop", "0", 
 +                                    "/media/usb/Audio/AssistancePapier.wav", 
 +                                    NULL)
 +                                } 
 +                            } 
 +                        } 
 +                    } 
 +                } 
 +                sleep(3); 
 +            } while (erreur != 0); 
 + 
 +            if (assistance != 0) { 
 + kill(pidAssistance, SIGTERM); 
 +        } 
 +            printf("Fin Photo\n"); 
 +            procedure = 0; 
 +            attente = 0;
         }         }
-        sleep(1); 
-        digitalWrite(26, LOW); 
     }     }
 } }
Ligne 234: Ligne 544:
 { {
     wiringPiSetup();     wiringPiSetup();
-    pinMode (22, INPUT); +    pinMode (boutonPhoto, INPUT); // Pin de l'interrupteur 
-    pullUpDnControl(22, PUD_UP); +    pullUpDnControl(boutonPhoto, PUD_UP); 
-    wiringPiISR (22, INT_EDGE_FALLING, &photo); +    pinMode (monnayeur, INPUT); // Pin du monnayeur 
-    pinMode (26, OUTPUT);+    pullUpDnControl(monnayeur, PUD_UP); 
 + 
 +    //   wiringPiISR (25, INT_EDGE_FALLING, &monnayeur); 
 +    pinMode (declenchementArduino, OUTPUT); // Pin de déclenchement de l'arduino 
 +    pinMode (vibrationArduino, OUTPUT); // Pin de déclenchement de l'arduino
     compteurTemps = time(NULL);     compteurTemps = time(NULL);
-    //system("mplayer -really-quiet /home/pi/Audio/audio01.wav"); +
-    static pid_t pid = 0; +
-    if((pid = fork()) == 0) +
-    { +
-        execl("/usr/bin/mplayer", "/usr/bin/mplayer", "-really-quiet", "/home/pi/Audio/audio01.wav", NULL);     +
-    }+
     // Comptage des fichiers     // Comptage des fichiers
     struct dirent *dir;     struct dirent *dir;
-    DIR *d = opendir("/home/pi/Photos/"); +    DIR *d = opendir("/media/usb/Photos/");
     if (d)     if (d)
     {     {
-        while ((dir = readdir(d)) != NULL) +        while ((dir = readdir(d)) != NULL)
         {         {
             if (dir->d_name[0] != '.')             if (dir->d_name[0] != '.')
Ligne 260: Ligne 569:
         closedir(d);         closedir(d);
     }     }
 +    // Efface tous les travaux d'impression en cours
 +    system("cancel -a -x");
     while(1) {     while(1) {
 +        if (attente == 0) 
 +        { 
 +            attente = 1; 
 +            printf("Invitation\n"); 
 +            // Message d'attente 
 +            if ((pidAttente = fork()) == 0) 
 +            { 
 +                execl("/usr/bin/mplayer", 
 +                    "/usr/bin/mplayer", 
 +                    "-really-quiet", 
 +                    "-loop", "0", 
 +                    "/media/usb/Audio/Attente.wav", 
 +                    NULL); 
 +            } 
 +        } 
 +        if ((digitalRead(monnayeur) == 0) && (attente == 1) &&  (procedure == 0)) { 
 +             photo(); 
 +        } 
 +        if ((digitalRead(boutonPhoto) == 0) && (attente == 1) &&  (procedure == 1)) { 
 +             photo(); 
 +        }
     }     }
     return 0;     return 0;
Ligne 273: Ligne 604:
 #define declencheur 2 #define declencheur 2
 #define posFermeVerrou 0 #define posFermeVerrou 0
-#define posOuvertVerrou 80+#define posOuvertVerrou 90
 #define posBrasLeve 137 #define posBrasLeve 137
 #define posBrasBaisse 65 #define posBrasBaisse 65
 +#define posVibHaut 0
 +#define posVibBas 30
  
 Servo verrou; Servo verrou;
Ligne 282: Ligne 615:
 void setup() { void setup() {
   pinMode(declencheur, INPUT);   pinMode(declencheur, INPUT);
 +  pinMode(8, INPUT);
 +  pinMode(13, OUTPUT);
 +
   bras.attach(6);   bras.attach(6);
   verrou.attach(5);   verrou.attach(5);
Ligne 290: Ligne 626:
   if (digitalRead(declencheur) == HIGH) {   if (digitalRead(declencheur) == HIGH) {
     sequence();     sequence();
 +  }
 +  if (digitalRead(8) == HIGH){
 +    vibration();
   }   }
 } }
  
 +void vibration() {
 +  for (int i = 0; i < 10; i++) {
 +    verrou.write(posVibBas);
 +    delay(150);
 +    verrou.write(posVibHaut);
 +    delay(150);
 +  }
 +  
 +}
 void sequence() { void sequence() {
-  delay(2500);+  delay(760);
   verrou.write(posOuvertVerrou);   verrou.write(posOuvertVerrou);
-  delay(2000);+  delay(1500);
   bras.write(posBrasLeve);   bras.write(posBrasLeve);
-  delay(2000); 
-  verrou.write(posFermeVerrou); 
   delay(1000);   delay(1000);
 +  verrou.write(posFermeVerrou);
 +  delay(500);
   bras.write(posBrasBaisse);   bras.write(posBrasBaisse);
-  delay(1000);+  delay(500);
 } }
 </code> </code>
 +===== Démarrage automatique =====
 +  sudo nano /etc/systemd/system/failomaton.service
 +
 +  [Unit]
 +  Description=Met en route l'installation Failomaton
 +  
 +  [Service]
 +  Type=simple
 +  WorkingDirectory=/home/pi/  
 +  ExecStart=/home/pi/./test  
 +  Restart=on-failure
 +  RestartSec=1 
 +  User=pi
 +  Group=pi
 +  
 +  [Install]
 +  WantedBy=multi-user.target
 +
 +  sudo systemctl enable failomaton.service
 +
 +  sudo systemctl status failomaton.service
 ===== Ressources en ligne ===== ===== Ressources en ligne =====
 [[https://trevilly.com/photomaton-a-base-de-raspberry-pi-choix-1-ou-4-ou-8-photos-et-impression-directe/|Photomaton avec une Raspberry Pi]] [[https://trevilly.com/photomaton-a-base-de-raspberry-pi-choix-1-ou-4-ou-8-photos-et-impression-directe/|Photomaton avec une Raspberry Pi]]
Ligne 339: Ligne 708:
  
 [[https://www.raspberrypi.com/documentation/computers/camera_software.html|Documentation des logiciels]] [[https://www.raspberrypi.com/documentation/computers/camera_software.html|Documentation des logiciels]]
 +
 +[[https://projects.raspberrypi.org/en/projects/infrared-bird-box/6|Mise au point module V2]]
 +
 +[[https://www.raspberrypi.com/news/raspberry-pi-camera-module-still-image-capture/|Déclenchement par signal]]
 +
 +[[https://www.framboise314.fr/test-des-nouvelles-cameras-raspberry-pi-v3-et-hq/|Pour la version 3]]
 +
 +[[https://blog.devmobile.co.nz/2022/01/24/libcamera-jpeg-on-raspberry-pi-os-bullseye-duration/|Liste des options]]
 ==== Synthèse vocale en ligne ==== ==== Synthèse vocale en ligne ====
 [[https://ttsreader.com/fr/|Simple d'utilisation]] [[https://ttsreader.com/fr/|Simple d'utilisation]]
Ligne 348: Ligne 725:
 === wiringPi === === wiringPi ===
 [[http://wiringpi.com|Site officiel]] [[http://wiringpi.com|Site officiel]]
-=== Pigpio === +
-[[http://abyz.me.uk/rpi/pigpio/cif.html#gpioSetISRFunc|Interruptions]]+
 === Lire fichier audio === === Lire fichier audio ===
 [[https://mplayerhq.hu/DOCS/man/en/mplayer.1.html#CONFIGURATION%20FILES|mplayer configuration]] [[https://mplayerhq.hu/DOCS/man/en/mplayer.1.html#CONFIGURATION%20FILES|mplayer configuration]]
Ligne 355: Ligne 731:
 [[https://github.com/jeffmachyo/Raspberry-Pi-Camera-C-and-CPP|Utilisation caméra]] [[https://github.com/jeffmachyo/Raspberry-Pi-Camera-C-and-CPP|Utilisation caméra]]
  
 +[[https://mtodorovic.developpez.com/linux/programmation-avancee/?page=page_3|Processus]]
 {{tag> raspberry_pi C++ sylvain}} {{tag> raspberry_pi C++ sylvain}}
failomaton.1700166506.txt.gz · Dernière modification : 2023/11/16 20:28 de Mushussu