Wearable Proto1

Salut à tous comment allez-vous?
J’espère que vos vacances sont bonnes, si vous en avez… Pour ma part, elles n’arriveront pas avant fin août, mais cela devrait me laisser le temps de vous rédiger un peu de lecture pour cette période estivale… 😆

Aujourd’hui, un petit projet wearable à base d’Arduino pour un habit que ma compagne va réaliser.

Autant partir du bon pied et se casser la tête  🙄 . Car si le montage est simple les contraintes exigées sont plus importantes que d’habitude :

  • Fixation résistante à toute épreuve
  • Fixation doit facilement être démontable (oui c’est bête vu le point précédent, mais nous n’avons pas envie de passer un arduino à la machine à laver… 😉 )
  • Placement de la batterie dans le vêtement ou sur la fixation
  • Organisation des composants (groupés à un endroit ou non)
  • Placement des composants à un endroit clé du vêtement : sans le projet le vêtement n’est pas portable, il ne tient pas ou juste apposer le projet pour de la décoration…

Des questions toutes simples qui peuvent vous empêcher de vous prendre la tête au moment du montage… 😉

Pour les composants la liste est relativement courte :

  • Un LilyPad USB de chez SnootLab (Merci les bons DefiDataPlus)
  • Un NeoPixel Ring de chez Adafruit (Merci les bons DefiDataPlus)
  • Un Capteur TL2561 (luminosité) de chez Adafruit
  • Une batterie LiPo

Le LilyPad en dessous, le NeoPixel Ring juste au-dessus et le capteur TL2561 au centre : On a choisi un montage dit « sandwich » 😉

lilypad_side
Lilypad + NeoPixel Ring + TL2561
lilypad_side_support_batterie
Lilypad + Baterie + Support + NeoPixel Ring + TL2561

Le montage est simple :

  • Soudez le NeoPixel Ring avec le moins de longueur de câble possible :

(pin élément -> pin LilyPad)

  • Vin -> +
  • GRND -> –
  • Data In -> D10
  • Soudez le Capteur TL2561 au centre avec des câbles un peu plus long pour que la luminosité des LED ne soit pas enregistrée. Car oui les NeoPixel Ring sont vraiment lumineux même en 3V…

(pin élément -> pin LilyPad)

  • SDA -> D2
  • SCL -> D3
  • 3V3 -> +
  • Grnd -> –

Les liens pour ajouter les librairies à l’Arduino IDE :

Voici le code que j’utilise, bon il faut encore l’optimiser, mais c’est déjà assez sympa, le NeoPixel Ring joue les animations de base de chez Adafruit en fonction de la valeur de lux que le capteur reçoit  :

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2561_U.h>
#include <Adafruit_NeoPixel.h>

Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT, 12345);
#define PIN 10
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);

void setup(void)
{
  Serial.begin(9600);
  strip.begin();
  strip.show();
  strip.setBrightness(50);
  tsl.setGain(TSL2561_GAIN_1X);      /* No gain ... use in bright light to avoid sensor saturation */
  //tsl.setGain(TSL2561_GAIN_16X);     /* 16x gain ... use in low light to boost sensitivity */
  //tsl.enableAutoRange(true);            /* Auto-gain ... switches automatically between 1x and 16x */
  tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS);      /* fast but low resolution */
  //tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_101MS);  /* medium resolution and speed   */
  //tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS);  /* 16-bit data but slowest conversions */
  if (!tsl.begin())
  {
    /* There was a problem detecting the ADXL345 ... check your connections */
    Serial.print("Ooops, no TSL2561 detected ... Check your wiring or I2C ADDR!");
    while (1);
  }


}

void loop(void)
{
  sensors_event_t event;
  tsl.getEvent(&event);
  if (event.light)
  {
    Serial.print(event.light);
    Serial.println(" lux");
    int t = map (event.light, 0, 62000, 0, 5);
    Serial.println(t);
    int e = constrain(t, 0, 5);
    Serial.println(e);
    switch (e) {
      case 0:
        Serial.println("cas 0");
        rainbowCycle(50);

        break;
      case 1:
        Serial.println("cas 1");
        rainbow(50);
        break;
      case 2:
        Serial.println("cas 2");
        colorWipe(strip.Color(255, 0, 0), 50); // Red
        colorWipe(strip.Color(0, 255, 0), 50); // Green
        colorWipe(strip.Color(0, 0, 255), 50); // Blue
        colorWipe(strip.Color(255, 0, 255), 50); // purple
        colorWipe(strip.Color(255, 255, 255), 50); // white
        break;
      case 3:
        Serial.println("cas 3");
        theaterChaseRainbow(50);
        break;
      case 4:
        Serial.println("cas 4");
        theaterChase(strip.Color(255, 255, 255), 50); // White
        theaterChase(strip.Color(255,   0,   0), 50); // Red
        theaterChase(strip.Color(  0,   0, 255), 50); // Blue
        theaterChase(strip.Color(  0,   255, 0), 50); // GReen
        theaterChase(strip.Color(  255,   0, 255), 50); // Purple

        break;
    }
  }
  else
  {
    rainbowCycle(50);
    Serial.println("Sensor overload");
  }

  delay(25);
}

