Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

Wat is MEMS? Versnellingsmeter, gyroscoop en magnetometer met Arduino

In deze tutorial leren we hoe de MEMS-versnellingsmeter, gyroscoop en magnetometer werken en hoe ze te gebruiken met het Arduino-bord. Ook met de Processing IDE gaan we wat praktische toepassingen maken met de sensoren. Je kunt de volgende video bekijken of de schriftelijke tutorial hieronder lezen.

Wat is MEMS?

De MEMS zijn zeer kleine systemen of apparaten, samengesteld uit microcomponenten met een grootte van 0,001 mm tot 0,1 mm. Deze componenten zijn gemaakt van silicium, polymeren, metalen en/of keramiek en worden meestal gecombineerd met een CPU (Microcontroller) om het systeem te completeren.

Nu zullen we kort uitleggen hoe elk van deze Micro-Electro-Mechanical-Systems (MEMS) sensoren werken.

MEMS-versnellingsmeter

Het meet versnelling door verandering in capaciteit te meten. De microstructuur ziet er ongeveer zo uit. Het heeft een massa die is bevestigd aan een veer die beperkt is om in één richting te bewegen en vaste buitenplaten. Dus wanneer een versnelling in de bepaalde richting wordt toegepast, zal de massa bewegen en zal de capaciteit tussen de platen en de massa veranderen. Deze verandering in capaciteit wordt gemeten, verwerkt en komt overeen met een bepaalde versnellingswaarde.

MEMS-gyroscoop

De gyroscoop meet de hoeksnelheid met behulp van het Coriolis-effect. Wanneer een massa met een bepaalde snelheid in een bepaalde richting beweegt en wanneer een externe hoeksnelheid wordt toegepast zoals weergegeven met de groene pijl, zal er een kracht optreden, zoals weergegeven met de blauwe rode pijl, die een loodrechte verplaatsing van de massa zal veroorzaken. Dus vergelijkbaar met de versnellingsmeter, zal deze verplaatsing een verandering in capaciteit veroorzaken die zal worden gemeten, verwerkt en zal overeenkomen met een bepaalde hoeksnelheid.

De microstructuur van de gyroscoop ziet er ongeveer zo uit. Een massa die constant in beweging is of oscilleert, en wanneer de externe hoeksnelheid wordt toegepast, zou een flexibel deel van de massa bewegen en de loodrechte verplaatsing maken.

MEMS-magnetometer

Het meet het aardmagnetisch veld met behulp van Hall-effect of magneto-resistief effect. Eigenlijk gebruikt bijna 90% van de sensoren op de markt het Hall-effect en hier is hoe het werkt.

Als we een geleidende plaat hebben zoals op de foto en we zetten er stroom doorheen, dan zouden de elektronen rechtstreeks van de ene naar de andere kant van de plaat stromen. Als we nu een magnetisch veld in de buurt van de plaat brengen, zouden we de rechte stroom verstoren en zouden de elektronen naar de ene kant van de plaat afbuigen en de positieve polen naar de andere kant van de plaat. Dat betekent dat als we nu een meter tussen deze twee zijden plaatsen, we een spanning krijgen die afhangt van de magnetische veldsterkte en de richting ervan.


De overige 10% van de sensoren op de markt gebruiken het magneto-resistieve effect. Deze sensoren gebruiken materialen die gevoelig zijn voor het magnetische veld, meestal samengesteld uit ijzer (Fe) en nikkel (Ne). Dus wanneer deze materialen worden blootgesteld aan een magnetisch veld, veranderen ze hun weerstand.

Arduino- en MEMs-sensoren


Oké, laten we nu deze sensoren op het Arduino-bord aansluiten en er gebruik van maken. Als voorbeeld zal ik het GY-80 breakout-bord gebruiken dat de volgende sensoren heeft:ADXL345 3-assige versnellingsmeter, L3G4200D 3-assige gyroscoop, MC5883L 3-assige magnetometer en ook een barometer en een thermometer die we in deze tutorial niet zullen gebruiken.

U kunt deze componenten op een van de onderstaande sites krijgen:

  • ADXL345 3-assige versneller…………………………………………………………
  • 2 in 1:MPU6050 6-assige gyroscoop en versnellingsmeter …………………
  • 3 in 1:GY-80 9-assige magnetische veldversnellingsgyroscoop……… Amazon 
  • 3 in 1: GY-86 10DOF MS5611 HMC5883L MPU6050-module……… Banggood  / AliExpress

Dit bord maakt gebruik van het I2C-communicatieprotocol, wat betekent dat we alle sensoren kunnen gebruiken met slechts twee draden. Dus om de communicatie tussen de Arduino en de sensoren tot stand te brengen, moeten we hun unieke apparaatadressen en hun interne registeradressen kennen om de gegevens eruit te halen. Deze adressen zijn te vinden in de datasheets van de sensoren:

  • ADXL345  Versnellingsmeter         Gegevensblad
  • L3G4200D  Gyroscoop              Gegevensblad
  • MC5883L  Magnetometer        Gegevensblad

Voor meer informatie over hoe de I2C-communicatie werkt, kun je mijn andere I2C-communicatieprotocolzelfstudie raadplegen.

Broncode

Laten we nu eens kijken naar de codes om de gegevens van de sensoren te krijgen. We beginnen met de versnellingsmeter en er zal wat uitleg voor elke code zijn, evenals een aanvullende beschrijving in de opmerkingen van de code.

