亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

Arduino 和 MPU6050 加速度计和陀螺仪教程

在本教程中,我们将学习如何将 MPU6050 加速度计和陀螺仪传感器与 Arduino 一起使用。首先,我将解释 MPU6050 的工作原理以及如何从中读取数据,然后我们将做两个实际示例。

您可以观看以下视频或阅读下面的书面教程。

概览

在第一个示例中,使用 Processing 开发环境,我们将对传感器方向进行 3D 可视化,在第二个示例中,我们将制作一个简单的自稳定平台或 DIY 云台。基于MPU6050的方位及其融合的加速度计和陀螺仪数据,我们控制三个舵机保持平台水平。

工作原理

MPU6050 IMU将3轴加速度计和3轴陀螺仪集成在一个芯片上。

陀螺仪沿 X、Y 和 Z 轴测量旋转速度或角位置随时间的变化率。它使用 MEMS 技术和科里奥利效应进行测量,但有关它的更多详细信息,您可以查看我的特定 MEMS 传感器如何工作教程。陀螺仪的输出是以度/秒为单位的,所以为了得到角位置,我们只需要对角速度进行积分。

另一方面,MPU6050 加速度计测量加速度的方式与之前视频中对 ADXL345 加速度计传感器的说明相同。简而言之,它可以测量沿 3 个轴的重力加速度,并使用一些三角数学,我们可以计算出传感器定位的角度。因此,如果我们融合或结合加速度计和陀螺仪数据,我们可以获得关于传感器方向的非常准确的信息。

MPU6050 IMU也被称为六轴运动跟踪设备或6 DoF(六自由度)设备,因为它有6个输出,或3个加速度计输出和3个陀螺仪输出。

Arduino 和 MPU6050

让我们看看如何使用 Arduino 连接和读取 MPU6050 传感器的数据。我们使用 I2C 协议与 Arduino 进行通信,因此我们只需要两根线来连接它,再加上两根用于供电的线。

您可以从以下链接获取本 Arduino 教程所需的组件:

  • MPU6050 IMU …………………………..……. 亚马逊棒棒哒 /速卖通
  • Arduino 开发板………………………….……..
  • 面包板和跳线………… 

MPU6050 Arduino代码

这是用于从 MPU6050 传感器读取数据的 Arduino 代码。在代码下方你可以找到它的详细描述。

