Affichage des articles dont le libellé est bricodeurs. Afficher tous les articles
Affichage des articles dont le libellé est bricodeurs. Afficher tous les articles

23/06/2018

YunDessinCollaboratif (YDC) et les Journées Européennes du Patrimoine (JEP)

A l'occasion des Journées Européennes du Patrimoine 2018 placées sous le thème de "L'art en partage", Smag0 et l'association "Les Bricodeurs" vous propose d'utiliser dans plusieurs espaces culturels le dispositif "YunDessinCollaboratif"

Démo Online http://dessincollaboratif.herokuapp.com/
Gallerie que Twitter (@DCollaboratif) : https://twitter.com/DCollaboratif


Qu'est ce que YunDessinCollaboratif (YDC) ?

YDC est un dispositif permettant à des dizaines d'utilisateurs de partager la création d'une oeuvre artistique.
Il suffit de se connecter sur le réseau Wifi du boitier, d'ouvrir la page d'accueil, et chacun peut dessiner grâce à son smartphone, sa tablette ou son ordinateur sur une oeuvre collaborative.
Chacun est libre de compléter l'oeuvre en temps réel.


Fonctionnalités complémentaires

YDC permet d'effectuer des captures d'écran afin de sauvegarder à tout moment une oeuvre
-à développer : YDC enregistre automatiquement à chaque minute une capture d'écran afin de recréer un historique de la création collaborative
- à développer : YDC permet la création de "salles" pour élaborer plusieurs oeuvres en même temps
- à développer : diffusion en temps réel des oeuvres sur un site internet

Technique : 

YunDessinCollaboratif est une application nodejs basée sur de https://sketchpad.tk/
installée sur une carte Arduino Yùn, cette carte proposant un hotspot Wifi.
YDC est installable en tout lieu à condition de disposer d'une prise electrique, et pour la diffusion un pc avec écran ou videoprojecteur avec écran.

Les dernières mises à jour de YunDessinCollaboratif se trouvent ici : 
 https://github.com/scenaristeur/lininoapps/tree/master/root/sketchpad

Et les Bricodeurs dans tout ça ? 

Les Bricodeurs
Collectif du numérique citoyen
Les Bricodeurs est le collectif des professionnels du numérique engagés pour que l’expertise numérique soit au service de l’utilité sociale.
Particulièrement attentifs à l’ouverture et la diversité de genre, culturelle et sociale dans nos actions et nos instances, nous établissons une passerelle entre les expertises techniques, les besoins sociétaux et le grand public."
YDC/sketchpad a été testé à plusieurs reprises mais nécessite encore quelques ajustements. Les Bricodeurs se proposent d'animer des ateliers pendant l'été pour les personnes qui souhaiteraient s'investir dans le projet et apprendre à programmer des applications sur ce type de plateforme.
Potentiel actuel : une dizaine de boitiers YDC
04/05/2019: Visite au festival 'Peinture fraîche' à la halle Debourg/ Gerland où j'ai discuté avec Maxime T du projet https://thelivedrawingproject.com/fr/
Les deux projets sont très proches et utilisent la même stack ( nodejs, socket.io, webapp, mobile utilisateur, vidéoprojecteur) pour une même finalité de dessin collaboratif.
Nouvelle inspiration : le dessin est organisé sous forme de calques / layers que les utilisateurs peuvent gérer sauvegarder, copier, partager...




03/02/2018

Quand l'environnement s'adapte à moi.


Aurélien du FAbLAB... a sollicité lesBricodeurs pour un atelier à la cité du Design.
Son idée étant d'illustrer de manière concrète une des possibilités de lier les données personnelles (issues de la personne, de capteurs physiques  --> environnement)

Un capteur de rythme cardiaque qui modifierait une playlist : plus le rythme cardique est lent, plus la musique est lente et inversement.

--> Arduino Yun avec lininoio

LA LIAISON CAPTEUR APPLI-WEB

