MEMS là các hệ thống hoặc thiết bị rất nhỏ, bao gồm các thành phần vi mô có kích thước từ 0,001 mm đến 0,1 mm. Những thành phần này được làm bằng silicon, polyme, kim loại và / hoặc gốm sứ, và chúng thường được kết hợp với một CPU (Vi điều khiển) để hoàn thành hệ thống. Bây giờ chúng tôi sẽ giải thích ngắn gọn về cách mà mỗi bộ cảm biến Micro-Electro-Mechanical-Systems (MEMS) hoạt động.
MEMS Accelerometer
Nó đo gia tốc bằng cách đo thay đổi về điện dung. Cấu trúc vi mô của nó trông giống như thế này. Nó có khối lượng gắn liền với một lò xo bị giới hạn để di chuyển theo một hướng và các tấm ngoài cố định. Vì vậy, khi một gia tốc theo hướng cụ thể sẽ được áp dụng khối lượng sẽ di chuyển và điện dung giữa các tấm và khối lượng sẽ thay đổi. Sự thay đổi về điện dung này sẽ được đo, xử lý và nó sẽ tương ứng với một giá trị gia tốc cụ thể.
MEMS Gyroscope
Con quay hồi chuyển đo tốc độ góc bằng cách sử dụng hiệu ứng Coriolis. Khi khối lượng di chuyển theo một hướng cụ thể với vận tốc cụ thể và khi tỷ lệ góc ngoài sẽ được áp dụng như hiển thị với mũi tên màu xanh, lực sẽ xuất hiện, như hiển thị với mũi tên màu xanh lam, sẽ làm chuyển vị vuông góc của khối lượng. Vì vậy, tương tự như gia tốc, chuyển dịch này sẽ gây ra thay đổi trong điện dung sẽ được đo, xử lý và nó sẽ tương ứng với một tỷ lệ góc cụ thể.
Cấu trúc vi mô của con quay hồi chuyển trông giống như thế này. Một khối lượng liên tục di chuyển, hoặc dao động, và khi tỷ lệ góc bên ngoài sẽ được áp dụng một phần linh hoạt của khối lượng sẽ di chuyển và làm cho chuyển vị vuông góc.
MEMS từ kế
Nó đo từ trường trái đất bằng cách sử dụng Hall Effect hoặc Magneto Resistive Effect. Trên thực tế gần 90% các cảm biến trên thị trường sử dụng hiệu ứng Hall và đây là cách nó hoạt động.
Nếu chúng ta có một tấm dẫn điện như được hiển thị trong ảnh và chúng ta đặt dòng điện chạy qua nó, các electron sẽ chảy thẳng từ một đến phía bên kia của tấm. Bây giờ nếu chúng ta mang một số từ trường gần tấm, chúng ta sẽ làm xáo trộn dòng chảy thẳng và các electron sẽ lệch sang một bên của tấm và các cực dương ở phía bên kia của tấm. Điều đó có nghĩa là nếu chúng ta đặt một đồng hồ giờ đây giữa hai bên, chúng ta sẽ nhận được một số điện áp phụ thuộc vào cường độ từ trường và hướng của nó.
10% cảm biến khác trên thị trường sử dụng hiệu ứng Magneto-resistive. Các cảm biến này sử dụng các vật liệu nhạy cảm với từ trường, thường bao gồm Sắt (Fe) và Nickel (Ne). Vì vậy, khi những vật liệu này được tiếp xúc với từ trường, chúng sẽ thay đổi sức đề kháng của chúng.
Arduino
Bây giờ chúng ta hãy kết nối các cảm biến này với Arduino Board và sử dụng chúng. Ví dụ, tôi sẽ sử dụng bảng đột phá GY-80 có các cảm biến sau: ADXL345 Máy gia tốc 3 trục, L3G4200D Con quay hồi chuyển 3 trục, MC5883L 3 Từ kế trục và đồng hồ áp kế và Nhiệt kế mà chúng tôi sẽ không sử dụng trong hướng dẫn này.
Bạn có thể lấy các thành phần này từ bất kỳ trang nào dưới đây:
- Máy gia tốc 3 trục ADXL345 ……………………………………………………… Amazon / Banggood
- 2 trong 1: Con quay hồi chuyển 6 trục MPU6050 và gia tốc kế ………………… Amazon / Banggood
- 3 trong 1: Gy-80 Con quay hồi chuyển tốc độ từ trường 9 trục ……… Amazon
- 3 trong 1: GY-86 10DOF MS5611 HMC5883L Mô-đun MPU6050 ……… Banggood
* Xin lưu ý: Đây là những liên kết liên kết. Tôi có thể thực hiện một khoản hoa hồng nếu bạn mua các thành phần thông qua các liên kết này.
Tôi sẽ đánh giá cao sự hỗ trợ của bạn theo cách này!
Tôi sẽ đánh giá cao sự hỗ trợ của bạn theo cách này!
Bảng này sử dụng giao thức truyền thông I2C có nghĩa là chúng ta có thể sử dụng tất cả các cảm biến chỉ với hai dây. Vì vậy, để thực hiện giao tiếp giữa Arduino và các cảm biến, chúng ta cần phải biết địa chỉ thiết bị duy nhất của chúng và địa chỉ đăng ký nội bộ của chúng để lấy dữ liệu ra khỏi chúng. Các địa chỉ này có thể được tìm thấy từ các biểu dữ liệu của các cảm biến:
Để biết thêm chi tiết về cách thức hoạt động của giao tiếp I2C, bạn có thể kiểm tra Hướng dẫn giao thức truyền thông I2C khác của tôi .
Mã nguồn
Bây giờ chúng ta hãy xem các mã để lấy dữ liệu từ các cảm biến. Chúng tôi sẽ bắt đầu với gia tốc kế và sẽ có một số giải thích trước mỗi mã, cũng như một số mô tả bổ sung trong các ý kiến của mã.
Mã gia tốc Arduino
Đầu tiên chúng ta cần phải bao gồm Thư viện dây Arduino và xác định địa chỉ đăng ký của cảm biến. Trong phần thiết lập, chúng ta cần khởi tạo Thư viện dây và bắt đầu truyền thông nối tiếp vì chúng ta sẽ sử dụng màn hình nối tiếp để hiển thị kết quả. Ngoài ra ở đây chúng ta cần phải kích hoạt cảm biến, hoặc kích hoạt phép đo bằng cách gửi byte thích hợp đến thanh ghi Power_CTL và đây là cách chúng ta làm điều đó. Sử dụng hàm Wire.beginTransmission (), chúng tôi chọn cảm biến mà chúng ta sẽ nói, Bộ gia tốc kế 3 trục trong trường hợp này. Sau đó, sử dụng hàm Wire.write (), chúng ta sẽ nói với thanh ghi bên trong nào chúng ta sẽ nói. Sau đó, chúng ta sẽ gửi byte thích hợp để kích hoạt phép đo. Sử dụng hàm Wire.endTransmission (), chúng ta sẽ kết thúc quá trình truyền và sẽ truyền dữ liệu đến thanh ghi.
Trong phần vòng lặp, chúng ta cần đọc dữ liệu cho mỗi trục. Chúng ta sẽ bắt đầu với X-Axis. Đầu tiên, chúng ta sẽ chọn các sổ đăng ký mà chúng ta sẽ nói, hai thanh ghi bên trong X-Axis trong trường hợp này. Sau đó, sử dụng hàm Wire.requestFrom (), chúng tôi sẽ yêu cầu dữ liệu được truyền hoặc hai byte từ hai thanh ghi. Hàm Wire.available () sẽ trả về số byte có sẵn để truy xuất và nếu số đó khớp với byte yêu cầu của chúng tôi, trong trường hợp của chúng tôi là 2 byte, sử dụng hàm Wire.read (), chúng ta sẽ đọc các byte từ hai thanh ghi trục X.
Dữ liệu đầu ra từ thanh ghi là bổ sung của hai, với X0 là byte quan trọng nhất và X1 là byte quan trọng nhất, do đó chúng ta cần chuyển đổi các byte này thành các giá trị float từ -1 đến +1 phụ thuộc vào hướng của trục tương đối X để tăng tốc Trái đất hoặc lực hấp dẫn. Chúng ta sẽ lặp lại quy trình này cho hai trục kia và cuối cùng chúng ta sẽ in các giá trị này trên màn hình nối tiếp.
- #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);
- }
Mã con quay hồi chuyển Arduino
Để lấy dữ liệu từ con quay hồi chuyển, chúng ta sẽ có một mã tương tự như mã trước đó. Vì vậy, trước tiên chúng ta phải xác định địa chỉ đăng ký và một số biến cho dữ liệu. Trong phần thiết lập, chúng ta phải thức dậy và đặt cảm biến ở chế độ bình thường bằng cách sử dụng CTRL_REG1 và cũng chọn độ nhạy của cảm biến. Trong ví dụ này, tôi sẽ chọn chế độ độ nhạy 2000dps.
Trong phần vòng lặp tương tự như gia tốc kế, chúng ta sẽ đọc dữ liệu cho trục X, Y và Z. Sau đó, dữ liệu thô phải được chuyển đổi thành các giá trị góc. Từ biểu dữ liệu của cảm biến, chúng ta có thể thấy rằng đối với chế độ độ nhạy 2000dps tương ứng với đơn vị 70 mdps / chữ số. Điều này có nghĩa rằng chúng ta phải nhân dữ liệu đầu ra thô với 0,07 để có được tốc độ góc theo độ / giây. Sau đó, nếu nhân tỷ lệ góc theo thời gian, nó sẽ cho chúng ta giá trị góc. Vì vậy, chúng ta cần tính toán khoảng thời gian của mỗi phần vòng lặp và chúng ta có thể làm điều đó bằng cách sử dụng hàm millis () ở trên cùng và dưới cùng của phần vòng lặp, và chúng ta sẽ lưu giá trị của nó vào biến "dt" này. Vì vậy, đối với mỗi vòng lặp thực hiện, chúng tôi sẽ tính toán góc và thêm nó vào giá trị góc cuối cùng.
- #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;
- }
Arduino từ kế mã
Một lần nữa chúng ta sẽ sử dụng một kỹ thuật tương tự với kỹ thuật trước đó. Đầu tiên chúng ta cần phải xác định địa chỉ đăng ký và phần thiết lập thiết lập cảm biến ở chế độ đo liên tục. Trong phần vòng lặp, chúng tôi sẽ lấy dữ liệu thô cho mỗi trục với cùng phương pháp như đối với các cảm biến trước đó.
Sau đó chúng ta cần chuyển đổi dữ liệu thô thành giá trị từ trường hoặc đơn vị Gauss. Từ biểu dữ liệu của cảm biến, chúng ta có thể thấy rằng chế độ nhạy mặc định là 0,92mG / chữ số. Điều đó có nghĩa là chúng ta cần phải nhân dữ liệu thô với 0,00092 để có được từ trường trái đất trong các đơn vị Gauss. Cuối cùng, chúng ta sẽ in các giá trị trên màn hình nối tiếp.
- #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);
- }
Không có nhận xét nào:
Đăng nhận xét