Skip to main content

Groupe A2 doigts de réussir

Prima BARCIET, Jules LAMARE, Milo BERTRAND, Coline CHEVALLIER

Journal de bord :

30/01/2024 : découverte du Fablab
  • Objectifs du FabLab : 

Le premier FabLab fut créé au MIT par Neil Gershenfeld en lien avec son cours "How to make (almost) anything". "Fab" correspond à fabrication numérique et "Lab" à laboratoire de prototypage. Son objectif était de proposer aux étudiants un espace ouvert leur permettant de donner vie à leurs projets scientifiques. Depuis, un réseau international dans le monde entier à été développé, le FabLab de Sorbonne Université en faisant partie. Pour prendre part à ce réseau, plusieurs conditions doivent être respectées, notamment la présence de certaines machines.

  • Outils et machines :

On retrouve ainsi au FabLab parmi tant d'autres machines:

- des imprimantes 3D

fablab1.jpeg

- des découpeuses laser (pour le plastique et bois) et à eau (pour le métal)

fablab2.jpeg

- des fraiseuses électroniques, ...

Il y a aussi des salles réservées à l'électronique (soudure) ou encore le travail du bois, un espace bibliothèque, un espace pédagogique, et des tables et tableaux blancs disponibles pour travailler en groupe. Des outils et composants électroniques sont également à disposition. 

  • Documentation :

Une des valeurs principales du FabLab est le partage, c'est pourquoi il est recommandé de travailler en groupe mais surtout il est important de veiller à la reproductibilité des projets et expériences réalisés par tous, via la documentation sur la plateforme Wiki. Il est obligatoire de fournir un résumé de nos travaux. On retrouve ainsi sur le site des tutoriels pour la prise en main des machines et les archives de tous projets, personnels et pédagogiques, réalisés par les étudiants et personnels du FabLab. 

06/02/2024 : introduction à la CAO

Lors de cette séance, nous avons pu découvrir le Computer-Aided Design, Conception Assistée par Ordinateur (CAO) en Français, qui est une partie importante de l'apprentissage de la FabAcademy. Nous utiliserons des logiciels gratuits, en accord avec les valeurs de partage du FabLab.

  • Design 2D :

Le design 2D, pour les découpeuses laser, se fait sur ordinateur via le logiciel Inkscape au FabLab. Ce logiciel permet d'obtenir des fichiers vectoriels au format SVG sans pixellisation ou problèmes de résolution, en créant les images avec des formes géométriques.

Des conventions doivent être absolument respectées pour que les découpeuses laser marchent correctement :

- utiliser des lignes d'1 pixel d'épaisseur

- utiliser des lignes rouges (#FF0000) pour la découpe

- le bleu correspond au marquage (juste des traits)

- utiliser des lignes noires pour la gravure (qui correspond à une puissance plus faible du laser)

Certaines commandes peuvent être utiles également : Ctrl + Maj + F pour déterminer la largeur des traits, clic sur l'objet + Maj + couleur pour changer la couleur du trait par exemple. Il est utile de regarder les tutos disponible sur ce wiki pour s'approprier d'avantage le logiciel. 

Nous nous sommes entraînés au dessin 2D en suivant le modèle donné par l'enseignant : 

image inkscape.png

Il nous faudra d'ici quelques semaines, dans le cadre de l'UE, faire un dessin 2D sur Inkscape sur une planche 30cm*30cm pour essayer les découpeuses laser par nous même.

  • Design 3D :

Nous pouvons utiliser 2 logiciels différents pour le design 3D nécessaire à l'impression 3D : OpenSCAD et FreeCAD. Ces logiciels nous donnent des fichiers 3D au format STL en générant du G-code, correspondant aux déplacements selon x, y et z de la pointe de l'imprimante.

Les éléments suivants peuvent être utiles sur les logiciels : 

- sur OpenSCAD : il faut fermer chaque ligne de code par des points virgules, la fonction F5 pour avoir un aperçu de l’objet généra par le code, F6 pour avoir l’objet final, 

- sur FreeScad : si le logiciel bug, c’est sûrement qu’une tâche en cour n'a pas été terminée/fermée, on peut utiliser la section “Part” pour générer des objets 3D directement et “Sketcher” pour travailler en 2D avant de transformer le dessin en objet 3D.

Nous pouvons chercher sur Internet “nom du logiciel + cheatsheet” pour de l’aide sur les commandes

Nous nous sommes aussi entraînés au dessin 3D en suivant les modèles donnés par l'enseignant : 

image open jsp quoi.png
image freecad.png

Il nous faudra d'ici quelques semaines, dans le cadre de l'UE, faire une modélisation 3D sur un de ces deux logiciels dans des dimensions 15cm*15cm*15cm pour essayer les imprimantes 3D par nous même.

  • Démonstration imprimantes 3D et découpeuses laser : 

Avant d’utiliser une machine/un ordinateur des salles de découpe et impression 3D, il faut noter que l’on s’est connecté sur les carnets de log in. 

On utilise du matériau PLA dans les imprimantes 3D, il est disponible en plusieurs couleurs. 2 types d’imprimantes sont disponibles : Pro2 et Pro2Plus. Nous devons choisir la densité de remplissage et la hauteur des couches. Plus les couches sont fines, plus l’impression est longue : c’est pourquoi il nous est conseillé d’utiliser des épaisseurs de 0.4mm et un remplissage de 15 ou 20%. 

20240206_113822.jpg

Différents rendus des épaisseurs de couches des imprimantes 3D

Les fichiers 3D doivent être ouverts sur IdeaMaker, un autre logiciel, avant d'imprimer sur les machines. Cela nous permet notamment de visualiser les supports automatiquement créés, ainsi que l’aide à l’adhérence et les différentes remplissages grâce à un code couleur. Si l’aperçu nous convient, on télécharge le fichier sur l’imprimante en réseau ou on “exporte sur le disque local” (clé USB) avant de la connecter sur la machine. Il est important de rester pendant les 20 premières minutes de l'impression, car la majorité des problèmes ont lieu au début (fil mal équipé, plateau pas droit, ...). A la fin de l’impression, il faut décoller l’objet du plateau avec une raclette. 

Au Green FabLab est aussi disponible une imprimante 3D à base de résine liquide qui est ensuite solidifiée, ce qui permet des rendus plus lisses. 

Quant aux découpes laser, il ne faut pas monopoliser les machines pendant plus de 30mn, la découpe en soit ne dure que quelques secondes. Si nous sommes les premiers de la journée à utiliser la machine, il faut l'allumer et la laisser se remettre en place avec le capot fermé. Il faut toujours tester sur des chutes au préalable, pour vérifier si c’est la bonne épaisseur de matériau notamment (surtout lorsqu’on découpe des encoches). Nous devons rester pendant tout l'usinage pour prévenir des potentiels départs de feu. Il ne faut pas utiliser son propre matériau à moins d’en connaître précisément la constitution : par exemple, le PVC contient du chlore qui, en brûlant sous le laser, dégage des vapeurs similaires au gaz moutarde. Il faut placer la plaque de matériau à la distance focale de la lentille de la découpeuse à l’aide d’un calpige sur les Speedy100, et placer l’origine du laser sur le dessin (en haut à gauche préférablement). Avant de commencer la découpe, on vérifie que l’on a sélectionné la bonne machine (comme une impression classique sur papier) et le bon matériau dans le logiciel.


20240206_121234.jpg
Différents rendus de la découpeuse laser sur les différents matériaux disponibles

Les autres découpeuses sont réglées automatiquement sur la bonne distance focale, et le logiciel sur lequel le dessin 2D ne s’ouvre pas sur Inkscape mais Trotec. 

Dans tous les cas, les explications et tutoriels sur l’utilisation des machines sont disponibles en salles d’impression et de découpage, mais aussi sur le Wiki. 

13/02/2024 : capteurs et cartes Arduino

Nous nous sommes concentrés sur l'utilisation de capteurs et la programmation de cartes Arduino. 

Dans Arduino IDE, en branchant le circuit Arduino à l'ordinateur, nous pouvons entrer du code et effectuer des actions. Un exemple de code bien connu est le blink, qui permet de faire clignoter une LED à court intervalle de temps, et nous avons eu l'occasion de le tester. Premièrement, directement sur la LED de la carte Arduino avec le code suivant :

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);  // turn the LED on (HIGH is the voltage level)
  delay(1000);                      // wait for a second
  digitalWrite(LED_BUILTIN, LOW);   // turn the LED off by making the voltage LOW
  delay(1000);                      // wait for a second
}
En remplaçant (LED_BUILTIN, OUTPUT) par (2, OUTPUT) (ce qui correspond au port D2 de la carte), et en branchant ce port à une breadboard, on a pu faire clignoter la LED de la breadboard. En changeant delay(1000) par delay(100), il y a un intervalle de 100ms et non plus 1000ms quand on éteint et allume la LED. 