Premier code côté javascript (node, express, socket.io, librairie lininoio, avant la réception du capteur, avec un potentiomètre branché sur A0 pour simuler les variations 


       
//https://github.com/ideino/ideino-linino-lib

///////////////////////////////////////////////////////////
// GESTION NODE EXPRESS SERVEUR
///////////////////////////////////////////////////////////
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var port = process.env.PORT || 3006;

///////////////////////////////////////////////////////////
// GESTION DES COMMANDES LINUX comme reboot
///////////////////////////////////////////////////////////
//var exec = require('child_process').exec;

///////////////////////////////////////////////////////////
// GESTION DE LA CARTE ARDUINO
///////////////////////////////////////////////////////////
var linino = require('ideino-linino-lib'),
board = new linino.Board(),
html = new linino.Htmlboard();
//var servoH = { pin: board.pin.servo.S9, value : 180 };
//var pin13 = board.pin.digital.D13;
var pot = board.pin.analog.A0;

// Routing
app.use(express.static(__dirname + '/public'));

//LANCEMENT SERVEUR
server.listen(port, function () {
 console.log('Server listening at port %d', port);
 console.log('potentiometre : A0');
 
});




board.connect(function(){
 console.log('CARTE Connected');
 io.on('connection', function (socket) {
  console.log("CLIENT connected");
  
  
  board.analogRead(pot, function(value){
   console.log('value: ' + value);
  // var data = {"AO": value};
   socket.emit('update', value);
  });
 });
 
}); 


accompagné d'un fichier /public/index.html qui fait appel aux librairies P5JS, socket.io :
https://github.com/scenaristeur/lininoapps/blob/master/root/cardio/public/index.html


       
<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0>
    <style> body {padding: 0; margin: 0;} </style>
    <script src="lib/p5.min.js"></script>
    <script src="lib/addons/p5.dom.min.js"></script>
    <script src="lib/addons/p5.sound.min.js"></script>
    <script src="js/sketch.js"></script>
  </head>
  <body>
  
  <script src="/socket.io/socket.io.js"></script>
  <script>
 var socket = io();
 console.log(socket);
 /*socket.on('update', function (data) {
  console.log(data);
 });*/
  
  </script>
  </body>
</html>


Et un fichier p5js /public/js/sketch.js :
https://github.com/scenaristeur/lininoapps/blob/master/root/cardio/public/js/sketch.js

Qui référence les chansons (sotckées dans le dossier /assets) selon leur BPM .
Comme d'hab : setup met en place l'environnement et définit le listener de la communication bi-directionnelle entre la page web et le serveur grâce au listener  'socket.on("update", function(data){...});




var bpm = 0
var play = false;
// convertisseur mp3 : http://youtubemp3.to/
// bpm search : https://songbpm.com/        https://www.bpmdatabase.com/music/search/?artist=&title=&bpm=70&genre=
// p5js playsound https://p5js.org/examples/sound-load-and-play-sound.html


var song ;
var ROAR_90, GETLUCKY_116, COME_100, WALK_105, CARMEN_150, CRUEL_168;
var slider;

function preload() {
 // soundFormats('mp3', 'ogg');
 // trover des chansons de 40 BPM à 220
  ROAR_90 = loadSound('assets/90BPM - Katy Perry - Roar Official.mp3');
 COME_100 = loadSound('assets/100BPM - Jain - Come.mp3');
 WALK_105 = loadSound('assets/105BPM - Lou Reed - Walk On The Wild Side.mp3');
 GETLUCKY_116 = loadSound('assets/116BPM - Daft Punk - Get Lucky.mp3');
 CARMEN_150 = loadSound('assets/150BPM - Stromae - carmen.mp3');
 CRUEL_168 = loadSound('assets/168BPM - Elvis Presley - Dont Be Cruel.mp3');
 console.log("chansons chargées");
}

function setup() {
 canvas = createCanvas(windowWidth, windowHeight);
 slider = createSlider(40, 220, 70);
 slider.position(10, 10);
 
 slider.style('width', width/2+'px');
 
 
 
 song = ROAR_90;
 fft = new p5.FFT();
 song.amp(0.2);
 //GETLUCKY_116.play();
 // GETLUCKY_116.pause();
 
 console.log("ready");
 console.log(socket);
   socket.on('update', function (data) {
  
  //var json = JSON.parse(data);
  
  bpm = Math.round(map(data,0,1023,40,220));
  console.log(bpm);
  slider.value(bpm);
  changeSong(ROAR_90, bpm, 80, 95);
  changeSong(COME_100, bpm, 95, 102);
  changeSong(WALK_105, bpm, 102, 110);
  changeSong(GETLUCKY_116, bpm, 110, 120);
  changeSong(CARMEN_150, bpm, 120, 160);
  changeSong(CRUEL_168, bpm, 160, 220);
 });
}

function draw() {
 var color = map(bpm,40,220,0,255);
 background(color);
 noStroke();
 //fill(255-color);
 fill(bpm, 255-bpm, 0);
 ellipse(width/2,height/2,bpm,bpm); 
 text(bpm,100,100);
 
 //visu
 var spectrum = fft.analyze();
 noStroke();
 fill(0,255,0); // spectrum is green
 for (var i = 0; i< spectrum.length; i++){
  var x = map(i, 0, spectrum.length, 0, width);
  var h = -height + map(spectrum[i], 0, 255, height, 0);
  rect(x, height, width / spectrum.length, h )
 }
 
 var waveform = fft.waveform();
 noFill();
 beginShape();
 stroke(255,0,0); // waveform is red
 strokeWeight(1);
 for (var i = 0; i< waveform.length; i++){
  var x = map(i, 0, waveform.length, 0, width);
  var y = map( waveform[i], -1, 1, 0, height);
  vertex(x,y);
 }
 endShape();
 
}


function changeSong(s, bpm, min, max){
 if ((bpm > min ) && (bpm <= max) && (song != s )){
  //ROAR_90.pause();
  song.pause();
  song = s;
  song.play()
  console.log(s);
 }
 
 
}


function mousePressed() {
 play = !play;
 console.log(play);
 if (play){
  console.log("play");
  song.play();
  
  }else{
  console.log("stop");
  song.stop();
 }
 }  


TRANSFORMATION DU SIGNAL

Une fois le capteur reçu, la difficulté était de récupéréer le rythme cardiaque . En effet, le code de base http://learn.linksprite.com/arduino/advanced-learning-kit-for-arduino/how-to-use-heatbeat-sensor-module-on-arduino/ permet de mesurer la variation d'oxygène contenue dans le sens. Il a fallu transformer le signal pour calculer une moyenne du nombre de battements par minutes.

Code de base pour Arduino :

       
// Pulse Monitor Test Script
 
int ledPin = 13;
 
int sensorPin = 0;
 
double alpha = 0.75;
 
int period = 20;
 
double change = 0.0;
 
void setup()                   
 
{
 
  pinMode(ledPin, OUTPUT);
 
  Serial.begin(115200);
 
}
 
void loop()                    
 
{
 
    static double oldValue = 0;
 
    static double oldChange = 0;
 
    int rawValue = analogRead(sensorPin);
 
    double value = alpha * oldValue + (1 - alpha) * rawValue;
 
    Serial.print(rawValue);
 
    Serial.print(",");
 
    Serial.println(value);
 
    oldValue = value;
 
    delay(period);
 
}









[ en cours de rédaction ]