void colorWipe(uint32_t c, uint8_t wait) {
  for (uint16_t i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for (j = 0; j < 256; j++) {
    for (i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel
    for (i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    //delay(wait);
  }
}

//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
  for (int j = 0; j < 10; j++) { //do 10 cycles of chasing
    for (int q = 0; q < 3; q++) {
      for (int i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, c);  //turn every third pixel on
      }
      strip.show();

      //delay(wait);

      for (int i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, 0);      //turn every third pixel off
      }
    }
  }
}

//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
  for (int j = 0; j < 256; j++) {   // cycle all 256 colors in the wheel
    for (int q = 0; q < 3; q++) {
      for (int i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, Wheel( (i + j) % 255)); //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (int i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, 0);      //turn every third pixel off
      }
    }
  }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if (WheelPos < 85) {
    return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
    WheelPos -= 170;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

Passons maintenant au support!!! À la base, je voulais l’imprimer en 3D, j’avais fait mon fichier STL, tout beau tout propre grâce à 123D Design. Je vais au FabLab, je lance l’impression en ABS au passage, car avec l’UltimMaker 2 c’est possible  😮 . J’étais content, jusqu’à 50% tout était nickel du premier coup pour ma première impression en ABS 🙂 . Mais arrivé à 55% la pièce à foirée sur une épaisseur dans le centre du rond, même pas sur les arrondis qui ont tendance à wrapper très/trop facilement surtout en ABS. GRRRRRRRR!!!!! 😥

support_3D
On voit l’épaisseur qui à ratée même du dessus…
support_3D_cote
Gros plan de l’épaisseur foireuse
support_3D_cote_2
Vue ensemble

Pourtant malgré ce problème, la pièce est impressionnante de résistance : Merci l’ABS, même les mini fixations de 1mm d’épais ne cassent pas entre mes doigts quand je force fortement dessus… Et croyez-moi, je n’y suis pas allé de main morte comme dirait l’autre… 😈

Bon pas de découragement, on vidange la 3D, on passe en PLA, on vérifie tous les réglages de la 3D et on relance l’impression. Et là BIMMMMM, de nouveau une couche qui déconne à 55% 😥

Comme le FabLab est un endroit plein de personnes qui sont 2500% plus douées que moi. Théo (mon grand Gorou de l’impression 3D 😀 ) m’a conseillé de faire ma pièce à la laser car je n’avais pas besoin de hauteur…

Et me voilà parti sur Illustrator pour faire ma pièce, je la réalise, je fais la première découpe : ce n’est pas la bonne échelle, les arrondis sont carrés (oui c’est un peu bête), rien n’est symétrique : EPIC FAIL!!!! 🙄

Comme je l’ai déjà dit un FabLab c’est plein de gens plus intelligents que moi :mrgreen: … Avec l’aide de Nathael (mon grand gourou de l’électronique 😀 ), tout semble symétrique comme je le veux. Bon soit dites en passant Nathael d’après ses dires ne taquine pas du tout InkScape mais il a fait le tracé en moins de 15minutes tout en discutant de connexion UART avec une autre personne… À chaque fois que je le vois, je suis 😯 devant ses compétences tant le fossé qui nous sépare semble être grand comme pour beaucoup de personnes que je croise au Fablab…

On passe le tout dans la laser : Parfait du premier coup… 🙂

Vue ensemble
Vue ensemble
Vue Ensemble 2
Vue Ensemble 2
Vue de coté
Vue de coté

Comme je suis un gros boulet, j’ai effacé le fichier de découpage… Du coup je ne peux pas le partager 😥 . J’espère que je pourrai le retrouver à la rentrée du FabLab, ou qu’un lecteur du FabLab l’a avec lui et pourra me l’envoyer…

lilypad_back_no_battery
Vue arrière du support
lilypad_top_suport
Vue de face
lilypad_top_support_battery
Vue de Face 2

lilypad_vg_2 lilypad_vg3 lilypad_vg

Vidéo montrant une des animations :

https://www.flickr.com/photos/anderson69s/14559758350

Pour le moment, ni la batterie ni le LilyPad ne sont collés sur le support, mais c’est normal, madame veut attendre de faire l’habit ce que je peux comprendre 8).

Quoiqu’il en soit tout est près pour son projet!!! 😉

@bientôt Anders

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

Traduction :