IMA4 2017/2018 P18 : Différence entre versions

De Wiki de Projets IMA
(Semaine 13)
(Semaine 14)
Ligne 526 : Ligne 526 :
 
Voila un extrait du code pour réaliser ces 3 animation.
 
Voila un extrait du code pour réaliser ces 3 animation.
  
#include <stdio.h>
+
#include <stdio.h>
 +
#include "time.h"
 +
#include "tlc5947.h"
 +
#include "zxgesture.h"
 +
#include "animations.h"
  
#include "time.h"
+
// Global variables
#include "tlc5947.h"
 
#include "zxgesture.h"
 
#include "animations.h"
 
  
// Global variables
+
/* Values for each LED sets */
 
 
/* Values for each LED sets */
 
 
unsigned int groupes[NB_GROUPES];
 
unsigned int groupes[NB_GROUPES];
  
/* Definition of LED sets */
+
/* Definition of LED sets */
int groupe1[]={
+
int groupe1[]={
 
   23,10,7,40,61,70,55,13,-1
 
   23,10,7,40,61,70,55,13,-1
 
   };
 
   };
int groupe2[]={
+
int groupe2[]={
 
   5,9,39,43,63,48,57,20,-1
 
   5,9,39,43,63,48,57,20,-1
 
   };
 
   };
int groupe3[]={
+
int groupe3[]={
  22,24,8,29,30,33,38,42,60,64,67,49,52,58,14,18,-1
+
  22,24,8,29,30,33,38,42,60,64,67,49,52,58,14,18,-1
 
   };
 
   };
int groupe4[]={
+
int groupe4[]={
 
   0,4,6,26,31,34,37,44,47,65,68,50,53,59,15,19,-1
 
   0,4,6,26,31,34,37,44,47,65,68,50,53,59,15,19,-1
  
 
   };
 
   };
int groupe5[]={
+
int groupe5[]={
 
   2,11,25,27,32,35,41,45,62,66,71,51,56,12,17,21,-1
 
   2,11,25,27,32,35,41,45,62,66,71,51,56,12,17,21,-1
 
};
 
};
int groupe6[]={
+
int groupe6[]={
 
   1,3,28,36,46,69,54,16,-1
 
   1,3,28,36,46,69,54,16,-1
 
};
 
};
  
int tous[]={
+
int tous[]={
 
   23,10,7,40,61,70,55,13,
 
   23,10,7,40,61,70,55,13,
 
   5,9,39,43,63,48,57,20,
 
   5,9,39,43,63,48,57,20,
Ligne 569 : Ligne 568 :
 
   };
 
   };
  
/* Animations1 */
+
/* Animations1 */
variation_params v1={.deltac=500,.deltad=500,.deltap=2000,.min=0,.max=1024};
+
variation_params v1={.deltac=500,.deltad=500,.deltap=2000,.min=0,.max=1024};
variation_params v2={.deltac=500,.deltad=500,.deltap=2000,.min=0,.max=1024};
+
variation_params v2={.deltac=500,.deltad=500,.deltap=2000,.min=0,.max=1024};
variation_params v3={.deltac=500,.deltad=500,.deltap=2000,.min=0,.max=256};
+
variation_params v3={.deltac=500,.deltad=500,.deltap=2000,.min=0,.max=256};
variation_params v4={.deltac=500,.deltad=500,.deltap=2000,.min=0,.max=1024};
+
variation_params v4={.deltac=500,.deltad=500,.deltap=2000,.min=0,.max=1024};
variation_params v5={.deltac=500,.deltad=500,.deltap=2000,.min=0,.max=1024};
+
variation_params v5={.deltac=500,.deltad=500,.deltap=2000,.min=0,.max=1024};
variation_params v6={.deltac=500,.deltad=500,.deltap=2000,.min=0,.max=1024};
+
variation_params v6={.deltac=500,.deltad=500,.deltap=2000,.min=0,.max=1024};
animation a1[]={
+
animation a1[]={
 
   {0,60000,groupe1,&v1,variation_groupes},
 
   {0,60000,groupe1,&v1,variation_groupes},
 
   {500,60000,groupe2,&v2,variation_groupes},
 
   {500,60000,groupe2,&v2,variation_groupes},
Ligne 586 : Ligne 585 :
 
   };
 
   };
  
/* Animation2 */
+
/* Animation2 */
variation_params v_tous={.deltac=100,.deltad=100,.deltap=0,.min=0,.max=255};
+
variation_params v_tous= {.deltac=100,.deltad=100,.deltap=0,.min=0,.max=255};
animation a2[]={
+
animation a2[]={
 
   {0,40000,tous,&v_tous,variation_groupe},
 
   {0,40000,tous,&v_tous,variation_groupe},
 
   {-1,-1,NULL,NULL,NULL}
 
   {-1,-1,NULL,NULL,NULL}
 
   };
 
   };
  
