Skip to content

🔌Test 2 Electronique : Boite Noire ​

🎯 Objectifs du projet ​

Objectifs généraux:

  • Concevoir une boite capable de collecter et de transmettre les donnĂ©es de vitesse et de position du capteur MPU6050 ;

  • CrĂ©er une station de contrĂŽle qui reçoit et affiche les donnĂ©es provenant de la boite

Objectifs spécifiques:

  • RĂ©aliser des schĂ©mas Ă©lectronique avec KICAD utilisant directement des ATMega328p;
  • Designer les PCB pour ensuite les produire.
  • Fabriquer votre propre alimentation Ă©lectrique pour alimenter le circuit qui ne devra pas ĂȘtre incluse dans la boĂźte.
  • Fabriquer un cube de 7 cm d'arrĂȘt pour reprĂ©senter la boĂźte noire. La face supĂ©rieure du cube devra ĂȘtre ouverte si elle est faite dans un matĂ©riau opaque afin de permettre de voir le circuit Ă  l'intĂ©rieur.
  • CrĂ©er un bus I2C dont le seul maĂźtre sera le microcontrĂŽleur Ă  l'intĂ©rieur du cube. Le capteur (dans le cube) et le microcontrĂŽleur (au niveau de la station de contrĂŽle) devront ĂȘtre les esclaves sur le bus. L'Ă©cran LCD doit ĂȘtre branchĂ© en mode 4 bits.
  • Produire une vidĂ©o dans laquelle on verra bouger le cube dans toutes les directions et les informations sur l'Ă©cran LCD.

1. Introduction ​

Lors du premier test, nous avons dĂ©couvert un capteur particulier alliant les fonctionnalitĂ©s d’un gyroscope et d’un accĂ©lĂ©romĂštre, dont l’usage nous a permis de dĂ©terminer le sens de dĂ©placement et l’accĂ©lĂ©ration de notre robot collecteur de dĂ©chets en mouvement. Cette fois-ci (pour le test 2), nous nous sommes proposĂ©s de dĂ©terminer des informations plus pertinentes et significatives que les prĂ©cĂ©dentes. Il s’agit de la vitesse de dĂ©placement et de la position spatiale. Ces valeurs, en raison de leur importance, seront collectĂ©es et enregistrĂ©es dans une boĂźte noire, puis affichĂ©es sur une station de contrĂŽle, le tout alimentĂ© par l’alimentation.

2. Architecture du systùme ​

Notre systĂšme qui se forme de trois sous-systĂšmes principaux qui:

  • la Boite Noire
  • la Station de contrĂŽle
  • l’Alimentation

Il est important de prĂ©ciser que le composant qui est le cƓur mĂȘme du systĂšme est le microcontrĂŽleur ATEMega328p.

PrĂ©sentation de l’ATMega 328p ​

L’ATMega 328p est un microcontrĂŽleur 8 bits de la famille AVR(Advanced Virtual RISC) dĂ©veloppĂ© par Microship qui est beaucoup utilisĂ© dans la rĂ©alisation de projets embarquĂ©s ou juste dans l’apprentissage. Il intĂšgre la technologie picoPower qui offre une consommation ultra faible et des modes de veille Ă  faible consommation idĂ©al pour les applications alimentĂ©es par batterie . C’est la version standard mais il en existe une version plus puissante ,le Atmega328 PB et qui est moins compatible avec Arduino mais qui dispose aussi d’un cƓur AVR 8 bits .

atmega_328p.png

SchĂ©ma d’un ATMega 328p

Ici pour notre projet , nous utiliserons un ATMega 328p-PU(voir image ci-dessus ). C’est le mĂȘme microcontrĂŽleur , mais dans un boĂźtier DIP-28 traversant , idĂ©al pour les breadboards et cartes Arduino .Ce boitier dispose de 28 broches traversantes qui assurent sa connexion aux Ă©lĂ©ments du circuit. Il peut ĂȘtre programmĂ© en C ou via l’environnement Arduino. Ce composant sera donc le cƓur de notre circuit et va permettre la liaison entre les diffĂ©rents Ă©lĂ©ments du circuit .

