Outils pour utilisateurs

Outils du site


wiki:flossmanuals:table-mixage-images-2:accueil

Table de Mixage pour Glitcher une images

  • Porteur(s) du projet : Flora Vander Poorte (DSAA DG2), Damien MUTI (Prof. de Numérique)
  • Date : 06/2021
  • Contexte : Macro-Projet
  • Fichiers :
  • Liens :
  • Capteurs/Actionneurs :
    • 3 potentiomètres
    • 2 boutons Grove
    • 1 carte Seeeduino

Intentions : explication du projet et objectifs

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.

Algorithme

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).

Montage Arduino

Câblage

Le montage comportant 3 potentiomètres et 2 boutons est le suivant :

Programmes Arduino

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);
  }
}

Programme Processing

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 :

asdfpixelglitch2.zip

/**  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();
  }
}

Réalisation de la maquette et visuels

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 :

box_180x140x70_4mm.pdf

Pour que votre fichier soit valide, referez au fichier exemple de la découpe laser.

Références :

wiki/flossmanuals/table-mixage-images-2/accueil.txt · Dernière modification: 2021/06/30 12:56 de flora