Maurin Donneaud

Designer d’interaction @ www.eTextile.org - Paris

Reactor/projet

S’habiller avec des vêtements technologiques c’est stylé ! c’est un jeu comme le cosplay, une manière d’incarner son temps dans une mixité des influences passées, présentes et futures. Les vêtements interactifs et musicaux que nous imaginons pourraient s’inscrire dans une démarche artistique et performative mais nous avons simplement choisi de nous adresser à des personnes qui souhaitent porter ce qu’on pourrait appeler un parfum sonore.

Le projet Reactor permet d’imaginer une multitude de modèles de vêtements instruments et articles sonores basés sur un principe de tricot capteur. Tricoté à la main à partir de fils de laine et de fils conducteurs, la maille permet ainsi de capter l’élongation, la tension du tissu ainsi que les plis et contacts de la matière pour déclencher ou contrôler des sons. Une attention particulière est portée à l’intégration du dispositif électronique qui disparaît totalement au profit d’une esthétique simple. Projet intergénérationnel, ce projet est aussi un prétexte pour organiser des ateliers avec des grand mères branchées qui pourront remettre le tricot au goût du jour.

C’est aussi pour solliciter des gestes que le vêtement est augmenté d’un parfum sonore, rendu réactif grâce à l’intégration d’une petite carte électronique le tricot adopte un nouveau statut d’objet instrument, la fonction musicale du vêtement entraine alors l’apprentissage d’une gestuelle particulière.

Scénario N°1 : suivi de partition
A chaque fois que l’on bouge, presse ou plie le tricot, on "avance" d’une note dans une mélodie. Le rythme de cette mélodie correspond ainsi au rythme du mouvement de celui ou celle qui porte le vêtement et la composition fonctionne en boucle.

Scénario N°2 : aléatoire contrôlé
Nous choisissons ici de distinguer plusieurs typologies de mouvement calme, en marche, excité, etc. Chacune de ces typologies est déterminée par la fréquence des mouvements captés. Plus on s’excite, plus les sons déclenchés sont aigus et distordus, à l’inverse, plus on est calme et plus les sons se réduisent à une sonorité simple.

Scénario N°3 : le son extensible
Le stress exercé sur le tricot est générateur d’un son qui varie en relation directe avec l’étirement de la matière, plus le tricot est tendu plus le son est aigu. L’onde sonore est générée par synthèse. Une carte électronique dédiée permet de programmer plusieurs types de sons qui se rapprochent des sons 8-bit. Cette orientation fera l’objet d’une mise au point ultérieure car vous avons souhaité privilégier dans un premier temps une solution qui utilise des samples.

Scénario N°4 : le son polyphonique
Dans ce dernier scénario le son sera généré par un téléphone portable assisté d’un
mini système son. Ce téléphone sera aussi équipé d’une application musicale contrôlée par le vêtement. Pour réaliser un premier prototype nous avons choisi de travailler avec le système Android et donc d’aborder le développement d’une application en Java...

- http://developer.android.com/sdk/index.html
Les données captées sur les vêtements seront transmises au téléphone par une liaison Bluetooth :
- http://developer.android.com/guide/topics/connectivity/bluetooth.html
- http://www.seeedstudio.com/depot/-p-1157:a8240cb8235e9c493a0c30607586166c.html

- git clone https://github.com/libpd/pd-for-android
- cd pd-for-android
- git submodule init
- git submodule update

- http://blog.rjdj.me/pages/pd-utilities

Solution alternative
http://www.pjrc.com/store/teensy3_audio.html

Reactor/tutoriel

La partie textile de ce projet est basée sur la technique du tricot traditionnel. Pour transformer ce tricot en capteur, l’astuce consiste à intégrer un fil résistif de type polyester argent d’environ 100 Ohm/mètre dans la contexture du tricot. Pour pouvoir être lavé, la connectique entre le tricot et la carte électronique est réalisée à partir de boutons pressions directement sertis sur le tricot conducteur.