Son architecture est la suivante :

atmega_328p-UP.png

SchĂ©ma de l’architecture d’un ATMega328p

RĂ©sumĂ© des broches de l’ATMega 328p et leurs fonctions

BrochesFonction
GNDMasse
VCCAlimentation de tous l’ATMega en dehors des broches d’entrĂ©es analogiques
AVCCAlimentation des broches analogiques
AREFReference de tensions pour les conversions analogiques
XTAL1,XTAL2Horloge externe
RESETRéinitialisation
PD0(RX),PD1(TX)UART (série)
PB3,PB4,PB5,PB2SPI
PC4(SDA),PC5(SCL)I2C
PC0 à PC5ADC(entrée analogique)
PD3,PD5,PD6,PB1,PB2,PB3PWM

Pour l’utiliser directement(sans carte Arduino) dans notre circuit , on utilisera les composants suivants:

  • un quartz de 16MHz entre les broches XTAL1 et XTAL2m qui nous servira d’oscillateur externe;

quartz.png

📌 UtilitĂ© : fournit un signal d’horloge trĂšs stable et prĂ©cis grĂące Ă  la vibration de son cristal Ă  une frĂ©quence spĂ©cifique (par exemple, 16 MHz).

Utilité du quartzDétail
Cadencer les instructionsLe quartz fixe la vitesse à laquelle les instructions sont exécutées.
Précision temporellePour que les temporisations (ex : delay(), millis()) soient exactes.
Communication fiablePour que les protocoles comme UART, SPI, I2C fonctionnent correctement.
Stabilité du systÚmeUn quartz est bien plus stable que les oscillateurs internes.
  • deux condensateurs de 22pF, un entre chaque broche du quartz et la masse GND ;

    condensateur_22pF.png

📌 UtilitĂ©: stabilise le quartz.

  • RĂ©sistance de 10 kΩ sur la broche RESET;

resistance_10k.png

📌 UtilitĂ© : Maintient la broche RESET à l'Ă©tat haut (HIGH) pour Ă©viter les redĂ©marrages intempestifs.

  • Condensateur de 100 nF (0.1 ”F) entre VCC et GND (dĂ©couplage)

condensateur_100nF.png

📌 UtilitĂ©: Supprime les bruits et pics de tension sur l’alimentation du microcontrĂŽleur.

Plus clairement, sans lui dans le circuit, il peut y avoir des comportements alĂ©atoires (bugs, plantages) lors d’une charge soudaine (ex: allumage LED, envoi UART).

  • Bouton poussoir

bouton_poussoir.png

📌 UtilitĂ©: rĂ©initialiser l’ATMega lorsqu’un problĂšme liĂ© au code survient

📩PrĂ©sentation de la Boite Noire ​

La Boite Noire est le sous systĂšme chargĂ©e de collecter, d’enregistrer, et d’envoyer les donnĂ©es provenant du capteur MPU 6050 Ă  la station de contrĂŽle.

đŸ› ïžMatĂ©riel ​

  • ATMega328p
  • MPU6050

MPU6050.png

📌 UtilitĂ©: permet de dĂ©terminer la vitesse de dĂ©placement et la position suivant chaque axe(X,Y,Z)

  • LEDs

LEDs.png

📌 UtilitĂ©: Pour signifier que la boite est effectivement alimentĂ©e.

  • Resistance de 220Ω

resistance_220.png

📌 UtilitĂ©: protĂ©ger la LED

🔧🔋📟 Montage ​

PrĂ©sentation du schĂ©ma du circuit Kicad du 1er PCB Pour notre 1er circuit, le microprocesseur ATMega en sera le cƓur. C’est Ă  lui que seront reliĂ©s les diffĂ©rents composants du circuit et il va servir de maĂźtre. Notre microprocesseur ne disposant pas directement d’un oscillateur interne, il a fallu faire un circuit d’oscillation externe composĂ© de quartz et deux condensateurs de 22pF. Les broches de notre quartz sont Ă©galement reliĂ©es aux broches XTAL1 et XTAL2 de notre microprocesseur. Afin de simplifier au maximum la comprĂ©hension de notre schĂ©ma, des labels XTAL1 et XTAL 2 ont Ă©tĂ© créés et utilisĂ©s. Les labels sont des connexions sans fils qui relient un composant Ă  un autre composant sur le schĂ©ma du circuit. L’onglet de crĂ©ation de label est disponible sur la bande verticale droite de notre environnement Kicad. C’est d’ailleurs ce qui est va ĂȘtre privilĂ©giĂ© dans tout notre schĂ©ma par rapport aux fils de connexion classiques.

