Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Что такое МЭМС? Акселерометр, гироскоп и магнитометр на Arduino

<основной класс="главный сайт" id="главный">

В этом руководстве мы узнаем, как работают акселерометр, гироскоп и магнитометр MEMS и как использовать их с платой Arduino. Также с помощью Processing IDE мы создадим несколько практических приложений с использованием датчиков. Вы можете посмотреть следующее видео или прочитать письменное руководство ниже.

Что такое МЭМС?

МЭМС — это очень маленькие системы или устройства, состоящие из микрокомпонентов размером от 0,001 мм до 0,1 мм. Эти компоненты изготовлены из кремния, полимеров, металлов и/или керамики и обычно объединяются с ЦП (микроконтроллером) для завершения системы.

Теперь мы кратко объясним, как работает каждый из этих датчиков микроэлектромеханических систем (МЭМС).

МЭМС-акселерометр

Он измеряет ускорение путем измерения изменения емкости. Его микроструктура выглядит примерно так. Он имеет массу, прикрепленную к пружине, которая может двигаться в одном направлении, и фиксированные внешние пластины. Таким образом, когда будет приложено ускорение в определенном направлении, масса будет двигаться, и емкость между пластинами и массой изменится. Это изменение емкости будет измерено, обработано и будет соответствовать определенному значению ускорения.

МЭМС-гироскоп

Гироскоп измеряет угловую скорость с помощью эффекта Кориолиса. Когда масса движется в определенном направлении с определенной скоростью и при приложении внешней угловой скорости, как показано зеленой стрелкой, возникает сила, как показано сине-красной стрелкой, которая вызывает перпендикулярное смещение массы. Подобно акселерометру, это смещение вызовет изменение емкости, которое будет измерено, обработано и будет соответствовать определенной угловой скорости.

Микроструктура гироскопа выглядит примерно так. Масса, которая постоянно движется или колеблется, и когда будет применена внешняя угловая скорость, гибкая часть массы будет двигаться и совершать перпендикулярное смещение.

Магнитометр MEMS

Он измеряет магнитное поле Земли с помощью эффекта Холла или магниторезистивного эффекта. На самом деле почти 90% датчиков на рынке используют эффект Холла, и вот как это работает.

Если у нас есть проводящая пластина, как показано на фотографии, и мы запустим ток через нее, электроны будут течь прямо с одной стороны пластины на другую. Теперь, если мы поднесем некоторое магнитное поле к пластине, мы нарушим прямолинейный поток, и электроны отклонятся к одной стороне пластины, а положительные полюса — к другой стороне пластины. Это означает, что если мы сейчас поместим метр между этими двумя сторонами, мы получим некоторое напряжение, которое зависит от напряженности магнитного поля и его направления.


Остальные 10% датчиков на рынке используют магниторезистивный эффект. В этих датчиках используются материалы, чувствительные к магнитному полю, обычно состоящие из железа (Fe) и никеля (Ne). Поэтому, когда эти материалы подвергаются воздействию магнитного поля, они меняют свое сопротивление.

Датчики Arduino и MEMs


Хорошо, теперь давайте подключим эти датчики к плате Arduino и используем их. В качестве примера я буду использовать коммутационную плату GY-80 со следующими датчиками:3-осевой акселерометр ADXL345, 3-осевой гироскоп L3G4200D, 3-осевой магнитометр MC5883L, а также барометр и термометр, которые мы не будем использовать в этом руководстве.

Вы можете получить эти компоненты на любом из следующих сайтов:

Эта плата использует протокол связи I2C, что означает, что мы можем использовать все датчики всего с двумя проводами. Таким образом, чтобы установить связь между Arduino и датчиками, нам нужно знать их уникальные адреса устройств и адреса их внутренних регистров для получения от них данных. Эти адреса можно найти в даташитах датчиков:

Для получения более подробной информации о том, как работает связь I2C, вы можете ознакомиться с моим другим учебным пособием по протоколу связи I2C.

Исходный код

Теперь посмотрим коды для получения данных с датчиков. Мы начнем с акселерометра, перед каждым кодом будет пояснение, а также дополнительное описание в комментариях к коду.

Код акселерометра Arduino