Arduino-versnellingsmetercode

Eerst moeten we de Arduino Wire Library toevoegen en de registeradressen van de sensor definiëren. In het setup-gedeelte moeten we de draadbibliotheek starten en de seriële communicatie starten, aangezien we de seriële monitor zullen gebruiken om de resultaten te tonen. Ook hier moeten we de sensor activeren of de meting inschakelen door de juiste byte naar het Power_CTL-register te sturen en zo doen we dat. Met behulp van de functie Wire.beginTransmission() selecteren we met welke sensor we willen praten, in dit geval de 3-Axis Accelerometer. Vervolgens vertellen we met behulp van de functie Wire.write() met welk intern register we zullen praten. Hierna sturen we de juiste byte om de meting mogelijk te maken. Met behulp van de functie Wire.endTransmission() beëindigen we de verzending en worden de gegevens naar de registers verzonden.

In de lussectie moeten we de gegevens voor elke as lezen. We beginnen met de X-as. Dus eerst zullen we selecteren met welke registers we zullen praten, in dit geval de twee X - Axis interne registers. Vervolgens zullen we met behulp van de functie Wire.requestFrom() de verzonden gegevens of de twee bytes van de twee registers opvragen. De Wire.available() functie retourneert het aantal bytes dat beschikbaar is voor ophalen en als dat aantal overeenkomt met de door ons gevraagde bytes, in ons geval 2 bytes, met behulp van de Wire.read() functie lezen we de bytes uit de twee registers van de X-as.

De uitvoergegevens van de registers zijn het complement van twee, met X0 als de minst significante byte en X1 als de meest significante byte, dus we moeten deze bytes converteren naar zwevende waarden van -1 tot +1, afhankelijk van de richting van de X - As relatief aan de versnelling van de aarde of de zwaartekracht. We zullen deze procedure herhalen voor de twee andere assen en aan het einde zullen we deze waarden op de seriële monitor afdrukken.

#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)

Arduino gyroscoopcode

Om de gegevens van de gyroscoop te krijgen, hebben we een vergelijkbare code als de vorige. Dus eerst moeten we de registeradressen en enkele variabelen voor de gegevens definiëren. In het setup-gedeelte moeten we wakker worden en de sensor in de normale modus zetten met behulp van de CTRL_REG1 en ook de gevoeligheid van de sensor selecteren. Voor dit voorbeeld zal ik de 2000dps gevoeligheidsmodus selecteren.

In de lussectie vergelijkbaar met de versnellingsmeter zullen we de gegevens voor de X-, Y- en Z-as lezen. Vervolgens moeten de ruwe gegevens worden omgezet in hoekwaarden. Uit de datasheet van de sensor kunnen we zien dat voor de 2000dps gevoeligheidsmodus overeenkomt met een 70 mdps/digit-eenheid. Dit betekent dat we de onbewerkte uitvoergegevens met 0,07 moeten vermenigvuldigen om de hoeksnelheid in graden per seconde te krijgen. Als u vervolgens de hoeksnelheid vermenigvuldigt met de tijd, krijgt u de hoekwaarde. We moeten dus het tijdsinterval van elke lussectie berekenen en dat kunnen we doen door de millis()-functie boven en onder aan de lussectie te gebruiken, en we zullen de waarde ervan opslaan in deze "dt" -variabele. Dus voor elke uitgevoerde lus zullen we de hoek berekenen en optellen bij de uiteindelijke hoekwaarde. We zullen hetzelfde doen voor de twee andere assen en aan het einde zullen we de resultaten afdrukken in de seriële monitor.

#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)

Arduino-magnetometercode

We zullen opnieuw een vergelijkbare techniek gebruiken als de vorige. Eerst moeten we de registeradressen definiëren en het setup-gedeelte zet de sensor in continue meetmodus. In het lusgedeelte krijgen we de onbewerkte gegevens voor elke as met dezelfde methode als voor de vorige sensoren.

Vervolgens moeten we de onbewerkte gegevens omzetten in magnetische veldwaarden of Gauss-eenheden. Uit de datasheet van de sensor kunnen we zien dat de standaard gevoeligheidsmodus 0,92mG/digit is. Dat betekent dat we de onbewerkte gegevens met 0,00092 moeten vermenigvuldigen om het aardmagnetisch veld in Gauss-eenheden te krijgen. Aan het einde zullen we de waarden op de seriële monitor afdrukken.

#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)

Hier is een cool uitziende toepassing van de sensor, een MEMS digitaal kompas, gemaakt met behulp van de Processing IDE. U kunt meer details en de broncode van dit voorbeeld vinden op de volgende link:


Productieproces

  1. Wat is een magnetometer?
  2. Wat moet ik doen met de gegevens?!
  3. Arduino-gyroscoopspel met MPU-6050
  4. Gyroscoopplezier met NeoPixel Ring
  5. CO2-monitoring met K30-sensor
  6. Doofblinde communicatie met 1Sheeld/Arduino
  7. Bedien muntvangers met Arduino
  8. Arduino met Bluetooth om een ​​LED te bedienen!
  9. Capacitieve vingerafdruksensor met een Arduino of ESP8266
  10. Spelen met Nextion Display
  11. Nunchuk-gestuurde robotarm (met Arduino)