Projet de Terminale

En Terminale STI2D nous avons, en groupe, choisir un système et l'améliorer. Ce projet était évalué au baccalauréat coefficient 12.


Un vélo "connecté"

Pour ce projet nous avons choisi d'ajouter trois systèmes sur un vélo grâce aux cartes type Arduino :

Le compteur de vitesse se présente sous la forme d'un petit écran sur le guidon.
Le détecteur d'accident envoie un SMS à la personne choisie avec les coordonnées GPS du vélo.
Le capteur du pollution envoie le taux de particules fines avec la localisation sur un serveur ThingSpeak .

Diagramme des cas d'utilisation

Diagramme des cas d'utilisation

Développement durable

Notre projet devais rentrer dans une demarche de developpement durrable.
Les 3 pilier du développement durable
Social :
Grâce au système embarqué, le cycliste sait que s'il a un accident, quelqu'un sera averti. Et inversement pour la famille. Par exemple pour des parents, ils savent que quoi qu'il arrive à leurs enfants ils seront avertis.
De plus, l'utilisateur a la possibilité de choisir son parcours en fonction de la pollution.

Environnemental :
Avec l'envoi des données de pollution et de localisation sur le serveur ThingSpeak, on peut, à terme, établir une carte assez précise de la pollution en France même dans les endroits plus reculés où l'installation de capteur fixe n'est pas utile.

Économique :
- Le système au complet doit pouvoir être vendu aux alentours de 50/60€. De plus, nous pourrions adapter le système selon les besoins de l'utilisateur et ainsi reduire le coût à l'achat.
- Création d'emplois pour la production, le service après vente, la collecte et la transmition des données.


Ma partie

Dans ce projet, je me suis occupé du compteur de vitesse avec son affichage.

Pour le compteur de vitesse j'ai utilisé un capteur à effet Hall (capteur de champ magnétique).
J'ai fixé le capteur sur la fourche et un aimant sur la roue ce qui me permet de détecter un tour de roue. À chaque tour de roue je lance un chronomètre pour obtenir le temps entre deux tours de roue. Ensuite je calcule la vitesse grâce à la formule :
périmètre de la roue / temps entre deux tours de roue .

Pour l'affichage, j'ai utilisé un écran OLED 0.96 pouce fixé sur le guidon avec une connexion en I2C.

Pour le micro-contrôleur j'ai utilisé un ESP8266 car pour l'envoi des données de pollution sur le serveur nous utilisons la puce WI-FI intégrée mais nous aurions aussi pu utiliser une carte Arduino complétée d'un module WI-FI (plus compliqué à mettre en place).


Voicie une vidéo du projet en fonctionnement. Je simule le tours de roue en passant l'aimant devant le capteur.


Mise en place

Pour réaliser le compteur de vitesse nous avons besoin :

  • D'un micro-contrôleur
  • D'un écran en I2C
  • D'un capteur à effet Hall
  • D'un bouton poussoir
  • De 2 resistances de 10kΩ
  • De câbles
Voici comment se présente le montage :

Shema de montage du projet

Le calcul de vitesse

photo du capteur
Le capteur fonctionne entre 3.3V et 24V. Idéal pour un Raspberry pi ou un ESP8266.
Sa distance de détection est de 0 à environ 15cm.
On peut le trouver aux allentours de 1€ sur AliExpress par exemple.
Pour ce qui est du montage en lui même voici un shéma éléctrique :
shema éléctrique


// ----------========== Partie déclarative ===========----------
// -----===== calcul du délai =====-----
float delais;
float temps;

int tempoV = 0;


// -----===== calcul de la vitesse =====-----
int etat_capt = 0;
float vitesse;
float moyV = 0;
float sommeV = 0;
int compteur = 1;
int arreter = 0;


// -----===== capteur =====-----
int capteur_hall = D4;     //capteur sur la pin digital 8


// -----===== roue =====-----
const float pi = 3.14;              //pi est egale a 3.14
const int Droue = 24;               //le diamètre de la roue en pouce
float Proue;                        //le périmètre de la roue


// ----------========== Partie SETUP ===========----------

void setup(){
  pinMode(capteur_hall, INPUT);     //le capteur en entrée
    Serial.begin(115200);

// -----===== calcul périmètre roue =====-----
  Proue = ((Droue * 2.54) * pi)/100;            //périmètre de la roue en m
  Serial.print("périmetre de la roue :   ");
  Serial.print(Proue);
  Serial.println("  mètre");

}