20240213_100949.jpg


Par la suite, on a utilisé un capteur d'humidité et de température SHT31 Sensor, branché au port IC2 du shield de la carte. En cherchant sur internet "nom du capteur + wiki", on peut trouver facilement le site fabriquant, ce qui nous permet de télécharger la library qui correspond au langage dans lequel le capteur a été fabriqué et doit être utilisé. Dans les exemples fournis avec cette library, nous en avons tester un dont le code se trouve ci-dessous, qui nous permet d'afficher toutes les secondes la température et l'humidité en temps réel :

#include <Arduino.h>
#include <Wire.h>
#include "SHT31.h"

SHT31 sht31 = SHT31();

void setup() {
    Serial.begin(9600);
    while (!Serial);
    Serial.println("begin...");
    sht31.begin();
}

void loop() {
    float temp = sht31.getTemperature();
    float hum = sht31.getHumidity();
    Serial.print("Temp = ");
    Serial.print(temp);
    Serial.println(" C"); //The unit for  Celsius because original arduino don't support speical symbols
    Serial.print("Hum = ");
    Serial.print(hum);
    Serial.println("%");
    Serial.println();
    delay(1000);
}

20240213_104604.jpg

 

Sur le site internet GoTronic qui est le fournisseur des capteurs du FabLab, nous pouvons retrouver la majorité des capteurs disponibles ici pour nos projets finaux. 

Nous avons ensuite eu l'occasion de brainstorm sur notre projet. Nous avons penser à faire une machine interactive pour calculer le temps de réaction d'une personne. Il faudra nous assurer d'avoir un protocole précis pour calculer une grandeur cohérente avec incertitudes. Par exemple, quel type de personne utilise la machine : sportif ou non, entraîné ou non, femme/hommes, debout ou assis; pour faire des prédictions et tracer des graphiques de données. Nous utiliserons des capteurs sensoriels, des led colorées piur indiquer le moment où appuyer, et des fonctions permettant de calculer le temps et la moyenne de temps entre les actions.

27/02/2024 : 1ère séance dédiée au projet, réflexion sur la conception et premier test

