failomaton
Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente | ||
failomaton [2023/11/05 15:31] – Mushussu | failomaton [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. | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | |||
+ | ==== A faire ==== | ||
+ | * Un bouton de redémarrage du programme | ||
+ | * La gestion du manque de papier | ||
+ | * Monnayeur | ||
+ | ===== Conception du distributeur de photos ===== | ||
+ | {{: | ||
+ | |||
+ | <code cpp> | ||
+ | |||
+ | $fn = 200; | ||
+ | |||
+ | // Épaisseur CP 10mm | ||
+ | |||
+ | cote(); | ||
+ | translate([350, | ||
+ | translate([290, | ||
+ | |||
+ | translate([305, | ||
+ | translate([330, | ||
+ | |||
+ | translate([15, | ||
+ | translate([123, | ||
+ | |||
+ | // Épaisseur CP 15mm | ||
+ | |||
+ | translate([-120, | ||
+ | translate([-10, | ||
+ | |||
+ | translate([-260, | ||
+ | translate([-30, | ||
+ | |||
+ | module cote() { | ||
+ | difference() { | ||
+ | union() { | ||
+ | square([290, | ||
+ | translate([90, | ||
+ | } | ||
+ | square([55, 6]); // Encoche rabat | ||
+ | translate([290, | ||
+ | translate([0, | ||
+ | translate([265, | ||
+ | translate([0, | ||
+ | // Encoches glissieres | ||
+ | translate([290, | ||
+ | translate([290, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | module support() { | ||
+ | difference() { | ||
+ | square([236, | ||
+ | translate([49.9, | ||
+ | translate([175.9, | ||
+ | translate([16.9, | ||
+ | translate([202.9, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | module glissiere() { | ||
+ | difference() { | ||
+ | square([331.6, | ||
+ | square([60.1, | ||
+ | translate([109.9, | ||
+ | translate([209.9, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | module trapeze() { | ||
+ | difference() { | ||
+ | square([135 * cos(30) + 40, 135 * sin(30)]); | ||
+ | rotate(30) square([200, | ||
+ | translate([0, | ||
+ | translate([0, | ||
+ | translate([0, | ||
+ | translate([0, | ||
+ | } | ||
+ | } | ||
+ | difference() { | ||
+ | rotate(30) translate([-20, | ||
+ | translate([0, | ||
+ | } | ||
+ | translate([135 * cos(30) + 39.9,0]) square([0.1, | ||
+ | } | ||
+ | |||
+ | module ecarteur() { | ||
+ | difference() { | ||
+ | rotate(30) translate([-20, | ||
+ | translate([0, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | module renfort1() { | ||
+ | difference() { | ||
+ | square([49.9, | ||
+ | translate([-15, | ||
+ | } | ||
+ | translate([17, | ||
+ | } | ||
+ | </ | ||
+ | ===== Installation de ImageMagick ===== | ||
+ | Installation du paquet | ||
+ | sudo apt-get install imagemagick | ||
+ | Vérifier la bonne installation de ImageMagick | ||
+ | identify -version | ||
+ | Pour tester le bon fonctionnement en convertissant un fichier .jpg en .png | ||
+ | convert photo.jpg photo.png | ||
+ | Voici la méthode pour recadrer la photo afin qu' | ||
+ | convert -crop 3836x2592+386+0 photo.jpg photo1.jpg | ||
+ | La méthode pour modifier l' | ||
+ | convert -rotate -90 photo.jpg photo1.jpg | ||
+ | ===== Installation de mplayer ===== | ||
+ | sudo apt-get install mplayer | ||
+ | Vérifier la bonne installation avec | ||
+ | mplayer --version | ||
+ | Afin d' | ||
+ | sudo nano ~/ | ||
+ | A la fin du fichier ajouter cette ligne qui indique que nous n' | ||
+ | lirc=no | ||
+ | Pour lancer un fichier audio | ||
+ | mplayer / | ||
+ | Le son sort par le mini-jack de la Raspberry Pi | ||
+ | ===== Réalisation de la voix de synthèse ===== | ||
+ | La réalisation des différentes instructions par des voix de synthèse a été faite à travers [[https:// | ||
+ | |||
+ | Voici les réglages : | ||
+ | |||
+ | {{: | ||
===== Matériel ===== | ===== Matériel ===== | ||
=== Monnayeur === | === Monnayeur === | ||
Ligne 8: | Ligne 140: | ||
[[https:// | [[https:// | ||
+ | ===== Installation de wiringPi ===== | ||
+ | Attention la librairie WiringPi ne fonctionne que sous Raspbian 32bits et pour un modèle 4B au maximum. | ||
+ | cd /tmp | ||
+ | wget https:// | ||
+ | sudo dpkg -i wiringpi-latest.deb | ||
+ | Vérifier l' | ||
+ | gpio -v | ||
+ | La version doit être la 2.52 | ||
===== Installation de l' | ===== Installation de l' | ||
+ | ==== Mise en route de l' | ||
+ | Suivre les instructions du mode d' | ||
+ | |||
+ | La seule configuration nécessaire est de désactiver l' | ||
+ | |||
+ | Avec les flèches aller sur le menu configuration (L' | ||
+ | |||
+ | Aller sur Réglage de l' | ||
+ | |||
+ | Aller avec la flèche du bas sur Extinction auto, OK | ||
+ | |||
+ | Sélectionner Désac. puis Ok | ||
+ | |||
+ | Puis appuyer sur Home | ||
+ | ==== Installation de CUPS ==== | ||
Sur une image de Raspberry fraichement installée et mise à jour. Installer CUPS : | Sur une image de Raspberry fraichement installée et mise à jour. Installer CUPS : | ||
sudo apt-get install cups | sudo apt-get install cups | ||
Ligne 20: | Ligne 174: | ||
Si vous êtes avec une Raspberry Pi sans écran et connectée en ssh, vous pouvez accéder à la page de configuration des imprimantes si vous suivez ces instructions : | Si vous êtes avec une Raspberry Pi sans écran et connectée en ssh, vous pouvez accéder à la page de configuration des imprimantes si vous suivez ces instructions : | ||
- | Éditer | + | Éditer |
sudo nano / | sudo nano / | ||
+ | Ajouter les ligne. suivantes au début du fichier : | ||
+ | # Efface l' | ||
+ | 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 59: | Ligne 216: | ||
Allow all | Allow all | ||
</ | </ | ||
+ | | ||
# Restrict access to configuration files... | # Restrict access to configuration files... | ||
< | < | ||
Ligne 69: | Ligne 226: | ||
Redémarrer ensuite CUPS : | Redémarrer ensuite CUPS : | ||
sudo / | sudo / | ||
+ | |||
+ | ==== Ajouter une nouvelle imprimante ==== | ||
+ | === Configuration de CUPS === | ||
Dès à présent, vous pouvez ouvrir un navigateur et accéder à la page de configuration à cette adresse : | Dès à présent, vous pouvez ouvrir un navigateur et accéder à la page de configuration à cette adresse : | ||
- | | + | |
+ | Si vous changez la configuration, | ||
+ | |||
+ | L' | ||
+ | |||
+ | Sur la page Ajouter une imprimante cliquer juste sur continuer | ||
+ | |||
+ | Sur la page suivante sélectionner dans le menu Canon SELPHY CP1300, driverless, cups-filters 1.28.17 (en), puis cliquer sur [Ajouter une imprimante] | ||
+ | |||
+ | Sur la page Définir les options de l’imprimante | ||
+ | Vérifier que les paramètres par défaut sont bien cela : | ||
+ | |||
+ | {{: | ||
+ | |||
+ | Cliquer sur [Définir les options par défaut] | ||
+ | |||
+ | === Impression d'une page test === | ||
+ | |||
+ | Cliquer sur [Imprimantes] | ||
+ | |||
+ | Cliquer sur [Canon_SELPHY_CP1300] | ||
+ | |||
+ | Maintenance > Imprimer une page test | ||
+ | |||
+ | === Impression d'une photo === | ||
+ | Dans un fenêtre du terminal : | ||
+ | Lister les imprimantes disponibles | ||
+ | lpstat -p -d | ||
+ | Définir l' | ||
+ | lpoptions -d Canon_SELPHY_CP1300 | ||
+ | Pour imprimer une photo | ||
+ | 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' | ||
+ | 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 / | ||
+ | Ensuite ouvrir le fichier mtab | ||
+ | sudo nano /etc/mtab | ||
+ | Observer le fichier aucune ligne ne doit commencer par : /dev/sda1 / | ||
+ | Ctrl + X pour quitter | ||
+ | Monter le la partition de la clef : | ||
+ | sudo mount -t vfat /dev/sda1 /media/usb -o rw, | ||
+ | Ouvrez de nouveau mtab | ||
+ | sudo nano /etc/mtab | ||
+ | La dernière ligne commence par : /dev/sda1 / | ||
+ | Copier cette ligne | ||
+ | Ctrl + x pour quitter | ||
+ | Ouvrez le fichier fstab | ||
+ | sudo nano / | ||
+ | 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 ===== | ||
+ | A tester : | ||
+ | cat file.wav > / | ||
+ | ==== Fichier de configuration de la caméra ==== | ||
+ | Placer un fichier config.txt dans le répertoire où est placé le fichier en C | ||
+ | sudo nano config.txt | ||
+ | Copier et coller ces éléments dans le fichier : | ||
+ | timeout=2 | ||
+ | verbose=0 | ||
+ | Ctrl O pour enregistrer puis valide puis Ctrl X pour quitter. | ||
+ | ==== Code C pour la Raspberry Pi ==== | ||
+ | <code c> | ||
+ | // g++ -Wall -o test `cups-config --cflags` test.c `cups-config --libs` -lwiringPi | ||
+ | |||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | #define boutonPhoto 26 // Fil rouge | ||
+ | #define vibrationArduino 27 // Fil vert | ||
+ | #define declenchementArduino 28 // Fil jaune | ||
+ | #define monnayeur 29 // Fil blanc | ||
+ | |||
+ | int nbPhotos = 0; | ||
+ | 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[]) | ||
+ | { | ||
+ | int i, j; | ||
+ | char c; | ||
+ | |||
+ | for (i = 0, j = strlen(s)-1; | ||
+ | c = s[i]; | ||
+ | s[i] = s[j]; | ||
+ | s[j] = c; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void itoa(int n, char s[]) | ||
+ | { | ||
+ | int i, sign; | ||
+ | |||
+ | if ((sign = n) < 0) /* record sign */ | ||
+ | n = -n; /* make n positive */ | ||
+ | i = 0; | ||
+ | do { /* generate digits in reverse order */ | ||
+ | | ||
+ | } while ((n /= 10) > 0); /* delete it */ | ||
+ | if (sign < 0) | ||
+ | | ||
+ | s[i] = ' | ||
+ | | ||
+ | } | ||
+ | |||
+ | void photo() { | ||
+ | time_t temps = time(NULL); | ||
+ | if (difftime(temps, | ||
+ | { | ||
+ | compteurTemps = temps; | ||
+ | if (procedure == 0) { | ||
+ | procedure = 1; | ||
+ | kill(pidAttente, | ||
+ | printf(" | ||
+ | if((pidProcedure = fork()) == 0) | ||
+ | { | ||
+ | execl("/ | ||
+ | "/ | ||
+ | " | ||
+ | " | ||
+ | "/ | ||
+ | NULL); | ||
+ | } | ||
+ | sleep(13); | ||
+ | digitalWrite(vibrationArduino, | ||
+ | sleep(1); | ||
+ | digitalWrite(vibrationArduino, | ||
+ | } else { | ||
+ | kill(pidProcedure, | ||
+ | printf(" | ||
+ | if((pidPhoto = fork()) == 0) | ||
+ | { | ||
+ | execl("/ | ||
+ | "/ | ||
+ | " | ||
+ | " | ||
+ | "/ | ||
+ | NULL); | ||
+ | } | ||
+ | sleep(5); | ||
+ | char buffer [6]; | ||
+ | itoa(nbPhotos, | ||
+ | char src[40] = "/ | ||
+ | strcat(src, buffer); | ||
+ | strcat(src, " | ||
+ | printf(" | ||
+ | nbPhotos++; | ||
+ | digitalWrite(declenchementArduino, | ||
+ | static pid_t pid = 0; | ||
+ | if ((pid = fork()) == 0) | ||
+ | { | ||
+ | // libcamera-jpeg -o photo_0.jpg -c config.txt | ||
+ | execl("/ | ||
+ | "", | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | NULL); | ||
+ | } | ||
+ | sleep(1); | ||
+ | digitalWrite(declenchementArduino, | ||
+ | FILE * fichier ; | ||
+ | do | ||
+ | { | ||
+ | fichier = fopen(src, " | ||
+ | } while (fichier == NULL); | ||
+ | fclose(fichier); | ||
+ | static pid_t pid1 = 0; | ||
+ | if ((pid1 = fork()) == 0) | ||
+ | { | ||
+ | // convert -crop 3836x2592+386+0 -rotate -90 Photos/ | ||
+ | execl( | ||
+ | "/ | ||
+ | "", | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | src, src, | ||
+ | NULL); | ||
+ | } | ||
+ | sleep(2); | ||
+ | //const char *filename = " | ||
+ | |||
+ | // Impression de la photo | ||
+ | http_t *http; | ||
+ | ipp_t *request, *response; | ||
+ | |||
+ | static const char * const requested_attributes[] = | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | }; | ||
+ | http = httpConnect2(" | ||
+ | |||
+ | request = ippNewRequest(IPP_OP_PRINT_JOB); | ||
+ | ippAddString(request, | ||
+ | ippAddString(request, | ||
+ | ippAddString(request, | ||
+ | ippAddString(request, | ||
+ | ippDelete(cupsDoFileRequest(http, | ||
+ | sleep(17); | ||
+ | kill(pidPhoto, | ||
+ | |||
+ | // 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, | ||
+ | ippAddString(request, | ||
+ | ippAddStrings(request, | ||
+ | |||
+ | response = cupsDoRequest(http, | ||
+ | for (attr = ippFirstAttribute(response); | ||
+ | { | ||
+ | if (strcmp(ippGetName(attr), | ||
+ | { | ||
+ | ippAttributeString(attr, | ||
+ | std::string valeur(value); | ||
+ | std::size_t erreurCartouche = valeur.find(" | ||
+ | std::size_t erreurPapier = valeur.find(" | ||
+ | if (erreurCartouche <= 2048) | ||
+ | { | ||
+ | // Plus d' | ||
+ | erreur = 1; | ||
+ | if (assistance == 0) { | ||
+ | printf(" | ||
+ | |||
+ | assistance = 1; | ||
+ | if((pidAssistance = fork()) == 0) | ||
+ | { | ||
+ | execl("/ | ||
+ | "/ | ||
+ | " | ||
+ | " | ||
+ | "/ | ||
+ | NULL); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | if (erreurPapier <= 2048) | ||
+ | { | ||
+ | // Plus de papier | ||
+ | erreur = 2; | ||
+ | if (assistance == 0) { | ||
+ | printf(" | ||
+ | |||
+ | assistance = 1; | ||
+ | |||
+ | if((pidAssistance = fork()) == 0) | ||
+ | { | ||
+ | execl("/ | ||
+ | "/ | ||
+ | " | ||
+ | " | ||
+ | "/ | ||
+ | NULL); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | sleep(3); | ||
+ | } while (erreur != 0); | ||
+ | |||
+ | if (assistance != 0) { | ||
+ | kill(pidAssistance, | ||
+ | } | ||
+ | printf(" | ||
+ | procedure = 0; | ||
+ | attente = 0; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | wiringPiSetup(); | ||
+ | pinMode (boutonPhoto, | ||
+ | pullUpDnControl(boutonPhoto, | ||
+ | pinMode (monnayeur, INPUT); // Pin du monnayeur | ||
+ | pullUpDnControl(monnayeur, | ||
+ | |||
+ | // | ||
+ | pinMode (declenchementArduino, | ||
+ | pinMode (vibrationArduino, | ||
+ | compteurTemps = time(NULL); | ||
+ | |||
+ | // Comptage des fichiers | ||
+ | struct dirent *dir; | ||
+ | DIR *d = opendir("/ | ||
+ | if (d) | ||
+ | { | ||
+ | while ((dir = readdir(d)) != NULL) | ||
+ | { | ||
+ | if (dir-> | ||
+ | { | ||
+ | nbPhotos++; | ||
+ | } | ||
+ | } | ||
+ | // | ||
+ | closedir(d); | ||
+ | } | ||
+ | // Efface tous les travaux d' | ||
+ | system(" | ||
+ | while(1) { | ||
+ | if (attente == 0) | ||
+ | { | ||
+ | attente = 1; | ||
+ | printf(" | ||
+ | // Message d' | ||
+ | if ((pidAttente = fork()) == 0) | ||
+ | { | ||
+ | execl("/ | ||
+ | "/ | ||
+ | " | ||
+ | " | ||
+ | "/ | ||
+ | NULL); | ||
+ | } | ||
+ | } | ||
+ | if ((digitalRead(monnayeur) == 0) && (attente == 1) && | ||
+ | | ||
+ | } | ||
+ | if ((digitalRead(boutonPhoto) == 0) && (attente == 1) && | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | ==== Code Arduino ==== | ||
+ | <code cpp> | ||
+ | |||
+ | #include < | ||
+ | |||
+ | #define declencheur 2 | ||
+ | #define posFermeVerrou 0 | ||
+ | #define posOuvertVerrou 90 | ||
+ | #define posBrasLeve 137 | ||
+ | #define posBrasBaisse 65 | ||
+ | #define posVibHaut 0 | ||
+ | #define posVibBas 30 | ||
+ | |||
+ | Servo verrou; | ||
+ | Servo bras; | ||
+ | |||
+ | void setup() { | ||
+ | pinMode(declencheur, | ||
+ | pinMode(8, INPUT); | ||
+ | pinMode(13, OUTPUT); | ||
+ | |||
+ | bras.attach(6); | ||
+ | verrou.attach(5); | ||
+ | sequence(); | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | if (digitalRead(declencheur) == HIGH) { | ||
+ | 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() { | ||
+ | delay(760); | ||
+ | verrou.write(posOuvertVerrou); | ||
+ | delay(1500); | ||
+ | bras.write(posBrasLeve); | ||
+ | delay(1000); | ||
+ | verrou.write(posFermeVerrou); | ||
+ | delay(500); | ||
+ | bras.write(posBrasBaisse); | ||
+ | delay(500); | ||
+ | } | ||
+ | </ | ||
+ | ===== Démarrage automatique ===== | ||
+ | sudo nano / | ||
+ | |||
+ | [Unit] | ||
+ | Description=Met en route l' | ||
+ | |||
+ | [Service] | ||
+ | Type=simple | ||
+ | WorkingDirectory=/ | ||
+ | ExecStart=/ | ||
+ | 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:// | [[https:// | ||
Ligne 80: | Ligne 682: | ||
[[https:// | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
==== Monnayeur ==== | ==== Monnayeur ==== | ||
[[https:// | [[https:// | ||
Ligne 100: | Ligne 707: | ||
[[https:// | [[https:// | ||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | ==== Synthèse vocale en ligne ==== | ||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | [[https:// | ||
==== Programmation ==== | ==== Programmation ==== | ||
- | === Pigpio | + | === wiringPi |
- | [[http://abyz.me.uk/ | + | [[http://wiringpi.com|Site officiel]] |
+ | === Lire fichier audio === | ||
+ | [[https:// | ||
=== Autres === | === Autres === | ||
[[https:// | [[https:// | ||
+ | [[https:// | ||
{{tag> raspberry_pi C++ sylvain}} | {{tag> raspberry_pi C++ sylvain}} |
failomaton.1699198306.txt.gz · Dernière modification : 2023/11/05 15:31 de Mushussu