/* Animation3 */
+
/* Animation3 */
variation_params v21={.deltac=500,.deltad=500,.deltap=0,.min=0,.max=1024};
+
variation_params v21={.deltac=500,.deltad=500,.deltap=0,.min=0,.max=1024};
variation_params v22={.deltac=500,.deltad=500,.deltap=0,.min=0,.max=1024};
+
variation_params v22={.deltac=500,.deltad=500,.deltap=0,.min=0,.max=1024};
variation_params v23={.deltac=500,.deltad=500,.deltap=0,.min=0,.max=256};
+
variation_params v23={.deltac=500,.deltad=500,.deltap=0,.min=0,.max=256};
variation_params v24={.deltac=500,.deltad=500,.deltap=0,.min=0,.max=1024};
+
variation_params v24={.deltac=500,.deltad=500,.deltap=0,.min=0,.max=1024};
variation_params v25={.deltac=500,.deltad=500,.deltap=0,.min=0,.max=1024};
+
variation_params v25={.deltac=500,.deltad=500,.deltap=0,.min=0,.max=1024};
variation_params v26={.deltac=500,.deltad=500,.deltap=0,.min=0,.max=1024};
+
variation_params v26={.deltac=500,.deltad=500,.deltap=0,.min=0,.max=1024};
animation a3[]={
+
animation a3[]={
 
   {0,60000,groupe1,&v21,variation_groupes},
 
   {0,60000,groupe1,&v21,variation_groupes},
 
   {0,60000,groupe2,&v22,variation_groupes},
 
   {0,60000,groupe2,&v22,variation_groupes},
Ligne 610 : Ligne 609 :
 
   };
 
   };
 
   
 
   
animation *anims[]={a1,a2,a3,NULL};
+
animation *anims[]={a1,a2,a3,NULL};
  
/* Variables for animation settings */  
+
/* Variables for animation settings */  
int quantum=1000;
+
int quantum=1000;
int stop;
+
int stop;
  
// Functions
+
// Functions
//
+
//
/* Handle the user input */
+
/* Handle the user input */
  
void user_input(void){
+
void user_input(void){
if(zx_gesture_ready()){
+
if(zx_gesture_ready()){
 
   int g=zx_get_gesture();
 
   int g=zx_get_gesture();
   printf("geste=%d quantum=%d\n",g,quantum);
+
   printf("geste=%d quantum=%d\n",g,quantum);
 
   switch(g){
 
   switch(g){
 
     case ZX_GEST_RIGHT:
 
     case ZX_GEST_RIGHT:
       if(quantum>QUANTUM_MIN) quantum -= QUANTUM_PAS;
+
       if(quantum>QUANTUM_MIN) quantum -= QUANTUM_PAS;
 
       break;
 
       break;
 
     case ZX_GEST_LEFT:
 
     case ZX_GEST_LEFT:
Ligne 635 : Ligne 634 :
 
       break;
 
       break;
 
     }
 
     }
  }
+
  }
}
+
}
  
/* Wait some time */
+
/* Wait some time */
  
void wait_us(unsigned long delay){
+
void wait_us(unsigned long delay){
static unsigned long start;
+
static unsigned long start;
if(delay==0) start=micros();
+
if(delay==0) start=micros();
else
+
else
 
   while(1){
 
   while(1){
 
     unsigned long now=micros();
 
     unsigned long now=micros();
Ligne 650 : Ligne 649 :
 
     if(delta>=delay) break;
 
     if(delta>=delay) break;
 
     }
 
     }
}
+
}
  
/* Get a set of LEDs size */
+
/* Get a set of LEDs size */
  
int taille_groupes(int leds[]){
+
int taille_groupes(int leds[]){
int i=0;
+
int i=0;
while(leds[i]>=0) i++;
+
while(leds[i]>=0) i++;
return i;
+
return i;
}
+
}
  
/* Set luminosity value to a set of LEDs */
+
/* Set luminosity value to a set of LEDs */
  
void valeur_groupes(int leds[],unsigned int valeur){
+
void valeur_groupes(int leds[],unsigned int valeur){
int i=0;
+
int i=0;
while(1){ if(leds[i]<0) break; groupes[leds[i++]]=valeur; }
+
while(1){ if(leds[i]<0) break; groupes[leds[i++]]=valeur; }
}
+
}
  
/* Compute variation of luminosity for a set of LEDs */
+
/* Compute variation of luminosity for a set of LEDs */
  
void variation_groupes(int leds[],void *arg,long temps){
+
void variation_groupes(int leds[],void *arg,long temps){
variation_params *p=arg;
+
variation_params *p=arg;
long periode=p->deltac+p->deltad+p->deltap; // Dans quelle phase de la variation se trouve-t-on ?
+
long periode=p->deltac+p->deltad+p->deltap; // Dans quelle phase de la variation se trouve-t-on ?
long instant=temps%periode;
+
long instant=temps%periode;
if(instant<=p->deltac){ // Cas de la phase de croissance de p->min à p->max
+
if(instant<=p->deltac){ // Cas de la phase de croissance de p->min à p->max
 
   long calc=(long)p->max-(long)p->min;
 
   long calc=(long)p->max-(long)p->min;
 
   calc=calc*instant/p->deltac+p->min;
 
   calc=calc*instant/p->deltac+p->min;
 
   valeur_groupes(leds,calc);
 
   valeur_groupes(leds,calc);
 
   }  
 
   }  
else if(instant<=p->deltac+p->deltad){ // Cas de la phase de décroissance
+
else if(instant<=p->deltac+p->deltad){ // Cas de la phase de décroissance
 
   long calc=(long)p->min-(long)p->max;
 
   long calc=(long)p->min-(long)p->max;
   calc=calc*(instant-p->deltac)/p->deltad+p->max;
+
   calc=calc*(instant-p->deltac)/p- >deltad+p->max;
 
   valeur_groupes(leds,calc);
 
   valeur_groupes(leds,calc);
 
   }
 
   }
else // Cas de la pause
+
else // Cas de la pause
 
   valeur_groupes(leds,p->min);
 
   valeur_groupes(leds,p->min);
}
+
}
  