Lors de cette séance, nous avons testé différents capteurs afin de réaliser notre projet. Le capteur qui nous semble le plus adapté est un capteur de vibration : Grove-Vibration Sensor (SW-420). Nous avons donc essayé de tester le seuil de vibration du capteur pour essayer dans un premier temps de comprendre comment il fonctionne. Pour y parvenir, nous avons donc utiliser et modifier le code ci-dessous. Ce code permet de voir si le capteur marche en nous indiquant si les vibrations captées sont basses ou hautes (code exemple de base que l'on trouve sur internet). Il n'y a besoin d'installer aucune library. 

// constants won't change. They're used here to set pin numbers:
const int buttonPin = 2;     // the number of the pushbutton pin
const int buzzer =  3;      // the number of the buzzer pin

// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status

void setup() {
  // initialize the LED pin as an output:
  pinMode(buzzer, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
  Serial.begin(9600);
}

void loop() {
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (buttonState == HIGH) {
    // turn LED on:
    Serial.println("niveau haut");
    delay(500);
  } else {
    // turn LED off:
    Serial.println("niveau bas");
    delay(500);
  }
}

Nous avons modifier le code pour ne pas utiliser de buzzer : le serial monitor affiche bien le niveau haut ou bas du capteur.

Pour le reste de notre montage, nous souhaitons avoir 5 "boutons"/plaques deux placés au niveau des épaules, deux placés au niveau des hanches et un au niveau du buste. 

05/03/2024 : 2ème séance du projet et test de l'accéléromètre

Aujourd'hui, nous allons essayer d'autres capteurs pour voir lequel nous semble le plus adapté à notre projet, ayant eu un peu de mal à utiliser le capteur de vibration la semaine dernière. Nous avons pensé au capteur de gestes et à l'accéléromètre.

Pour l'accéléromètre, on doit le brancher à la port I2C de la carte Arduino et il faut installer la library suivante : https://github.com/Seeed-Studio/Seeed_Arduino_LIS3DHTR/archive/master.zip

Nous avons copier l'exemple de code suivant, en mettant le serial monitor en 115200 baud sinon on n'a pas de chiffres affichés en coordonnées mais des symboles illisibles.

// This example use I2C.
#include "LIS3DHTR.h"
#include <Wire.h>
LIS3DHTR<TwoWire> LIS; //IIC
#define WIRE Wire

void setup()
{
  Serial.begin(115200);
  while (!Serial)
  {
  };
  LIS.begin(WIRE,0x19); //IIC init
  //LIS.begin(0x19);
  LIS.openTemp();  //If ADC3 is used, the temperature detection needs to be turned off.
  //  LIS.closeTemp();//default
  delay(100);
    LIS.setFullScaleRange(LIS3DHTR_RANGE_2G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_4G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_8G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_16G);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_1HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_10HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_25HZ);
  LIS.setOutputDataRate(LIS3DHTR_DATARATE_50HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_100HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_200HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_1_6KHZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_5KHZ);
}
void loop()
{
  if (!LIS)
  {
    Serial.println("LIS3DHTR didn't connect.");
    while (1)
      ;
    return;
  }
  //3 axis
    Serial.print("x:"); Serial.print(LIS.getAccelerationX()); Serial.print("  ");
    Serial.print("y:"); Serial.print(LIS.getAccelerationY()); Serial.print("  ");
    Serial.print("z:"); Serial.println(LIS.getAccelerationZ());
delay(1000);  
  //ADC
  //    Serial.print("adc1:"); Serial.println(LIS.readbitADC1());
  //    Serial.print("adc2:"); Serial.println(LIS.readbitADC2());
  //    Serial.print("adc3:"); Serial.println(LIS.readbitADC3());

}

image.png

On ouvre le serial plotter pour afficher le graphique en temps réel.

Capture d'écran 2024-03-22 173424.png

Nous avons fait un prototype avec une petite plaque en bois trouvée dans la salle de découpe et des ressorts en scotchant l'accéléromètre à la plaque. 

20240305_111055.jpg

 20240305_111102.jpg

 

 

 

Lorsqu'on laisse le capteur en position repos horizontale sur la plaque, puis qu'on appuie sur la plaque, on voir bien une modification très soudaine des coordonnées, surtout de z (la hauteur). Nous allons donc pouvoir fixer un seuil en dessous de la valeur normale (1) mais suffisamment basse pour que les plus faibles perturbations passe au dessus de ce seuil : -1.2 semble correspondre. Nous utiliserons cette valeur lors des prochaines séances pour le calibrage du capteur. 

image.png

Pour les prochaines séances, nous devons réfléchir à un moyen de différentier les plaques et indiquer à l'utilisateur sur laquelle appuyer. Utiliser une LED pour chacune des plaques semble trop encombrant. Nous pourrions utiliser une LED RBG au centre entre les plaques qui s'allumerai de différentes aléatoirement parmi celles formatées, et chaque plaque serait associée à une couleur de la LED.

12/03/2024 : 3ème séance du projet, LED RGB et plaques

Nous avons tenter de programmer la LED RGB pour la faire s'allumer de 4 couluers différentes aléatoirement. Il faut télécharger sa library avec ce lien : https://github.com/pjpmarques/ChainableLED/releases

Nous avons utiliser le code d'exemple suivant disponible sur internet bien que nous n'utilisons qu'une LED et pas 5. La ligne 11 indique qu'il faut la brancher au port D7 de la carte Arduino.

/* 
 * Example of using the ChainableRGB library for controlling a Grove RGB.
 * This code cycles through all the colors in an uniform way. This is accomplished using a HSL color space. 
 */


#include <ChainableLED.h>

#define NUM_LEDS  5

ChainableLED leds(7, 8, NUM_LEDS);

void setup()
{
  leds.init();
}

float hue = 0.0;
boolean up = true;

void loop()
{
  for (byte i=0; i<NUM_LEDS; i++)
    leds.setColorHSL(i, hue, 1.0, 0.5);
    
  delay(50);
    
  if (up)
    hue+= 0.025;
  else
    hue-= 0.025;
    
  if (hue>=1.0 && up)
    up = false;
  else if (hue<=0.0 && !up)
    up = true;
}

20240312_095504.jpg

Le code suivant ne marche pas mais nous l'avons garder en ébauche pour la séance suivante. Nous avons tenter d'introduire les fonctions millis pour mesurer le temps puis faire la différence pour avoir le temps de réaction puis en calculer la moyenne, ainsi que programmer la LED pour qu'elle s'allume aléatoirement parmi 4 couleurs différentes définies par la variable hue

/* 
 * Example of using the ChainableRGB library for controlling a Grove RGB.
 * This code cycles through all the colors in an uniform way. This is accomplished using a HSL color space. 
 */


#include <ChainableLED.h>

#define NUM_LEDS  5

ChainableLED leds(7, 8, NUM_LEDS); //brancher au port D7

void setup()
{
  leds.init();
int Moyenne (int pp,int mes) { // sur 4 mesures
 int total;
 for (byte i=0; i<4; i++) {
 total += mes;
 delay(pp);
 }
 return (total/4) ;
}
byte Ldr;

} 


float hue = 0.0;
boolean go = true;

long num; //variable numéro pour choisir chiffre aléatoire 
byte i=0; // initialise sa valeur à 0

void loop()
{
  for (byte i=0; i<NUM_LEDS; i++)
    leds.setColorHSL(i, hue, 1.0, 0.5);
    
  delay(50);
    
  long f;
  byte i = 0;

  long d;
  byte i = 0;

  if (go)
    unsigned long f=millis(); //mesure du temps (correspond à la fin/quand la plaque est touchée)
    
    int num = random(4); // definir la couleur en choisissant un nombre de 0 à 4
    int hue = num / 5; //lui associer une couleur entre 0 et 1 pour la LED

    unsigned long d=millis(); //mesure le temps au début 

  int t = 0;
  t = f - d; // t le temps de réaction 

  Ldr = Moyenne(10, analogRead(A0)); //... if (Ldr > MaxLight) ...
}

Pour le code de l'accéléromètre, nous avons tenter de rajouter le seuil à z=-1.2 mentionné plus haut en reprenant le code de la séance précédente.

bool go = false; //à mettre avant void setup

//à la fin
if(LIS.getAccelerationZ()<-1.2); //valeur normale à -1 car capteur retourné
go = true;
delay (1000);
go = false;

Pendant ce temps, nous avons aussi  découper les 4 plaques à la découpeuse 3D, des carrés de 12cm de coté qui nous semblait être une dimension adaptée.  

IMAGE SCHEMA INKSCAPE CARRE + LOGO SORBONNE SUR LOGICIEL

20240312_110812.jpg

Durant la prochaine séance, nous devrons corriger le code de la LED qui ne marche pas et trouver une manière de différencier les différents ports I2C, pour différencier les accéléromètre comme chacun des 4 capteurs sera brancher sur 1 des 4 ports I2C de la carte. 

19/03/2024 : 4ème séance du projet, code combinant tous les capteurs

Durant cette séance, nous nous sommes concentrée sur le code, car si il ne marche pas rien d'autre ne marchera dans notre projet. Nous avons repris les codes des 2 dernières séances et après avoir corriger de nombreuses erreurs pendant un long moment, voici un code sans erreur que nous obtenons.

// This example use I2C.
#include "LIS3DHTR.h"
#include <Wire.h>
LIS3DHTR<TwoWire> LIS; //IIC
#define WIRE Wire

#include <ChainableLED.h>
#define NUM_LEDS  1
ChainableLED leds(7, 8, NUM_LEDS); //brancher au port D7

void setup() {

    Serial.begin(115200);
  while (!Serial)
  {
  };
  LIS.begin(WIRE,0x19); //IIC init
  //LIS.begin(0x19);
  LIS.openTemp();  //If ADC3 is used, the temperature detection needs to be turned off.
  //  LIS.closeTemp();//default
  delay(100);
    LIS.setFullScaleRange(LIS3DHTR_RANGE_2G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_4G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_8G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_16G);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_1HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_10HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_25HZ);
  LIS.setOutputDataRate(LIS3DHTR_DATARATE_50HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_100HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_200HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_1_6KHZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_5KHZ);

}

float hue = 0.0;

unsigned long d;
unsigned long f;
long t = 0;


void loop() {

  leds.init();
  Serial.print("z:"); Serial.println(LIS.getAccelerationZ());

  for (byte i=0; i<NUM_LEDS; i++) {
    leds.setColorHSL(i, hue, 1.0, 0.5);
    hue = 0.7;
    d=millis(); //mesure le temps au début 
  }
  delay(100);

  // Check accelerometers for Z-axis value below -1.2
  if(LIS.getAccelerationZ()<-1.2); { //valeur normale à -1 car capteur retourné
    f=millis(); //mesure du temps (correspond à la fin/quand la plaque est touchée)

    delay(100); 
   t = f - d; // t le temps de réaction
    Serial.print("le temps de réaction est de :  "); Serial.print(t); Serial.println("    ");
  

   for (byte i=0; i<NUM_LEDS; i++) {
    leds.setColorHSL(i, 0.2, 1.0, 0.5);
    }
  }

 delay(3000);

}

Le serial monitor affiche un temps de réaction de 101ms ce qui correspond au delay ligne 54. Nous voyons qu'il y a donc 1ms de décalage lorsque que l'on utilise les fonctions millis, ce qu'il pourra être intéressant de prendre en compte dans notre calcul de temps de réaction final. Nous avons donc corriger cette erreur en rajoutant les accolades de la fonction if ligne 57 (le temps f se calculait tout le temps est pas seulement lorsque la condition du if était vérifiée).

Il nous a était conseillé d'utiliser la condition while plutôt que if

// This example use I2C.
#include "LIS3DHTR.h"
#include <Wire.h>
LIS3DHTR<TwoWire> LIS; //IIC
#define WIRE Wire

#include <ChainableLED.h>
#define NUM_LEDS  1
ChainableLED leds(7, 8, NUM_LEDS); //brancher au port D7

