Images Saisonnières

Porteur du projet : Floriane Robert de Latour

Date : 26/01/2015

Contexte : Macro projet DSAA 1

Macro Projet 2

espace d'échange : partout

Description

Images Saisonnières est un projet dont le point de départ est un sketch très simple récupéré sur open processing (lien). Une première étape a consisté en la duplication et la modification de ce sketch, en modifiant très peu de lignes de codes. Une deuxième étape a porté le projet plus loin en réunissant ces sketchs, dont le thème commun est la météorologie, et en les faisant réagir à des capteurs. La troisième étape doit permettre l'articulation entre l'image générée, leur code source, et leur généalogie (à savoir la provenance des différents éléments du code); à savoir les trois éléments dont sont composés une image numérique.

Ce projet est donc à la fois un observatoire de phénomènes naturels et de la création d'images. Être graphiste à l'ère du numérique nécessite de pouvoir agir sur le code source des formes s'il on veut avoir une maîtrise de son travail. Cela nécessite aussi de savoir se servir des ressources que l'on peut avoir à sa disposition. Le code est une activité nécessairement participative, qui convoque quelque chose qui appartient à tout le monde, comme la pluie ou la neige.

Ce travail permet de repérer les moments dans la création où la propriété intellectuelle est remise en cause. Si toutes les ressources dont je me suis servie pour ce projet avaient été propriétaires, tant au niveau du code emprunté que des programmes utilisés, il n'aurait jamais vu le jour.4

Généalogie

lien à venir

Matériel

un ordinateur

une carte Arduino avec une breadbord

2 potentiomètres (idéalement remplacés par un capteur de température et un capteur de flexion)

2 résistances 10kOhm

un rétro-projecteur

logiciels : arduino et processing

Images

(à venir)

(ACC) : vous n'avez pas prévu de lieu d'échanges avec le lecteur (est-ce un vieux réflexe propriétaire?) du coup je me mets où je peux : John Maeda, évoqué par Annick Lantenois, a créé un dispositif simple de corrélation entre un visuel et le code source permettant de l'obtenir. Vous pouvez peut-être réfléchir à de tels dispositifs. Qu'arrive-t-il si le code est fourni avec le produit?

Lien externe

Montage

Code

Arduino

int firstSensor = 0; // first analog sensor
int secondSensor = 0; // second analog sensor
int thirdSensor = 0; // digital sensor
int inByte = 0; // incoming serial byte
void setup()
{
// start serial port at 9600 bps:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
pinMode(2, INPUT); // digital sensor is on digital pin 2
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();
// read first analog input, divide by 4 to make the range 0-255:
firstSensor = analogRead(A0)/4;
// delay 10ms to let the ADC recover:
delay(10);
// read second analog input, divide by 4 to make the range 0-255:
secondSensor = analogRead(A1)/4;
// read switch, map it to 0 or 255L
thirdSensor = map(digitalRead(2), 0, 1, 0, 255);
// send sensor values:
Serial.write(firstSensor);
Serial.write(secondSensor);
Serial.write(thirdSensor);
}
}
void establishContact() {
while (Serial.available() <= 0) {
Serial.print('A'); // send a capital A
delay(300);
}
}

Processing