/* Variation set by set */
+
/* Variation set by set */
  
void variation_groupe(int leds[],void *arg,long temps){
+
void variation_groupe(int leds[],void *arg,long temps){
variation_params *p=arg;
+
variation_params *p=arg;
long periode=p->deltac+p->deltad+p->deltap;
+
long periode=p->deltac+p->deltad+p->deltap;
long nb=temps/periode; // Quel groupe de LED est concerné ?
+
long nb=temps/periode; // Quel groupe de LED est concerné ?
nb=nb%taille_groupes(leds);
+
nb=nb%taille_groupes(leds);
int instant=temps%periode; // Quelle est la phase courante de la variation ?
+
int instant=temps%periode; // Quelle est la phase courante de la variation ?
if(instant<=p->deltac){ // Cas de la phase de croissance de p->min à p->max
+
if(instant<=p->deltac){ // Cas de la phase de croissance de p->min à p->max
 
   long calc=(long)p->max-(long)p->min; calc=calc*instant/p->deltac+p->min;
 
   long calc=(long)p->max-(long)p->min; calc=calc*instant/p->deltac+p->min;
 
   groupes[leds[nb]]=calc;
 
   groupes[leds[nb]]=calc;
 
   }
 
   }
else if(instant<=p->deltac+p->deltad){ // Cas de la phase de décroissance
+
else if(instant<=p->deltac+p->deltad){ // Cas de la phase de décroissance
 
   long calc=(long)p->min-(long)p->max; calc=calc*(instant-p->deltac)/p->deltad+p->max;
 
   long calc=(long)p->min-(long)p->max; calc=calc*(instant-p->deltac)/p->deltad+p->max;
 
   groupes[leds[nb]]=calc;
 
   groupes[leds[nb]]=calc;
 
   }
 
   }
else // Cas de la pause
+
else // Cas de la pause
 
   groupes[leds[nb]]=p->min;
 
   groupes[leds[nb]]=p->min;
}
+
}
  
/* Play an animation */
+
/* Play an animation */
  
void animation_play(animation *a){
+
void animation_play(animation *a){
static unsigned char init;
+
static unsigned char init;
if(init==0){ init_LED_Drivers(NB_DRIVERS); init_time(); init=1; }
+
if(init==0){   init_LED_Drivers(NB_DRIVERS); init_time(); init=1; }
animation *p;
+
animation *p;
unsigned long temps=0;
+
unsigned long temps=0;
int i;
+
int i;
for(i=0;i<NB_GROUPES;i++) groupes[i]=0;
+
for(i=0;i<NB_GROUPES;i++) groupes[i]=0;
while(stop==0){
+
while(stop==0){
 
   unsigned char actif=0;
 
   unsigned char actif=0;
 
   wait_us(0);
 
   wait_us(0);
Ligne 731 : Ligne 730 :
 
   temps++;
 
   temps++;
 
   }
 
   }
stop=0;
+
stop=0;
}
+
}
  
/* Play all animations */
+
/* Play all animations */
  
void animation_all(void){
+
void animation_all(void){
printf("Play all\n");
+
printf("Play all\n");
animation **a=anims;
+
animation **a=anims;
while(*a!=NULL) animation_play(*a++);
+
while(*a!=NULL) animation_play(*a++);
}
+
}
  
 
=Documents Rendus=
 
=Documents Rendus=

Version du 16 mai 2018 à 06:37


Présentation générale

Description

Le mot mandala vient d‘une très ancienne langue indienne.Il signifiant:

  1. disque, cercle, sphère ;
  2. toute figure géométrique apparentée au cercle ;
  3. structure, forme d'organisation ;
  4. dessin que l'on trace sur le sol ou sur un autre support à l'occasion de divers rites.

Il s'exprime dans un dessin circulaire, convergeant vers un centre porteur d'infini. Dans la tradition orientale, le cercle représente le Divin, sa manifestation, sa création. Ce symbole du cercle se retrouve dans toutes les cultures et toutes les traditions, tant occidentales qu'orientales.

Le cercle est le symbole de la vie: la naissance, la maturité, la mort et la résurrection ou la renaissance. Dans le bouddhisme, il est utilisé surtout pour la méditation. Le diagramme est dans tous les cas rempli de symboles; il peut être associé à une divinité.

Objectifs

L'objectif est de réaliser un mandala électronique.

Analyse du projet

Analyse du premier concurrent

2018 P18 kit noel.png

Un premier concurrent pourrait être ce kit électronique de sapin de noël avec 16 LEDs clignotantes. Par rapport à notre mandala ce kit comporte peu de LEDs et ne réalise qu'une seule animation sans interaction avec les visiteurs.