kicad_1er_PCB.png

SchĂ©ma du circuit d’oscillation

**-**AprĂšs il a fallu cĂąbler le circuit de reset qui va nous permettre de rĂ©initialiser notre ATMega en cas de problĂšme avec notre code. Pour le faire, on a utilisĂ© un bouton poussoir qui va nous servir de bouton « reset » qui sera connectĂ© Ă  une rĂ©sistance de 10k et un condensateur de 100nF, tout ça pour veiller Ă  la sĂ©curitĂ© de notre circuit et Ă  la dissipation de la chaleur. Cet ensemble est connectĂ© au label Reset qui est quant Ă  lui connectĂ© Ă  la broche RESET de notre ATMega , toujours dans la perspective d’éviter au maximum les fils de connexion classiques dans notre schĂ©ma.

circuit_d'oscillation.png

Schéma du circuit de Reset

**-**Une LED d’Etat associĂ©e Ă  une rĂ©sistance sera Ă©galement utilisĂ©e pour permettre en quelque sorte de notifier si notre circuit est parcouru par un courant comme avec l’arduino. Elle a Ă©tĂ© mise sur la broche D7 de notre microprocesseur.

circuit_reset.png

SchĂ©ma du cĂąblage de la LED d’état

-En ce qui concerne la broche d’alimentation de l’ATMega, le bus I2C ainsi que le capteur MPU-6050, le choix a Ă©tĂ© portĂ© sur l’utilisation respective d’un connecteur 2 pin, d’un connecteur 4 pin ainsi que d’un connecteur 8 pin que nous avons renommĂ© avec les noms de broches correspondants avec l’éditeur de symbole disponible dans la section outils du menu Kicad. Ces diffĂ©rents circuits ont Ă©tĂ© rĂ©alisĂ©s avec l’ajout de rĂ©sistances de 4.7 kΩ sur les broches SDA et SCL. Des labels  SDA et SCL ont Ă©tĂ© créés, toujours dans l’optique d’une comprĂ©hension facile de notre circuit.

LED_d'etat.png

Schéma du circuit du 1er PCB

-Il est important de noter que les broches VCC et GND de nos diffĂ©rents circuits sont connectĂ©s Ă  toutes les autres broches du mĂȘme nom sur le schĂ©ma. C’est une caractĂ©ristique intrinsĂšque au logiciel Kicad. 🧐L’exĂ©cution du contrĂŽle des rĂšgles Ă©lectriques affiche le message suivant :

circuit_1er_PCB.png

En voyant l’inscription 0 erreurs , l’équipe s’était dit que le travail Ă©tait fait (😏)et qu’elle pouvait dĂ©jĂ  passer au PCB en ignorant les avertissements du logiciel mais ce fut une grossiĂšre erreur de notre part.

AprĂšs les empreintes des diffĂ©rents composants ont Ă©tĂ© assignĂ©es dont le rĂ©capitulatif se trouve sur l’image suivante :

differents_composants.png

😼Mais lors du passage au PCB, on a obtenu le message suivant :

passage_PCB.png