// ----------========== Partie code (LOOP) ===========----------

void loop(){

  if(digitalRead(capteur_hall) == 0){
    if(etat_capt == 0){                 //pour détécter l'aimant
    delais = millis() - temps;          //temps en ms
    Serial.println(delais);
    temps = millis();
    etat_capt = 1;
    arreter = 0;

    delais = delais / 1000;              //temps en s
    vitesse = Proue / delais;            //vitesse en m/s
    vitesse = (vitesse * 3600) / 1000;   //vitesse en km/h


    // -----===== calcul de la moyenne =====-----
      sommeV = sommeV + vitesse;
      moyV = sommeV / compteur;
      compteur++;


    // -----===== affichage vitesse =====-----
    Serial.print("vitesse :  ");
    Serial.print(vitesse);
    Serial.println("  en km/h");
    Serial.print("vitesse moy :  ");
    Serial.print(moyV);
    Serial.println("  en km/h");
    }
  }

   // ---== en cas d'arrêt ==---
    else{
    etat_capt = 0;
      if(arreter == 0){
      if((millis() - temps) >= 5000){
        Serial.println ("vitesse : 0km/h ");
        arreter = 1; }
    }
  }
}
          

L'affichage sur l'écran

L'affichage sur l'écran I2C se fait grâce à la bibliothèque Adafruit_SSD1306. Elle permet d'écrire mais aussi d'afficher différents effets graphiques comme des formes géométriques ou du texte défilant par exemple.
Photo de l'écran
L'écran a :
- Une taille de 0.96 pouce, d'où son nom.
- Une résolution de 128 x 32 pixels.
- Un voltage entre 3.3 et 5V.
Pour un prix avoisinant les 2€50.

// -------======== Déclaration de bibliothèque ========-------

#include 
#include 

// adresse de l'écran OLED
#define OLED_ADDR   0x3C

Adafruit_SSD1306 display(-1);

#if (SSD1306_LCDHEIGHT != 64)
//#error("largeur incorrect, fix Adafruit_SSD1306.h!");
#endif

void setup() {

  // Initialisation de l'écran
  display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
  display.clearDisplay();
  display.display();
  display.setTextSize(2);         //taille du texte à 1
  display.setTextColor(WHITE);    //couleur blanche
}

void loop() {
  display.clearDisplay();         //on efface l'écran

  display.setCursor(1,9);         //on met le curseur à 1 pixel du bord gauche et à 9 pixels du haut

  display.print("Hello world");   //on affiche "Hello world"

  display.display();              //update de l'écran
}
          

Le code complet

Voici le code complet et commenté de ma partie du projet. Avec un suivi des actions effectuées par le système dans le moniteur série.
Une amélioration qui pourrait être effectuée est d'ajouter des fonctions pour les instructions que l'on répéte souvent. Pour le calcul de vitesse ou de vitesse moyenne entre autres.

// -------======== Déclaration de bibliothèque ========-------

#include 
#include 

// adresse de l'écran OLED
#define OLED_ADDR   0x3C

Adafruit_SSD1306 display(-1);

#if (SSD1306_LCDHEIGHT != 64)
//#error("largeur incorrect, fix Adafruit_SSD1306.h!");
#endif


// -------======== Déclaration de Variable/capteur ========-------

// -----===== calcul delais =====-----
float delais;
float temps;

// -----===== calcul vitesse =====-----
int etat_capt = 0;
float vitesse;
float moyV = 0;
float Vmax = 0;
float sommeV = 0;
int compteur = 1;
int arreter = 0;
int nbr_tour = 0;
float distance = 0;

// -----===== Bouton =====-----
int BP = D3;               //bouton sur la pin digital 7
int Etat_BP = 1;           //variable pour savoir sur quel écran on est
int nbr_ecran = 5;         //pour définir le nombre d'écran
int affichage = 0;

// -----===== capteur =====-----
int capteur_hall = D4;     //capteur sur la pin digital 8

// -----===== roue =====-----
const float pi = 3.14;              //pi est egal a 3.14
const int Droue = 15;               //le diamètre de la roue en pouce
float Proue;                        //le périmètre de la roue