Analyse du second concurrent

2018 P18 Xiaojingling1.png

Un second concurrent plus en rapport avec l'apparence de notre mandala est un tableau lumineux pour décoration de chambre d'enfant. Il s'agit d'une peinture avec un éclairage par LEDs. Là encore moins de LEDs et d'interaction qu'avec notre mandala.


Originalité de notre mandala

L'originalité de notre mandala, par rapport aux objets décoratifs déjà existants, est qu'il comportant un grand nombre de LEDs (environ 200), qu'il intègre un micro-contrôleur permettant des animations variées (contrôle de la luminosité des LEDs) et qu'enfin le mandala est interactif grâce à un détecteur de gestes.

Scénario d'usage du produit ou du concept envisagé

Notre mandala est un élément de décoration et, avec des animations adaptées, peut être un objet de relaxation.

Le visiteur est tout d'abord attiré par l'objet artistique, en effet quand il entre dans la pièce, le mandala apparaît comme une peinture sur bois. Au second regard le circuit central pique la curiosité du visiteur. En s'approchant le visiteur déclenche une animation lumineuse. Surpris, il fait un mouvement involontaire qui déclenche un autre type d'animation. Le visiteur teste alors d'autres gestes pour rentrer en interaction avec le mandala.

Le mandala réagissant aux gestes du visiteur, des gestes lents conduisent à des animations relaxantes.

Réponse à la question difficile

Durant la présentation de notre projet les deux questions suivantes nous ont été posées.

Première question

Combien de LEDs le mandala va-t-il comporter, combien de groupes de LEDs indépendants pour les animations ?

Nous avons fait une première esquisse de notre mandala :

2018 P18 mandala brouillon.jpg

Au vu de ce premier dessin, nous avons décidé de rajouter encore des LEDs. Nous partons sur 6 groupes de LEDs pour un total de 256 LEDs :

  • un premier cercle de 32 LEDs oranges ;
  • un deuxième cercle de 32 LEDs jaunes ;
  • un troisième cercle de 32 LEDs bleues ;
  • un quatrième cercle de 64 LEDs jaunes ;
  • un cinqième cercle de 64 LEDs oranges ;
  • enfin un dernier cercle de 32 LEDs oranges.

Seconde question

Le mandala sera alimenté de quelle façon pour quelle autonomie ?

Un rapide calcul de la consommation des LEDs toutes allumées donne un total de 20mA par 256 LEDs soit près de 4A. Même pour une autonomie de 24h, il faudrait une batterie trop importante. Les LEDs ne doivent donc être allumées que lorsqu'un visiteur est présent et les animations doivent éviter les tableaux avec toutes les LEDs allumées à pleine puissance. En partant sur l'équivalent de deux LEDs allumées à pleine puissance tout le temps et sur une consommation du circuit d'environ 40mA nous obtenons une consommation moyenne d'environ 100mA. Avec une alimentation par 8 piles rechargeables AA de 2600MAh nous avons une autonomie d'environ un jour. Il faut donc prévoir que la carte électronique puisse entrer dans un mode d'économie d'énergie ou plus simplement un interrupteur pour éviter de décharger les piles.

Extension de fonction

Utiliser avec ZX Distance et Gesture Sensor

Préparation du projet

Cahier des charges

L'objet final sera constitué des composants ci-dessous.

  1. une peinture de type mandala sur une planche de contre-plaqué réalisée à la gouache ;
  2. une carte électronique centrale à base de micro-contrôleur utilisant des pilotes de LEDs ;
  3. des petites cartes dissiminés sur l'ensemble de la peinture pour porter les LEDs, les connexions avec la carte centrale se fait par des fils passant à l'arrière de la planche ;
  4. les boitiers de piles sont aussi à fixer à l'arrière du mandala ;
  5. pour la détection des gestes nous utiliserons une carte "ZX Distance et Gesture Sensor" de SparkFun.

Choix techniques : matériel et logiciel

Inkscape: pour dessiner un dessin mandala

Frizing: dessiner tous les circuits imprimés et PCBs

Ardunio: programmation informatique pour contrôler les LEDs

Liste des tâches à effectuer

Les tâches à effectuer pour ce projet sont :

  1. faire un dessin précis du mandala avec la position des cartes électronique et celles des trous pour faire passer les câbles permettant de relier les cartes, il faut aussi ajouter les ouvertures permettant d'intégrer le détecteur de gestes ;
  2. choisir un dispositif pour contrôleur les LEDs (registre à décalage ou pilote de LEDs) ;
  3. concevoir le circuit à base de micro-contrôleur pour contrôler les très nombreuses LEDs ;
  4. réaliser (souder) la carte électronique et la tester ;
  5. concevoir les cartes électroniques porte LEDs et les réaliser ;
  6. Programmer des animations pouvant être déclenchées par le capteur de gestes.

Calendrier prévisionnel

Réalisation du Projet

Feuille d'heures

Tâche Prélude Heures S1 Heures S2 Heures S3 Heures S4 Heures S5 Heures S6 Heures S7 Heures S8 Heures S9 Heures S10 Heures S11 Heures S12 Heures S13 Heures S14 Total
Dessin du mandala 0 4 4
Contrôle des LEDs 0 4 4
Réalisation du circuit principal 0 4 4 4 12
Réalisation des circuits porte-LEDs 0 4 4 4 12
Réalisation du mandala 0 4 4 4 4 6 4 4 30
Programmation des animations 0 8 8