void setup() {

    Serial.begin(115200);
  while (!Serial)
  {
  };
  LIS.begin(WIRE,0x19); //IIC init
  //LIS.begin(0x19);
  LIS.openTemp();  //If ADC3 is used, the temperature detection needs to be turned off.
  //  LIS.closeTemp();//default
  delay(100);
    LIS.setFullScaleRange(LIS3DHTR_RANGE_2G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_4G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_8G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_16G);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_1HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_10HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_25HZ);
  LIS.setOutputDataRate(LIS3DHTR_DATARATE_50HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_100HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_200HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_1_6KHZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_5KHZ);

}

float hue = 0.0;

unsigned long d;
unsigned long f;
long t = 0;


void loop() {

  leds.init();

  for (byte i=0; i<NUM_LEDS; i++) {
    leds.setColorHSL(i, hue, 1.0, 0.5);
    hue = 0.7; //bleu violet
    d=millis(); //mesure le temps au début 
  }

  // Check accelerometers for Z-axis value below -1.2
  while(LIS.getAccelerationZ()>-1.2);{ //valeur normale à -1 car capteur retourné
  Serial.print("z:"); Serial.println(LIS.getAccelerationZ()); 
    Serial.println("Attente    ");
    delay(100);
  }
    
  f=millis(); //mesure du temps (correspond à la fin/quand la plaque est touchée)

  delay(100); 
  t = f - d; // t le temps de réaction
  Serial.print("le temps de réaction est de :  "); Serial.print(t); Serial.println("ms");
  
  for (byte i=0; i<NUM_LEDS; i++) {
    leds.setColorHSL(i, 0.2, 1.0, 0.5); //jaune
    }
  
 delay(3000);
}

Nous avons un problème avec la chaine while qui s'enclenche que quand on secoue l'accéléromètre, il semblerait qu'il faille inverser la condition., ce que nous ferons la prochaine fois. 

26/03/2024 : 5ème séance, mesure du temps de réaction sur une seule carte

Nous avons finalisé le code de la séance précédente qui nous permet d'allumer la LED RGB, de calculer le temps de réaction lorsque l'on bouge l'accéléromètre et d'éteindre la LED pendant 3s avant de la rallumer et de répéter l'opération : 

// This example use I2C.
#include "LIS3DHTR.h"
#include <Wire.h>
LIS3DHTR<TwoWire> LIS; //IIC
#define WIRE Wire

#include <ChainableLED.h>
#define NUM_LEDS  1
ChainableLED leds(7, 8, NUM_LEDS); //brancher au port D7

void setup() {

    Serial.begin(115200);
  while (!Serial)
  {
  };
  LIS.begin(WIRE,0x19); //IIC init
  //LIS.begin(0x19);
  LIS.openTemp();  //If ADC3 is used, the temperature detection needs to be turned off.
  //  LIS.closeTemp();//default
  delay(100);
    LIS.setFullScaleRange(LIS3DHTR_RANGE_2G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_4G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_8G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_16G);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_1HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_10HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_25HZ);
  LIS.setOutputDataRate(LIS3DHTR_DATARATE_50HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_100HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_200HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_1_6KHZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_5KHZ);

}

float hue = 0.0;

unsigned long d;
unsigned long f;
long t = 0;
byte power = 0;
float z;

void loop() {

  leds.init();

  for (byte i=0; i<NUM_LEDS; i++) {
    leds.setColorHSL(i, hue, 1.0, 0.5);
    hue = 0.7; //bleu violet
    d=millis(); //mesure le temps au début 
  }
  
 
z = LIS.getAccelerationZ();
Serial.print("z avant:"); Serial.println(z);

  // Check accelerometers for Z-axis value below -1.1
 while(z>(-1.1))
 { //valeur normale à -1 car capteur retourné
  z = LIS.getAccelerationZ();
  Serial.print("Attente, z boucle :"); Serial.println(z); 
    delay(50);
  }
    
  f=millis(); //mesure du temps (correspond à la fin/quand la plaque est touchée)

  delay(100); 
  t = f - d; // t le temps de réaction
  Serial.print("le temps de réaction est de :  "); Serial.print(t); Serial.println("ms");
  
  for (byte i=0; i<NUM_LEDS; i++) {
    leds.setColorHSL(i, 0, 255-power, 0); //éteindre
    }
  
 delay(3000);
  }

Il nous reste désormais à faire un code pour la carte centrale qui va permettre d'allumer aléatoirement la LED d'une des 4 cartes, ainsi que récupérer les temps de réaction de chacune des 4 cartes et en calculer la moyenne/faire un graphique des différentes valeurs. Pour cela, nous avons essayer d'utiliser la fonction analogRead() :

// This example use I2C.
#include "LIS3DHTR.h"
#include <Wire.h>
LIS3DHTR<TwoWire> LIS; //IIC
#define WIRE Wire

#include <ChainableLED.h>
#define NUM_LEDS  1
ChainableLED leds(7, 8, NUM_LEDS); //brancher au port D7

#define POEPIN A0

void setup() {

  Serial.begin(115200);
  while (!Serial)
  {
  };
  LIS.begin(WIRE,0x19); //IIC init
  //LIS.begin(0x19);
  LIS.openTemp();  //If ADC3 is used, the temperature detection needs to be turned off.
  //  LIS.closeTemp();//default
  delay(100);
    LIS.setFullScaleRange(LIS3DHTR_RANGE_2G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_4G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_8G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_16G);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_1HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_10HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_25HZ);
  LIS.setOutputDataRate(LIS3DHTR_DATARATE_50HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_100HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_200HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_1_6KHZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_5KHZ);

}

float hue = 0.0;

unsigned long d;
unsigned long f;
long t = 0;
byte power = 0;
float z;

void loop() {

  leds.init();

  int val;
  // lecture de la tension sur la broche A0 -> brancher la carte centrale sur A0
  val = analogRead(POEPIN);
  // affichage de la tension sur le moniteur serie
  Serial.println(val);

  if (val<500) { 
  val = analogRead(POEPIN);
  Serial.println(val);
  }

  else {

  for (byte i=0; i<NUM_LEDS; i++) {
    leds.setColorHSL(i, hue, 1.0, 0.5);
    hue = 0.7; //bleu violet
    d=millis(); //mesure le temps au début 
  }
  
z = LIS.getAccelerationZ();
Serial.print("z avant:"); Serial.println(z);

  // Check accelerometers for Z-axis value below -1.1
 while(z>(-1.1))
 { //valeur normale à -1 car capteur retourné
  z = LIS.getAccelerationZ();
  Serial.print("Attente, z boucle :"); Serial.println(z); 
    delay(5000);
  }
    
  f=millis(); //mesure du temps (correspond à la fin/quand la plaque est touchée)

  delay(100); 
  t = f - d; // t le temps de réaction
  Serial.print("le temps de réaction est de :  "); Serial.print(t); Serial.println("ms");
  
  for (byte i=0; i<NUM_LEDS; i++) {
    leds.setColorHSL(i, 0, 255-power, 0); //éteindre
    }
  
 delay(3000);
  }
}

Pour la partie montage, nous avons découper à la scie la grand planche qui nous servira de support pour notre installation, que l'on a ensuite poncée et limée pour éliminer les échardes. 

Nous avons aussi imprimer en 3D des demi sphères creuses en PLA transparent à mettre sur les LED RGB pour diffuser la lumière.

image du fichier 3d + de l'objet imprimé
Avancement pendant les vacances

J'ai essayé de faire le code de la "carte mère", soit celle qui envoie des signaux aléatoirement aux autres cartes (qui elles sont connectées aux LEDs et accéléromètres) pour leur indiquer que c'est à leur tour de fonctionner. Pour cela, j'ai utilisé les niveaux des pins des différentes ports digitaux (un associé à chaque carte périphérique) en output et input. Pour cela, j'ai utilisé les différentes liens suivant : 

