Ce dispositif est une table de mixage avec différents boutons et potentiomètres afin que les visiteurs puissent créer des images et modifier le son. C’est un peu comme un Photoshop tangible. Ce dispositif est composé de différents boutons qui modifient certains paramètres comme l’ajout d’image, la colorimétrie, l’ajout d’un son, et la possibilité de glitcher les images. On peut manipuler la matière numérique et altérer les pixels.
Pour cela j’ai utilisé une carte Seeduino, Processing, deux boutons et trois potentiomètres.
La carte Arduino mesure la valeur donnée par chacun des 3 potentiomètres et 2 boutons. Elle envoie ensuite chacune des valeurs via le port série vers le programme Processing qui gère le visuel. Le programme Processing récupère les 5 valeurs envoyées par la carte et les considère chacune comme 5 paramètres permettant de faire varier la teinte d'une image (pour les valeurs correspondant aux potentiomètres), lancer aléatoirement du son et faire varier aléatoirement l'affichage d'images (pour les deux boutons).
Le montage comportant 3 potentiomètres et 2 boutons est le suivant :
Le code permettant de mesurer les valeurs sur les 5 potentiomètres et de les envoyer via le port série est le suivant :
int capteurs[] = {0, 0, 0, 0, 0}; // valeur des capteurs.5 capteurs. 0,1,2 : potentiomètres; 3,4 : boutons byte bouton[] = {2, 3}; // pate des boutons byte potPin[] = {0, 2, 5}; byte Ncapteurs = 5, Npotentiometres = 3, Nboutons = 2; int inByte = 0; // incoming serial byte // mode debug boolean debug = false; // mettre "false" pour envyer les données à Procssing void setup() { // initialisation pattes boutons for (byte i = 0; i < Nboutons; i++) { pinMode(bouton[i], INPUT); } // start serial port at 9600 bps: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } // établir le contact avec Processing establishContact(); // send a byte to establish contact until receiver responds } void loop() { // if we get a valid byte, read analog ins: if (Serial.available() > 0) { // get incoming byte: inByte = Serial.read(); if (inByte == 'A') { // read first analog input, divide by 4 to make the range 0-255: // lecture des donées siur les potars for (byte i = 0; i < Npotentiometres ; i++) { //Npotentiometre=3 capteurs[i] = analogRead(potPin[i]) / 4; // delay 10ms to let the ADC recover: delay(10); } // lecture des données sur les boutons (à partir de capteur[3]) // read switch, map it to 0 or 255 for (byte i = 0; i < Nboutons; i++) { capteurs[i + 3] = map(digitalRead(bouton[i]), 0, 1, 0, 255); } // send sensor values: if (debug) { Serial.println("val capteurs : "); for (byte i = 0; i < Npotentiometres + Nboutons; i++) { //Npotentiometres + Nboutons = 5 Serial.print(capteurs[i]); Serial.print(" "); } Serial.println(""); } else { ///////////////////Envoie des octets bruts à PROCESING ////////////////////// for (byte i = 0; i < Npotentiometres + Nboutons; i++) { //Npotentiometres + Nboutons = 5 Serial.write(capteurs[i]); } } } } } void establishContact() { while (Serial.available() <= 0) { Serial.print('A'); // send a capital A delay(300); } }
Le programme Processing permettant de récupérer les données envoyées par la cartes et de les considérer comme des paramètres permettant “Glitcher” une images, et de lancer aléatoirement du son et l'affichage d'image est le suivant :
Programme principal :
/** Affiche tactile interactive - * Quand on appuie sur une touche (UP, DOWN, RIGHT, LEFT et espace ' '), cela lance une image, une vidéo, une annim, un son, etc... */ /// librairies import processing.sound.*; import processing.video.*; import processing.serial.*; // bouton image active ? // est-ce que l'image est active ? Si oui, on affiche l'image boolean animation_active = false; // true ou false (2 valleurs possibles) => 1 bit (0 ou 1) // bouton son actif ? boolean son_actif = false; float tempsDebutSon = 0; // temps du début de la musique a été joué // bouton video active ? boolean video_active = false; //potar teinte int potVal = 0; int redVal = 0; /// dialogue avec la carte Arduino Serial myPort; // Create object from Serial class int inBuffer; // Data received from the serial port int donneePortSerie; // entier converti de la chaine de caractère reçue sur le port série // seuil de détection float seuil = 300; // port serie int nCapteurs = 5; int[] capteurs = new int[nCapteurs]; // données reçues via la carte Arduino int serialCount = 0; // compteur de données reçues boolean firstContact = false; // Whether we've heard from the microcontroller // média int nImages = 3; String[] nomImages = new String[nImages]; PImage[] images = new PImage[nImages]; int nSon = 3; String[] nomSon=new String[nSon]; SoundFile[] son; // un son - un seul lecteur CD audio //Movie vid; // une vidéo - un seul lecteur DVD vidéo // annim : glitch PImage imageAffichee, imageInitiale; int mode=0; Glitch glitch; // mode debug boolean debug=true; void setup() { // initialisation des paramètres d'affichage & chargement des sons, vidéos, etc. size(1000, 800); noStroke(); background(0); colorMode(HSB); // initialisation des variables globales // capteurs for (int i=0; i<nCapteurs; i++) { capteurs[i]=0; } // nom son nomSon[0]= "sons/son2.mp3"; //nomSon[1]= "sons/Armstrong.wav"; //nomSon[2]= "sons/beat.aiff"; // nom images nomImages[0]= "images/img1.jpg"; nomImages[1]= "images/img2.jpg"; nomImages[2]= "images/img3.jpg"; // images for (int i=0; i<nImages; i++) { images[i]=loadImage(nomImages[i]); } // chargement des sons son =new SoundFile[nCapteurs]; for (int i=0; i<nSon; i++) { son[i] = new SoundFile(this, nomSon[i]); } /// Port série // Print a list of the serial ports, for debugging purposes: printArray(Serial.list()); String portName = Serial.list()[2]; myPort = new Serial(this, portName, 9600); // intstanciation de la classe Glitch //glitch = new Glitch(); //glitch = new Glitch("images/fond3.jpg"); imageInitiale = loadImage("images/fond3.jpg"); imageAffichee = imageInitiale.copy(); glitch = new Glitch(imageAffichee); } void draw() { // chargement des pixels de l'image affichee imageAffichee.loadPixels(); //loadPixels(); //arrayCopy(pixels, imageAffichee.pixels); ///////////////////////// interactivités liées aux capteurs // potentiomètres : capteurs[0]-> capteurs[2] // potar 0: teinte tint(capteurs[0],255,255, capteurs[2]); // potar 1: glitch glitch.mode = floor(map(capteurs[1], 0, 255, 0, 2)); // sélection du mode de glitch : 0,1 2 if (debug) { println("glitch.mode="+glitch.mode); } glitch.draw(imageAffichee); // potar 2: sound // interactivité liée aux boutons capteurs[3] et capteurs[4] if (capteurs[3]==255 && !son[0].isPlaying()) { // capteurs[3] ->son son[0].play(); } if (capteurs[4]==255) { // capteurs[4] ->img for (int i=0; i<nImages; i++) { //float x = random(0, images[i].width); //float y = random(0, images[i].height); //image(images[i], x, y); float x = random(0, 400); float y = random(0, 400); image(images[i], x, y, 400, 400); // enregistrement de l'image dessinée dans imageAffichee } imageAffichee.updatePixels(); } }
serialEvent :
void serialEvent(Serial myPort) { // read a byte from the serial port: int inByte = myPort.read(); // if this is the first byte received, and it's an A, // clear the serial buffer and note that you've // had first contact from the microcontroller. // Otherwise, add the incoming byte to the array: if (firstContact == false) { if (inByte == 'A') { myPort.clear(); // clear the serial port buffer firstContact = true; // you've had first contact from the microcontroller myPort.write('A'); // ask for more println("Communication avec la carte établie"); } } else { // Add the latest byte from the serial port to array: capteurs[serialCount] = inByte; serialCount++; // If we have nCapteurs=5 bytes: if (serialCount > nCapteurs-1 ) { // print the values (for debugging purposes only): if (debug) { for (int i =0; i<nCapteurs; i++) { print("capteur_" + i + "="+ capteurs[i]+ " "); } println(""); } // Send a capital A to request new sensor readings: myPort.write('A'); // Reset serialCount: serialCount = 0; } } }
Gestion Interactivité :
//////////////////////////////////////////////// animation /////////////////////////////////////////////////// void gestionAnimation() { if (donneePortSerie > 100) { // on appuie sur la touche "espace" => lancer l'animation "image" animation_active = true; } else { animation_active = false; } } void lancerAnimation() { float x = 30 + random(-20, 20); // random sur la position float y = 30 + random(-20, 20); //image(im, x, y, 200, 200); }
Class “Glitch” parmettant de glitcher une image. Ce programme est un sketch du site OpenProcessing :
/** Affiche tactile interactive - * Quand on appuie sur une touche (UP, DOWN, RIGHT, LEFT et espace ' '), cela lance une image, une vidéo, une annim, un son, etc... */ /// librairies import processing.sound.*; import processing.video.*; import processing.serial.*; // bouton image active ? // est-ce que l'image est active ? Si oui, on affiche l'image boolean animation_active = false; // true ou false (2 valleurs possibles) => 1 bit (0 ou 1) // bouton son actif ? boolean son_actif = false; float tempsDebutSon = 0; // temps du début de la musique a été joué // bouton video active ? boolean video_active = false; //potar teinte int potVal = 0; int redVal = 0; /// dialogue avec la carte Arduino Serial myPort; // Create object from Serial class int inBuffer; // Data received from the serial port int donneePortSerie; // entier converti de la chaine de caractère reçue sur le port série // seuil de détection float seuil = 300; // port serie int nCapteurs = 5; int[] capteurs = new int[nCapteurs]; // données reçues via la carte Arduino int serialCount = 0; // compteur de données reçues boolean firstContact = false; // Whether we've heard from the microcontroller // média int nImages = 3; String[] nomImages = new String[nImages]; PImage[] images = new PImage[nImages]; int nSon = 3; String[] nomSon=new String[nSon]; SoundFile[] son; // un son - un seul lecteur CD audio //Movie vid; // une vidéo - un seul lecteur DVD vidéo // annim : glitch PImage imageAffichee, imageInitiale; int mode=0; Glitch glitch; // mode debug boolean debug=true; void setup() { // initialisation des paramètres d'affichage & chargement des sons, vidéos, etc. size(1000, 800); noStroke(); background(0); colorMode(HSB); // initialisation des variables globales // capteurs for (int i=0; i<nCapteurs; i++) { capteurs[i]=0; } // nom son nomSon[0]= "sons/son2.mp3"; //nomSon[1]= "sons/Armstrong.wav"; //nomSon[2]= "sons/beat.aiff"; // nom images nomImages[0]= "images/img1.jpg"; nomImages[1]= "images/img2.jpg"; nomImages[2]= "images/img3.jpg"; // images for (int i=0; i<nImages; i++) { images[i]=loadImage(nomImages[i]); } // chargement des sons son =new SoundFile[nCapteurs]; for (int i=0; i<nSon; i++) { son[i] = new SoundFile(this, nomSon[i]); } /// Port série // Print a list of the serial ports, for debugging purposes: printArray(Serial.list()); String portName = Serial.list()[2]; myPort = new Serial(this, portName, 9600); // intstanciation de la classe Glitch //glitch = new Glitch(); //glitch = new Glitch("images/fond3.jpg"); imageInitiale = loadImage("images/fond3.jpg"); imageAffichee = imageInitiale.copy(); glitch = new Glitch(imageAffichee); } void draw() { // chargement des pixels de l'image affichee imageAffichee.loadPixels(); //loadPixels(); //arrayCopy(pixels, imageAffichee.pixels); ///////////////////////// interactivités liées aux capteurs // potentiomètres : capteurs[0]-> capteurs[2] // potar 0: teinte tint(capteurs[0],255,255, capteurs[2]); // potar 1: glitch glitch.mode = floor(map(capteurs[1], 0, 255, 0, 2)); // sélection du mode de glitch : 0,1 2 if (debug) { println("glitch.mode="+glitch.mode); } glitch.draw(imageAffichee); // potar 2: sound // interactivité liée aux boutons capteurs[3] et capteurs[4] if (capteurs[3]==255 && !son[0].isPlaying()) { // capteurs[3] ->son son[0].play(); } if (capteurs[4]==255) { // capteurs[4] ->img for (int i=0; i<nImages; i++) { //float x = random(0, images[i].width); //float y = random(0, images[i].height); //image(images[i], x, y); float x = random(0, 400); float y = random(0, 400); image(images[i], x, y, 400, 400); // enregistrement de l'image dessinée dans imageAffichee } imageAffichee.updatePixels(); } }
Pour la maquette, j'ai utilisé une planche de bois MDH 3mm et j'ai fais mon fichier sur AI pour utiliser la découpe laser. Je me suis servie de ce site qui permet de faire une boîte personnalisée : http://carrefour-numerique.cite-sciences.fr/wiki/doku.php?id=projets:generateur_de_boites Ensuite, j'ai ajouté mon design sur le fichier. Il faut bien séparer les éléments qu'on veut découper et les éléments qu'on veut graver en deux couleurs distinctes. J'ai fais 2 calques : 1 pour la découpe, 1 autre pour la gravure.
Ci-joint mon fichier en PDF :
Pour que votre fichier soit valide, referez au fichier exemple de la découpe laser.