Semaine 1

Nous avons établi une première liste de matériel nécessaire pour le mandala.

Nous avons aussi utilisé le logiciel inkscape pour dessiner les éléments artistiques du mandala. Le fichier vectoriel est disponible : Media:2018_P18_Mandala Drawing.svg, l'image ci-dessous en donne un aperçu.

2018 P18 Mandala Drawing.png

Semaine 2

L'encadrant en électronique a conseillé d'utiliser des circuits pilotes de LEDs pour gérer les LEDs. Nous avons préféré utiliser des contrôleurs TLC59711 et TLC5947 car ces circuits sont bien documents sur ce document [1].

Pour savoir quel circuit et à combien d'exemplaires il faut utiliser, nous devons décider du voltage d'alimentation et en déduire le nombre de sorties dont nous avons besoin.

Nous allons utiliser 8 accumulateurs à 1,2v nous disposons donc d'une tension d'alimentation de 9,6v.

Chaque sortie des pilotes va donc pouvoir contrôler 4 LEDs à 2v et 2 LEDs à 3,3v.

Pour nos cinq cercles de LEDs cela donne donc les nombres suivant de sorties nécessaires :

  • un premier cercle de 32 LEDs rouges (2v), soit 8 sorties nécessaires ;
  • un deuxième cercle de 32 LEDs oranges (2v), soit 8 sorties nécessaires ;
  • un troisième cercle de 48 LEDs bleues (3v), soit 16 sorties nécessaires  ;
  • un quatrième cercle de 64 LEDs jaunes (2v), soit 16 sorties nécessaires ;
  • un cinqième cercle de 64 LEDs rouges (2v), soit 16 sorties nécessaires ;
  • enfin un dernier cercle de 32 LEDs jaunes (2v), soit 8 sorties nécessaires.

En définitive 72 sorties sont nécessaires. En choisissant des circuits TLC5947 à 24 sorties nous couvront les besoins avec 3 circuits et en laissant une marge pour ajouter des LEDs si nécessaire.

2018-P18-Montage-TLC59771.png

Pour tester un circuit pilote de LEDs nous avons réalisé un montage avec une plaque d'essai, une pile de 9v et un circuit d'Adafruit à base de TLC59711 (un circuit très proche du TLC5947 mais avec seulement 12 sorties).

Nous avons connecté notre montage à un Arduino et nous avons programmé l'Arduino pour allumer les LEDs sur les différentes sorties alternativement. Le code est disponible : Media:2018-P18-TestLeds.ino.zip

Voici le montage sur plaque d'essai pour allumer 8 LEDs alternativement en utilisant 4 sorties (2 LEDs par sortie). Et ça marche.


Semaine 3

Pour réaliser la carte électronique principale nous utilisons le logiciel Fritzing.

Ce logiciel ne possède pas d'empreinte pour le TLC5947. Nous devons la créer nous même.

Nous avons étudié la façon pour créer de nouvelles empreintes.

D'abord, nous avons trouvé un composant avec une empreinte de type HTSSOP 28 broches que nous pouvons transformer en 32 broches. Nous avons utilisé inkscape pour dessiner les différentes vues et puis nous importons les dessins dans Fritzing.

Pour cette séance nous nous sommes occupés de la vue "plaque d'essai" et de la vue "schématique".


  • schéma de la vue "breadboard" :
    2018 P18 TLC5947 breadboard.png
  • schéma de la vue "schematic" :
    2018 P18 TLC5947 schematic.png

Semaine 4

Nous avons continué à réaliser l'empreinte pour un TLC5947. Voici le dessin pour la vue PCB :
2018 P18 TLC5947 PCB.png

Le fichier du nouveau composant est disponible : Media:2018_P18_TLC5947_v3.zip.

Pour l'utiliser il faut renommer le fichier en .fzpz et l'importer dans la fenêtre "composants" de Fritzing.

Nous avons commencé à concevoir la carte principale avec cette nouvelle empreinte.

Voila la vue "plaque d'essai" de notre circuit principal :

2018 P18 CP breadboard.png

Le circuit avec les composants placés mais non routé :

2018 P18 PCB CP nonroute.png

Semaine 5

Le schématique du circuit principal :

2018 P18 CP schematic.png

Et le circuit finalement routé :

2018 P18 CP PCB.png

Le fichier Fritzing du circuit principal est disponible : Media:2018 P18 CP.zip.

Après la conception et la validation des règles (écart entre les pistes, etc) nous avons demandé la fabrication de la carte. La carte a été réalisée par une entreprise extérieure pour obtenir un rendu propre avec un vernis. La couleur du vernis des différentes cartes a été choisie pour obtenir un résultat esthétique.

Une fois la carte réceptionnée, nous avons soudé les composants sur la carte. Plusieurs séances ont été nécessaires car nous avons soudé les composants des grandes parties de la carte en testant ces parties avant de continuer : partie micro-contrôleur (Atmega328p), partie alimentation, partie interface USB (FTDI), pilotes de LEDS (TLC5947). Il n’est pas facile de souder les composants comme l’Atmega328p et les TLC5947 qui on un grand nombre de pattes très fines.

