基于ESP32-E与MPU6050的三轴加速度记录仪DIY全攻略

发布时间:2026/7/28 13:10:24

基于ESP32-E与MPU6050的三轴加速度记录仪DIY全攻略 1. 从想法到实物为什么我们需要一个三轴加速度记录仪几年前我在调试一个智能穿戴设备的原型时遇到了一个棘手的问题设备在特定动作下偶尔会误触发。当时手头只有万用表和逻辑分析仪对于运动姿态这种动态变化的数据完全抓瞎。后来不得不借来一台昂贵的专业数据采集器才定位到是某个轴向的加速度在临界点产生了毛刺。那次经历让我深刻意识到一个能随时随地、低成本记录三维运动数据的工具对硬件开发者、创客甚至运动爱好者来说有多重要。这就是DIY一个X/Y/Z三轴加速度数据记录仪的初衷。它本质上是一个便携式的“运动黑匣子”可以持续测量并存储物体在空间三个方向前后、左右、上下上的加速度变化。听起来很高端其实核心部件就是一个加速度传感器和一块微控制器。市面上当然有成品但自己动手做一个成本可能不到五十块钱更重要的是你可以完全掌控它的采样率、量程、存储格式和触发条件让它百分百贴合你的特定需求。无论是想分析网球拍的挥拍轨迹、监测快递包裹的运输颠簸、记录模型飞机的飞行G值还是像我当初一样调试嵌入式设备这个小工具都能派上大用场。它剥离了复杂的外设和界面只专注于最核心的“感知”与“记录”功能。接下来我就结合热门的ESP32-E开发板和OLED屏幕带你从零开始打造一个功能完整、可扩展性强的三轴加速度数据记录仪。2. 核心器件选型为什么是ESP32-E和OLED工欲善其事必先利其器。DIY的第一步永远是器件选型这直接决定了项目的性能上限、复杂度和成本。对于数据记录仪我们需要几个核心模块主控、传感器、存储、显示和电源。2.1 主控芯片ESP32-E的压倒性优势在众多微控制器中我选择了ESP32-E通常指ESP32-DevKitC V4这类开发板使用的模组。这几乎是当前DIY领域在功能、性价比和生态上的最优解理由非常充分双核处理器与充足内存记录数据尤其是高速数据时主控需要在读取传感器、处理数据、写入存储等多个任务间快速切换。ESP32的Xtensa双核处理器通常运行在240MHz和520KB的SRAM为多任务调度提供了充沛的算力和内存空间这是很多传统单片机如STM32F103难以比拟的。你可以轻松地用FreeRTOS创建一个任务专用于高速采集另一个任务负责管理存储和显示互不干扰。内置无线功能Wi-Fi 蓝牙这是ESP32的杀手锏。数据记录完成后你可以通过Wi-Fi将存储卡里的数据文件直接上传到电脑或云端无需插拔SD卡。蓝牙则可以用于连接手机APP进行实时数据预览或参数配置极大提升了使用的便捷性。虽然我们核心功能是记录但预留的无线能力为未来扩展如远程触发、实时监控打开了大门。丰富的外设接口它支持SPI、I2C、UART、I2S等多种通信协议。我们的加速度计常用I2C或SPI、OLED屏幕常用I2C和SD卡模块必需SPI都能轻松挂载无需额外的电平转换或接口扩展芯片。极低的功耗与深度睡眠对于需要长期记录的应用如环境监测ESP32出色的功耗控制能力至关重要。在两次采集间隔我们可以让CPU进入深度睡眠Deep Sleep模式此时功耗可低至10μA左右仅由RTC定时器唤醒能极大地延长电池续航。成熟的生态与低成本围绕ESP32的Arduino核心、ESP-IDF框架资料海量社区活跃遇到问题几乎都能找到解决方案。其开发板价格已非常亲民ESP32-E开发板通常在20-30元人民币左右。相比之下像MSP430或STM32G0系列虽然功耗可能更低但无线功能的缺失和相对较小的内存使其在需要复杂任务管理和数据导出的记录仪场景中优势不大。2.2 运动感知核心三轴加速度计选型要点加速度计是项目的心脏选型主要看几个参数通信接口I2C和SPI是最常见的。I2C接线简单仅需两根线但速度较慢SPI速度更快适合高速采集但占用引脚多。对于大多数记录场景采样率500HzI2C足以胜任且能简化电路。我推荐使用I2C接口的型号。量程Range指能测量的最大加速度。常见有±2g, ±4g, ±8g, ±16g。g是重力加速度9.8m/s²。对于人体运动或设备振动±8g通常足够如果是冲击性测试可能需要±16g。量程越小在测量微小变化时分辨率越高。分辨率Resolution输出数据的位数常见有10位、12位、14位、16位。位数越高能将量程划分得越细数据越精细。例如一个±2g量程的12位传感器其最小分辨率约为 (4g) / (2^12) ≈ 0.98mg。采样率Output Data Rate, ODR传感器每秒输出数据的次数。从1Hz到几千Hz不等。需要根据被测运动的最高频率来选择根据奈奎斯特采样定理ODR至少需为信号最高频率的2倍。对于步态分析~10Hz100Hz ODR足够对于振动分析可能需要500Hz或更高。基于以上我推荐两款非常经典且易用的传感器MPU6050老牌明星产品集成三轴加速度计三轴陀螺仪价格极低约5元。通过I2C通信加速度计量程可编程±2g, ±4g, ±8g, ±16g最高ODR可达1kHz。缺点是相对功耗稍高且需要处理陀螺仪数据如果不用可以关闭。ADXL345Analog Devices的经典数字加速度计性能稳定噪声低。I2C/SPI可选量程可调±2g至±16g最高ODR达3.2kHz且内置多种动作检测自由落体、敲击等功能非常强大。本项目以MPU6050为例进行讲解因其性价比超高且资料极多。2.3 数据存储SD卡模块的可靠性与文件系统记录仪的核心任务是存储数据。虽然ESP32有SPIFFS或LittleFS这类片内闪存文件系统但容量有限通常4MB且频繁擦写会影响寿命。外接一个SD卡模块是最佳选择。模块选择选择一款支持SPI模式、带电平转换将5V/3.3V转换为SD卡所需的3.3V信号的Micro SD卡模块。注意有些廉价模块可能不支持SDHC/SDXC大容量卡最好选择明确支持FAT32文件系统的通用模块。文件系统我们将使用Arduino的SD库它基于著名的SDFat库支持在SD卡上创建、读取、写入文件。数据通常以文本格式如CSV存储方便后续用Excel、Python或MATLAB分析。每一行数据包含一个时间戳和三个轴向的加速度值例如1234567, 0.12, 0.98, -0.05。存储策略为了降低因意外断电导致数据丢失的风险不应每采集一次就打开文件写入一次。正确的做法是在内存中开辟一个缓冲区buffer例如存储100组数据当缓冲区满后再一次性打开文件将所有数据追加写入然后立即关闭文件。这能显著减少文件系统的操作次数提高稳定性和速度。2.4 人机交互OLED屏幕的直观反馈一个0.96英寸的I2C接口OLED屏幕通常使用SSD1306驱动是点睛之笔。它功耗极低显示对比度高无需背光。在记录仪中它可以实时显示当前三轴加速度的实时数值或简易波形。记录状态“Recording”、“Stopped”、“Error”。已记录的数据点数或文件大小。电池电量如果连接了电池电压检测电路。设备配置参数如采样率、量程。这让你无需连接电脑就能对设备工作状态一目了然。Adafruit_SSD1306和Adafruit_GFX库是驱动它的绝佳选择。2.5 电源管理续航与稳定的基石记录仪经常需要移动使用因此一个可靠的电源方案至关重要。供电首选一块3.7V的锂聚合物电池如常见的104050型号。其电压范围3.0V - 4.2V完美匹配ESP32的工作电压3.3V。充电与管理需要一个充电管理芯片如TP4056它可以通过Micro USB口为电池安全充电并带有充电状态指示。同时需要一个低压差稳压器LDO如AMS1117-3.3将电池电压稳定到3.3V为整个系统供电。特别注意ESP32在射频工作时峰值电流可能超过500mAAMS1117-3.3的最大输出电流需达到1A并需配备足够的输入/输出滤波电容。电量监测为了在OLED上显示电量可以通过一个电阻分压电路将电池电压最高4.2V分压到ESP32的ADC引脚可测量的范围0-3.3V然后通过程序换算成电量百分比。这是一个非常有用的功能。3. 硬件电路设计与焊接要点有了核心器件接下来就是将它们正确地连接起来。电路设计的原则是清晰、可靠、便于调试。3.1 系统连接图与引脚分配下图清晰地展示了各模块与ESP32-E开发板的连接关系。ESP32-E的引脚功能是复用的我们需要为每个外设分配合适的GPIO引脚。模块接口类型连接至ESP32引脚备注MPU6050I2CSDA - GPIO21, SCL - GPIO22I2C默认引脚需接上拉电阻通常模块已集成OLED (SSD1306)I2CSDA - GPIO21, SCL - GPIO22与MPU6050共享I2C总线地址不同SD卡模块SPICS/SS - GPIO5, MOSI - GPIO23, MISO - GPIO19, SCK - GPIO18SPI的HSPI接口注意CS引脚可自定义用户按钮GPIOGPIO0 (BOOT)用于开始/停止记录内部上拉按下接地电池电压检测ADCGPIO34 (VP)仅输入功能的ADC1通道通过分压电路连接重要提示MPU6050和OLED可以共享同一组I2C引脚21和22因为它们有各自唯一的I2C设备地址MPU6050通常为0x68OLED为0x3C。这节省了宝贵的GPIO资源。3.2 焊接与组装中的“坑”在万能板或PCB上焊接时以下几个细节决定了项目的成败电源去耦电容必须在ESP32的3.3V电源入口处以及AMS1117-3.3的输入和输出端就近并联一个10μF的钽电容或电解电容低频滤波和一个0.1μF的陶瓷电容高频滤波。这是消除电源噪声、防止系统随机重启的关键尤其是SD卡和Wi-Fi工作时电流波动很大。I2C上拉电阻虽然很多模块板载了上拉电阻通常4.7kΩ但如果总线较长或设备较多信号可能仍不稳定。如果发现I2C设备偶尔无法识别可以在SDA和SCL线上各焊接一个4.7kΩ电阻到3.3V作为加强上拉。SD卡模块的电源确保SD卡模块的VCC引脚连接到3.3V而不是5V连接5V会损坏模块和SD卡。同时SD卡模块的MOSI、MISO、SCK、CS信号线已经是3.3V电平可以直接与ESP32连接。按钮防抖机械按钮在按下和释放时会产生物理抖动导致单片机误判为多次按下。必须在软件中实现消抖。一个简单有效的方法是检测到引脚电平变化后延时50ms再次检测如果状态稳定则确认为有效按键。天线区域净空ESP32的PCB天线区域开发板上通常是一根弯曲的走线周围尽量不要铺设地线或走其他信号线保持净空以确保无线信号质量。4. 软件框架设计与关键代码解析硬件是躯体软件是灵魂。记录仪的软件需要稳定、高效地协调数据采集、存储和显示。我们将采用基于FreeRTOS的简单多任务架构。4.1 任务划分与优先级设计我们创建三个主要任务传感器采集任务(Task_Sensor): 优先级最高。它以一个固定的高频率如1kHz运行从MPU6050读取原始数据进行单位换算将原始数字转换为g值或m/s²并存入一个全局的环形缓冲区Ring Buffer。这个任务必须保证准时执行不能因其他任务而阻塞。数据存储任务(Task_Storage): 优先级中等。它定期检查环形缓冲区。当缓冲区中的数据量达到一个预设的块大小如512字节时它将这块数据取出以追加写入的方式保存到SD卡上的CSV文件中。文件操作打开、写入、关闭是相对慢速的I/O操作因此单独成一个任务避免阻塞高速采集。用户界面任务(Task_UI): 优先级最低。它负责扫描按键状态、更新OLED显示如实时加速度值、记录状态、存储空间等。这个任务对实时性要求不高可以以较低的频率如10Hz运行。这种设计确保了数据采集的连续性即使存储或显示偶尔卡顿也不会丢失数据。4.2 核心代码实现与注释以下是基于Arduino框架的核心代码片段及详细解释。#include Wire.h #include Adafruit_MPU6050.h #include Adafruit_Sensor.h #include Adafruit_SSD1306.h #include SD.h #include SPI.h // 硬件引脚定义 #define BUTTON_PIN 0 #define SD_CS_PIN 5 #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 // 全局变量与对象 Adafruit_MPU6050 mpu; Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, Wire, OLED_RESET); File dataFile; // 环形缓冲区结构体 #define BUFFER_SIZE 1000 struct SensorData { unsigned long timestamp; // 微秒时间戳 float ax, ay, az; // 加速度值 (单位: g 或 m/s²) }; SensorData dataBuffer[BUFFER_SIZE]; volatile uint16_t bufferHead 0; // 生产者采集任务写入位置 volatile uint16_t bufferTail 0; // 消费者存储任务读取位置 volatile bool isRecording false; // 采集任务函数 void Task_Sensor(void *pvParameters) { const TickType_t xFrequency 1 / portTICK_PERIOD_MS; // 1ms周期即1kHz TickType_t xLastWakeTime xTaskGetTickCount(); while (1) { if (isRecording) { // 1. 读取传感器数据 sensors_event_t a, g, temp; mpu.getEvent(a, g, temp); // 2. 获取高精度时间戳微秒 unsigned long ts micros(); // 3. 写入环形缓冲区 uint16_t nextHead (bufferHead 1) % BUFFER_SIZE; if (nextHead ! bufferTail) { // 缓冲区未满 dataBuffer[bufferHead].timestamp ts; dataBuffer[bufferHead].ax a.acceleration.x; dataBuffer[bufferHead].ay a.acceleration.y; dataBuffer[bufferHead].az a.acceleration.z; bufferHead nextHead; } else { // 缓冲区满可在此处点亮错误LED或增加丢包计数 } } vTaskDelayUntil(xLastWakeTime, xFrequency); // 精确周期延迟 } } // 存储任务函数 void Task_Storage(void *pvParameters) { const TickType_t xFrequency 100 / portTICK_PERIOD_MS; // 100ms检查一次 TickType_t xLastWakeTime xTaskGetTickCount(); while (1) { if (isRecording bufferTail ! bufferHead) { // 打开文件以追加模式 dataFile SD.open(/datalog.csv, FILE_APPEND); if (dataFile) { while (bufferTail ! bufferHead) { SensorData d dataBuffer[bufferTail]; // 写入CSV格式时间戳(us), X(g), Y(g), Z(g) dataFile.print(d.timestamp); dataFile.print(,); dataFile.print(d.ax, 4); // 保留4位小数 dataFile.print(,); dataFile.print(d.ay, 4); dataFile.print(,); dataFile.println(d.az, 4); bufferTail (bufferTail 1) % BUFFER_SIZE; } dataFile.close(); // 及时关闭文件确保数据写入物理介质 } } vTaskDelayUntil(xLastWakeTime, xFrequency); } } void setup() { Serial.begin(115200); pinMode(BUTTON_PIN, INPUT_PULLUP); // 按钮引脚上拉 // 初始化I2C Wire.begin(21, 22); // 初始化MPU6050 if (!mpu.begin()) { Serial.println(MPU6050 not found!); while (1); } mpu.setAccelerometerRange(MPU6050_RANGE_8_G); // 设置量程为±8g // 初始化OLED if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println(SSD1306 allocation failed); while (1); } display.display(); delay(2000); display.clearDisplay(); // 初始化SD卡 if (!SD.begin(SD_CS_PIN)) { Serial.println(SD Card initialization failed!); display.println(SD Card Error!); display.display(); } // 创建FreeRTOS任务 xTaskCreatePinnedToCore(Task_Sensor, Sensor, 4096, NULL, 3, NULL, 1); // 高优先级运行在核心1 xTaskCreatePinnedToCore(Task_Storage, Storage, 4096, NULL, 2, NULL, 1); // UI任务可以放在loop()中或单独创建 } void loop() { // 处理按钮消抖处理 static unsigned long lastDebounceTime 0; if (digitalRead(BUTTON_PIN) LOW (millis() - lastDebounceTime) 50) { lastDebounceTime millis(); isRecording !isRecording; // 切换记录状态 display.clearDisplay(); display.setCursor(0,0); display.println(isRecording ? RECORDING : STOPPED); display.display(); } // 更新OLED显示简易实时数值 display.clearDisplay(); display.setCursor(0,0); display.print(X:); display.println(dataBuffer[(bufferHead-1)%BUFFER_SIZE].ax, 2); display.print(Y:); display.println(dataBuffer[(bufferHead-1)%BUFFER_SIZE].ay, 2); display.print(Z:); display.println(dataBuffer[(bufferHead-1)%BUFFER_SIZE].az, 2); display.print(Count:); display.println(bufferHead); display.display(); delay(100); // UI刷新率约10Hz }关键点解析环形缓冲区这是解决生产者采集和消费者存储速度不匹配问题的经典数据结构。bufferHead和bufferTail的移动通过取模运算实现循环高效利用内存。vTaskDelayUntilFreeRTOS提供的精确周期延迟函数能确保任务以固定频率执行比简单的delay()更准。文件操作时机在Task_Storage中我们不是采集一次就写一次文件而是积累一定数据后批量写入。并且文件在写入循环结束后立即关闭dataFile.close()。这个操作非常重要它会强制将操作系统的文件缓冲区数据真正写入SD卡的物理扇区防止因突然断电而丢失已“写入”的数据。时间戳使用micros()函数获取微秒级时间戳这对于分析高速运动或计算频率成分至关重要。注意micros()函数大约每70分钟会溢出归零但对于大多数单次记录场景这足够了。如需长时间记录需要处理溢出。5. 校准、测试与数据分析实战硬件组装好代码烧录进去只是成功了一半。接下来的校准、功能测试和数据分析才是让数据变得可信、有用的关键。5.1 加速度计的校准消除零偏和尺度误差任何加速度计出厂都有误差主要体现在两点零偏Offset当传感器静止时三个轴的输出理论上应该是(0, 0, 1g)或(0, 0, -1g)取决于安装方向但实际上会有微小偏差。尺度误差Scale Error传感器输出的数值与真实重力加速度的比值不是绝对准确的。一个简单的六点校准法可以修正这些误差步骤将设备在六个方向上±X ±Y ±Z轴分别朝下各静止放置一段时间记录每个方向下的传感器原始输出值。计算对于每个轴其零偏 (该轴朝下时的读数 该轴朝上时的读数) / 2。其尺度因子 (该轴朝下时的读数 - 该轴朝上时的读数) / (2 * 1g)。应用在代码中每次读取原始数据后进行修正修正值 (原始值 - 零偏) / 尺度因子。你可以写一个简单的校准程序通过串口输出六个面的数据然后在电脑上用Excel或Python计算出零偏和尺度因子最后将这些常数硬编码到主程序中。5.2 功能测试与常见问题排查烧录程序后按以下步骤测试上电自检观察OLED是否正常显示初始化信息SD卡是否被识别。静态测试将设备水平静止放置OLED显示的Z轴加速度应接近1.0g或-1.0g取决于安装X和Y轴接近0g。轻轻晃动设备数值应有相应变化。记录测试按下按钮开始记录移动设备几秒钟后停止。将SD卡插入电脑用文本编辑器打开datalog.csv文件检查数据是否被正确记录格式是否正确。无线功能测试可选可以编写一个简单的Wi-Fi服务器代码让ESP32启动一个Web服务器。通过浏览器访问其IP地址可以实时查看加速度数据曲线或下载已记录的数据文件。常见问题与排查I2C设备不响应首先检查接线然后用Wire库的扫描程序Arduino示例中有I2CScanner检查设备地址是否正确出现。SD卡无法初始化检查接线尤其是MOSI, MISO, SCK, CS四根线是否接对。尝试更换一张容量较小如8GB或16GB、且已格式化为FAT32文件系统的SD卡。某些高速卡或exFAT格式的卡兼容性可能有问题。检查电源SD卡工作时需要较大电流确保3.3V电源稳定。数据记录不连续或丢失检查环形缓冲区大小是否足够。如果存储任务写入太慢可能导致缓冲区被快速填满新数据覆盖旧数据。可以增大缓冲区大小或者优化存储任务的写入效率例如使用更大的数据块写入。5.3 从数据到洞察基础数据分析示例记录下来的CSV数据是宝藏但需要工具来挖掘。这里介绍两种最快捷的方法方法一使用Excel进行可视化将CSV文件导入Excel。选中时间戳和某一轴加速度的数据列。点击“插入” - “图表” - “散点图”或“折线图”。你立刻就能看到加速度随时间变化的波形。可以添加趋势线计算平均值、标准差振动强度或者通过观察峰值来分析冲击事件。方法二使用Python (Matplotlib Pandas) 进行进阶分析Python是处理这类数据的利器。以下是一个简单的脚本示例用于绘制三轴加速度曲线并计算基本统计量import pandas as pd import matplotlib.pyplot as plt # 读取数据假设CSV文件没有表头 data pd.read_csv(datalog.csv, headerNone, names[timestamp_us, accel_x_g, accel_y_g, accel_z_g]) # 将时间戳转换为秒从第一点开始 data[timestamp_s] (data[timestamp_us] - data[timestamp_us].iloc[0]) / 1_000_000.0 # 绘制三轴加速度曲线 plt.figure(figsize(12, 6)) plt.plot(data[timestamp_s], data[accel_x_g], labelX Axis, alpha0.7) plt.plot(data[timestamp_s], data[accel_y_g], labelY Axis, alpha0.7) plt.plot(data[timestamp_s], data[accel_z_g], labelZ Axis, alpha0.7) plt.xlabel(Time (s)) plt.ylabel(Acceleration (g)) plt.title(Triaxial Acceleration Recording) plt.legend() plt.grid(True) plt.show() # 计算基本统计信息 print(Statistical Summary:) print(data[[accel_x_g, accel_y_g, accel_z_g]].describe()) # 计算合成加速度矢量模 data[accel_total_g] (data[accel_x_g]**2 data[accel_y_g]**2 data[accel_z_g]**2)**0.5 print(f\nPeak Total Acceleration: {data[accel_total_g].max():.2f} g)通过这个脚本你可以直观地看到运动过程并量化运动的强度。更进一步你可以使用NumPy和SciPy库进行频域分析FFT找出振动的主要频率成分这对于故障诊断或运动分析极具价值。6. 项目优化与扩展思路一个基础版本完成后你可以根据具体需求从以下几个方向进行深化和扩展6.1 功耗优化让记录仪续航数周如果希望设备能长期野外工作功耗是关键。降低采样率在满足需求的前提下尽可能降低MPU6050的ODR和ESP32的采集任务频率。利用睡眠模式在两次采集间隔让ESP32进入轻睡眠Light Sleep或深度睡眠Deep Sleep模式。轻睡眠下RAM数据保留可由定时器唤醒唤醒速度快深度睡眠下仅RTC模块和少量RAM工作功耗极低但唤醒后程序从setup()重新开始。你需要根据数据连续性的要求来选择。关闭无线模块在记录期间如果不需要Wi-Fi/蓝牙务必调用WiFi.mode(WIFI_OFF)和btStop()来彻底关闭射频电路这能节省大量电量。优化外设供电可以通过MOSFET开关电路在睡眠时切断SD卡模块、OLED屏幕等非核心外设的电源进一步省电。6.2 触发记录捕捉关键事件持续记录会产生海量冗余数据。可以增加基于事件的触发记录功能。阈值触发当合成加速度或某一轴加速度超过设定的阈值时自动开始记录并在事件结束后持续记录一段时间再停止。MPU6050本身内置了运动中断Motion Interrupt和自由落体中断Free-Fall Interrupt功能可以直接配置使用无需CPU持续轮询更省电。定时触发例如每天只在特定时间段进行记录。6.3 无线数据导出与实时监控利用ESP32的Wi-Fi能力可以大大提升易用性。Web服务器设备启动后作为一个Wi-Fi热点AP模式用户手机或电脑连接后通过浏览器访问一个网页可以实时查看加速度曲线、下载数据文件、甚至动态修改采样率等参数。数据上传记录完成后设备自动连接家庭路由器STA模式将数据文件通过HTTP POST或MQTT协议上传到指定的服务器或云平台如ThingsBoard、阿里云IoT。6.4 增加更多传感器ESP32的接口资源还有富余可以轻松扩展陀螺仪MPU6050本身自带可以同时记录角速度实现更复杂的姿态解算。磁力计增加一个HMC5883L或QMC5883L结合加速度计和陀螺仪构成完整的9轴惯性测量单元IMU能提供绝对方向电子罗盘。温湿度传感器如DHT22或SHT30记录环境数据。GPS模块记录位置轨迹对于车载或户外移动监测非常有用。将这些传感器的数据同步记录你得到的就是一个多参数环境与运动综合记录仪应用场景会更加广阔。整个项目的魅力就在于这个小小的黑匣子完全按照你的想法去定义和进化。

相关新闻