On a obtenu 12 erreurs lors de la gĂ©nĂ©ration de notre PCB et c’est aprĂšs une lecture profonde qu’on s’est rendus compte que quand on renommait les connecteurs, ils n’étaient pas directement inclus dans la bibliothĂšque de composants de Kicad. C’était comme si on crĂ©ait un Ă©lĂ©ment et qu’on l’incluait dans la bibliothĂšque de Kicad, ce que l’on ne pouvait pas faire. En gros, les connecteurs n’étaient pas reconnus par le logiciel, ce qui entraĂźnait leur non connexion aux diffĂ©rents Ă©lĂ©ments sur le PCB. Trois options s’offraient donc Ă  nous :

  • Soit on crĂ©ait nos propres connecteurs que l’on allait inclure dans une bibliothĂšque que l’on aurait nous-mĂȘme crĂ©e ;
  • Soit on cherchait si ces connecteurs Ă©taient disponibles dans des bibliothĂšques en ligne ;
  • Ou soit on utilisait simplement les symboles d’origine non renommĂ©s disponibles dans le logiciel Kicad.

Notre choix s’est donc portĂ© sur la 3Ăšme option et aprĂšs reprise du schĂ©ma on a obtenu le schĂ©ma final suivant :

schema_final_circuit_1er_PCB.png

Schéma final du circuit du 1er PCB

WARNING

Il est important de notifier que les broches non utilisĂ©es de l’ATMega ont Ă©tĂ© notifiĂ©es au logiciel grĂące Ă  des marqueurs de non connexion sinon on aurait eu des erreurs inutiles par rapport Ă  ces broches. Par ailleurs les diffĂ©rents circuits ont Ă©tĂ© mis dans des cadres prĂ©cis et nommĂ©s, toujours pour permettre aux lecteurs une comprĂ©hension totale de notre circuit.

L’exĂ©cution du contrĂŽle des rĂšgles Ă©lectriques sur ce schĂ©ma a permis l’obtention de 0 erreurs ainsi que 0 avertissements comme souhaitĂ©(😏). Le mĂȘme rĂ©sultat a Ă©tĂ© observĂ© lors de ma mise Ă  jour du PCB depuis notre schĂ©ma.

actualisation_PCB.png

AprĂšs actualisation du PCB Ă  partir de notre schĂ©ma, on obtenait un 1er PCB oĂč tous les Ă©lĂ©ments Ă©taient collĂ©s l’un Ă  l’autre et les fils se chevauchaient.

1er_PCB_obtenu.png

On voit clairement sur cette image comment les diffĂ©rents composants Ă©taient mĂ©langĂ©s et comment les fils s’entrecoupaient.

Ce n’est qu’aprĂšs des heures de rĂ©organisation de tout ce schĂ©ma, de reprise et des tonnes d’erreurs qu’on a obtenu notre PCB final : PCB_final.png

Schéma du PCB final de la Boite Noire

Vue 3D du PCB final de la Boite Noire:

Dimensions  :

  • 6cmx 6,5cm (taille)
  • 0.5mm (0001969 in)
  • Grille : 2. 5 mm
  • 0.05 mm : Ă©paisseur de la ligne de contour
  • 1.6 mm : Ă©paisseur de tout le PCB

RĂ©sultat final ​

Image physique de la Boite Noire

đŸ–„ïžPrĂ©sentation de la station de contrĂŽle ​

La station de contrÎle est un systÚme qui permettra de suivre en temps réel notre robot à travers la connaissance de sa vitesse et de sa position.

đŸ› ïžMatĂ©riel ​

  • ATMega328p
  • Ecran LCD

ecran_LCD.png

📌 UtilitĂ©: Afficher les valeurs de position et de vitesses du provenant du capteur

🔧🔋📟 Montage ​

Présentation du circuit KiCad du PCB de la station contrÎle

En ce qui concerne le schĂ©ma du circuit de la station de contrĂŽle, on a Ă©galement utilisĂ© un ATMega 328p auquel on a associĂ© le circuit de Reset, le circuit d’oscillation, le circuit de la LED d’alimentation.

Pour notre Ă©cran LCD I2C, on a choisi d’utiliser un connecteur 16 pin qu’on a cĂąblĂ© selon le modĂšle suivant :

LCD PinFonctionBroche Arduino (Digital)Port ATmega328PBroche physique ATmega328P
1GND---GND
2VCC (5V)---VCC
3Vo (contraste)---PotentiomĂštre
4RSD12PB418
5RWGND-GND-GND
6ED11PB317
11D4D5PD511
12D5D4PD46
13D6D3PD35
14D7D2PD24
15A (LED+)VCC (via résistance 220Ω)--GND
16K (LED-)GND--GND

