Qu'est-ce que le MEMS ? Accéléromètre, Gyroscope et Magnétomètre avec Arduino
Dans ce didacticiel, nous apprendrons comment fonctionnent l'accéléromètre, le gyroscope et le magnétomètre MEMS et comment les utiliser avec la carte Arduino. De plus, avec l'IDE de traitement, nous réaliserons des applications pratiques à l'aide des capteurs. Vous pouvez regarder la vidéo suivante ou lire le didacticiel écrit ci-dessous.
Les MEMS sont de très petits systèmes ou dispositifs, composés de microcomposants dont la taille varie de 0,001 mm à 0,1 mm. Ces composants sont constitués de silicium, de polymères, de métaux et/ou de céramique, et ils sont généralement associés à un CPU (microcontrôleur) pour compléter le système.
Nous allons maintenant expliquer brièvement le fonctionnement de chacun de ces capteurs de systèmes micro-électro-mécaniques (MEMS).
Il mesure l'accélération en mesurant le changement de capacité. Sa microstructure ressemble à ceci. Il a une masse attachée à un ressort qui est confiné pour se déplacer le long d'une direction et des plaques extérieures fixes. Ainsi, lorsqu'une accélération dans la direction particulière sera appliquée, la masse se déplacera et la capacité entre les plaques et la masse changera. Ce changement de capacité sera mesuré, traité et il correspondra à une valeur d'accélération particulière.
Le gyroscope mesure la vitesse angulaire à l'aide de l'effet Coriolis. Lorsqu'une masse se déplace dans une direction particulière avec une vitesse particulière et lorsqu'une vitesse angulaire externe sera appliquée comme le montre la flèche verte, une force se produira, comme le montre la flèche rouge bleue, qui provoquera un déplacement perpendiculaire de la masse. Donc similaire à l'accéléromètre, ce déplacement va provoquer un changement de capacité qui va être mesuré, traité et il va correspondre à une vitesse angulaire particulière.
La microstructure du gyroscope ressemble à ceci. Une masse qui bouge constamment, ou oscille, et lorsque la vitesse angulaire externe sera appliquée, une partie flexible de la masse se déplacera et fera le déplacement perpendiculaire.
Il mesure le champ magnétique terrestre en utilisant l'effet Hall ou l'effet magnéto résistif. En fait, près de 90 % des capteurs sur le marché utilisent l'effet Hall et voici comment cela fonctionne.
Si nous avons une plaque conductrice comme sur la photo et que nous laissons passer le courant, les électrons passeront directement de l'un à l'autre côté de la plaque. Maintenant, si nous amenons un champ magnétique près de la plaque, nous perturberions le flux rectiligne et les électrons seraient déviés d'un côté de la plaque et les pôles positifs de l'autre côté de la plaque. Cela signifie que si nous mettons maintenant un mètre entre ces deux côtés, nous obtiendrons une tension qui dépend de l'intensité du champ magnétique et de sa direction.
Ok maintenant, connectons ces capteurs à la carte Arduino et utilisons-les. À titre d'exemple, j'utiliserai la carte de dérivation GY-80 qui possède les capteurs suivants :accéléromètre à 3 axes ADXL345, gyroscope à 3 axes L3G4200D, magnétomètre à 3 axes MC5883L ainsi qu'un baromètre et un thermomètre que nous n'utiliserons pas dans ce tutoriel.
Vous pouvez obtenir ces composants sur l'un des sites ci-dessous :
Cette carte utilise le protocole de communication I2C, ce qui signifie que nous pouvons utiliser tous les capteurs avec seulement deux fils. Donc, pour établir la communication entre l'Arduino et les capteurs, nous devons connaître leurs adresses de périphérique uniques et leurs adresses de registre internes pour en extraire les données. Ces adresses se trouvent dans les fiches techniques des capteurs :
Pour plus de détails sur le fonctionnement de la communication I2C, vous pouvez consulter mon autre didacticiel sur le protocole de communication I2C.
Voyons maintenant les codes pour obtenir les données des capteurs. Nous allons commencer par l'accéléromètre et il y aura des explications avant chaque code, ainsi qu'une description supplémentaire dans les commentaires du code.
Nous devons d'abord inclure la bibliothèque de câbles Arduino et définir les adresses des registres du capteur. Dans la section de configuration, nous devons lancer la bibliothèque de fils et démarrer la communication série car nous utiliserons le moniteur série pour afficher les résultats. Ici aussi, nous devons activer le capteur ou activer la mesure en envoyant l'octet approprié au registre Power_CTL et voici comment nous procédons. En utilisant la fonction Wire.beginTransmission(), nous sélectionnons le capteur auquel nous allons parler, l'accéléromètre 3 axes dans ce cas. Ensuite, en utilisant la fonction Wire.write(), nous indiquons à quel registre interne nous allons parler. Après cela, nous enverrons l'octet approprié pour activer la mesure. En utilisant la fonction Wire.endTransmission(), nous mettrons fin à la transmission et cela transmettra les données aux registres.
Dans la section de boucle, nous devons lire les données pour chaque axe. Nous allons commencer par l'axe X. Nous allons donc d'abord sélectionner les registres auxquels nous allons parler, les deux registres internes de l'axe X dans ce cas. Ensuite, en utilisant la fonction Wire.requestFrom(), nous demanderons les données transmises ou les deux octets des deux registres. Le Wire.available() La fonction renverra le nombre d'octets disponibles pour la récupération et si ce nombre correspond à nos octets demandés, dans notre cas 2 octets, en utilisant le Wire.read() fonction nous allons lire les octets des deux registres de l'axe X.
Les données de sortie des registres sont un complément à deux, avec X0 comme octet le moins significatif et X1 comme octet le plus significatif, nous devons donc convertir ces octets en valeurs flottantes de -1 à +1 en fonction de la direction de l'axe X relatif. à l'accélération terrestre ou à la gravité. Nous répéterons cette procédure pour les deux autres axes et à la fin nous imprimerons ces valeurs sur le moniteur série.
Pour obtenir les données du gyroscope, nous aurons un code similaire au précédent. Nous devons donc d'abord définir les adresses de registre et certaines variables pour les données. Dans la section de configuration, nous devons réveiller et mettre le capteur en mode normal à l'aide de CTRL_REG1 et également sélectionner la sensibilité du capteur. Pour cet exemple, je sélectionnerai le mode de sensibilité 2000dps.
Dans la section de boucle similaire à l'accéléromètre, nous lirons les données pour les axes X, Y et Z. Ensuite, les données brutes doivent être converties en valeurs d'angle. D'après la fiche technique du capteur, nous pouvons voir qu'au mode de sensibilité 2000dps correspond une unité de 70 mdps/chiffre. Cela signifie que nous devons multiplier les données de sortie brutes par 0,07 afin d'obtenir la vitesse angulaire en degrés par seconde. Ensuite, si vous multipliez la vitesse angulaire par le temps, cela nous donnera la valeur de l'angle. Nous devons donc calculer l'intervalle de temps de chaque section de boucle et nous pouvons le faire en utilisant la fonction millis() en haut et en bas de la section de boucle, et nous stockerons sa valeur dans cette variable "dt". Ainsi, pour chaque boucle exécutée, nous calculerons l'angle et l'ajouterons à la valeur finale de l'angle. Nous ferons de même pour les deux autres axes et à la fin nous imprimerons les résultats dans le moniteur série.
Encore une fois, nous utiliserons une technique similaire à la précédente. Nous devons d'abord définir les adresses des registres et la section de configuration définit le capteur en mode de mesure continue. Dans la section boucle, nous obtiendrons les données brutes pour chaque axe avec la même méthode que pour les capteurs précédents.
Ensuite, nous devons convertir les données brutes en valeur de champ magnétique ou en unités Gauss. D'après la fiche technique du capteur, nous pouvons voir que le mode de sensibilité par défaut est de 0,92 mG/chiffre. Cela signifie que nous devons multiplier les données brutes par 0,00092 afin d'obtenir le champ magnétique terrestre en unités Gauss. À la fin, nous imprimerons les valeurs sur le moniteur série.
Voici une application sympa du capteur, une boussole numérique MEMS, réalisée à l'aide de l'IDE de traitement. Vous pouvez trouver plus de détails et le code source de cet exemple sur le lien suivant :Qu'est-ce que MEMS ?
Accéléromètre MEMS
Gyroscope MEMS
Magnétomètre MEMS
Les 10 % restants des capteurs sur le marché utilisent l'effet magnéto-résistif. Ces capteurs utilisent des matériaux sensibles au champ magnétique, généralement composés de Fer (Fe) et de Nickel (Ne). Ainsi, lorsque ces matériaux sont exposés à un champ magnétique, leur résistance change.Capteurs Arduino et MEMs
Code source
Code de l'accéléromètre Arduino
#include <Wire.h>
//--- Accelerometer Register Addresses
#define Power_Register 0x2D
#define X_Axis_Register_DATAX0 0x32 // Hexadecima address for the DATAX0 internal register.
#define X_Axis_Register_DATAX1 0x33 // Hexadecima address for the DATAX1 internal register.
#define Y_Axis_Register_DATAY0 0x34
#define Y_Axis_Register_DATAY1 0x35
#define Z_Axis_Register_DATAZ0 0x36
#define Z_Axis_Register_DATAZ1 0x37
int ADXAddress = 0x53; //Device address in which is also included the 8th bit for selecting the mode, read in this case.
int X0,X1,X_out;
int Y0,Y1,Y_out;
int Z1,Z0,Z_out;
float Xa,Ya,Za;
void setup() {
Wire.begin(); // Initiate the Wire library
Serial.begin(9600);
delay(100);
Wire.beginTransmission(ADXAddress);
Wire.write(Power_Register); // Power_CTL Register
// Enable measurement
Wire.write(8); // Bit D3 High for measuring enable (0000 1000)
Wire.endTransmission();
}
void loop() {
// X-axis
Wire.beginTransmission(ADXAddress); // Begin transmission to the Sensor
//Ask the particular registers for data
Wire.write(X_Axis_Register_DATAX0);
Wire.write(X_Axis_Register_DATAX1);
Wire.endTransmission(); // Ends the transmission and transmits the data from the two registers
Wire.requestFrom(ADXAddress,2); // Request the transmitted two bytes from the two registers
if(Wire.available()<=2) { //
X0 = Wire.read(); // Reads the data from the register
X1 = Wire.read();
/* Converting the raw data of the X-Axis into X-Axis Acceleration
- The output data is Two's complement
- X0 as the least significant byte
- X1 as the most significant byte */
X1=X1<<8;
X_out =X0+X1;
Xa=X_out/256.0; // Xa = output value from -1 to +1, Gravity acceleration acting on the X-Axis
}
// Y-Axis
Wire.beginTransmission(ADXAddress);
Wire.write(Y_Axis_Register_DATAY0);
Wire.write(Y_Axis_Register_DATAY1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress,2);
if(Wire.available()<=2) {
Y0 = Wire.read();
Y1 = Wire.read();
Y1=Y1<<8;
Y_out =Y0+Y1;
Ya=Y_out/256.0;
}
// Z-Axis
Wire.beginTransmission(ADXAddress);
Wire.write(Z_Axis_Register_DATAZ0);
Wire.write(Z_Axis_Register_DATAZ1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress,2);
if(Wire.available()<=2) {
Z0 = Wire.read();
Z1 = Wire.read();
Z1=Z1<<8;
Z_out =Z0+Z1;
Za=Z_out/256.0;
}
// Prints the data on the Serial Monitor
Serial.print("Xa= ");
Serial.print(Xa);
Serial.print(" Ya= ");
Serial.print(Ya);
Serial.print(" Za= ");
Serial.println(Za);
}
Code language: Arduino (arduino)Code du gyroscope Arduino
#include <Wire.h>
//--- Gyro Register Addresses
#define Gyro_gX0 0x28
#define Gyro_gX1 0x29
#define Gyro_gY0 0x2A
#define Gyro_gY1 0x2B
#define Gyro_gZ0 0x2C
#define Gyro_gZ1 0x2D
int Gyro = 0x69; //Device address in which is also included the 8th bit for selecting the mode, read in this case.
int gX0, gX1, gX_out;
int gY0, gY1, gY_out;
int gZ0, gZ1, gZ_out;
float Xg,Yg,Zg;
float angleX,angleY,angleZ,angleXc,angleYc,angleZc;
unsigned long start, finished, elapsed;
float dt=0.015;
void setup()
{
Wire.begin();
Serial.begin(9600);
delay(100);
Wire.beginTransmission(Gyro);
Wire.write(0x20); // CTRL_REG1 - Power Mode
Wire.write(15); // Normal mode: 15d - 00001111b
Wire.endTransmission();
Wire.beginTransmission(Gyro);
Wire.write(0x23); // CTRL_REG4 - Sensitivity, Scale Selection
Wire.write(48); // 2000dps: 48d - 00110000b
Wire.endTransmission();
}
void loop()
{
start=millis();
//---- X-Axis
Wire.beginTransmission(Gyro); // transmit to device
Wire.write(Gyro_gX0);
Wire.endTransmission();
Wire.requestFrom(Gyro,1);
if(Wire.available()<=1)
{
gX0 = Wire.read();
}
Wire.beginTransmission(Gyro); // transmit to device
Wire.write(Gyro_gX1);
Wire.endTransmission();
Wire.requestFrom(Gyro,1);
if(Wire.available()<=1)
{
gX1 = Wire.read();
}
//---- Y-Axis
Wire.beginTransmission(Gyro); // transmit to device
Wire.write(Gyro_gY0);
Wire.endTransmission();
Wire.requestFrom(Gyro,1);
if(Wire.available()<=1)
{
gY0 = Wire.read();
}
Wire.beginTransmission(Gyro); // transmit to device
Wire.write(Gyro_gY1);
Wire.endTransmission();
Wire.requestFrom(Gyro,1);
if(Wire.available()<=1)
{
gY1 = Wire.read();
}
//---- Z-Axis
Wire.beginTransmission(Gyro); // transmit to device
Wire.write(Gyro_gZ0);
Wire.endTransmission();
Wire.requestFrom(Gyro,1);
if(Wire.available()<=1)
{
gZ0 = Wire.read();
}
Wire.beginTransmission(Gyro); // transmit to device
Wire.write(Gyro_gZ1);
Wire.endTransmission();
Wire.requestFrom(Gyro,1);
if(Wire.available()<=1)
{
gZ1 = Wire.read();
}
//---------- X - Axis
// Raw Data
gX1=gX1<<8;
gX_out =gX0+gX1;
// From the datasheet: 70 mdps/digit
Xg=gX_out*0.07; // Angular rate
// Angular_rate * dt = angle
angleXc = Xg*dt;
angleX = angleX + angleXc;
//---------- Y - Axis
gY1=gY1<<8;
gY_out =gY0+gY1;
Yg=gY_out*0.07;
angleYc = Yg*dt;
angleY = angleY + angleYc;
//---------- Z - Axis
gZ1=gZ1<<8;
gZ_out =gZ0+gZ1;
Zg=gZ_out*0.07;
angleZc = Zg*dt;
angleZ = angleZ + angleZc;
// Prints the data on the Serial Monitor
Serial.print("angleX= ");
Serial.print(angleX);
Serial.print(" angleY= ");
Serial.print(angleY);
Serial.print(" angleZ= ");
Serial.println(angleZ);
delay(10);
// Calculating dt
finished=millis();
elapsed=finished-start;
dt=elapsed/1000.0;
start = elapsed = 0;
}
Code language: Arduino (arduino)Code du magnétomètre Arduino
#include <Wire.h> //I2C Arduino Library
#define Magnetometer_mX0 0x03
#define Magnetometer_mX1 0x04
#define Magnetometer_mZ0 0x05
#define Magnetometer_mZ1 0x06
#define Magnetometer_mY0 0x07
#define Magnetometer_mY1 0x08
int mX0, mX1, mX_out;
int mY0, mY1, mY_out;
int mZ0, mZ1, mZ_out;
float Xm,Ym,Zm;
#define Magnetometer 0x1E //I2C 7bit address of HMC5883
void setup(){
//Initialize Serial and I2C communications
Serial.begin(9600);
Wire.begin();
delay(100);
Wire.beginTransmission(Magnetometer);
Wire.write(0x02); // Select mode register
Wire.write(0x00); // Continuous measurement mode
Wire.endTransmission();
}
void loop(){
//---- X-Axis
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mX1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mX0 = Wire.read();
}
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mX0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mX1 = Wire.read();
}
//---- Y-Axis
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mY1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mY0 = Wire.read();
}
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mY0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mY1 = Wire.read();
}
//---- Z-Axis
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mZ1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mZ0 = Wire.read();
}
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mZ0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mZ1 = Wire.read();
}
//---- X-Axis
mX1=mX1<<8;
mX_out =mX0+mX1; // Raw data
// From the datasheet: 0.92 mG/digit
Xm = mX_out*0.00092; // Gauss unit
//* Earth magnetic field ranges from 0.25 to 0.65 Gauss, so these are the values that we need to get approximately.
//---- Y-Axis
mY1=mY1<<8;
mY_out =mY0+mY1;
Ym = mY_out*0.00092;
//---- Z-Axis
mZ1=mZ1<<8;
mZ_out =mZ0+mZ1;
Zm = mZ_out*0.00092;
//Print out values of each axis
Serial.print("x: ");
Serial.print(Xm);
Serial.print(" y: ");
Serial.print(Ym);
Serial.print(" z: ");
Serial.println(Zm);
delay(50);
}
Code language: Arduino (arduino)
Processus de fabrication
- Qu'est-ce qu'un magnétomètre ?
- Que dois-je faire avec les données ? !
- Jeu de gyroscope Arduino avec MPU-6050
- Gyroscope amusant avec l'anneau NeoPixel
- Surveillance du CO2 avec le capteur K30
- Communication sourds-aveugles avec 1Sheeld/Arduino
- Contrôler l'accepteur de pièces avec Arduino
- Arduino avec Bluetooth pour contrôler une LED !
- Capteur d'empreintes digitales capacitif avec un Arduino ou ESP8266