Semaine 6

Les dessins pour la découpeuse laser (Media:2018_P18_Mandala_Decoupe.svg, Media:2018_P18_Mandala_Decoupe_Anneau.svg) sont représentés ci-dessous.

2018 P18 Mandala Decoupe.png
2018 P18 Mandala Decoupe Anneau.png


Circuit porte 2 LEDs : 2018 P18 Porte2LEDs PCB.png

Circuit porte 4 LEDs : 2018 P18 Porte4LEDs PCB.png

Circuit lune porte 4 LEDs : 2018 P18 Lune.png


Les fichiers Fritzing sont disponibles : Media:2018_P18_Porte2LEDs.zip Media:2018 P18 Porte4LEDs.zip Media:2018_P18_Lune.zip

Semaine 7

Cette semaine, nous avons terminé tous les dessins sur l'ordinateur, cette semaine nous avons imprimé notre dessins sur la blaque de bois.

Bois.jpg

Et nous avons soudé des LEDs CMS aux PCBs.

LesPCB.jpg

Semaine 8

Nous avons continué le travail de soudage et vérifié le bon soudage avec un multimètre.

Bois1.jpg

Démonstration du bon fonctionnement du circuit principal.

Media:2018_P18_demo_TLC5947.mp4


Semaine 9

Nous avons essayé de tester le capteur ZX DISTANCE AND GESTURE SENSOR. Dans des circonstances normales, la poignée est placée 10 à 25 cm au-dessus du capteur, et nous pouvons observer les informations de position renvoyées. Z (hauteur au-dessus du capteur) et X (position d'un côté à l'autre).


ZX tset.jpg


Pour la décoration du mandala, nous voulions peindre le mandala dans un style bouddhiste. Au début, nous avons utilisé de la gouache. Mais la peinture avait tendance à baver sur le contre-plaqué. Pour améliorer notre mandala, nous avons acheté des paillettes or pour couvrir la gouache jaune. Nous avons aussi acheté des perles pour décorer les bords. Nous avons utilisé de la colle liquide pour coller les perles sur le bois. Vous pouvez voir le résultat sur la photo ci-dessous. Nous avons passé 2 semaines pour réaliser ce travail.

Mandala decoration.jpg

Semaine 10

Pour connecter les cartes portes LEDs, le contrôleur de gestes “ZX gesture” avec la carte principale, nous avons passé des câbles au verso du mandala avec les trous que nous avions déjà percés et nous les avons soudé.

Connection cables.jpg

Semaine 11 et 12

Il reste une petite partie du travail au cours des deux semaines précédentes, et nous allons le terminer.

Et support du mandala est réalisé par une imprimante 3D en utilisant le logiciel Freecad pour la conception. Le support permet de fixer les piles et de supporter le mandala. La première version a été modifiée pour ajouter les fentes pour le circuit de détection de gestes “ZX gesture” et ses câbles.

Support mandala2.jpg
Support-mandala3.jpg


Le support du Mandala est disponible: Media:Support_mandala.zip

Semaine 13

Pour trouver les dispositon des LEDs, nous avons fait un programme de pilote des LEDs qui peut allumer des LEDs une à une dans l'ordre du première sortie jusqu’au dernière. Voici un extrait du code.


TLC5947 LEDs driver 
Include files
#include <avr/io.h>
#include "tlc5947.h"
// Global variables
// Functions
void init_LED_Drivers(int nb){
 // LED drivers I/O as outputs
 DDR_DLED |= (1<<PIN_DLED_CLOCK) |   (1<<PIN_DLED_DATA) | (1<<PIN_DLED_LATCH);
                       // Set LATCH   output low
 PORT_DLED &= ~(1<<PIN_DLED_LATCH);
}
void set_LED_Drivers(unsigned int   pwm[],int nb){
 int c,b;
                       // Set LATCH    output low
 PORT_DLED &= ~(1<<PIN_DLED_LATCH);
 // 24 channels per TLC5947
 for(c=DLED_CHANNELS*nb-1;c>=0;c--){
   // 12 bits per channel, send MSB first
   int v=pwm[c];
   for(b=0;b<12;b++){
                       // Set CLOCK  output low
     PORT_DLED &= ~(1<<PIN_DLED_CLOCK);
                       // Set DATA as  stated by bit #b of c
     if(v & 0x0800)
       PORT_DLED |= (1<<PIN_DLED_DATA);
     else
       PORT_DLED &= ~(1<<PIN_DLED_DATA);
                       // Set CLOCK output HIGH
     PORT_DLED |= (1<<PIN_DLED_CLOCK);
     v <<= 1;
   }
 }
                       // Set CLOCK output low
 PORT_DLED &= ~(1<<PIN_DLED_CLOCK);
                       // Set LATCH output high
 PORT_DLED |= (1<<PIN_DLED_LATCH);
                       // Set LATCH output low
 PORT_DLED &= ~(1<<PIN_DLED_LATCH);
}


Et nous avons trouvé le position des LEDs.

LEDs Position.jpg