void setup() {
  // ----------------======================= SET UP =======================---------------
  Serial.begin(115200);                  //lancement du moniteur série à 115 200 baud
  Serial.println(" ----- SET UP -----");

  // initialisation de l'écran
  display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
  display.clearDisplay();
  display.display();
  display.setTextSize(2);         //taille du texte à 1
  display.setTextColor(WHITE);    //couleur blanche

  // afficher un pixel à chaque coin de l'écran
  /*display.drawPixel(0, 0, WHITE);
  display.drawPixel(127, 0, WHITE);
  display.drawPixel(0, 32, WHITE);
  display.drawPixel(127, 32, WHITE);*/


  pinMode(capteur_hall, INPUT);       //le capteur est en entrée
  pinMode(BP, INPUT);                 //le bouton est en entrée

  // -----===== calcul périmètre roue =====-----
  Proue = ((Droue * 2.54) * pi)/100;            //périmètre de la roue en m
  Serial.print("périmetre de la roue :   ");    //affichage dans le moniteur série
  Serial.print(Proue);
  Serial.println("  mètre");
  Serial.println(" ----- fin SET UP ----- ");

}

void loop() {
  // ----------------======================= LOOP =======================----------------

  // -----===== changement d'écran =====-----
  if(Etat_BP <= nbr_ecran){
    if(digitalRead(BP) == 0){
      Etat_BP++;
      //Serial.print("Etat bouton   ");
      //Serial.println(Etat_BP);
      delay(250);
  }}
  else{
    Etat_BP = 1;
  }



  // --------------------==================== Ecran 1 : vitesse ====================--------------------
  if(Etat_BP == 1){

    if (affichage == 0){
       Serial.println(" --------------- ");
       Serial.println("écran 1 : vitesse actuelle");
       affichage = 1;
    }

  if(digitalRead(capteur_hall) == 0){
    if(etat_capt == 0){                       //pour détecter l'entrée de l'aimant
       delais = millis() - temps;             //délai entre 2 tours en ms
        //Serial.println(delais);             //affichage du temps en ms
        temps = millis();
        etat_capt = 1;                        //le capteur est déjà là
        arreter = 0;                          //on met la variable "arrêter" à 0

    // -----===== calcul de la vitesse =====-----
    delais = delais / 1000;                //temps en s
    vitesse = Proue / delais;              //vitesse en m/s
    vitesse = (vitesse * 3600) / 1000;     //vitesse en km/h


    // -----===== calcul de la moyenne =====-----
      sommeV = sommeV + vitesse;            //on calcule la somme de toutes les vitesses
      moyV = sommeV / compteur;             //et on divise par la somme des tours de roue
      nbr_tour++;                           //on ajoute 1 au nombre de tours (pour calculer la moyenne et la distance)


    // -----===== calcul de la vitesse max =====-----
      if (vitesse > Vmax){
        Vmax = vitesse;
      }

    // -----===== affichage vitesse dans le moniteur série =====-----
    Serial.println("---------------");
    Serial.print("vitesse :  ");
    Serial.print(vitesse);
    Serial.println(" en km/h");

    Serial.print("vitesse moyenne :  ");
    Serial.print(moyV);
    Serial.println("  en km/h");

    Serial.print("vitesse max :   ");
    Serial.print(Vmax);
    Serial.println("  en km/h");



  // -----===== affichage écran =====-----

  display.clearDisplay();         //on efface l'écran

  display.setCursor(1,9);         //on met le curseur à 1 pixel du bord gauche et à 9 pixels du haut
  if(vitesse >=10){
    display.print(vitesse);       //on affiche la vitesse
    display.print(" km/h");       //en km/h
  }
  if(vitesse < 10){
    display.print(vitesse);       //on affiche la vitesse
    display.print("  km/h");      //en km/h
  }

  display.display();              //update de l'écran


 }
}

  // --=== si le capteur ne détecte pas l'aimant (la roue ne tourne pas) ===--
  else{
    //Serial.println("capteur plus detecté");
    etat_capt = 0;                                 //on met la variable pour détecter l'entrée de l'aimant à 0

    if(arreter == 0){                              //si on n'est pas déjà arrêté
      if((millis() - temps) >= 3000){              //si le capteur n'a rien détecté depuis x secondes
        Serial.println ("vitesse : 0km/h ");
        arreter = 1;                               //on passe à arrêter
        vitesse = 0;                               //et on met la vitesse à 0


    // --=== affiche la vitesse à l'arrêt ===--
    display.clearDisplay();
    display.setCursor(1,9);         //on met le curseur à 1 pixel du bord gauche et à 9 pixels du haut
    display.print(vitesse);
    display.print("  km/h");
    display.display();
    }
   }
  }

 }
    // --------------------=================== Ecran 2 : vitesse moyenne ====================--------------------
    if(Etat_BP == 2){

      if (affichage == 1){
      Serial.println(" --------------- ");
      Serial.println("écran 2 : vitesse moyenne");
      affichage = 0;
      }

    if(digitalRead(capteur_hall) == 0){
      if(etat_capt == 0){                   //Pour détécter l'entrée de l'aimant
      delais = millis() - temps;            //temps en ms
      //Serial.println(delais);
      temps = millis();
      etat_capt = 1;                        //le capteur est déjà là
      arreter = 0;                          //on passe à "en mouvement"

    // -----===== calcul de la vitesse =====-----
    delais = delais / 1000;                 //temps en s
    vitesse = Proue / delais;               //vitesse en m/s
    vitesse = (vitesse * 3600) / 1000;      //vitesse en km/h

    nbr_tour++;                             //on ajoute 1 au nombre de tours (pour calculer la moyenne et la distance)

    // ---==== calcul distance ====---
    distance = nbr_tour * Proue;               //la distance en mètre
    distance = distance / 1000;                //la distance en km


    // -----===== calcul de la moyenne =====-----
      moyV = distance / millis();


    // -----===== calcul de la vitesse max =====-----
      if (vitesse > Vmax){
        Vmax = vitesse;
      }


    // -----===== affichage vitesse =====-----
    Serial.println("---------------");
    Serial.print("vitesse :  ");
    Serial.print(vitesse);
    Serial.println(" en km/h");

    Serial.print("vitesse moynne :  ");
    Serial.print(moyV);
    Serial.println("  en km/h");

    Serial.print("vitesse max :   ");
    Serial.print(Vmax);
    Serial.println("  en km/h");

  // -----===== affichage écran =====-----

  display.clearDisplay();         //on efface l'écran

  display.setCursor(1,9);         //on met le curseur à 1 pixel du bord gauche et à 9 pixels du haut
  if(moyV >=10){
  display.print(moyV);            //on affiche la vitesse
  display.print(" Vmoy");         //en km/h
  }
  if(moyV < 10){
  display.print(moyV);            //on affiche la vitesse
  display.print("  Vmoy");        //en km/h
  }


  display.display();              //update de l'écran

  }
}

  // --=== si le capteur ne détecte pas l'aimant ===--
  else{
    etat_capt = 0;                //on met la variable pour détecter l'entrée de l'aimant à 0
  }
 }

   // --------------------==================== Ecran 3 : vitesse max ====================--------------------
  if(Etat_BP == 3){

    if(affichage == 0){
      Serial.println(" --------------- ");
      Serial.println("écran 3 : vitesse max");
      affichage = 1;
}

   if(digitalRead(capteur_hall) == 0){
    if(etat_capt == 0){                   //pour détécter l'entrée de l'aimant
    delais = millis() - temps;            //délai entre 2 tours en ms
    //Serial.println(delais);             //affichage temps en ms
    temps = millis();
    etat_capt = 1;                        //le capteur est déjà là
    arreter = 0;                          //on passe à "en mouvement"

    // -----===== calcul de la vitesse =====-----
    delais = delais / 1000;                //temps en s
    vitesse = Proue / delais;              //vitesse en m/s
    /*Serial.print("vitesse :  ");
    Serial.print(vitesse);
    Serial.println(" en m/s");*/
    vitesse = (vitesse * 3600) / 1000;     //vitesse en km/h

    nbr_tour++;                            //on ajoute 1 au nombre de tours (pour calculer la moyenne et la distance)


    // -----===== calcul de la vitesse max =====-----
      if (vitesse > Vmax){
        Vmax = vitesse;
      }

    // -----===== affichage vitesse dans le moniteur série =====-----
    Serial.println("---------------");
    Serial.print("vitesse :  ");
    Serial.print(vitesse);
    Serial.println(" en km/h");

    Serial.print("vitesse moyenne :  ");
    Serial.print(moyV);
    Serial.println("  en km/h");

    Serial.print("vitesse max :   ");
    Serial.print(Vmax);
    Serial.println("  en km/h");




    // -----===== affichage écran =====-----

     display.clearDisplay();          //on efface l'écran

      display.setCursor(1,9);         //on met le curseur à 1 pixel du bord gauche et à 9 pixels du haut
      if(Vmax >=10){
      display.print(Vmax);            //on affiche la vitesse
      display.print(" VMax");         //en km/h
     }
      if(Vmax < 10){
      display.print(Vmax);            //on affiche la vitesse
      display.print("  Vmax");        //en km/h
     }


  display.display();                 //update de l'écran

   }
}
    // --=== si le capteur ne détecte pas l'aimant ===--
  else{
    etat_capt = 0;                //on met la variable pour détecter l'entré de l'aimant à 0
  }
  }

   // --------------------==================== Ecran 4 : distance ====================--------------------
   if(Etat_BP == 4){

    if (affichage == 1){
      Serial.println(" --------------- ");
      Serial.println("écran 4 : distance");
      affichage = 0;
   }

    if(digitalRead(capteur_hall) == 0){
    if(etat_capt == 0){                    //pour détécter l'entrée de l'aimant
      Serial.println("capteur detecté");
      delais = millis() - temps;            //délai entre 2 tours en ms
      //Serial.println(delais);             //affichage temps en ms
      temps = millis();
      etat_capt = 1;                        //le capteur est déjà là
      arreter = 0;                          //on passe à "en mouvement"

    // -----===== calcul de la vitesse =====-----
    delais = delais / 1000;                //temps en s
    vitesse = Proue / delais;              //vitesse en m/s
    /*Serial.print("vitesse :  ");
    Serial.print(vitesse);
    Serial.println(" en m/s");*/
    vitesse = (vitesse * 3600) / 1000;     //vitesse en km/h

    nbr_tour++;                            //on ajoute 1 au nombre de tours (pour calculer la moyenne et la distance)


    // -----===== calcul de la vitesse max =====-----
      if (vitesse > Vmax){
        Vmax = vitesse;
      }

    // -----===== affichage vitesse dans le moniteur série =====-----
    Serial.println("---------------");
    Serial.print("vitesse :  ");
    Serial.print(vitesse);
    Serial.println(" en km/h");

    Serial.print("vitesse moyenne :  ");
    Serial.print(moyV);
    Serial.println("  en km/h");

    Serial.print("vitesse max :   ");
    Serial.print(Vmax);
    Serial.println("  en km/h");


    // ---==== calcul distance ====---
    distance = nbr_tour * Proue;               //la distance en mètre
    distance = distance / 1000;                //la distance en km

    display.clearDisplay();
    display.setCursor(1,9);                    //on met le curseur à 1 pixel du bord gauche et à 9 pixels du haut
    display.print(distance);
    display.print("  km");
    display.display();

    }
    }

    else{
    etat_capt = 0;                //on met la variable pour detecter l'entrée de l'aimant à 0
       }

   }
   // --------------------==================== Ecran 5 : pollution ====================--------------------
   if(Etat_BP == 5){

    if (affichage == 0){
    Serial.println(" --------------- ");
    Serial.println("écran 5 : pollution");
    affichage = 1;
    }

    if(digitalRead(capteur_hall) == 0){
    if(etat_capt == 0){                    //pour détécter l'entrée de l'aimant
      Serial.println("capteur detecté");
      delais = millis() - temps;            //délai entre 2 tours en ms
      //Serial.println(delais);             //affichage temps en ms
      temps = millis();
      etat_capt = 1;                        //le capteur est déjà là
      arreter = 0;                          //on passe à "en mouvement"

    // -----===== calcul de la vitesse =====-----
    delais = delais / 1000;                //temps en s
    vitesse = Proue / delais;              //vitesse en m/s
    /*Serial.print("vitesse :  ");
    Serial.print(vitesse);
    Serial.println(" en m/s");*/
    vitesse = (vitesse * 3600) / 1000;     //vitesse en km/h

    nbr_tour++;                            //on ajoute 1 au nombre de tours (pour calculer la moyenne et la distance)


    // -----===== calcul de la vitesse max =====-----
      if (vitesse > Vmax){
        Vmax = vitesse;
      }

    // -----===== affichage vitesse dans le moniteur série =====-----
    Serial.println("---------------");
    Serial.print("vitesse :  ");
    Serial.print(vitesse);
    Serial.println(" en km/h");

    Serial.print("vitesse moyenne :  ");
    Serial.print(moyV);
    Serial.println("  en km/h");

    Serial.print("vitesse max :   ");
    Serial.print(Vmax);
    Serial.println("  en km/h");


    display.clearDisplay();
    display.setCursor(1,9);         //on met le curseur à 1 pixel du bord gauche et à 9 pixels du haut
    display.print("pollution");
    display.display();

    }
    }

    else{
    etat_capt = 0;                //on met la variable pour detecter l'entrée de l'aimant à 0
    }
   }
}