Сначала нам нужно подключить Arduino Wire Library и определить адреса регистров датчика. В разделе настройки нам нужно инициировать Wire Library и запустить последовательную связь, так как мы будем использовать последовательный монитор для отображения результатов. Также здесь нам нужно активировать датчик или включить измерение, отправив соответствующий байт в регистр Power_CTL, и вот как мы это делаем. Используя функцию Wire.beginTransmission(), мы выбираем, с каким датчиком мы будем общаться, в данном случае с 3-осевым акселерометром. Затем с помощью функции Wire.write() мы сообщаем, к какому внутреннему регистру мы будем обращаться. После этого мы отправим соответствующий байт для включения измерения. Используя функцию Wire.endTransmission(), мы закончим передачу, и это передаст данные в регистры.

В секции цикла нам нужно прочитать данные для каждой оси. Мы начнем с оси X. Итак, сначала мы выберем, с какими регистрами мы будем разговаривать, в данном случае с двумя внутренними регистрами оси X. Затем с помощью функции Wire.requestFrom() мы будем запрашивать передаваемые данные или два байта из двух регистров. Провод.доступный() функция вернет количество байтов, доступных для извлечения, и, если это число совпадает с запрошенными байтами, в нашем случае 2 байта, используя Wire.read() функцией мы будем считывать байты из двух регистров оси X.

Выходные данные из регистров представляют собой дополнение до двух, где X0 – младший значащий байт, а X1 – старший значащий байт, поэтому нам нужно преобразовать эти байты в значения с плавающей запятой от -1 до +1 в зависимости от направления относительно оси X. к ускорению Земли или гравитации. Мы повторим эту процедуру для двух других осей и в конце выведем эти значения на серийный монитор.

#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

Для получения данных с гироскопа у нас будет код, аналогичный предыдущему. Итак, сначала мы должны определить адреса регистров и некоторые переменные для данных. В разделе настройки мы должны разбудить и перевести датчик в нормальный режим с помощью CTRL_REG1, а также выбрать чувствительность датчика. Для этого примера я выберу режим чувствительности 2000 кадров в секунду.

В секции цикла, похожей на акселерометр, мы будем считывать данные для осей X, Y и Z. Затем необработанные данные необходимо преобразовать в значения углов. Из таблицы данных датчика видно, что для режима чувствительности 2000dps соответствует единица измерения 70 mdps/разряд. Это означает, что мы должны умножить необработанные выходные данные на 0,07, чтобы получить угловую скорость в градусах в секунду. Затем, если умножить угловую скорость на время, это даст нам значение угла. Итак, нам нужно рассчитать временной интервал каждой секции цикла, и мы можем сделать это, используя функцию millis() в верхней и нижней части секции цикла, и мы сохраним ее значение в этой переменной «dt». Таким образом, для каждого выполненного цикла мы будем вычислять угол и добавлять его к конечному значению угла. Мы сделаем то же самое для двух других осей и в конце выведем результаты в серийный монитор.

#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

Снова воспользуемся техникой, аналогичной предыдущей. Сначала нам нужно определить адреса регистров, и в разделе настройки установить датчик в режим непрерывного измерения. В разделе цикла мы получим необработанные данные для каждой оси тем же методом, что и для предыдущих датчиков.

Затем нам нужно преобразовать необработанные данные в значение магнитного поля или единицы Гаусса. Из таблицы данных датчика видно, что режим чувствительности по умолчанию составляет 0,92 мГс/цифру. Это означает, что нам нужно умножить необработанные данные на 0,00092, чтобы получить магнитное поле Земли в единицах Гаусса. В конце мы выведем значения на серийный монитор.

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

Вот круто выглядящее приложение датчика, цифровой компас MEMS, сделанное с помощью Processing IDE. Вы можете найти более подробную информацию и исходный код этого примера по  следующей ссылке:


Производственный процесс

  1. Что такое магнитометр?
  2. Что мне делать с данными ?!
  3. Игра с гироскопом Arduino с MPU-6050
  4. Удовольствие от гироскопа с кольцом NeoPixel
  5. Мониторинг CO2 с помощью датчика K30
  6. Слепоглухое общение с 1Sheeld / Arduino
  7. Управление монетоприемником с помощью Arduino
  8. Arduino с Bluetooth для управления светодиодом!
  9. Емкостной датчик отпечатков пальцев с Arduino или ESP8266
  10. Игра с дисплеем Nextion