Un capteur de distance et de mouvement ZX est installé sur le bois du mandala. Nous utilisons des capteurs pour controler les changement de l'animation du mandala et la vitesse du changement. Lorsque le geste sur le coté droit est détecter, g=1 et la valeur du quantum plus 100 ,ce qui signifie que accélérer de la vitesse du luminance des LEDs. Lorsque le geste sur le coté gauche est détecter, g=2 et la valeur du quantum moins 100 ,ce qui signifie que diminuer de la vitesse du luminance des LEDs. Chaque fois qu'un geste up est détecté, g=3 et le mandala va changer un animation.

#include "i2cmaster.h"
#include "zxgesture.h"
// Functions 
/* Get ZX gesture register value */
int zx_getreg(int reg){
int ret;
i2c_start_wait(ZX_ADDR|I2C_WRITE);
i2c_write(reg);
i2c_rep_start(ZX_ADDR|I2C_READ);
ret=i2c_readNak();
i2c_stop();
return ret;
}
/* Get ZX gesture model number */
int zx_get_model(void){
int model=zx_getreg(ZX_REG_MODEL);
return model;
}
/* Is a position ready to be read ? */
unsigned char zx_position_ready(void){
int status=zx_getreg(ZX_REG_STATUS);
return (status&ZX_BIT_POSITION)?1:0;
}
/* Is a gesture ready to be read ? */
unsigned char zx_gesture_ready(void){
int status=zx_getreg(ZX_REG_STATUS);
return (status&ZX_BIT_GESTURE)?1:0;
}
/* Get X and Z positions */
void zx_get_positions(int *x,int *z){
*x=zx_getreg(ZX_REG_XPOS);
*z=zx_getreg(ZX_REG_ZPOS);
}
/* Get gesture */
int zx_get_gesture(void){
int gesture=zx_getreg(ZX_REG_GESTURE);
return gesture;
}

Semaine 14

Pour la programmation, l'IDE Arduino utilise du c++ qui n'est pas assez efficace pour un micro-controôeur qui ne dispose que de 16Ko pour le programme et 2Ko de RAM.

Nous avons terminé le travail de programmation et réalisé le changement de l'ensemble du modèle Mandala contrôlé par des capteurs détectant différents gestes.

Nous avons conçu trois méthodes de transformation.

Dans le premier type, les lumières sont allumées de l'intérieur vers l'extérieur;

Le deuxième type, les lumières s'allument une à une dans le sens antihoraire et l'ordre du cercle intérieur à extérieur;

Le troisième type, toutes les lumières sont allumées en même temps.

Voila un extrait du code pour réaliser ces 3 animation.

#include <stdio.h>
#include "time.h"
#include "tlc5947.h"
#include "zxgesture.h"
#include "animations.h"
// Global variables
/* Values for each LED sets */

unsigned int groupes[NB_GROUPES];

/* Definition of LED sets */
int groupe1[]={
 23,10,7,40,61,70,55,13,-1
 };
int groupe2[]={
 5,9,39,43,63,48,57,20,-1
 };
int groupe3[]={
  22,24,8,29,30,33,38,42,60,64,67,49,52,58,14,18,-1
 };
int groupe4[]={
 0,4,6,26,31,34,37,44,47,65,68,50,53,59,15,19,-1
 };
int groupe5[]={
 2,11,25,27,32,35,41,45,62,66,71,51,56,12,17,21,-1

};

int groupe6[]={
 1,3,28,36,46,69,54,16,-1

};

int tous[]={
 23,10,7,40,61,70,55,13,
 5,9,39,43,63,48,57,20,
 22,24,8,29,30,33,38,42,60,64,67,49,52,58,14,18,
 0,4,6,26,31,34,37,44,47,65,68,50,53,59,15,19,
 2,11,25,27,32,35,41,45,62,66,71,51,56,12,17,21,
 1,3,28,36,46,69,54,16,
 -1
 };
/* Animations1 */
variation_params v1={.deltac=500,.deltad=500,.deltap=2000,.min=0,.max=1024};
variation_params v2={.deltac=500,.deltad=500,.deltap=2000,.min=0,.max=1024};
variation_params v3={.deltac=500,.deltad=500,.deltap=2000,.min=0,.max=256};
variation_params v4={.deltac=500,.deltad=500,.deltap=2000,.min=0,.max=1024};
variation_params v5={.deltac=500,.deltad=500,.deltap=2000,.min=0,.max=1024};
variation_params v6={.deltac=500,.deltad=500,.deltap=2000,.min=0,.max=1024};
animation a1[]={
 {0,60000,groupe1,&v1,variation_groupes},
 {500,60000,groupe2,&v2,variation_groupes},
 {1000,60000,groupe3,&v3,variation_groupes},
 {1500,60000,groupe4,&v4,variation_groupes},
 {2000,60000,groupe5,&v5,variation_groupes},
 {2500,60000,groupe6,&v6,variation_groupes},
 {-1,-1,NULL,NULL,NULL}
 };
/* Animation2 */
variation_params v_tous= {.deltac=100,.deltad=100,.deltap=0,.min=0,.max=255};
animation a2[]={
 {0,40000,tous,&v_tous,variation_groupe},
 {-1,-1,NULL,NULL,NULL}
 };
/* Animation3 */
variation_params v21={.deltac=500,.deltad=500,.deltap=0,.min=0,.max=1024};
variation_params v22={.deltac=500,.deltad=500,.deltap=0,.min=0,.max=1024};
variation_params v23={.deltac=500,.deltad=500,.deltap=0,.min=0,.max=256};
variation_params v24={.deltac=500,.deltad=500,.deltap=0,.min=0,.max=1024};
variation_params v25={.deltac=500,.deltad=500,.deltap=0,.min=0,.max=1024};
variation_params v26={.deltac=500,.deltad=500,.deltap=0,.min=0,.max=1024};
animation a3[]={
 {0,60000,groupe1,&v21,variation_groupes},
 {0,60000,groupe2,&v22,variation_groupes},
 {0,60000,groupe3,&v23,variation_groupes},
 {0,60000,groupe4,&v24,variation_groupes},
 {0,60000,groupe5,&v25,variation_groupes},
 {0,60000,groupe6,&v26,variation_groupes},
 {-1,-1,NULL,NULL,NULL}
 };

animation *anims[]={a1,a2,a3,NULL};
/* Variables for animation settings */ 
int quantum=1000;
int stop;
// Functions
//
/* Handle the user input */
void user_input(void){
if(zx_gesture_ready()){
 int g=zx_get_gesture();
 printf("geste=%d  quantum=%d\n",g,quantum);
 switch(g){
   case ZX_GEST_RIGHT:
     if(quantum>QUANTUM_MIN) quantum -=  QUANTUM_PAS;
     break;
   case ZX_GEST_LEFT:
     if(quantum<QUANTUM_MAX) quantum += QUANTUM_PAS;
     break;
   case ZX_GEST_UP:
     stop=1;
     break;
   }
  }
}
/* Wait some time */
void wait_us(unsigned long delay){
static unsigned long start;
if(delay==0) start=micros();
else
 while(1){
   unsigned long now=micros();
   unsigned long delta=now-start;
   user_input();
   if(delta>=delay) break;
   }
}
/* Get a set of LEDs size */
int taille_groupes(int leds[]){
int i=0;
while(leds[i]>=0) i++;
return i;
}
/* Set luminosity value to a set of LEDs  */
void valeur_groupes(int leds[],unsigned int valeur){
int i=0;
while(1){ if(leds[i]<0) break;  groupes[leds[i++]]=valeur; }
}
/* Compute variation of luminosity for a set of LEDs */
void variation_groupes(int leds[],void *arg,long temps){
variation_params *p=arg;
long periode=p->deltac+p->deltad+p->deltap;	// Dans quelle phase de la  variation se trouve-t-on ?
long instant=temps%periode;
if(instant<=p->deltac){				 // Cas de la phase de croissance de p->min à p->max
 long calc=(long)p->max-(long)p->min;
 calc=calc*instant/p->deltac+p->min;
 valeur_groupes(leds,calc);
 } 
else if(instant<=p->deltac+p->deltad){		 // Cas de la phase de décroissance
 long calc=(long)p->min-(long)p->max;
 calc=calc*(instant-p->deltac)/p- >deltad+p->max;
 valeur_groupes(leds,calc);
 }
else 						 // Cas de la pause
 valeur_groupes(leds,p->min);
}
/* Variation set by set */
void variation_groupe(int leds[],void *arg,long temps){
variation_params *p=arg;
long periode=p->deltac+p->deltad+p->deltap;
long nb=temps/periode;				 // Quel groupe de LED est concerné ?
nb=nb%taille_groupes(leds);
int instant=temps%periode;			 // Quelle est la phase courante de la variation ?
if(instant<=p->deltac){				 // Cas de la phase de croissance de p->min à p->max
 long calc=(long)p->max-(long)p->min; calc=calc*instant/p->deltac+p->min;
 groupes[leds[nb]]=calc;
 }
else if(instant<=p->deltac+p->deltad){		// Cas de la phase de décroissance
 long calc=(long)p->min-(long)p->max; calc=calc*(instant-p->deltac)/p->deltad+p->max;
 groupes[leds[nb]]=calc;
 }
else 						// Cas de la pause
 groupes[leds[nb]]=p->min;
}
/* Play an animation */
void animation_play(animation *a){
static unsigned char init;
if(init==0){   init_LED_Drivers(NB_DRIVERS); init_time(); init=1; }
animation *p;
unsigned long temps=0;
int i;
for(i=0;i<NB_GROUPES;i++) groupes[i]=0;
while(stop==0){
 unsigned char actif=0;
 wait_us(0);
 for(p=a;p->depart>=0;p++){
   user_input();
   if(temps>p->arret) continue;
   actif=1;
   if(temps<p->depart) continue;
   p->fun_anim(p->groupes,p->params,temps-p->depart);
   }
 if(!actif) break;
 set_LED_Drivers(groupes,NB_DRIVERS);
 wait_us(quantum);
 temps++;
 }
stop=0;
}
/* Play all animations */
void animation_all(void){
printf("Play all\n");
animation **a=anims;
while(*a!=NULL) animation_play(*a++);
}

Documents Rendus

Fichier:Rapport P18.odt

Media:led_code.zip