mappage_PINS.png

Schéma du montage de la station de contrÎle

Ayant retenu la leçon du montage prĂ©cĂ©dent, on a compris qu’il serait inutile de renommer les broches de notre Ă©cran dans notre schĂ©ma donc on l’a laissĂ© sous la forme disponible dans le logiciel Kicad. Ce qui nous a conduits Ă  0 erreurs et 0 avertissements (😏) lors de l’exĂ©cution du contrĂŽle des rĂšgles Ă©lectriques.

Cela nous a permis de gĂ©nĂ©rer le PCB et c’est aussi aprĂšs un travail fastidieux qu’on a pĂ» rĂ©organiser les fils pour obtenir le rĂ©sultat suivant :

station_controle.png

Vue 3D du PCB final:

Les dimensions de ce PCB sont les mĂȘmes que pour le PCB prĂ©cĂ©dent.

RĂ©sultat final ​

🔌PrĂ©sentation de l’alimentation ​

đŸ› ïžMatĂ©riel ​

  • Batterie au mercure de 8V

batterie_mercure_8V.jpeg

📌 UtilitĂ©: source de tension

  • Coupleur

📌 UtilitĂ©: associer les batteries en sĂ©rie pour avoir en sortie une tension qui est la somme des tensions

  • RĂ©gulateur non linĂ©aire de type abaisseur (Buck)(XL4015)

regulateur_XL4015.jpeg