J'ai réussi à réaliser ce code après avoir corrigé certaines erreurs : 

const int carte_1 = 2; // Digital 2 pour la plaque 1 
const int carte_2 = 3; // Digital 3 pour la plaque 2 
const int carte_3 = 4; // Digital 4 pour la plaque 3 
const int carte_4 = 5; // Digital 5 pour la plaque 4

long carte; //fonction random marche que avec des variables long

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
DDRD = B00111100; // set PORTD (digital 2~5) to outputs (0 and 1 must not be changed)
PORTD = B00000000; // all on LOW
Serial.println("    "); Serial.println("lets go"); Serial.println("    ");

}

void loop() {
  // put your main code here, to run repeatedly:

carte=random(2,6);
Serial.print("Le port sélectionné est le port D"); Serial.println(carte);

if (carte=2) {
digitalWrite(carte_1, HIGH); // tension envoyée sur D2 carte 1
delay(10);
pinMode(carte_1,INPUT); //port D2 changée en entrée pour attendre retoru de l'autre carte périphérique
int read = digitalRead(carte_1);
Serial.print("Première mesure, read= "); Serial.println(read);

while (read=0) //tant que le port D2 ne reçoit pas de tension 
{ read = digitalRead(carte_1); //continue de lire la tension
Serial.print("En attente, read= "); Serial.print(read);
delay(10);
}

Serial.println("Tension reçue donc plaque touchée"); Serial.println("    ");
delay(10);
pinMode(carte_1,OUTPUT);
delay(4000);
}
}

Je lis ça sur le Serial Monitor, infiniment toutes les 4 secondes grâce au delay(4000), avec le nom du port qui change grâce à la fonction random

Capture d'écran 2024-04-12 185020.png

On voit que cela indique que le niveau est haut sur les ports lorsqu'ils sont en mode input alors que aucune tensions n'est délivrée sur les ports. C'est normal que les pins renvoient des valeurs non cohérentes lorsqu'elles ne sont connectées à rien.

Je dois maintenant recopier le code pour les autres valeurs de la variable carte, soient pour les 3 autres cartes avec LEDs et accéléromètres, ainsi que vérifier si le signal sur les ports est détecté comme haut que lorsque une tension est reçu sur le port connecté. Il faut donc que j'ajoute une partie sur l'envoi de tension dans le code des autres cartes également. 

J'ai changé la variable carte en port pour plus de clarté et j'ai ajouté des précision dans les Serial.print pour savoir grâce au Serial Monitor quelle partie du code est en cours, notamment quelle carte/port est censé.e être activée/lu à quel moment :

const int carte_1 = 2; // Digital 2 pour la plaque 1 
const int carte_2 = 3; // Digital 3 pour la plaque 2 
const int carte_3 = 4; // Digital 4 pour la plaque 3 
const int carte_4 = 5; // Digital 5 pour la plaque 4

long port; //fonction random marche que avec des variables long

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
DDRD = B00111100; // set PORTD (digital 2~5) to outputs (0 and 1 must not be changed)
PORTD = B00000000; // all on LOW
Serial.println("    "); Serial.println("lets go"); Serial.println("    ");

}

void loop() {
  // put your main code here, to run repeatedly:

port=random(2,6);
Serial.print("Le port sélectionné est le port D"); Serial.println(port);

if (port=2) {
digitalWrite(carte_1, HIGH); // tension envoyée sur D2 carte 1
delay(10);
pinMode(carte_1,INPUT); //port D2 changé en entrée pour attendre retoru de l'autre carte périphérique
int read = digitalRead(carte_1);
Serial.print("Première mesure sur carte 1, read= "); Serial.println(read);

while (read=0) //tant que le port D2 ne reçoit pas de tension 
{ read = digitalRead(carte_1); //continue de lire la tension
Serial.print("En attente carte 1, read= "); Serial.print(read);
delay(10);
}

Serial.println("Tension reçue sur carte 1 donc plaque touchée"); Serial.println("    ");
delay(10);
pinMode(carte_1,OUTPUT);
delay(4000);
}

else {

if (port=3){
digitalWrite(carte_2, HIGH); // tension envoyée sur D3 carte 2
delay(10);
pinMode(carte_2,INPUT); //port D3 changé en entrée pour attendre retoru de l'autre carte périphérique
int read = digitalRead(carte_2);
Serial.print("Première mesure sur carte 2, read= "); Serial.println(read);

while (read=0) //tant que le port D3 ne reçoit pas de tension 
{ read = digitalRead(carte_2); //continue de lire la tension
Serial.print("En attente carte 2, read= "); Serial.print(read);
delay(10);
}

Serial.println("Tension reçue carte 2 donc plaque touchée"); Serial.println("    ");
delay(10);
pinMode(carte_2,OUTPUT);
delay(4000);
}

else {

if (port=4){
digitalWrite(carte_3, HIGH); // tension envoyée sur D4 carte 3
delay(10);
pinMode(carte_3,INPUT); //port D4 changé en entrée pour attendre retoru de l'autre carte périphérique
int read = digitalRead(carte_3);
Serial.print("Première mesure sur carte 3, read= "); Serial.println(read);

while (read=0) //tant que le port D4 ne reçoit pas de tension 
{ read = digitalRead(carte_3); //continue de lire la tension
Serial.print("En attente carte 3, read= "); Serial.print(read);
delay(10);
}

Serial.println("Tension reçue carte 3 donc plaque touchée"); Serial.println("    ");
delay(10);
pinMode(carte_3,OUTPUT);
delay(4000);
}

else { // donc carte=5 si aucun des autres

digitalWrite(carte_4, HIGH); // tension envoyée sur D5 carte 4
delay(10);
pinMode(carte_4,INPUT); //port D5 changé en entrée pour attendre retoru de l'autre carte périphérique
int read = digitalRead(carte_4);
Serial.print("Première mesure sur carte 4, read= "); Serial.println(read);

while (read=0) //tant que le port D5 ne reçoit pas de tension 
{ read = digitalRead(carte_4); //continue de lire la tension
Serial.print("En attente carte 4, read= "); Serial.print(read);
delay(10);
}

Serial.println("Tension reçue carte 4 donc plaque touchée"); Serial.println("    ");
delay(10);
pinMode(carte_4,OUTPUT);
delay(4000);

}
}
}
}

Le Serial Monitor m'indique que peu importe le numéro du port choisi avec random, c'est la boucle if de la carte_1 (port=2) qui est réalisée...

image.png

Comme cela ne marche pas, nous avons décider de faire les 4 plaques avec 4 cartes différentes reliées à 4 ordis qui renvoient les valeurs, plutôt que d'essayer de connectées les cartes entres elles. Chaque cartes réaliseraient le code que nous avons écrit avant les vacances et qui marche. 

23/04/2024 : dernière séance avant les présentations

Le code principale fonctionne, nous devons maintenant créer une fonction qui stocke/calcule la moyenne sur les mesures effectuées. Comme nous ne savons pas faire de moyenne glissante au fur et à mesure que les mesures sont prises, on doit fixer un nombre spécifique de mesures à l'avance puis diviser la somme de toutes les mesures de temps de réaction par ce nombre.  Nous avons essayer de créer une fonction qui nous permettrais de choisir le nombre de mesures réalisées sur chaque plaque parmi différents modes prédéfinis. 

int total; // à mettre dans le void loop
int donnee; 
while (Serial.available() !=0) {
  donnee = Serial.read(); //chargemùent des données 
  Serial.print("Le mode choisi est le mode ");
  Serial.println(donnee); //affichage de la donnée 
  total = 0;
  delay(2000);
}

while (total=0){
if (donnee = 1) {
  total = 10;
  Serial.println(total); Serial.print(" mesures du temps de récation seront effectuées");
} else {
if (donnee = 2) {
  total = 25; 
  Serial.println(total); Serial.print(" mesures du temps de récation seront effectuées");}
  else {
    if (donnee = 3){
      total = 40;
      Serial.println(total); Serial.print(" mesures du temps de récation seront effectuées");}
    else {
      total = 0;
      Serial.println("Mode indéfini, veuillez reessayer"); }
    }
  }
}

Le code ne marchait pas donc on a abandonné car il nous reste que peut de temps avant la présentation. chaque carte réalisera ainsi 10 mesures uniquement. Comme on a 4 plaques, cela fait un total de 40mesures par personne, ce qui semble un chiffre raisonnable pour être fiable. Nous avons donc ajouter des variables moyenne et somme, ainsi qu'un compteur c et des Serial.print() qui nous indique dans le Serial Monitor quelle étape est effectuée quand. 

// This example use I2C.
#include "LIS3DHTR.h"
#include <Wire.h>
LIS3DHTR<TwoWire> LIS; //IIC
#define WIRE Wire

#include <ChainableLED.h>
#define NUM_LEDS  1
ChainableLED leds(7, 8, NUM_LEDS); //brancher au port D7

void setup() {

    Serial.begin(115200);
  while (!Serial)
  {
  };
  LIS.begin(WIRE,0x19); //IIC init
  //LIS.begin(0x19);
  LIS.openTemp();  //If ADC3 is used, the temperature detection needs to be turned off.
  //  LIS.closeTemp();//default
  delay(100);
    LIS.setFullScaleRange(LIS3DHTR_RANGE_2G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_4G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_8G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_16G);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_1HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_10HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_25HZ);
  LIS.setOutputDataRate(LIS3DHTR_DATARATE_50HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_100HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_200HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_1_6KHZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_5KHZ);

}

float hue = 0.0;

unsigned long d;
unsigned long f;
long t = 0;
byte power = 0;
float z;

float c; //compteur
float moy; //moyenne
float mesures; // nombre de mesures à réaliser 
float somme; //somme des t pour après faire la moyenne

void loop() {

  leds.init();
mesures = 10; // nb de mesures qui seront réalisées (jsp si on met un fonction ici pour pouvoir changer)
Serial.println(" "); Serial.print("nous effectuerons "); Serial.print(mesures); Serial.println(" mesures"); Serial.println(" ");
c = 0; 
somme = 0;
moy = 0;

unsigned long temps;

while (c<mesures) {

temps = random(500, 5000);
Serial.print("le temps d'attente avant d'allumer la LED est de "); Serial.print(temps); Serial.print(" ms");
delay(temps);


  for (byte i=0; i<NUM_LEDS; i++) {
    leds.setColorHSL(i, hue, 1.0, 0.5);
    hue = 0.7; //bleu violet
    d=millis(); //mesure le temps au début 
  }


z = LIS.getAccelerationZ();
Serial.print("z avant:"); Serial.println(z);

  // Check accelerometers for Z-axis value below -1.1
 while(z>(-1.1))
 { //valeur normale à -1 car capteur retourné
  z = LIS.getAccelerationZ();
  Serial.print("Attente, z boucle :"); Serial.println(z); 
    delay(50);
  }
    
  f=millis(); //mesure du temps (correspond à la fin/quand la plaque est touchée)

  delay(100); 
  t = f - d; // t le temps de réaction
 Serial.println(" "); Serial.print("le temps de réaction instantané est de :  "); Serial.print(t); Serial.println("ms");
  
  for (byte i=0; i<NUM_LEDS; i++) {
    leds.setColorHSL(i, 0, 255-power, 0); //éteindre
    }

  c = c+1;
  somme = somme+t;
  Serial.print(c); Serial.println("mesure(s) on était effectuées"); Serial.println("______________________________________________");
 delay(500);
}

moy = somme/c;
Serial.println(" "); Serial.print("le temps de réaction moyen sur "); Serial.print(c); Serial.print(" mesures est de "); Serial.print(moy); Serial.println("ms"); Serial.println(" "); Serial.println("______________________________________________");
delay(5000);
  }

Nous avons également collé des rebord en bois sur notre plaque principale, ainsi que coller certains ressort avec de la colle à bois car le pistolet à colle n'adhérer pas. C'est un processus très long car nous devons maintenir appuyer les deux éléments qui doivent être collés sans bouger pendant plusieurs minutes. Nous avons également découper à la découpeuse laser un trou dans les plaques pour y coller les dômes transparents imprimés en 2D par dessus. 

26/04/2024 : après-midi au FabLab pour avancer

Nous avons apporter les dernière touches au code ainsi que avancer la structure, notamment en continuant à coller les ressorts/plaques. 

// This example use I2C.
#include "LIS3DHTR.h"
#include <Wire.h>
LIS3DHTR<TwoWire> LIS; //IIC
#define WIRE Wire

#include <ChainableLED.h>
#define NUM_LEDS  1
ChainableLED leds(7, 8, NUM_LEDS); //brancher au port D7


void setup() {

    Serial.begin(115200);
  while (!Serial)
  {
  };
  LIS.begin(WIRE,0x19); //IIC init
  //LIS.begin(0x19);
  LIS.openTemp();  //If ADC3 is used, the temperature detection needs to be turned off.
  //  LIS.closeTemp();//default
  delay(100);
    LIS.setFullScaleRange(LIS3DHTR_RANGE_2G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_4G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_8G);
  //  LIS.setFullScaleRange(LIS3DHTR_RANGE_16G);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_1HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_10HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_25HZ);
  LIS.setOutputDataRate(LIS3DHTR_DATARATE_50HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_100HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_200HZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_1_6KHZ);
  //  LIS.setOutputDataRate(LIS3DHTR_DATARATE_5KHZ);

}

float hue = 0.0;

unsigned long d;
unsigned long f;
long t = 0;
byte power = 0;
float z;

float c; //compteur
float moy; //moyenne
float mesures; // nombre de mesures à réaliser 
float somme; //somme des t pour après faire la moyenne

void loop() {

  leds.init();

Serial.println("Attente de 30sec avant de commencer pour mettre en place");
 for (byte i=0; i<NUM_LEDS; i++) {
leds.setColorHSL(i, 0.2, 1.0, 0.5); }// jaune

delay(30000);

mesures = 10; // nb de mesures qui seront réalisées (jsp si on met un fonction ici pour pouvoir changer)
Serial.println(" "); Serial.print("nous effectuerons "); Serial.print(mesures); Serial.println(" mesures"); Serial.println(" ");
c = 0; 
somme = 0;
moy = 0;

unsigned long temps; 

for (byte i=0; i<NUM_LEDS; i++) {
    leds.setColorHSL(i, 0, 255-power, 0); } //éteindre

while (c<mesures) {

temps = random(499, 10002);
Serial.print("le temps d'attente avant d'allumer la LED est de "); Serial.print(temps); Serial.print(" ms");
delay(temps);

  for (byte i=0; i<NUM_LEDS; i++) {
    leds.setColorHSL(i, 0.7, 1.0, 0.5); //bleu violet
    d=millis(); //mesure le temps au début 
  }


z = LIS.getAccelerationZ();
Serial.print("z avant:"); Serial.println(z);

  // Check accelerometers for Z-axis value below -1.1
 while(z>(-1.1))
 { //valeur normale à -1 car capteur retourné
  z = LIS.getAccelerationZ();
  Serial.print("Attente, z boucle :"); Serial.println(z); 
    delay(50);
  }
    
  f=millis(); //mesure du temps (correspond à la fin/quand la plaque est touchée)

  delay(100); 
  t = f - d; // t le temps de réaction
 Serial.println(" "); Serial.print("le temps de réaction instantané est de :  "); Serial.print(t); Serial.println("ms");
  
  for (byte i=0; i<NUM_LEDS; i++) {
    leds.setColorHSL(i, 0, 255-power, 0); //éteindre
    }

  
  c = c+1;
  somme = somme+t;
  Serial.print(c); Serial.println("mesure(s) on était effectuées"); Serial.println("______________________________________________");

 delay(500);
}

moy = somme/c;
Serial.println(" "); Serial.print("le temps de réaction moyen sur "); Serial.print(c); Serial.print(" mesures est de "); Serial.print(moy); Serial.println("ms"); Serial.println(" "); Serial.println("______________________________________________");
for (byte i=0; i<NUM_LEDS; i++) {
leds.setColorHSL(i, 0.4, 1.0, 0.5); }// vert

Serial.println("  "); Serial.println("Fin, attente d'une minute"); Serial.println("  ");
delay(60000);
  }

La fonction random qui choisit entre 0.5s et 10s pour que la LED s'allume renvoie toujours les mêmes valeurs à chaque fois, ce qui perd tous son interêt, surtout si l'on souhaite que les 4 LEDs des 4 plaques ne s'allume pas en même temps. Nous avons donc 4 fichiers différentes pour chaque LED en changeant les bornes de 500ms à 10000ms de quelques ms (i.e 495 à 10001).

Nous voulions aussi tenter d'exporter les données de temps de réaction dans un tableur pour que la moyenne soit calculer automatiquement et non manuellement en s'inspirant d'un code trouver sur internet mais nous n'avons pas réussi. 

https://forum.arduino.cc/t/comment-transferer-des-donnees-dans-un-tableur/1129755

Brancher 2 cartes Arduino sur un même ordinateur marche, en ouvrant deux onglets différents on peut afficher les 2 Serial Monitor séparément et ainsi lire les mesures réalisées des différentes plaques. Milo dispose d'un adaptateur pour avoir 4 ports USB sur un seul ordinateur ce qui nous permettrait de relier toutes les cartes à un seul ordi. C'est pourquoi j'ai ajouté un temps d'attente au début, le temps qu'on mette en place le code sur chaque carte (surtout si on a 4 fichiers différents)/ Durant l'attente au début, les LEDs sont allumées en jaune et lorsque les 10 mesures ont été faites, les LEDs s'allument en vert pendant 1mn avant d'effectuer le programme à nouveau.

Comme nous avions fait dans une des premières séances, nous avons coller scotcher l'accéléromètre et les LEDs sur les 2 plaques qui étaient prêtes pour faire un essai avant de coller définitivement. Le seuil de l'accéléromètre semble être adapté car les LEDs s'éteignent bien quand on tape sur la plaque, la longueur des ressorts est correctes. Si on appuie trop fort, la plaque entière bouge ce qui pourrait aussi éteindre les autres LEDs, nous devons être vigilants sur ce problème. 

 

 

Présentation finale :

  • l'idée qu'on a eu (exemple d'appareil qui existe déjà),
  • processus : 

tester plein de capteurs/lequel choisir 

tester la LED

code

structure (bois/3D)

tentative de centraliser avec une seule LED qui traite les données/fait les calculs

produit final 

  • ce qu'on voulait faire de base : 
  • problèmes qu'on a rencontré : peut pas envoyer des données numériques autres que tensions entre carte, la colle fait que se décoller, court circuit que j'ai fait, random qui renvoit les mêmes trucs 
  • protocole qui mesure le temps de réaction, fiabilité : 

debout/assis, droitier/gaucher, que avec une main ou 2 mains, sportif ou pas, homme/femme -> comparer avec valeurs usuelles 

fiabilité -> vérifier les delay() pour voir si on a pas qql millisecondes qui s'ajoutent au temps moyen obtenus 

  • ce qu'on peut améliorer : mettre les valeurs de temps de réaction dans un tableur qui calcule la moyenne des 4 plaques, fonction qui choisit le nombre de mesures prises (plutôt que forcément 10 ou autre nombre fixe), résultat plus propre (pas de scotch, cacher les cartes et les fils derrière les plaques, ...), fixer au mur, écarter plus les plaques 


Projets personnels
Coline
  • Objets 2D à la découpeuse laser :

Je vais faire une médaille pour le chien de ma sœur, elle la veut de dimensions 5cm sur 3 cm environ, avec le nom du chien sur le recto, et son numéro de téléphone ainsi que ses coordonnées Instagram sur le verso. Pour pouvoir imprimer le resto et le verso, je prendrai un matériaux opaques (un des bois disponibles au FabLab).

J'ai fait plusieurs croquis au brouillon sur papier au crayon, elle a sélectionné son préféré, que j'ai alors scanné sur mon téléphone avec l'application CamScanner et importé via mon ordinateur sur Inkscape. 

20240330_125632.jpg

capture-decran-2024-03-23-124651.png

J'ai baisser l'opacité du calque de l'image puis créer un autre calque par dessus, sur lequel j'ai retracé au propre l'image en transparence en faisant quelques modifications. Les lettres sont en noir car elles seront gravées. J'ai utilisé l'outil plume (au milieu à gauche) en mode séquence de segments de lignes droites (en haut à gauche) pour faire des formes, puis l'outil nœud (en haut à gauche) pour modifier les coins des lettres qui ne me convenaient pas. 

Capture d'écran 2024-03-30 130219.pngCapture d'écran 2024-03-30 130234.pngCapture d'écran 2024-03-30 130248.png

J'ai ensuite tracé le contour de la médaille avec une ligne de 1px en rouge car il devra être découpé. Je me suis aidé de lignes (tracées en vert sur l'image, je l'ai ai ensuite supprimée) pour essayer d'avoir un contour le plus symétrique possible. En retournant verticalement l'image comme dans un miroir, on voit que ce n'est pas totalement symétrique mais ça ne ne voit pas à l'œil nu donc j'ai gardé cette forme. 

Capture d'écran 2024-03-24 121405.png

A plusieurs reprises, j'ai modifié la taille du dessin, ce qui a aussi modifié l'épaisseur des lignes ce qui était très énervant. 

J'ai ensuite rajouter l'attache de la médaille en créant deux cercles. J'ai reproduit à l'échelle le dessin sur du papier pour m'assurer que les dimensions étaient bonne, notamment que l'on peut faire passer une attache de porte clé dedans, puisque c'est comme ça qu'elle sera attaché au collier du chien. Pour que l'intersection entre le demi cercle et les lignes droites rouges du reste de contour soit bien nette, j'ai ajouté des rectangles blancs (qui ne se voient donc pas sur le fond blanc).

J'ai ensuite créer un carré autour en bleu (1px, marquage) qui me servira de repère pour que le verso soit bien superposé au recto. J'ai ensuite copié le contour rouge et le carré bleu puis l'ai retourné. En bleu, avec l'outil texte, j'ai noté le numéro de téléphone (pas celui sur la photo évidemment, c'est juste un exemple) ainsi que le compte Instagram (allez vous abonner).

Capture d'écran 2024-03-24 134908.png

Le plus important lors de la découpe sera que les lettres stylisées du devant soient bien dans le cadre rouge, c'est pas très grave si les textes derrière ne sont pas très bien centrés et qu'il y ai un petit décalage. Il faudrait donc d'abord que je découpe le grand carré autour et que je marque les numéro et l'Instagram, puis que retourne le carré et que je fasse gravé les lettres et découpe le contour rouge de la médaille. Le contour rouge ne devra être découpé qu'une fois par la machine pour être sure que la découpe soit nette.  J'ai donc supprimé la version retournée du contour rouge autour du numéro de téléphone et est mis le grand carré en rouge à la place. Il faut maintenant que je fasse deux fichiers différents tout en gardant les mêmes dimensions pour le recto et le verso pour que la machine fasse l'un après l'autre. J'ai donc simplement fait un couper coller du recto sur un autre fichier, en m'assurant que les dimensions et épaisseur des lignes n'est pas étaient modifiées. 

Capture d'écran 2024-03-30 132458.png

Parmi les bois disponibles à l'impression , j'ai pris un chute de peuplier 3mm. J'ai commencé par le verso (marquage du numéro) qui a été très rapide (moins d'1mn). Mais pour le resto, j'ai du changer mon fichier Inkscape car les rectangles blancs n'apparaissaient pas donc l'attache aurait été découpée du reste de la médaille. J'ai réutilise l'outil plume en commençant à gauche de l'attache, puis en faisant le tour du contour et en finissant à droite de l'attache. De près, les finissions/l'intersection entre l'arc de cercle et les lignes rouges n'est pas très nette mais cela sera suffisant pour la découpeuse laser.  

Sur l'ordinateur de la découpeuse, le dessin ne voulait être déplacer jusque dans le coin de la planche, j'ai donc décalé la planche du coin de quelques centimètre et ai essayer de replacer le cadre bleu pour que cela correspond au rectangle de la planche, avant de placer le curseur sur une des lignes rouges. 

20240404_175307.jpg

Le cadrage n'était pas exact, ce qui a décentré les écritures du verso par rapport à l'avant mais la découpe a réussi. Voici le résultat final : 

        20240404_180410.jpgScreenshot_20240404_180448_Gallery.jpg

 

Comme nous devions faire un objet sur une planche de maximum 30cm sur 30cm et que la médaille était petite, j'ai décidé en plus de graver une image que j'ai pris sur internet. Je l'ai importée sur Inkscape puis je l'ai redimensionné environ au format A5 (21cm sur 14cm au lieu de 14.8cm pour ne pas déformer ou couper l'image). Elle est issue d'un manga donc elle est déjà en noir et blanc mais il fallait tout de même vectorisé l'image. J'ai adapté le seuil de luminosité de la vectorisation pour conserver le maximum de détails mais certains détails ne me convenait pas donc j'ai utiliser les outils gomme et calligraphie pour corriger certaines imperfections. J'ai également rajouter une ligne rouge de 1px tout autour pour la découpe (rectangle de même dimension et même position en X et Y que l'image pour que ça suive bien les bords).

7721ae5cc8fc0e97158bdd26b5da4374.jpg     image.png      

 

  • Objet 3D à l'imprimante 3D : porte-clé

J'ai décidé de faire un lanceur de paintball en 3D pour en faire un porte-clé. J'utiliserai OpenSCAD. Voici une des images que j'ai utilisée comme référence : paintball-gun.jpg

J'ai commencé par réalisé le canon et le corps du lanceur avec des cylindre et pavé. J'ai utiliser la fonction rotate pour les orientations de la manière dont je voulais mais j'ai fait en sorte que toute mes formes restent au centre avec une coordonnée en y de 0 pour faciliter le placement (je changerai donc uniquement les coordonnées des x et z en utilisant la fonction translate). J'ai ajusté plusieurs fois la taille des composants jusqu'à ce que cela me convienne. 

Capture d'écran 2024-03-29 112912.png


Capture d'écran 2024-03-29 114159.png

J'ai aussi augmenté au fur et à mesure la fonction $fn= pour lisser les cylindres et par la suite les sphères. 

Ensuite, j'ai généré des sphères et d'autres cylindres/cônes pour la bouteille d'air comprimé et le loader.

Capture d'écran 2024-03-29 134445.png

Pour la gâchette, j'ai utilisé la fonction difference() entre deux cylindres pour faire une forme de croissant de lune. 

En remontant au début du code, j'ai à nouveau utilisé la fonction difference() entre deux cylindres pour faire le creux du canon. Capture d'écran 2024-03-29 155138.png

Les détails des vis en dessous du loader et sur le air source adaptater ont été faits avec 3 cylindres simples. 

Capture d'écran 2024-03-29 170830.png

Enfin, j'ai ajouté l'attache du porte clé au bout de la bouteille d air comprimé en faisant une difference() entre deux cercles , et j'ai également ajouté un couvercle au loader en faisant une différence entre un disque et la sphère du loader pour avoir une surface plane sur la sphère, puis en ajoutant un disque :

Capture d'écran 2024-03-29 171208.pngCapture d'écran 2024-03-29 171332.png

 

Capture d'écran 2024-03-29 171550.png

 

 

Capture d'écran 2024-03-29 171601.png

 

 

Voici le modèle 3d final : 

Capture d'écran 2024-03-29 171812.png

Nous verrons à l'impression si les détails ne sont pas trop petits pour avoir un bon rendu. Avant de le mettre sur l'ordinateur de la salle des imprimantes 3D, il faut convertir le fichier en STL, et avant ça render avec F6 pour avoir l'aperçu final. Un warning c'est affiché me disant que les objets 2D ne pouvaient être combinés avec les objets 3D et certains des objets ont disparu de l'aperçu, j'ai du donc remplacer tous les cercles par des cylindres. 

Voici le code final, certaines modifications pourraient être apportées pour qu'il soit optimisé : 

$fn=100;
rotate([0,90,0])
{
difference(){
cylinder(h=30,r=0.8);
translate([0,0,25]){
cylinder(h=6,r=0.5);}}
cube([3,3,13],center=true);
translate([0,0,6])
cylinder(6,1.5,0.9);
}

rotate([0,190,0])
translate([0,0,5])
cube([4,2,10],center=true);

rotate([0,180,0])
translate([-9,0,0])
cylinder(h=9,r=1.1);

translate([1,0,-10])
rotate([0,-90,0])
cylinder(h=10,r=1);

translate([-2,0,0]){
translate([-10,0,-10])
sphere(4);
translate([-16,0,-10])
sphere(4);
rotate([0,90,0])
translate([10,0,-16])
cylinder(h=6,r=4);}

cylinder(h=6,r=1.2);

rotate([0,-5,0])
translate([-2,0,8.5])
rotate([0,110,0])
cylinder(8,5,1.9);

difference(){
rotate([0,-5,0]){
translate([-3.1,0,8.9])
    sphere(5.06);}
rotate([0,-47,0]){
translate([3.5,0,12.8])
cylinder(h=2,r=3);}}
   
difference(){
rotate ([0,90,0]){
translate([3,0,3])
cube([5,1.5,5], center=true);}
rotate ([0,90,0]){
translate([3,0,3])
cube([4.5,2,4.5], center=true);
}}


difference(){
rotate([90,0,0]){
translate([2.9,-2.8,0]){
cylinder(h=1,r=1.7,center=true);}}
rotate([90,0,0]){
translate([3.5,-2.9,0]){
cylinder(h=2,r=1.5,center=true);}}};

translate([-7,0,-11.5])
cylinder(h=3,r=0.6);

translate([-7,0,-12.1])
cylinder(h=0.7,r=1);

translate([-0.5,0,3])
cylinder(h=1, r=1.8, center=true);

translate([-23,0,-10]){
rotate([90,0,0])
difference(){
circle(h=1, r=2,center=true);
circle(h=1, r=1.3, center=true);}}

rotate([0,-47,0])
translate([3.6,0,12.6])
cylinder(h=0.5, r=3);

A la première simulation, le temps d'impression était estimée à 56mn pour une échelle de 7cm de long. Comme le lanceur est "debout" (pas couche à plat) les supports étaient plutôt nombreux. J'ai donc décidé de créé un autre fichier avec le lanceur à plat (rotate sur l'ensemble de mon code), pour voir si je peux avoir un temps moins long.