/*
   Arduino and MPU6050 Accelerometer and Gyroscope Sensor Tutorial
   by Dejan, https://howtomechatronics.com
*/
#include <Wire.h>
const int MPU = 0x68; // MPU6050 I2C address
float AccX, AccY, AccZ;
float GyroX, GyroY, GyroZ;
float accAngleX, accAngleY, gyroAngleX, gyroAngleY, gyroAngleZ;
float roll, pitch, yaw;
float AccErrorX, AccErrorY, GyroErrorX, GyroErrorY, GyroErrorZ;
float elapsedTime, currentTime, previousTime;
int c = 0;
void setup() {
  Serial.begin(19200);
  Wire.begin();                      // Initialize comunication
  Wire.beginTransmission(MPU);       // Start communication with MPU6050 // MPU=0x68
  Wire.write(0x6B);                  // Talk to the register 6B
  Wire.write(0x00);                  // Make reset - place a 0 into the 6B register
  Wire.endTransmission(true);        //end the transmission
  /*
  // Configure Accelerometer Sensitivity - Full Scale Range (default +/- 2g)
  Wire.beginTransmission(MPU);
  Wire.write(0x1C);                  //Talk to the ACCEL_CONFIG register (1C hex)
  Wire.write(0x10);                  //Set the register bits as 00010000 (+/- 8g full scale range)
  Wire.endTransmission(true);
  // Configure Gyro Sensitivity - Full Scale Range (default +/- 250deg/s)
  Wire.beginTransmission(MPU);
  Wire.write(0x1B);                   // Talk to the GYRO_CONFIG register (1B hex)
  Wire.write(0x10);                   // Set the register bits as 00010000 (1000deg/s full scale)
  Wire.endTransmission(true);
  delay(20);
  */
  // Call this function if you need to get the IMU error values for your module
  calculate_IMU_error();
  delay(20);
}
void loop() {
  // === Read acceleromter data === //
  Wire.beginTransmission(MPU);
  Wire.write(0x3B); // Start with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
  //For a range of +-2g, we need to divide the raw values by 16384, according to the datasheet
  AccX = (Wire.read() << 8 | Wire.read()) / 16384.0; // X-axis value
  AccY = (Wire.read() << 8 | Wire.read()) / 16384.0; // Y-axis value
  AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0; // Z-axis value
  // Calculating Roll and Pitch from the accelerometer data
  accAngleX = (atan(AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI) - 0.58; // AccErrorX ~(0.58) See the calculate_IMU_error()custom function for more details
  accAngleY = (atan(-1 * AccX / sqrt(pow(AccY, 2) + pow(AccZ, 2))) * 180 / PI) + 1.58; // AccErrorY ~(-1.58)
  // === Read gyroscope data === //
  previousTime = currentTime;        // Previous time is stored before the actual time read
  currentTime = millis();            // Current time actual time read
  elapsedTime = (currentTime - previousTime) / 1000; // Divide by 1000 to get seconds
  Wire.beginTransmission(MPU);
  Wire.write(0x43); // Gyro data first register address 0x43
  Wire.endTransmission(false);
  Wire.requestFrom(MPU, 6, true); // Read 4 registers total, each axis value is stored in 2 registers
  GyroX = (Wire.read() << 8 | Wire.read()) / 131.0; // For a 250deg/s range we have to divide first the raw value by 131.0, according to the datasheet
  GyroY = (Wire.read() << 8 | Wire.read()) / 131.0;
  GyroZ = (Wire.read() << 8 | Wire.read()) / 131.0;
  // Correct the outputs with the calculated error values
  GyroX = GyroX + 0.56; // GyroErrorX ~(-0.56)
  GyroY = GyroY - 2; // GyroErrorY ~(2)
  GyroZ = GyroZ + 0.79; // GyroErrorZ ~ (-0.8)
  // Currently the raw values are in degrees per seconds, deg/s, so we need to multiply by sendonds (s) to get the angle in degrees
  gyroAngleX = gyroAngleX + GyroX * elapsedTime; // deg/s * s = deg
  gyroAngleY = gyroAngleY + GyroY * elapsedTime;
  yaw =  yaw + GyroZ * elapsedTime;
  // Complementary filter - combine acceleromter and gyro angle values
  roll = 0.96 * gyroAngleX + 0.04 * accAngleX;
  pitch = 0.96 * gyroAngleY + 0.04 * accAngleY;
  
  // Print the values on the serial monitor
  Serial.print(roll);
  Serial.print("/");
  Serial.print(pitch);
  Serial.print("/");
  Serial.println(yaw);
}
void calculate_IMU_error() {
  // We can call this funtion in the setup section to calculate the accelerometer and gyro data error. From here we will get the error values used in the above equations printed on the Serial Monitor.
  // Note that we should place the IMU flat in order to get the proper values, so that we then can the correct values
  // Read accelerometer values 200 times
  while (c < 200) {
    Wire.beginTransmission(MPU);
    Wire.write(0x3B);
    Wire.endTransmission(false);
    Wire.requestFrom(MPU, 6, true);
    AccX = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
    AccY = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
    AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
    // Sum all readings
    AccErrorX = AccErrorX + ((atan((AccY) / sqrt(pow((AccX), 2) + pow((AccZ), 2))) * 180 / PI));
    AccErrorY = AccErrorY + ((atan(-1 * (AccX) / sqrt(pow((AccY), 2) + pow((AccZ), 2))) * 180 / PI));
    c++;
  }
  //Divide the sum by 200 to get the error value
  AccErrorX = AccErrorX / 200;
  AccErrorY = AccErrorY / 200;
  c = 0;
  // Read gyro values 200 times
  while (c < 200) {
    Wire.beginTransmission(MPU);
    Wire.write(0x43);
    Wire.endTransmission(false);
    Wire.requestFrom(MPU, 6, true);
    GyroX = Wire.read() << 8 | Wire.read();
    GyroY = Wire.read() << 8 | Wire.read();
    GyroZ = Wire.read() << 8 | Wire.read();
    // Sum all readings
    GyroErrorX = GyroErrorX + (GyroX / 131.0);
    GyroErrorY = GyroErrorY + (GyroY / 131.0);
    GyroErrorZ = GyroErrorZ + (GyroZ / 131.0);
    c++;
  }
  //Divide the sum by 200 to get the error value
  GyroErrorX = GyroErrorX / 200;
  GyroErrorY = GyroErrorY / 200;
  GyroErrorZ = GyroErrorZ / 200;
  // Print the error values on the Serial Monitor
  Serial.print("AccErrorX: ");
  Serial.println(AccErrorX);
  Serial.print("AccErrorY: ");
  Serial.println(AccErrorY);
  Serial.print("GyroErrorX: ");
  Serial.println(GyroErrorX);
  Serial.print("GyroErrorY: ");
  Serial.println(GyroErrorY);
  Serial.print("GyroErrorZ: ");
  Serial.println(GyroErrorZ);
}Code language: Arduino (arduino)

代码说明: 所以首先我们需要包含用于 I2C 通信的 Wire.h 库,并定义一些存储数据所需的变量。

在设置部分,我们需要初始化线库并通过电源管理寄存器重置传感器。为此,我们需要查看传感器的数据表,从中可以看到寄存器地址。

此外,如果需要,我们可以使用它们的配置寄存器为加速度计和陀螺仪选择满量程范围。在本例中,我们将使用默认的 +- 2g 范围的加速度计和 250 度/s 的陀螺仪范围,因此我将保留这部分代码的注释。

// Configure Accelerometer Sensitivity - Full Scale Range (default +/- 2g)
  Wire.beginTransmission(MPU);
  Wire.write(0x1C);                  //Talk to the ACCEL_CONFIG register (1C hex)
  Wire.write(0x10);                  //Set the register bits as 00010000 (+/- 8g full scale range)
  Wire.endTransmission(true);
  // Configure Gyro Sensitivity - Full Scale Range (default +/- 250deg/s)
  Wire.beginTransmission(MPU);
  Wire.write(0x1B);                   // Talk to the GYRO_CONFIG register (1B hex)
  Wire.write(0x10);                   // Set the register bits as 00010000 (1000deg/s full scale)
  Wire.endTransmission(true);
  */Code language: Arduino (arduino)

在循环部分,我们首先读取加速度计数据。每个轴的数据存储在两个字节或寄存器中,我们可以从传感器的数据表中看到这些寄存器的地址。

为了全部读取它们,我们从第一个寄存器开始,并使用 requestFrom() 函数请求读取 X、Y 和 Z 轴的所有 6 个寄存器。然后我们从每个寄存器中读取数据,因为输出是二进制补码,所以我们适当地组合它们以获得正确的值。

// === Read acceleromter data === //
  Wire.beginTransmission(MPU);
  Wire.write(0x3B); // Start with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
  //For a range of +-2g, we need to divide the raw values by 16384, according to the datasheet
  AccX = (Wire.read() << 8 | Wire.read()) / 16384.0; // X-axis value
  AccY = (Wire.read() << 8 | Wire.read()) / 16384.0; // Y-axis value
  AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0; // Z-axis valueCode language: Arduino (arduino)

为了得到从-1g到+1g的输出值,适合计算角度,我们将输出除以之前选择的灵敏度。

最后,利用这两个公式,我们根据加速度计数据计算出横滚角和俯仰角。

// Calculating Roll and Pitch from the accelerometer data
  accAngleX = (atan(AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI) - 0.58; // AccErrorX ~(0.58) See the calculate_IMU_error()custom function for more details
  accAngleY = (atan(-1 * AccX / sqrt(pow(AccY, 2) + pow(AccZ, 2))) * 180 / PI) + 1.58; // AccErrorY ~(-1.58)Code language: Arduino (arduino)

接下来用同样的方法得到陀螺仪数据。

我们读取六个陀螺仪寄存器,将它们的数据适当组合,然后除以先前选择的灵敏度,以获得以度/秒为单位的输出。

// === Read gyroscope data === //
  previousTime = currentTime;        // Previous time is stored before the actual time read
  currentTime = millis();            // Current time actual time read
  elapsedTime = (currentTime - previousTime) / 1000; // Divide by 1000 to get seconds
  Wire.beginTransmission(MPU);
  Wire.write(0x43); // Gyro data first register address 0x43
  Wire.endTransmission(false);
  Wire.requestFrom(MPU, 6, true); // Read 4 registers total, each axis value is stored in 2 registers
  GyroX = (Wire.read() << 8 | Wire.read()) / 131.0; // For a 250deg/s range we have to divide first the raw value by 131.0, according to the datasheet
  GyroY = (Wire.read() << 8 | Wire.read()) / 131.0;
  GyroZ = (Wire.read() << 8 | Wire.read()) / 131.0;Code language: Arduino (arduino)

在这里你可以注意到我用一些小的计算误差值纠正了输出值,我将在一分钟内解释我们如何得到它们。因此,由于输出以每秒度数为单位,现在我们需要将它们与时间相乘以获得度数。使用millis()函数在每次读取迭代之前捕获时间值。

// Correct the outputs with the calculated error values
  GyroX = GyroX + 0.56; // GyroErrorX ~(-0.56)
  GyroY = GyroY - 2; // GyroErrorY ~(2)
  GyroZ = GyroZ + 0.79; // GyroErrorZ ~ (-0.8)
  // Currently the raw values are in degrees per seconds, deg/s, so we need to multiply by sendonds (s) to get the angle in degrees
  gyroAngleX = gyroAngleX + GyroX * elapsedTime; // deg/s * s = deg
  gyroAngleY = gyroAngleY + GyroY * elapsedTime;
  yaw =  yaw + GyroZ * elapsedTime;Code language: Arduino (arduino)

最后,我们使用互补滤波器融合加速度计和陀螺仪数据。在这里,我们采用了 96% 的陀螺仪数据,因为它非常准确并且不受外力的影响。陀螺仪的缺点是它会漂移,或者随着时间的推移在输出中引入误差。因此,从长远来看,我们使用加速度计的数据,在这种情况下为 4%,足以消除陀螺仪漂移误差。

// Complementary filter - combine acceleromter and gyro angle values
  roll = 0.96 * gyroAngleX + 0.04 * accAngleX;
  pitch = 0.96 * gyroAngleY + 0.04 * accAngleY;Code language: Arduino (arduino)

但是,由于我们无法从加速度计数据中计算出 Yaw,因此我们无法在其上实现互补滤波器。

在我们看结果之前,让我快速解释一下如何获得纠错值。为了计算这些误差,我们可以在传感器处于平坦静止位置时调用 calculate_IMU_error() 自定义函数。在这里,我们为所有输出读取 200 个读数,将它们相加并除以 200。由于我们将传感器保持在平坦静止位置,因此预期输出值应该为 0。因此,通过此计算,我们可以得到传感器的平均误差制作。

void calculate_IMU_error() {
  // We can call this funtion in the setup section to calculate the accelerometer and gyro data error. From here we will get the error values used in the above equations printed on the Serial Monitor.
  // Note that we should place the IMU flat in order to get the proper values, so that we then can the correct values
  // Read accelerometer values 200 times
  while (c < 200) {
    Wire.beginTransmission(MPU);
    Wire.write(0x3B);
    Wire.endTransmission(false);
    Wire.requestFrom(MPU, 6, true);
    AccX = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
    AccY = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
    AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
    // Sum all readings
    AccErrorX = AccErrorX + ((atan((AccY) / sqrt(pow((AccX), 2) + pow((AccZ), 2))) * 180 / PI));
    AccErrorY = AccErrorY + ((atan(-1 * (AccX) / sqrt(pow((AccY), 2) + pow((AccZ), 2))) * 180 / PI));
    c++;
  }
  //Divide the sum by 200 to get the error value
  AccErrorX = AccErrorX / 200;
  AccErrorY = AccErrorY / 200;
  c = 0;
  // Read gyro values 200 times
  while (c < 200) {
    Wire.beginTransmission(MPU);
    Wire.write(0x43);
    Wire.endTransmission(false);
    Wire.requestFrom(MPU, 6, true);
    GyroX = Wire.read() << 8 | Wire.read();
    GyroY = Wire.read() << 8 | Wire.read();
    GyroZ = Wire.read() << 8 | Wire.read();
    // Sum all readings
    GyroErrorX = GyroErrorX + (GyroX / 131.0);
    GyroErrorY = GyroErrorY + (GyroY / 131.0);
    GyroErrorZ = GyroErrorZ + (GyroZ / 131.0);
    c++;
  }
  //Divide the sum by 200 to get the error value
  GyroErrorX = GyroErrorX / 200;
  GyroErrorY = GyroErrorY / 200;
  GyroErrorZ = GyroErrorZ / 200;
  // Print the error values on the Serial Monitor
  Serial.print("AccErrorX: ");
  Serial.println(AccErrorX);
  Serial.print("AccErrorY: ");
  Serial.println(AccErrorY);
  Serial.print("GyroErrorX: ");
  Serial.println(GyroErrorX);
  Serial.print("GyroErrorY: ");
  Serial.println(GyroErrorY);
  Serial.print("GyroErrorZ: ");
  Serial.println(GyroErrorZ);
}Code language: Arduino (arduino)

我们只需在串行监视器上打印这些值,一旦我们知道它们,就可以在代码中实现它们,如前所示,用于滚动和俯仰计算,以及 3 个陀螺仪输出。

最后,使用 Serial.print 函数,我们可以在串口监视器上打印 Roll、Pitch 和 Yaw 值,看看传感器是否正常工作。

MPU6050 方向跟踪 - 3D 可视化

接下来,为了制作 3D 可视化示例,我们只需要在 Processing 开发环境中接受 Arduino 通过串口发送的数据。这是完整的处理代码:

/*
    Arduino and MPU6050 IMU - 3D Visualization Example 
     by Dejan, https://howtomechatronics.com
*/
import processing.serial.*;
import java.awt.event.KeyEvent;
import java.io.IOException;
Serial myPort;
String data="";
float roll, pitch,yaw;
void setup() {
  size (2560, 1440, P3D);
  myPort = new Serial(this, "COM7", 19200); // starts the serial communication
  myPort.bufferUntil('\n');
}
void draw() {
  translate(width/2, height/2, 0);
  background(233);
  textSize(22);
  text("Roll: " + int(roll) + "     Pitch: " + int(pitch), -100, 265);
  // Rotate the object
  rotateX(radians(-pitch));
  rotateZ(radians(roll));
  rotateY(radians(yaw));
  
  // 3D 0bject
  textSize(30);  
  fill(0, 76, 153);
  box (386, 40, 200); // Draw box
  textSize(25);
  fill(255, 255, 255);
  text("www.HowToMechatronics.com", -183, 10, 101);
  //delay(10);
  //println("ypr:\t" + angleX + "\t" + angleY); // Print the values to check whether we are getting proper values
}
// Read data from the Serial Port
void serialEvent (Serial myPort) { 
  // reads the data from the Serial Port up to the character '.' and puts it into the String variable "data".
  data = myPort.readStringUntil('\n');
  // if you got any bytes other than the linefeed:
  if (data != null) {
    data = trim(data);
    // split the string at "/"
    String items[] = split(data, '/');
    if (items.length > 1) {
      //--- Roll,Pitch in degrees
      roll = float(items[0]);
      pitch = float(items[1]);
      yaw = float(items[2]);
    }
  }
}Code language: Arduino (arduino)

在这里,我们从 Arduino 读取传入数据并将其放入适当的 Roll、Pitch 和 Yaw 变量中。在主绘制循环中,我们使用这些值来旋转 3D 对象,在本例中,这是一个带有特定颜色和文本的简单框。

如果我们运行该草图,我们可以看到 MPU6050 传感器在跟踪方向方面的表现如何。 3D 物体可以非常准确地跟踪传感器的方向,而且反应灵敏。

正如我所提到的,唯一的缺点是偏航会随着时间的推移而漂移,因为我们不能使用互补滤波器。为了改善这一点,我们需要使用一个额外的传感器。这通常是一个磁力计,可以用作陀螺仪偏航漂移的长期校正。不过,MPU6050其实有一个功能叫Digital Motion Processor,用于板载数据计算,可以消除Yaw漂移。

这是使用数字运动处理器的相同 3D 示例。我们可以看到方向跟踪现在有多准确,没有偏航漂移。板载处理器还可以计算和输出四元数,用于在三个维度上表示对象的方向和旋转。在这个例子中,我们实际上使用四元数来表示方向,它也不会受到使用欧拉角时发生的万向锁的影响。

然而,从传感器获取这些数据比我们之前解释的要复杂一些。首先,我们需要将额外的电线连接到 Arduino 数字引脚。这是一个中断引脚,用于从 MPU6050 读取该数据类型。

代码也有点复杂,所以我们将使用 Jeff Rowberg 的 i2cdevlib 库。该库可以从 GitHub 下载,我将在网站文章中包含一个链接。

安装库后,我们可以从库中打开 MPU6050_DMP6 示例。这个例子很好地解释了每一行的注释。

在这里,我们可以选择我们想要的输出类型,四元数、欧拉角、偏航、俯仰和滚动、加速度值或 3D 可视化的四元数。该库还包括 3D 可视化示例的处理草图。我只是修改它以获得与前面示例中一样的盒子形状。这是与 MPU6050_DPM6 示例一起使用的 3D 可视化处理代码,用于选定的“OUTPUT_TEAPOT”输出:

/*
    Arduino and MPU6050 IMU - 3D Visualization Example 
     by Dejan, https://howtomechatronics.com
*/
import processing.serial.*;
import java.awt.event.KeyEvent;
import java.io.IOException;
Serial myPort;
String data="";
float roll, pitch,yaw;
void setup() {
  size (2560, 1440, P3D);
  myPort = new Serial(this, "COM7", 19200); // starts the serial communication
  myPort.bufferUntil('\n');
}
void draw() {
  translate(width/2, height/2, 0);
  background(233);
  textSize(22);
  text("Roll: " + int(roll) + "     Pitch: " + int(pitch), -100, 265);
  // Rotate the object
  rotateX(radians(-pitch));
  rotateZ(radians(roll));
  rotateY(radians(yaw));
  
  // 3D 0bject
  textSize(30);  
  fill(0, 76, 153);
  box (386, 40, 200); // Draw box
  textSize(25);
  fill(255, 255, 255);
  text("www.HowToMechatronics.com", -183, 10, 101);
  //delay(10);
  //println("ypr:\t" + angleX + "\t" + angleY); // Print the values to check whether we are getting proper values
}
// Read data from the Serial Port
void serialEvent (Serial myPort) { 
  // reads the data from the Serial Port up to the character '.' and puts it into the String variable "data".
  data = myPort.readStringUntil('\n');
  // if you got any bytes other than the linefeed:
  if (data != null) {
    data = trim(data);
    // split the string at "/"
    String items[] = split(data, '/');
    if (items.length > 1) {
      //--- Roll,Pitch in degrees
      roll = float(items[0]);
      pitch = float(items[1]);
      yaw = float(items[2]);
    }
  }
}Code language: Arduino (arduino)

所以在这里使用 serialEvent() 函数我们接收来自 Arduino 的四元数,在主绘制循环中我们使用它们来旋转 3D 对象。如果我们运行这个草图,我们可以看到四元数对于在三个维度上旋转物体是多么的好。

为了不超出本教程的内容,我将第二个示例,即 DIY Arduino 万向节或自稳定平台放在了另一篇文章中。

随时在下面的评论部分提出与本教程相关的任何问题,也不要忘记查看我收集的 Arduino 项目。


制造工艺

  1. Arduino RFID 锁教程
  2. LCD 动画和游戏
  3. 使用 Arduino 和 MPU6050 控制伺服电机
  4. Python3 和 Arduino 通信
  5. 使用 Arduino 和 RDA8057M 的 FM 收音机
  6. 将加速度转换为来自 MPU6050 I2C 传感器的角度
  7. Arduino 指纹传感器教程
  8. Arduino 教程:迷你钢琴
  9. Raspberry Pi 和 Arduino 笔记本电脑
  10. 使用加速度计和 ESP 的手势识别
  11. 如何使用 Arduino 和 ADXL345 加速度计跟踪方向
  12. Arduino教程01:入门