📌 UtilitĂ©: conversion de la tension fournie par la source en une tension plus stable(5V adaptĂ©e pour l’ATMega328p

  • Diode Zener de 5V

📌 UtilitĂ©: protĂ©ger au cas oĂč il y a surtension

  • RĂ©sistance de 1K

📌 UtilitĂ©: protĂ©ger au cas oĂč il y a surtension

🔧🔋📟 Montage ​

Notre alimentation est une source comme par exemple une batterie à laquelle on a ajouté un régulateur de tension pour maintenir la sortie constante.

Connexions Ă  l’intĂ©rieur du systĂšme

Comme point de dĂ©part ,nous allons utiliser comme source de tension, 02 batteries au mercure d’environ 8 V chacune que nous allons assembler avec un coupleur, soit un total de 16V environ.

Par rapport au rĂ©gulateur non linĂ©aire, il est connectĂ© directement Ă  la source pour effectuer la conversion de la tension fournie en entrĂ©e par cette derniĂšre en une tension plus stable, constante de 5V pour alimenter les ATMega des autres sous systĂšmes. Plus prĂ©cisĂ©ment nous faisons usage d’un XL4015 qui est un modĂšle trĂšs particulier capable de prendre entre 3 et 32 volts et de restituer entre 1.5 et 35 volts(ajustable) de tension en sortie.

La diode Zener et la résistance, quant à elles, sont cùblées entre la sortie et le régulateur, de sorte que l'alimentation du circuit soit coupée dÚs que la tension va au-delà de 5V.

Voici une complĂšte de notre alimentation.

Schéma KiCad de l'alimentation sur KICAD

alimentation_kicad.png

RĂ©sultat final ​

Image physique de l’alimentation

alimentation_physique.jpeg

⚒Montage final ​

  • Connexions entre les sous systĂšmes

    De tout ce qui prĂ©cĂšde, on comprend que le systĂšme entier est l’ensemble formĂ© de la boite noire (Premier PCB) , de la station de contrĂŽle (second PCB) et de l’alimentation.

    • La Boite Noire et la station de contrĂŽle communiquent via un bus I2C qui est reprĂ©sentĂ© physiquement par un connecteur 4pin avec des rĂ©sistances 4.7kOhm sur les SDA et SCL.
    • L’alimentation sert de source directe (sans intermĂ©diaire) Ă  la Boite Noire et la station de ContrĂŽle via un connecteur 2pin placĂ© sur la source.
  • Rendu final physique du systĂšme complet

  • DifficultĂ©s rencontrĂ©es et solutions apportĂ©es

3. Code ​

🚌CrĂ©ation du bus I2C ​

🧐C’est quoi l’I2C? ​

L’I2C (prononcĂ© "I deux C" ou "I-squared-C") signifie Inter-Integrated Circuit. C’est un protocole de communication sĂ©rie inventĂ© par Philips (aujourd’hui NXP) pour permettre Ă  plusieurs circuits intĂ©grĂ©s (CI) de communiquer entre eux avec seulement deux fils.


🔧 Principes de base de l’I2C ​

  • Nombre de fils : 2
    • SDA (Serial Data Line) : ligne de donnĂ©es
    • SCL (Serial Clock Line) : ligne d’horloge
  • Architecture :
    • Un maĂźtre (master) contrĂŽle la communication.
    • Un ou plusieurs esclaves (slaves) rĂ©pondent.
    • Un seul maĂźtre, plusieurs esclaves possibles sur le mĂȘme bus.

🧠 Fonctionnement gĂ©nĂ©ral ​

  1. Le maĂźtre envoie un signal d’horloge (SCL) et contrĂŽle le moment oĂč les donnĂ©es (SDA) sont envoyĂ©es ou lues.
  2. Chaque esclave a une adresse unique (ex : 0x68 pour un MPU6050).
  3. Le maütre commence par envoyer une adresse d’esclave, puis des ordres ou des demandes de lecture.
  4. L’esclave rĂ©pond si l’adresse reçue correspond Ă  la sienne.

Explication du code du maĂźtre

⚙ 1. ATMega maĂźtre (le principal) ​

📌 Fonction :

  • Lit les donnĂ©es du capteur MPU6050 (avec DMP) via I2C.

    📌 A noter :

    Le DMP (Digital Motion Processor) est un processeur embarquĂ© Ă  l’intĂ©rieur de certains capteurs comme le MPU6050 (gyroscope + accĂ©lĂ©romĂštre). Il est intĂ©grĂ© pour traiter les donnĂ©es brutes directement dans le capteur, sans trop solliciter le microcontrĂŽleur (Arduino, etc.).


    Ce que le DMP fait : ​

    ✅ Filtrage des donnĂ©es

    ✅ Fusion des capteurs (accĂ©lĂ©romĂštre + gyroscope)

    ✅ Calcul d’orientation (quaternions, angles d’Euler)

    ✅ RĂ©duction du bruit et des erreurs dues Ă  la dĂ©rive

    ✅ Calcul automatique de la gravitĂ© et orientation

  • Calcule : accĂ©lĂ©ration rĂ©elle, vitesse, position

  • Transmet ces donnĂ©es (6 float, soit 24 octets) via I2C Ă  l’esclave

Code ​

cpp
/*Inclusion des bibliothÚques nécéssaires*/
#include <Wire.h>
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"

/*Adresse de l'esclave*/
#define SLAVE_ADDR 0x08

/* CrĂ©ation d’un objet de la classe MPU6050 */
MPU6050 mpu;

/* Variables liées au DMP (Digital Motion Processor) */
bool dmpReady = false;            // Drapeau indiquant si le DMP est initialisé 
uint8_t devStatus;                // Code de retour de l'initialisation du DMP
uint16_t packetSize;              // Taille attendue des paquets FIFO DMP 
uint16_t fifoCount;               // Nombre de bytes actuellement dans le FIFO 
uint8_t fifoBuffer[64];           // Tampon de lecture des données DMP 

/* Accélérations et gravité */
VectorInt16 accelerationBrut;     // Accélération brute (avec gravité)
VectorInt16 accelerationReel;     // Accélération réelle (sans gravité)
VectorInt16 accelerationMonde;     //Accélération dans le repere terrestre
VectorFloat gravity;              // Vecteur gravité calculé à partir du quaternion

Quaternion q;                     // Quaternion reprĂ©sentant l’orientation absolue

float accelerationX, accelerationY, accelerationZ; // acceleration sans gravite (dans le repere monde)
float vitesseX = 0, vitesseY = 0, vitesseZ = 0; // vitesse en m/s
float positionX = 0, positionY = 0, positionZ = 0; // position en m

const float constAccelGravit = 9.81;
const float sensibiliteAccel = 16384.0;

unsigned long lastTime = 0;

void setup() {
  /*Initialisation de la communication serie */
  Serial.begin(9600);

  /*Initialisation du bus I2C en mode maitre */
  Wire.begin();

  /*Pause pour stabiliser le bus et les periphériques */
  delay(1000);

  /*Initialisation du MPU6050 */
  mpu.initialize();

  /* Verification de la connexion I2C avec le capteur MPU */
  while(!mpu.testConnection()) 
  {
  Wire.beginTransmission(SLAVE_ADDR);
  Wire.write("ERRMPU");  // 6 caractĂšres = 6 octets
  Wire.endTransmission();
  }

  
  devStatus = mpu.dmpInitialize();//Initialisation du DMP

  /* Verification de l'initialisation du DMP */
  while(devstatus!=0) 
  {
  Wire.beginTransmission(SLAVE_ADDR);
  Wire.write("ERRDMP");  // 6 caractĂšres = 6 octets
  Wire.endTransmission();
  }
  
  /*Activation du DMP */
  mpu.setDMPEnabled(true);

  /* DMP est prĂȘt */ 
  dmpReady = true;

  /*Récuperation de la taille des paquets de données générés par le DMP */
  packetSize = mpu.dmpGetFIFOPacketSize();

  lastTime = millis();
}

void loop() {
  if (!dmpReady) return; //arrĂȘt de la boucle si le DMP n'est pas prĂȘt 

  fifoCount = mpu.getFIFOCount();//taille actuelle des données dans la FIFO
  
  /*ArrĂȘt de la boucle si le FIFO ne contient pas de packets complets */
  if (fifoCount < packetSize) return;

  mpu.getFIFOBytes(fifoBuffer, packetSize);//Lecture d'un paquet complet

   /*Calcul de la gravite */
  mpu.dmpGetGravity(&gravity, &q);

  /*Determination du vecteur accélération brute dans le repere du capteur  */
  mpu.dmpGetAccel(&accelerationBrut, fifoBuffer);
  
  /*Obtention de l'acceleration sans la gravité dans le repere du capteur */
  mpu.dmpGetLinearAccel(&accelerationReel, &accelerationBrut, &gravity);

  /*Determination du vecteur acceleration dans le monde reelle(repere fixe)  */
  mpu.dmpGetLinearAccelInWorld(&accelerationMonde, &accelerationReel, &q);

  /*Conversion des donnees brutes d'acceleration en valeurs physiques reelles */
  accelerationX = accelerationMonde.x / sensibiliteAccel * constAccelGravit;
  accelerationY = accelerationMonde.y / sensibiliteAccel * constAccelGravit;
  accelerationZ = accelerationMonde.z / sensibiliteAccel * constAccelGravit;

  unsigned long now = millis();
  float dt = (now - lastTime) / 1000.0;
  lastTime = now;

  /*Integration de l'accélération pour obtention de la vitesse */
  vitesseX += accelerationX * dt;
  vitesseY += accelerationY * dt;
  vitesseZ += accelerationZ * dt;

  /*Integration de la vitesse pour obtention de la position */
  positionX += vitesseX * dt;
  positionY += vitesseY * dt;
  positionZ += vitesseZ * dt;

/*Envoie des donnees de position et de vitesses (dans cet ordre) Ă  l'esclave Ă  travers son adresse */
  Wire.beginTransmission(SLAVE_ADDR);
  Wire.write((byte *)&positionX, 4);
  Wire.write((byte *)&positionY, 4);
  Wire.write((byte *)&positionZ, 4);

  Wire.write((byte *)&vitesseX, 4);
  Wire.write((byte *)&vitesseY, 4);
  Wire.write((byte *)&vitesseZ, 4);
  Wire.endTransmission();

  delay(50);
}

⚙ 2. ATMega esclave (le secondaire) ​

📌 Fonction :

  • Reçoit les donnĂ©es envoyĂ©es par le maĂźtre
  • Affiche position (X, Y) et vitesse (X, Y) sur un Ă©cran LCD 16x2 en mode 4 bits

Code

cpp
#include <Wire.h> //communication I2C
#include <LiquidCrystal.h> //pour contrÎler un écran LCD en mode parallÚle 4 bits

// LCD en mode 4 bits : RS, E, D4, D5, D6, D7
LiquidCrystal lcd(12,11, 5, 4, 3, 2);

// Données reçues
float px = 0, py = 0, pz = 0;
float vx = 0, vy = 0, vz = 0;

void setup() {

  /*Configure l’écran comme LCD 16 colonnes × 2 lignes */
  lcd.begin(16, 2);

  lcd.print("Esclave pret");

  /*Initialistion de la communication en mode esclave avec l'adresse 0x08*/
  Wire.begin(0x08);

  /*Définition de la fonction recevoir() comme handler à appeler quand le maßtre envoie des données I2C */
  Wire.onReceive(recevoir);
}

void loop() {

  /*Affichage de la position sur la premiere ligne de l'ecran LCD */
  lcd.setCursor(0, 0);

  lcd.print("Pos:");
  lcd.print(px, 1);
  lcd.print(":");
  lcd.print(py, 1);
  lcd.print(":");
  lcd.print(pz,1);

  /*Affichage de la vitesse sur la 2e ligne de l'ecran */
  lcd.setCursor(0, 1);
  lcd.print("Vit:");
  lcd.print(vx, 1);
  lcd.print(":");
  lcd.print(vy, 1);
  lcd.print(":");
  lcd.print(vz, 1);
  delay(500);

   /*Nettoyage de l'ecran */
  lcd.clear();
}

/*Fonction de reception des donnees provenant du maĂźtre */
void recevoir(int n) 
{
  if (n == 6) 
  { // Un message d'erreur de 6 caractĂšres
    char msg[7] = {0}; // +1 pour null-terminator
    for (int i = 0; i < 6; i++) {
      msg[i] = Wire.read();
    }

    if (strcmp(msg, "ERRMPU") == 0) {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Erreur capteur:");
      lcd.setCursor(0, 1);
      lcd.print("MPU non detecte");
    }
    else if(strcmp(msg, "ERRDMP") == 0)
    {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Erreur capteur:");
      lcd.setCursor(0, 1);
      lcd.print("DMP INACTIF");
    }
  }

  else if (n >= 24) //Si la taille des données reçues est au moins 24 octets
  {
    /*Lecture des 24e premiers octets reçues dans un tableau */
    byte buffer[24];
    for (int i = 0; i < 24; i++) 
    {
      buffer[i] = Wire.read();
    }

    /*Recuperation de chaque float dans les bonnes variables */
    memcpy(&px, &buffer[0], 4);
    memcpy(&py, &buffer[4], 4);
    memcpy(&pz, &buffer[8], 4);
    memcpy(&vx, &buffer[12], 4);
    memcpy(&vy, &buffer[16], 4);
    memcpy(&vz, &buffer[20], 4);
  }
}

4. DifficultĂ©s ​

  • DifficultĂ©s Ă  redisposer les Ă©lĂ©ments lors de la gĂ©nĂ©ration du PCB
  • Conflits avec la bibliothĂšque Kicad en raison de la modification des noms des connecteurs, ce qui a conduit Ă  une reprise du schĂ©ma
  • ImpossibilitĂ© d’impression de notre PCB en raison de la couche manquante, ce qui a conduit Ă  l’utilisation d’un veroboard
  • Manque de matĂ©riel lors du montage de notre circuit sur le veroboard ProblĂšmes de tension avec l’alimentation en raison de l’utilisation de piles qui se dĂ©chargent

5. CompĂ©tences tirĂ©es de ce test ​

  • Creation d’un bus I2C
  • Design d’un PCB
  • CĂąblage d’un LCD en parallĂšle (mode 4bits)
  • Comprehension de l’utilisation directe d’un ATMega328p avec d’autres sans arduino.

6. Annexe ​

Retrouvez ici les fichiers sources: