산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

MEMS란 무엇입니까? Arduino를 사용한 가속도계, 자이로스코프 및 자력계

<메인 클래스="사이트 메인" id="메인">

이 가이드에서는 MEMS 가속도계, 자이로스코프 및 자력계가 작동하는 방식과 Arduino 보드와 함께 사용하는 방법을 배웁니다. 또한 Processing IDE와 함께 센서를 사용하여 몇 가지 실용적인 응용 프로그램을 만들 것입니다. 다음 비디오를 보거나 아래에 작성된 튜토리얼을 읽을 수 있습니다.

MEMS란 무엇입니까?

MEMS는 0.001mm에서 0.1mm 크기 범위의 마이크로 구성 요소로 구성된 매우 작은 시스템 또는 장치입니다. 이러한 구성 요소는 실리콘, 폴리머, 금속 및/또는 세라믹으로 만들어지며 일반적으로 시스템을 완성하기 위해 CPU(마이크로 컨트롤러)와 결합됩니다.

이제 이러한 각 MEMS(Micro-Electro-Mechanical-Systems) 센서가 어떻게 작동하는지 간략하게 설명하겠습니다.

MEMS 가속도계

정전용량의 변화를 측정하여 가속도를 측정합니다. 그 미세 구조는 다음과 같습니다. 그것은 한 방향으로 움직이도록 제한된 스프링과 고정된 외부 플레이트에 부착된 덩어리를 가지고 있습니다. 따라서 특정 방향의 가속이 적용될 때 질량이 이동하고 플레이트와 질량 사이의 정전 용량이 변경됩니다. 커패시턴스의 이러한 변화는 측정되고 처리되며 특정 가속 값에 해당합니다.

MEMS 자이로스코프

자이로스코프는 코리올리 효과를 사용하여 각속도를 측정합니다. 질량이 특정 속도로 특정 방향으로 이동하고 녹색 화살표로 표시된 것처럼 외부 각속도가 적용될 때 파란색 빨간색 화살표로 표시된 것처럼 힘이 발생하여 질량의 수직 변위를 유발합니다. 가속도계와 유사하게 이 변위는 측정되고 처리될 정전용량의 변화를 야기하며 특정 각속도에 해당합니다.

<그림 클래스="aligncenter">

자이로스코프의 미세 구조는 다음과 같습니다. 지속적으로 움직이거나 진동하는 질량, 외부 각속도가 적용될 때 질량의 유연한 부분이 이동하여 수직 변위를 만듭니다.

MEMS 자력계

홀 효과 또는 자기 저항 효과를 사용하여 지구 자기장을 측정합니다. 실제로 시중에 나와 있는 센서의 거의 90%가 홀 효과를 사용하며 작동 방식은 다음과 같습니다.

<그림 클래스="aligncenter">

사진에 표시된 것과 같은 전도성 플레이트가 있고 이를 통해 전류가 흐르도록 설정하면 전자가 플레이트의 한쪽에서 다른 쪽으로 직선으로 흐를 것입니다. 이제 우리가 판 근처에 자기장을 가져오면 직선 흐름을 방해하고 전자는 판의 한쪽으로 편향되고 양극은 판의 다른 쪽으로 편향됩니다. 즉, 이제 이 두 측면 사이에 미터를 놓으면 자기장 강도와 방향에 따라 달라지는 전압이 발생합니다.


시장에 나와 있는 다른 10%의 센서는 자기 저항 효과를 사용합니다. 이 센서는 일반적으로 철(Fe)과 니켈(Ne)로 구성된 자기장에 민감한 재료를 사용합니다. 따라서 이러한 재료가 자기장에 노출되면 저항이 변경됩니다.

Arduino 및 MEMs 센서


자, 이제 이 센서를 Arduino 보드에 연결하고 사용해 보겠습니다. 예를 들어 ADXL345 3축 가속도계, L3G4200D 3축 자이로스코프, MC5883L 3축 자력계 및 이 자습서에서 사용하지 않을 기압계 및 온도계와 같은 센서가 있는 GY-80 브레이크아웃 보드를 사용합니다.

다음 사이트에서 이러한 구성요소를 얻을 수 있습니다.

이 보드는 I2C 통신 프로토콜을 사용하므로 단 2개의 와이어로 모든 센서를 사용할 수 있습니다. 따라서 Arduino와 센서 간의 통신을 위해서는 고유한 장치 주소와 데이터를 가져오기 위한 내부 레지스터 주소를 알아야 합니다. 이 주소는 센서의 데이터시트에서 찾을 수 있습니다.

I2C 통신 작동 방식에 대한 자세한 내용은 제 다른 I2C 통신 프로토콜 튜토리얼을 참조하세요.

소스 코드

이제 센서에서 데이터를 가져오는 코드를 살펴보겠습니다. 가속도계부터 시작하여 각 코드 앞에 몇 가지 설명이 있을 뿐만 아니라 코드 주석에 몇 가지 추가 설명이 있습니다.

Arduino 가속도계 코드

먼저 Arduino Wire Library를 포함하고 센서의 레지스터 주소를 정의해야 합니다. 설정 섹션에서 와이어 라이브러리를 시작하고 결과를 표시하기 위해 직렬 모니터를 사용할 것이기 때문에 직렬 통신을 시작해야 합니다. 또한 여기에서 센서를 활성화하거나 적절한 바이트를 Power_CTL 레지스터에 전송하여 측정을 활성화해야 합니다. 이를 수행하는 방법은 다음과 같습니다. Wire.beginTransmission() 함수를 사용하여 대화할 센서(이 경우 3축 가속도계)를 선택합니다. 그런 다음 Wire.write() 함수를 사용하여 우리가 이야기할 내부 레지스터를 알려줍니다. 그런 다음 측정을 활성화하기 위해 적절한 바이트를 보냅니다. Wire.endTransmission() 함수를 사용하여 전송을 종료하고 데이터를 레지스터로 전송합니다.

루프 섹션에서 각 축에 대한 데이터를 읽어야 합니다. X축부터 시작하겠습니다. 따라서 먼저 대화할 레지스터, 이 경우 두 개의 X 축 내부 레지스터를 선택합니다. 그런 다음 Wire.requestFrom() 함수를 사용하여 전송된 데이터 또는 두 레지스터에서 2바이트를 요청합니다. Wire.available() 함수는 검색에 사용할 수 있는 바이트 수를 반환하고 해당 수가 요청된 바이트와 일치하는 경우 Wire.read()를 사용하여 이 경우에는 2바이트입니다. 함수는 X축의 두 레지스터에서 바이트를 읽습니다.

레지스터의 출력 데이터는 2의 보수이며 X0은 최하위 바이트이고 X1은 최상위 바이트이므로 X축 상대 방향에 따라 이 바이트를 -1에서 +1까지의 부동 소수점 값으로 변환해야 합니다. 지구 가속도 또는 중력. 다른 두 축에 대해 이 절차를 반복하고 마지막에 이 값을 직렬 모니터에 인쇄합니다.

#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을 사용하여 센서를 정상 모드로 전환하고 센서의 감도를 선택해야 합니다. 이 예에서는 2000dps 감도 모드를 선택하겠습니다.

가속도계와 유사한 루프 섹션에서 X, Y 및 Z 축에 대한 데이터를 읽습니다. 그런 다음 원시 데이터를 각도 값으로 변환해야 합니다. 센서의 데이터시트에서 2000dps 감도 모드의 경우 70mdps/digit 단위에 해당함을 알 수 있습니다. 이것은 초당 각도 비율을 얻기 위해 원시 출력 데이터에 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.92mG/digit임을 알 수 있습니다. 즉, 가우스 단위로 지구 자기장을 얻으려면 원시 데이터에 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)

다음은 Processing IDE를 사용하여 만든 MEMS 디지털 나침반인 센서의 멋진 응용 프로그램입니다. 다음 링크에서 이 예시의 소스 코드와 자세한 내용을 확인할 수 있습니다.

<그림 클래스="wp-block-image">

제조공정

  1. 자력계란 무엇입니까?
  2. 데이터로 무엇을 해야 합니까?!
  3. MPU-6050을 사용한 Arduino 자이로스코프 게임
  4. NeoPixel Ring으로 재미있는 자이로스코프
  5. K30 센서로 CO2 모니터링
  6. 1Sheeld/Arduino를 사용한 청각 장애인용 통신
  7. Arduino로 코인 억셉터 제어
  8. Bluetooth가 탑재된 Arduino로 LED 제어!
  9. Arduino 또는 ESP8266이 있는 정전 용량 지문 센서
  10. Nextion 디스플레이로 재생