La partite électronique est basée sur un principe simple : le pont diviseur de tension. Un pont diviseur est constitué de deux résistances montées en séries. Dans notre cas la résistance R1 est constituée par notre tricot résistif, cette résistance varie en fonction de l’élongation du tricot, la résistance R2 est une résistance fixe qui ce calcule avec la formule suivante : R2 = sqrt(R1max X R1min). La somme des résistances R1 et R2 ne doit pas être trop faible pour éviter une consommation excessive du circuit. D’autre part cette somme ne doit pas être trop grande car cela introduit de l’imprécision ou “bruit” dans la captation. http://www.sonelec-musique.com/electronique_bases_diviseurs_res.html

PNG - 30 ko

Arduino et ATTiny85

Pour faire la lecture du pont diviseur nous avons choisi d’utiliser le micro-contrôleur ATTiny85 et l’environnement de programmation Arduino. Pour programmer ce micro-contrôleur avec Arduino, il suffit d’ajouter l’extension arduino-tiny à l’IDE Arduino. Cette extension doit être déposée dans le répertoire : Documents/Arduino/hardware Il faut ensuite utiliser une Arduino comme programmateur ISP ou un programmateur comme celui-ci : http://www.ladyada.net/make/usbtinyisp

l’ATTiny85 et le module audio WTV020SD

Le module audio WTV020SD présent sur la carte électronique est commercialisé par la société Waytronic pour 2,50$. Ce module est une solution propriétaire dont le code source n’est pas disponible, la documentation technique décrit comment contrôller ce module par une liaison série. Il existe aussi un module commercialisé sous le nom de SOMO-14D mais ce module est une copie du module WTV020SD et la société SOMO efface les références présentes sur les puces du module, ce qui ne permet pas de retrouver les documents techniques originales des composants utilisés.

Consommation d’énergie

Pour optimiser l’autonomie de la carte électronique qui fonctionne sur batterie, une attention particulière est portée à la consommation d’énergie des composants. Tout d’abord le microcontrôleur est configuré pour fonctionner à 8 Mhz. Le mode veille (Idle) de l’ATTiny85 et du module audio WTV020SD est aussi utilisé pour réduire la consommation. L’alimentation du pont diviseur est contrôlée par une broche I/O du micro-contrôleur pour pouvoir stopper sa consommation lors de la mise en veille du dispositif. Au regard du nombre limité de broches disponibles sur un ATTiny85, cette dernière fonctionnalité a nécessité l’utilisation de la broche RESET comme une broche I/O. La broche RESET étant nécessaire pour programmer la puce, nous devons alors utiliser un programmateur high-voltage (HVSP) pour pouvoir réaliser cette opération. Cf : http://www.rickety.us/2010/03/arduino-avr-high-voltage-serial-programmer

PNG - 22.9 ko

Créer votre propre “parfum sonore”

Pour changer les samples de la carte SD, vous devez tout d’abord formater la carte en FAT16. A partir d’un terminal, le programme Diskutil vous permettra de réaliser cette opération en tapant la commande suivante : diskutil partitionDisk /dev/disk1 1 MBRFormat "MS-DOS FAT16" "REACTOR" 100% Pour convertir vos fichiers sons au bon format, vous pouvez réaliser un traitement par lot à partir du programme Sox, qui s’utilise aussi en ligne de commande. Il faut tout d’abord vous déplacer dans le répertoire qui contient vos fichiers sons à l’aide de la commande cd [nom du répertoire cible] La commande ls vous permettra de visualiser les documents contenus dans le répertoire courant. ls Vous devez créer un nouveau répertoire “reactor” à l’intérieur du répertoire contenant vos fichiers sons, ce répertoire sera utilisé pour stocker vos fichiers transcodés. Pour créer ce nouveau répertoire : mkdir ./reactor Pour finir, Il vous reste à taper la commande suivante pour lancer les conversions for FILE in *; do sox $FILE -b 16 ./reactor/$FILE channels 1 rate 16k norm; done Le format des fichiers de sortie : WAV mono, rate 16 K, résolution 16 bits

