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 ]










Aucun commentaire:

Enregistrer un commentaire