import processing.serial.*; // importer la librairie sérial
float fgcolor;
Serial myPort; // Le port de série
float[] serialInArray = new float[3]; // Tableau pour stocker les données reçues
int serialCount = 0; // Initialisation du compteur de bytes
boolean firstContact = false; // Si oui ou non il y a contact avec le microcontrolleur
//les coordonnées à changer
float etoiles; //variable concernant les particules, en rapport avec le premier capteur
float angleChng; //variable concernant leur direction, en rapport avec le deuxième capteur
//variables d'effacements
int contrainte01 = 0; //variable de limite d'effacement pour les étoiles filantes
int contrainte02 = 700; // variable de limite d'effacement pour la neige
int contrainte03a = 400; //variables de limite d'effacement pour la pluie
int contrainte03b = 400;
//tableaux : étoiles filantes
float[] xCoord = new float[250]; //coordonnées X
float[] yCoord = new float[250]; //coordonnées Y
float[] speed = new float[250]; //vitesse de chute
float[] angle = new float[250]; //angle de chute
//tableaux : neige
float[] xCoord02 = new float[700]; //coordonnées X
float[] yCoord02 = new float[700]; //coordonnées Y
float[] speed02 = new float[700]; //vitesse de chute
//tableaux : pluie
int[] xCoord03 = new int[400]; //coordonnées X
int[] yCoord03 = new int[400]; //coordonnées Y
float[] speed03 = new float[400]; //vitesse de chute
float[] angle03 = new float[400]; //angle de chute
//INITIALISATION
void setup() {
frameRate(40); //nombre d'images par seconde
size(300,650); //taille de la fenêtre
((javax.swing.JFrame) frame).getContentPane().setBackground(new java.awt.Color(0,0,0));
//pour changer la couleur d'arrière plan autour du sketch en mode "present"
colorMode(HSB); //mode de couleur : teinte, saturation, luminosité
background(255,0,10); //couleur de l'arrière plan
//initialisation des étoiles filantes avec une boucle int
for (int i = 0; i < xCoord.length; i++) {
xCoord[i] = i*width/(250); //il y a 250 étoiles filantes réparties sur la largeur de la fenêtre
yCoord[i] = (int)random(-height, 0); //les etoiles sont créées aléatoirement entre 0 et l'inverse de la hauteur
//pour apparaître au fur et à mesure quand le sketch est lancé (à confirmer ?)
speed[i] = random(1,5)/2; //la vitesse est différente pour chaque étoile
angle[i] = noise(2)*2.5; //l'angle est différent pour chaque étoile
}
//initialisation de la neige avec une boucle int
for (int j = 0; j < xCoord02.length; j++) {
xCoord02[j] = j*width/400; //il y a 400 flocons de neige répartis sur la largeur de la fenêtre
yCoord02[j] = (int)random(-height, 0);// même chose que précédemment
speed02[j] = random(1,4); //la vitesse est différente pour chaque flocon
}
//initialisation de la pluie avec une boucle int
for (int k = 0; k < xCoord03.length; k++) {
xCoord03[k] = k*width/400;//il y a 400 gouttes de pluie réparties sur la largeur de la fenêtre
yCoord03[k] = (int)random(-height, 0);//même chose que ci-dessus
speed03[k] = random(10,14); //la vitesse est différente pour chaque goutte de pluie
angle03[k] = random(2,3); //l'angle est différent pour chaque goutte de pluie
}
// Imprimer une liste des ports de série, pour debugger
printArray(Serial.list());
// Ouverture du port de série (ici COM1)
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
}
//MISE A JOUR DU SKETCH
void draw() {
//ajustement des variables de contrainte d'effacement grâce à de savants calculs.
//ces variables déterminent à quel moment les particules d'un tableau s'effacent ou apparaissent
//de manière à ce que ça soit progressif
//elles exprimées en fonction de la variable "etoiles", qui est en rapport avec le 1er capteur
//les valeurs sont contraintes entre 0 et le maximum qu'elles doivent avoir.
int contrainte01 = constrain(int(xCoord.length - etoiles*2.5), 0, 250); //les étoiles filantes
int contrainte02 = constrain(int(xCoord02.length - etoiles*5.70 + 730),0,700); //la neige
int contrainte03a = constrain(int(xCoord03.length - etoiles*5.71 + 18), 0, 400); //la pluie
int contrainte03b = constrain(int(xCoord03.length - etoiles*4 + 400), 0, 400);
//opRect : variable concernant l'opacité du rectangle noir derrière les particules
//exprimé lui aussi en fonction de "etoiles"
//l'opacité change quand on passe de la neige à la pluie et vice versa
float valOp = constrain(etoiles, 130, 150); //seuls les variations entre etoile=130 et etoiles=150 nous intéressent
float opRect = 10 + (valOp-130)*12.25; //si etoiles=130, alors l'opacité est de 10. si etoiles = 150, alors l'opacité est de 255.
//pour débugguer
//println(contrainte01 + "\t" + contrainte02 + "\t" + contrainte03a + "\t" + contrainte03b);
//println(etoiles);
//rectangle d'arrière plan des particules, permet d'avoir un effet de traînée
pushMatrix();
noStroke(); //pas de contours
fill(255,0,10, opRect); //couleur du rectangle, avec opacité variable
rect(0,0, width, height); //le rectangle fait la taille de la fenêtre
popMatrix();
//création des etoiles filantes grâce à une boucle int
for (int i = 0; i < contrainte01 ; i++) { //la boucle est limitée par la variable contrainte01.
//en changeant celle ci permet d'effacer ou de révéler les etoiles filantes
pushMatrix();
stroke(40, 255, 255); //couleur des contours
strokeWeight(1); //épaisseur des contours
point(xCoord[i], yCoord[i]); //création des étoiles
popMatrix();
xCoord[i] += angle[i]*angleChng; //déplacement en X, grâce à l'angle (variable déterminée par le capteur*variable aléatoire)
yCoord[i] += speed[i]; //déplacement en y, grâce à la vitesse
//quand l'étoile filante atteint le bas de la fenêtre, elle réapparaît en haut
if(yCoord[i] > height){
yCoord[i] = 0;
}
//quand l'étoile filante atteint le bord droit de la fenêtre, elle réapparaît à gauche
if(xCoord[i]>width){
xCoord[i]=0;
}
}
//création de la neige grâce à une boucle int
for (int j = contrainte02; j < xCoord02.length; j++) {//la boucle est limitée par la variable contrainte02
//en changeant celle ci permet d'effacer ou de révéler des flocons de neige
stroke(255, 0, 255);//couleur des contours
strokeWeight(5); //épaisseur des contours
point(xCoord02[j], yCoord02[j]); //création de la neige
xCoord02[j] += random(-5, 5) + pow(angleChng, 2);//déplacement en X, grâce à l'angle
// ajout d'une variable aléatoire (pour l'effet de vibration) et d'une variable déterminée par le 2ème capteur (pow = exposant)
yCoord02[j] += speed02[j];//déplacement en y, grâce à la vitesse
//quand le flocon de neige atteint le bas de la fenêtre, il réapparaît en haut
if(yCoord02[j] > height){
yCoord02[j] = 0;
}
//quand le flocon de neige atteint le bord droit de la fenêtre, il réapparaît à gauche
if(xCoord02[j]>width){
xCoord02[j]=0;
}
}
//création de la pluie grâce à une boucle int
for (int k = contrainte03a; k < contrainte03b; k++) {//la boucle est limitée par les variables contrainte03a et contrainte03b
//en changeant celles ci permettent d'effacer ou de révéler des gouttes de pluie
stroke(130, random(155,255), random(155,255)); //couleur des contours
strokeWeight(2); //épaisseur des contours
point(xCoord03[k], yCoord03[k]); //création de la pluie
yCoord03[k] += speed03[k];//déplacement en y, grâce à la vitesse
xCoord03[k] += 0.5*angle03[k] + pow(angleChng, 3); //déplacement en X, grâce à l'angle
//quand la goutte de pluie atteint le bas de la fenêtre, elle réapparaît en haut
if(yCoord03[k] >
height){
yCoord03[k] = 0;
}
//quand la goutte de pluie atteint le bord droit de la fenêtre, elle réapparaît à gauche
if(xCoord03[k]>width){
xCoord03[k]=0;
}
}
}
//}
void serialEvent(Serial myPort) {
// lire un byte du port de série:
int inByte = myPort.read();
// si c'est le premier byte reçu, et que c'est un A,
// effacer le serial buffer et noter
// que l'on a eu un premier contact avec le microcontrolleur.
// Sinon, ajouter le byte entrant byte dans le tableau:
if (firstContact == false) {
if (inByte == 'A') {
myPort.clear(); // effacer le serial buffer
firstContact = true; // premier contact avec le microcontrolleur
myPort.write('A'); // demander plus
}
}
else {
// Ajouter le dernier byte du port de série au tableau:
serialInArray[serialCount] = inByte;
serialCount++;
// Si on a 3 bytess:
if (serialCount > 2 ) {
etoiles = serialInArray[0]; //valeur provenant du premier capteur
angleChng = serialInArray[1]/125; //valeur provenant du second capteur
fgcolor = serialInArray[2]; //valeur provenant du 3ème capteur
// print the values (for debugging purposes only):
//println(etoiles + "\t" + fgcolor);
// Envoyer "A" pour demander plus de valeurs des capteurs:
myPort.write('A');
// Remettre à 0 serialCount:
serialCount = 0;
}
}
}

Problèmes

capteur de température : je n'ai jamais réussi à le faire fonctionner, je le branchait à l'envers au début et du coup il m'a brûlé la main. il est peut être grillé. quoiqu'il en soit, après l'avoir remis dans le bon sens, je me suis aperçue que le capteur de température et le potentiomètre se perturbaient l'un l'autre, à savoir que quand j'actionnais le potentiomètre, la valeur du capteur de température bougeait aussi.

capteur de flexion : je l'attends toujours.

en fait le choix de ces deux capteurs est à reconsidérer. en ce qui concerne le capteur de température, il place le spectateur dans une position passive par rapport aux images générées par le programme, puisqu'il ne peux pas décider de la température qu'il fait.