BUG rencontré

http://code.google.com/p/arduino-tiny/issues/detail?id=70

Reactor/Arduino/firmware

  1. <script src="https://gist.github.com/4065069.js"> </script>
  2. // The Reactor project is combining ATTiny85 and WTV020-SD-20S chip
  3. // the electronic board is made for stand alone audio player controlled by a knitted  sensor fabric
  4. // this sketch implement sleep mode to reduce power consumption
  5. // you will need first to install ATTiny library for Arduino
  6. // http://hlt.media.mit.edu/?p=1695
  7. // change the boards.txt ligne attiny85at8.upload.using=usbtiny depending on you programmer
  8. // Tools > Board > ATTiny85 @ 8 MHz
  9. //////////////////////////////////////// CONSTANTES declaration and initialisation
  10. int sensorPin = 3;                    // PB3 (ADC3) ATTiny analog pin 3 to sens potentiometer scarf (voltage divider)
  11. int volumePin = 2;                    // PB4 (ADC2) ATTiny analog pin 2 as input to trigger SOMO volume (10k pullUp resistor)
  12. #define resetPin             PB0      // ATTiny analog 1 to SOMO reset pin
  13. #define clockPin             PB1      // SOMO clock pin
  14. #define dataPin              PB2      // SOMO data pin
  15. #define MIN_SOUND            16       // reserved sound file for volume menu 0...7
  16. #define MAX_SOUND            64       // how many sound file you have on the SD card
  17. #define DEBOUNCETIME         20       // debounce to avoid double playing instructions
  18. #define THRESHOLD_SENS       20       // threshold apply on derivative sensor value
  19. #define THRESHOLD_SWITCH     100      // threshold apply on derivative sensor value
  20. #define INACTIVETIME         5000     // time before sleeping mode
  21. //////////////////////////////////////// variables declaration and initialisation
  22. unsigned long curentMillis = 0;             //
  23. unsigned long lastMillisSens = 0;           //
  24. unsigned long lastMillisSleep = 0;          //
  25. unsigned int rowSensorScarfVal = 0;         //
  26. unsigned int lastrowSensorScarfVal = 0;     //
  27. int deriveeScarf = 0;                       // derivative variable used to detect mouvments
  28. unsigned int rowSensorSwitchVal = 0;        //
  29. boolean debounceToggleScarf = true;          // avoid double clic instructions
  30. boolean debounceToggleSwitch = true;        // avoid double clic instructions
  31. boolean toggelsomoLowPower = false;         // avoid SOMO waking up during sleep mode
  32. boolean wakeUpToggelVolumeSwitch = true;    //
  33. unsigned int volumeArray[] = {
  34.   0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7
  35. };
  36. unsigned int curentVolume = 7;              // initial volume level
  37. //////////////////////////////////////// Initialisation
  38. void setup(){
  39.   pinMode(clockPin, OUTPUT);                // set pin has an output for clock
  40.   pinMode(dataPin, OUTPUT);                 // set pin has an output for data
  41.   pinMode(resetPin, OUTPUT);                // set pin has an output to reset SOMO
  42.   digitalWrite(clockPin, HIGH);             //
  43.   digitalWrite(dataPin, LOW);               //
  44.   digitalWrite(resetPin, HIGH);             //
  45.   /////////////////////// initialize watchdog timer
  46.   somoReset();
  47.   sendData(volumeArray[curentVolume]);   // set SOMO-14D volume
  48. }
  49. //////////////////////////////////////// boucle principale
  50. void loop(){
  51.   curentMillis = millis();
  52.   // set SOMO lowPower MODE
  53.   if( ((curentMillis - lastMillisSleep) >= INACTIVETIME) && toggelsomoLowPower){
  54.     toggelsomoLowPower = false;                 // invert toggle to give sleep instruction only one time
  55.     wakeUpToggelVolumeSwitch = true;            // invert toggle to permit reset after wakeUn
  56.     somoLowPower();                             // put SOMO in to idle MODE
  57.   }
  58.   // slow down analog readings
  59.   if((curentMillis - lastMillisSens) >= DEBOUNCETIME){
  60.     // read switch plugged on to Analog pin
  61.     rowSensorSwitchVal = analogRead(volumePin);
  62.     if((rowSensorSwitchVal <= THRESHOLD_SWITCH) && debounceToggleSwitch){
  63.       // wakeUp SOMO with the first volume switch presed
  64.       if(wakeUpToggelVolumeSwitch){
  65.         wakeUpToggelVolumeSwitch = false;         // invert toggle to reset only one time
  66.         lastMillisSleep = curentMillis;           // reset sleep counter
  67.         somoReset();                              // reset SOMO
  68.       }
  69.       else {
  70.         curentVolume++;                           // increase the volume
  71.         sendData(curentVolume % 8);               // play coresponding file
  72.         sendData(volumeArray[curentVolume % 8]);  // set SOMO volume
  73.         debounceToggleSwitch = false;             // invert toggle value to avoid double instructions
  74.         lastMillisSleep = curentMillis;           // reset sleep counter
  75.       }
  76.     }
  77.     if((rowSensorSwitchVal > THRESHOLD_SWITCH) && !debounceToggleSwitch){
  78.       debounceToggleSwitch = true;                // invert toggle to debounce playing instructions
  79.     }
  80.     rowSensorScarfVal = analogRead(sensorPin);      
  81.     deriveeScarf = abs(rowSensorScarfVal - lastrowSensorScarfVal);
  82.     if((deriveeScarf >= THRESHOLD_SENS) && debounceToggleScarf){
  83.       sendData(random(MIN_SOUND, MAX_SOUND));       // play a sample randomly
  84.       debounceToggleScarf = false;                   // invert toggle to debounce playing instructions
  85.       toggelsomoLowPower = true;                    // invert toggle to avoide SOMO sleep MODE
  86.       lastMillisSleep = curentMillis;               // reset sleep counter
  87.     }
  88.     if(!debounceToggleScarf && (deriveeScarf < THRESHOLD_SENS)){   // wait until derivative go under threshold
  89.       debounceToggleScarf = true;                                  // invert toggle to debounce playing instructions
  90.     }
  91.     lastrowSensorScarfVal = rowSensorScarfVal;                    // remind curent scarf sensor value
  92.     lastMillisSens = curentMillis;                                // reset sleep counter
  93.   }
  94. }
  95. /////////////////////////////// send data to SOMO module
  96. void sendData(unsigned int command){
  97.   // start bit
  98.   digitalWrite(clockPin, LOW);
  99.   delay(2);
  100.   // bit15, bit14, ... bit0
  101.   for (unsigned int mask = 0x8000; mask > 0; mask >>= 1) {
  102.     if (command & mask) {
  103.       digitalWrite(dataPin, HIGH);
  104.     }
  105.     else {
  106.       digitalWrite(dataPin, LOW);
  107.     }
  108.     // clock low
  109.     digitalWrite(clockPin, LOW);
  110.     delayMicroseconds(15);
  111.     // clock high
  112.     digitalWrite(clockPin, HIGH);
  113.     delayMicroseconds(15);
  114.   }
  115.   // stop bit
  116.   delay(2);
  117. }
  118. /////////////////////// Reset SOMO
  119. void somoReset(){
  120.   digitalWrite(resetPin, LOW);
  121.   delay(10);
  122.   digitalWrite(resetPin, HIGH);
  123.   delay(10);
  124. }
  125. /////////////////////// SOMO lowPower MODE
  126. // Stops playing the current audio file and puts the module in the ow power idle mode.
  127. void somoLowPower(){
  128.   sendData(0xFFFF);
  129. }

Forum sur abonnement

Pour participer à ce forum, vous devez vous enregistrer au préalable. Merci d'indiquer ci-dessous l'identifiant personnel qui vous a été fourni. Si vous n'êtes pas enregistré, vous devez vous inscrire.

Connexions'inscriremot de passe oublié ?