reTerminal E系列Arduino开发全攻略:从环境搭建到传感器数据可视化

reTerminal E系列Arduino开发全攻略:从环境搭建到传感器数据可视化 1. 项目概述为什么是 reTerminal E 系列如果你玩过 Arduino Uno、ESP32 这些开发板可能会觉得它们功能强大但“裸奔”感太强每次做个项目都得外接一堆屏幕、按键、传感器连线复杂不说成品也显得不够规整。而 reTerminal E 系列在我看来就是为那些想把想法快速变成“产品级”原型的开发者准备的“瑞士军刀”。reTerminal E 系列本质上是一个集成了丰富板载外设的嵌入式 Linux 计算平台核心通常是一颗 Raspberry Pi Compute Module 4CM4。它最大的魅力在于官方提供了完整的 Arduino 核心支持。这意味着你可以用熟悉的 Arduino IDE 和那套简洁的编程逻辑去直接驱动这块板子上自带的 5 英寸 IPS 触摸屏、六轴 IMU、光线传感器、RGB LED、用户按键甚至 GPIO 扩展接口。这彻底改变了 Arduino 项目的开发体验你不再需要为了一个简单的用户界面而去研究复杂的 GUI 库和驱动也不用担心陀螺仪和加速度计的 I2C 地址冲突问题所有硬件都已经被预先集成和抽象好了。这个“菜谱”项目就是要系统性地“烹饪”这块开发板。我将带你从零开始解锁 reTerminal E 系列上每一个板载外设的 Arduino 玩法。无论你是想做一个带漂亮界面的智能家居中控一个可以感知姿态的物联网数据采集器还是一个互动式的工业控制面板这里都有现成的“食材”和“烹饪步骤”。我们不止讲“怎么用”更会深入“为什么这么用”以及我在实际调试中踩过的那些坑。你会发现用 Arduino 开发带屏的嵌入式 Linux 设备可以如此高效和有趣。2. 开发环境搭建与核心概念解析在开始炒菜之前我们得先把厨房收拾好。用 Arduino 开发 reTerminal E 系列和开发传统的 AVR 或 ESP 单片机有些不同关键在于理解“双系统”和“桥接”的概念。2.1 硬件准备与系统刷写首先你需要一块 reTerminal E 系列设备如 reTerminal DM、 reTerminal E 等型号。拿到手后第一件事不是接电而是准备一张高质量的 MicroSD 卡建议 16GB 以上 Class 10 或更高速度。reTerminal 的核心 CM4 模块本身没有存储系统完全运行在 SD 卡上。前往 Seeed Studio 的官方 Wiki 或 GitHub 仓库下载为 reTerminal E 系列预构建的 Raspberry Pi OS 镜像。这个镜像是特别的它除了包含完整的 Linux 系统还内置了支持 Arduino 的“桥接”服务通常是arduino-agent和必要的硬件访问层库。使用 Raspberry Pi Imager 或 BalenaEtcher 将镜像写入 SD 卡。写入完成后不要急着拔卡——这是一个关键步骤。你需要用读卡器在电脑上打开 SD 卡的boot分区编辑里面的config.txt文件。找到关于屏幕和触摸的配置行确保它们与你的 reTerminal 型号匹配例如取消注释正确的dtoverlay行。对于首次启动我强烈建议同时编辑userconf.txt或wpa_supplicant.conf文件预先设置好用户名密码和 Wi-Fi这样启动后就能直接通过网络访问方便后续操作。将 SD 卡插入 reTerminal连接电源和网络网线或配置好的 Wi-Fi首次启动会进行系统扩展和初始化需要几分钟时间。完成后你可以通过 SSH使用ssh pireTerminal的IP或者接上 HDMI 显示器如果有的话来访问系统。在终端输入hostname -I获取 IP 地址。2.2 Arduino IDE 的特别配置在你的电脑上打开 Arduino IDE建议使用 1.8.x 或 2.x 稳定版。传统的“开发板管理器”在这里不直接适用。我们需要手动添加一个特殊的“开发板支持包”。添加开发板管理网址打开“文件”-“首选项”在“附加开发板管理器网址”中填入 Seeed 提供的特定网址。这个网址通常能在其官方 Arduino 示例仓库的 README 中找到。安装开发板支持包打开“工具”-“开发板”-“开发板管理器”搜索“reTerminal”或“Seeed”。你应该能看到一个名为“Seeed reTerminal Boards”的包。选择并安装它。关键配置安装完成后在“工具”-“开发板”菜单下选择“Seeed reTerminal Boards”下的对应型号如Seeed reTerminal DM。接下来是最重要的几步编程端口这里不是选择 COM 口而是选择Network Ports下的一个选项格式通常是[你的 reTerminal IP 地址]例如192.168.1.100。这建立了 IDE 和板载arduino-agent服务的网络连接。上传方法选择Arduino Agent。这告诉 IDE 通过我们刚刚建立的网络连接将编译好的代码发送到 reTerminal 上执行。注意首次进行网络上传时可能会弹出安全警告需要在 reTerminal 的终端里执行一个命令来授权。具体命令在 Arduino IDE 的输出窗口会有提示通常是sudo arduino-agent --authorize之类的。务必按照提示操作。这个配置过程的核心是理解 Arduino IDE 在这里扮演了一个“远程编译和上传客户端”的角色。代码在你的电脑上编译生成的是适用于 CM4ARM Cortex-A72架构的可执行文件然后通过 SSH 或 HTTP 协议传输到 reTerminal 上由arduino-agent服务负责加载运行。这和我们直接向单片机烧录二进制固件有本质区别。2.3 第一个测试程序点亮 RGB LED环境配好了我们来点个灯这是嵌入式世界的“Hello World”。reTerminal E 系列通常板载了一个可编程的 RGB LED。// reTerminal RGB LED 测试 // 该LED通常通过一个特定的内核接口或Sysfs控制这里使用常见抽象 void setup() { // 初始化RGB LED具体引脚号需查阅对应板型的定义文件 // 例如在Seeed提供的库中可能定义为 LED_R, LED_G, LED_B pinMode(LED_R, OUTPUT); pinMode(LED_G, OUTPUT); pinMode(LED_B, OUTPUT); Serial.begin(115200); // 初始化串口用于调试输出 } void loop() { Serial.println(Red ON); digitalWrite(LED_R, HIGH); // 红色亮 digitalWrite(LED_G, LOW); digitalWrite(LED_B, LOW); delay(1000); Serial.println(Green ON); digitalWrite(LED_R, LOW); digitalWrite(LED_G, HIGH); // 绿色亮 digitalWrite(LED_B, LOW); delay(1000); Serial.println(Blue ON); digitalWrite(LED_R, LOW); digitalWrite(LED_G, LOW); digitalWrite(LED_B, HIGH); // 蓝色亮 delay(1000); Serial.println(Cyan (GB) ON); digitalWrite(LED_R, LOW); digitalWrite(LED_G, HIGH); digitalWrite(LED_B, HIGH); // 青色亮 delay(1000); }点击上传如果一切顺利你会看到 reTerminal 板载的 RGB LED 开始循环显示红、绿、蓝、青四种颜色同时 Arduino IDE 的串口监视器注意这里监视的是 reTerminal 上运行的程序的输出会打印出对应的状态信息。这个简单的测试验证了开发环境、网络上传、基础 GPIO 控制以及串口调试通道全部工作正常。实操心得第一次网络上传可能会失败常见原因是防火墙阻止或arduino-agent服务未运行。在 reTerminal 上通过 SSH 执行sudo systemctl status arduino-agent检查服务状态。如果服务挂了尝试sudo systemctl restart arduino-agent。另外确保你的电脑和 reTerminal 在同一个局域网网段内。3. 核心外设驱动与图形界面开发环境跑通了现在我们来处理主菜屏幕和触摸。这是 reTerminal 区别于普通开发板的核心价值所在。3.1 驱动 LCD 显示屏与基础绘图reTerminal 的 5 英寸 IPS 屏分辨率通常是 720x1280竖屏或 1280x720横屏。在 Arduino 环境下我们一般通过TFT_eSPI或LovyanGFX这类强大的图形库来驱动。Seeed 通常会提供适配好的库和配置文件。安装与配置图形库通过 Arduino IDE 的库管理器搜索并安装TFT_eSPI。安装后找到其安装目录下的User_Setup.h文件。这是一个关键的配置文件。你需要根据 reTerminal 的硬件连接通常是 SPI 或 DPI 接口来修改它。幸运的是Seeed 通常会提供一个现成的User_Setup.h示例。你需要将这个示例文件的内容复制并替换掉原来的文件或者根据注释仔细修改引脚定义、屏幕驱动芯片型号如 ST7789或ILI9488、分辨率等参数。编写第一个图形程序配置好后就可以像在 ESP32 上一样使用TFT_eSPI了。#include TFT_eSPI.h TFT_eSPI tft TFT_eSPI(); void setup() { Serial.begin(115200); tft.init(); tft.setRotation(1); // 设置屏幕旋转方向1通常是横屏 tft.fillScreen(TFT_BLACK); // 清屏为黑色 tft.setTextColor(TFT_WHITE, TFT_BLACK); tft.setTextSize(2); tft.drawString(Hello reTerminal!, 50, 50); tft.drawRect(100, 100, 200, 100, TFT_GREEN); // 画一个绿色矩形框 tft.fillCircle(300, 300, 50, TFT_RED); // 画一个实心红色圆 } void loop() { // 可以在这里实现动态图形 static uint32_t lastTime 0; if (millis() - lastTime 100) { // 每100ms更新一次 lastTime millis(); int x random(tft.width()); int y random(tft.height()); tft.drawPixel(x, y, TFT_YELLOW); // 随机画黄点 } }这个程序初始化屏幕显示文字和静态图形并在循环中随机绘制像素点。上传后你应该能在屏幕上看到对应的显示效果。TFT_eSPI库功能非常丰富支持绘制线条、矩形、圆形、三角形、显示位图、字体等足以满足大部分 UI 需求。注意事项TFT_eSPI的帧缓冲可能直接操作内存在复杂的动态界面下如果刷新区域过大或过于频繁可能会感觉到卡顿。对于需要高性能或复杂动画的场景可以考虑使用LovyanGFX它针对某些硬件有更好的优化或者采用局部刷新策略。3.2 触摸屏交互处理有了显示自然要有交互。reTerminal 的触摸屏通常是电容屏驱动芯片可能是 FT6236 或 GT911通过 I2C 接口连接。TFT_eSPI库也集成了触摸支持但需要正确配置。配置触摸引脚在刚才的User_Setup.h文件中找到触摸相关的定义。你需要设置正确的 I2C 引脚TOUCH_SDA,TOUCH_SCL、中断引脚如果有以及触摸芯片的 I2C 地址。读取触摸坐标配置完成后在代码中就可以方便地读取触摸点了。#include TFT_eSPI.h TFT_eSPI tft TFT_eSPI(); void setup() { Serial.begin(115200); tft.init(); tft.setRotation(1); tft.fillScreen(TFT_BLACK); tft.setTextColor(TFT_WHITE, TFT_BLACK); tft.setTextSize(2); tft.drawString(Touch Test, 100, 100); tft.drawString((0,0), 10, 10); // 显示坐标原点 } void loop() { uint16_t x, y; bool touched tft.getTouch(x, y); // 获取触摸状态和坐标 if (touched) { // 将获取的原始坐标转换为屏幕坐标转换函数取决于屏幕旋转和校准 // 这里假设已经校准直接使用 tft.fillCircle(x, y, 5, TFT_BLUE); // 在触摸点画一个蓝色小圆 Serial.printf(Touched: X%d, Y%d\n, x, y); // 简单的按钮检测示例 if (x 200 x 400 y 400 y 500) { tft.fillRect(200, 400, 200, 100, TFT_GREEN); tft.drawString(Button Pressed!, 220, 440); delay(300); // 防抖 tft.fillRect(200, 400, 200, 100, TFT_RED); tft.drawString(Press Me, 240, 440); } } delay(10); // 降低查询频率 }实操心得触摸的原始数据可能需要校准才能准确对应屏幕像素。TFT_eSPI库提供了touch_calibrate()函数可以引导用户在屏幕四个角依次点击生成校准矩阵。建议在产品初始化时进行一次校准并将参数保存到非易失存储中。另外电容屏容易受干扰在代码中增加简单的去抖逻辑如连续多次检测到同一区域触摸才认为有效能提升体验。3.3 构建简单的 GUI 界面基于基础绘图和触摸我们可以构建更复杂的 GUI例如按钮、滑块、图表等。虽然 Arduino 生态没有像 LVGL 那样重量级的嵌入式 GUI 库直接集成但我们可以自己实现轻量级控件或者利用TFT_eSPI的一些扩展。一个典型的自制按钮类可能如下class Button { private: int x, y, w, h; char* label; bool pressed; uint16_t color, textColor; public: Button(int xPos, int yPos, int width, int height, char* text) { x xPos; y yPos; w width; h height; label text; pressed false; color TFT_BLUE; textColor TFT_WHITE; } void draw(TFT_eSPI tft) { tft.fillRect(x, y, w, h, color); tft.drawRect(x, y, w, h, TFT_WHITE); tft.setTextColor(textColor); tft.setTextSize(2); int textX x (w - tft.textWidth(label)) / 2; int textY y (h - 16) / 2; // 假设字体高度约16像素 tft.drawString(label, textX, textY); } bool checkTouch(int tx, int ty) { if (tx x tx xw ty y ty yh) { return true; } return false; } void setPressed(bool state, TFT_eSPI tft) { pressed state; color state ? TFT_DARKBLUE : TFT_BLUE; draw(tft); // 重绘按钮 } }; // 在主程序中使用 Button myBtn(100, 200, 120, 60, Click Me); myBtn.draw(tft); // 在loop的触摸检测中 if (touched) { if (myBtn.checkTouch(x, y)) { myBtn.setPressed(true, tft); // 执行按钮动作... delay(200); myBtn.setPressed(false, tft); } }通过这种方式你可以逐步搭建起自己的简单 UI 系统。对于更复杂的界面可以考虑移植 LVGL 库到 reTerminal 的 Arduino 环境但这需要更多的移植和调试工作。4. 传感器数据采集与融合应用reTerminal 板载的传感器是其另一大亮点让我们能轻松为项目添加环境感知能力。4.1 六轴 IMU加速度计陀螺仪数据读取IMU 芯片通常是 MPU6050 或 ICM-20948通过 I2C 通信。我们可以使用流行的Adafruit_MPU6050或MPU6050_light库。#include Adafruit_MPU6050.h #include Adafruit_Sensor.h #include Wire.h Adafruit_MPU6050 mpu; void setup() { Serial.begin(115200); while (!Serial) delay(10); if (!mpu.begin()) { Serial.println(Failed to find MPU6050 chip); while (1) { delay(10); } } Serial.println(MPU6050 Found!); mpu.setAccelerometerRange(MPU6050_RANGE_8_G); // 设置量程 mpu.setGyroRange(MPU6050_RANGE_500_DEG); mpu.setFilterBandwidth(MPU6050_BAND_21_HZ); // 设置滤波器带宽 } void loop() { sensors_event_t a, g, temp; mpu.getEvent(a, g, temp); // 获取数据 Serial.print(Accel X:); Serial.print(a.acceleration.x); Serial.print(, ); Serial.print(Y:); Serial.print(a.acceleration.y); Serial.print(, ); Serial.print(Z:); Serial.print(a.acceleration.z); Serial.println( m/s^2); Serial.print(Gyro X:); Serial.print(g.gyro.x); Serial.print(, ); Serial.print(Y:); Serial.print(g.gyro.y); Serial.print(, ); Serial.print(Z:); Serial.print(g.gyro.z); Serial.println( rad/s); Serial.print(Temperature:); Serial.print(temp.temperature); Serial.println( degC); delay(500); }数据解读与滤波原始 IMU 数据噪声很大直接使用会抖动严重。对于加速度计可以通过低通滤波器来平滑数据获取稳定的重力方向或检测震动。对于陀螺仪其数据是角速度积分可以得到角度但存在漂移。通常需要结合加速度计能提供绝对姿态参考但动态响应差和陀螺仪动态响应好但会漂移进行互补滤波或卡尔曼滤波得到更稳定的姿态角俯仰、横滚、偏航。网上有大量开源的 Arduino 滤波库如ComplementaryFilter或MadgwickAHRS可以集成使用。4.2 环境光传感器应用环境光传感器如 LTR-553ALS可以自动调节屏幕亮度或者根据环境光强触发某些操作。它通常也是 I2C 设备。#include Wire.h // 假设使用 Seeed 提供的 Grove 库或者根据传感器手册实现 #include Seeed_Arduino_LTR553ALS.h LTR553ALS lightSensor; void setup() { Serial.begin(115200); while (!Serial); if (!lightSensor.init()) { Serial.println(Light sensor init failed!); while(1); } } void loop() { uint16_t visibleLight, infrared; if (lightSensor.get_als_data(visibleLight, infrared)) { Serial.printf(Visible: %d lux, Infrared: %d\n, visibleLight, infrared); // 根据光照自动调节屏幕背光假设背光可通过PWM控制 int brightness map(visibleLight, 0, 1000, 50, 255); // 映射亮度值 brightness constrain(brightness, 50, 255); // analogWrite(TFT_BL, brightness); // 控制背光引脚PWM } delay(1000); }实操心得IMU 和光传感器的 I2C 地址可能与 reTerminal 的扩展接口上的其他设备冲突。务必使用i2cdetect命令在 reTerminal 的 Linux 终端中运行扫描 I2C 总线确认各设备的地址。在 Arduino 代码中如果库支持也需要正确设置地址。4.3 传感器数据可视化将传感器数据实时显示在屏幕上是调试和演示的绝佳方式。结合前面学到的图形库我们可以轻松实现。// 在setup中初始化屏幕和传感器 // 在loop中 void loop() { // 1. 读取传感器数据如加速度计X轴 sensors_event_t a, g, temp; mpu.getEvent(a, g, temp); float accelX a.acceleration.x; // 2. 清空上一帧的特定区域局部刷新以提高性能 tft.fillRect(50, 100, 200, 20, TFT_BLACK); // 清空数值显示区 tft.setTextColor(TFT_CYAN); tft.drawString(Accel X:, 50, 100); tft.drawFloat(accelX, 2, 120, 100); // 显示两位小数 // 3. 绘制实时波形图简化示例 static int graphX 300; int graphY map(accelX, -10, 10, 50, 250); // 将加速度值映射到屏幕Y坐标 tft.drawPixel(graphX, graphY, TFT_GREEN); graphX; if (graphX 500) { graphX 300; tft.fillRect(300, 50, 200, 200, TFT_BLACK); // 清空波形图区域 } // 4. 根据数据改变UI状态 if (abs(accelX) 5.0) { // 如果震动剧烈 tft.fillCircle(400, 400, 30, TFT_RED); tft.drawString(SHAKE!, 370, 390); } else { tft.fillCircle(400, 400, 30, TFT_GREEN); tft.drawString(Steady, 370, 390); } delay(50); // 控制刷新率 }这种数据可视化方法非常直观对于监控系统状态、调试算法参数、制作数据仪表盘都很有帮助。5. 高级功能与系统集成掌握了核心外设后我们可以探索一些更高级的用法让 reTerminal 的能力更上一层楼。5.1 用户按键与 GPIO 扩展口的使用reTerminal 通常有几个用户可编程按键如 Home、Back和一组标准的 40-pin GPIO 排针兼容树莓派。这些 GPIO 可以用来连接更多的传感器、执行器、通信模块等。用户按键这些按键通常已经被映射到了特定的 GPIO 引脚并可能配有上拉电阻。在 Arduino 中你可以像读取普通数字输入一样读取它们。#define HOME_BUTTON_PIN 25 // 具体引脚号需查手册 #define BACK_BUTTON_PIN 24 void setup() { pinMode(HOME_BUTTON_PIN, INPUT_PULLUP); // 启用内部上拉 pinMode(BACK_BUTTON_PIN, INPUT_PULLUP); } void loop() { if (digitalRead(HOME_BUTTON_PIN) LOW) { // 按键按下为低电平 Serial.println(Home button pressed); // 执行返回主页操作例如清屏显示主菜单 while(digitalRead(HOME_BUTTON_PIN) LOW) delay(10); // 等待释放 } if (digitalRead(BACK_BUTTON_PIN) LOW) { Serial.println(Back button pressed); // 执行返回上一级操作 while(digitalRead(BACK_BUTTON_PIN) LOW) delay(10); } }GPIO 扩展口这 40 个引脚包含了电源、地、I2C、SPI、UART、PWM 等多种接口。你可以连接 DS18B20 温度传感器、继电器模块、舵机、RFID 读卡器等。使用方法与在普通 Arduino 或树莓派上无异但需要注意电平兼容性reTerminal GPIO 是 3.3V。重要警告GPIO 排针直接连接到 CM4 的处理器引脚操作不当极易造成硬件损坏。务必注意切勿带电插拔连接外部模块前务必断开 reTerminal 电源。确认电压确保外部模块是 3.3V 电平兼容的。如果是 5V 模块必须使用电平转换器。注意驱动能力GPIO 引脚输出电流有限通常几个mA驱动继电器、电机等大电流设备必须通过三极管或MOS管隔离驱动。防止短路仔细检查接线避免电源和地短路。5.2 利用 Linux 系统能力这是 reTerminal 运行完整 Linux 系统带来的巨大优势。你的 Arduino 程序可以通过“系统调用”来执行一些超出传统单片机范畴的任务。文件读写你可以将传感器数据记录到 CSV 文件中。#include SD.h // 可能需要额外库或者使用Linux系统调用 // 更简单的方式使用Process类如果支持或直接调用系统命令 // 例如在loop中定期将数据追加到文件 void logData(float value) { char cmd[128]; sprintf(cmd, echo %lu,%.2f /home/pi/sensor_data.csv, millis(), value); system(cmd); // 调用系统命令 }注意频繁调用system()开销较大。对于高性能日志可以考虑在 Arduino 程序中打开一个文件描述符进行持续写入或者使用更高效的 IPC 方式与另一个后台进程通信。网络通信虽然 Arduino 代码本身可以集成网络库如WiFi、Ethernet但在 reTerminal 上你更可以直接利用系统的网络栈。例如通过curl命令发送 HTTP 请求到云平台。void sendToCloud(float temp) { char cmd[256]; sprintf(cmd, curl -X POST http://api.thingspeak.com/update?api_keyYOUR_KEYfield1%.2f, temp); system(cmd); }调用 Python 脚本你可以用 Arduino 处理实时控制和传感器读取然后将数据传递给更擅长数据处理的 Python 脚本进行分析或上传。void runPythonAnalysis() { system(python3 /home/pi/analyze_data.py ); // 后台运行Python脚本 }实操心得混合编程时要处理好进程间通信和资源竞争。例如如果 Arduino 程序和 Python 脚本都要写同一个文件就需要用文件锁flock来避免数据损坏。另外system()调用是阻塞的可能会影响实时性对于关键控制循环要谨慎使用。5.3 性能优化与稳定性考量reTerminal 性能强大但不当使用也会卡顿或出问题。图形优化局部刷新只重绘屏幕上发生变化的部分而不是整个屏幕。tft.setAddrWindow()和tft.pushColors()可以实现矩形区域更新。使用双缓冲在内存中创建一块和屏幕一样大的缓冲区TFT_eSPI支持createSprite所有绘图操作先在缓冲区完成然后一次性pushSprite到屏幕可以消除闪烁。简化图形减少抗锯齿、复杂几何图形的使用。内存管理Linux 环境下的 Arduino 程序内存管理不如单片机严格但仍需注意。避免在循环中动态分配大块内存如String拼接防止内存碎片。对于需要频繁使用的缓冲区在全局或setup中静态分配。程序守护与自启动我们希望项目上电就能运行。可以将编译好的 Arduino 程序通常是一个可执行文件添加到系统服务中。在 reTerminal 上创建一个 systemd 服务文件例如/etc/systemd/system/my-arduino-app.service。[Unit] DescriptionMy Arduino Application Afternetwork.target [Service] Typesimple Userpi WorkingDirectory/home/pi ExecStart/home/pi/my_arduino_sketch.elf # 你的程序路径 Restarton-failure RestartSec5 [Install] WantedBymulti-user.target然后执行sudo systemctl enable my-arduino-app.service和sudo systemctl start my-arduino-app.service。这样你的 Arduino 应用就能在系统启动时自动运行并在崩溃后自动重启。6. 项目实战打造一个环境监测仪表盘让我们综合运用所有知识构建一个简单的环境监测仪表盘。这个项目将显示实时传感器数据、绘制历史趋势图并通过触摸屏提供交互。6.1 系统架构设计数据层在loop()中定时如每秒读取 IMU温度和环境光传感器数据。显示层主屏幕分为几个区域标题区、实时数值显示区、光强波形图区、温度历史趋势图区、按钮区。使用TFT_eSPI的Sprite实现双缓冲避免闪烁。实时数值区直接显示最新数据。波形图区用滚动方式显示最近一段时间的光强变化。温度趋势图区每 10 秒记录一个点显示更长时间段的变化。交互层两个触摸按钮“记录”按钮按下后将当前数据追加到日志文件。“清屏”按钮清除波形图和趋势图。系统集成使用 Linux 系统调用将“记录”的数据写入/home/pi/log.csv文件。6.2 核心代码片段这里展示关键部分的代码思路#include TFT_eSPI.h #include Adafruit_MPU6050.h #include Seeed_Arduino_LTR553ALS.h TFT_eSPI tft TFT_eSPI(); TFT_eSprite graphSprite TFT_eSprite(tft); // 用于波形图的精灵 Adafruit_MPU6050 mpu; LTR553ALS lightSensor; // 数据结构 float temperatureHistory[100]; // 存储最近100个温度值 int historyIndex 0; uint16_t lightHistory[200]; // 存储最近200个光强值 int lightIndex 0; // 按钮定义区域 #define BTN_REC_X 50 #define BTN_REC_Y 400 #define BTN_CLR_X 200 #define BTN_CLR_Y 400 #define BTN_W 100 #define BTN_H 50 void setup() { // 初始化串口、屏幕、传感器... tft.init(); tft.setRotation(1); graphSprite.createSprite(400, 150); // 创建波形图精灵 // ... 其他初始化 drawStaticUI(); // 绘制静态UI元素标题、坐标轴等 } void loop() { uint32_t now millis(); static uint32_t lastSensorRead 0; static uint32_t lastGraphUpdate 0; // 1. 定时读取传感器 if (now - lastSensorRead 1000) { lastSensorRead now; sensors_event_t a, g, temp; mpu.getEvent(a, g, temp); float currentTemp temp.temperature; uint16_t currentLight 0; uint16_t ir; lightSensor.get_als_data(currentLight, ir); // 更新历史数据 temperatureHistory[historyIndex] currentTemp; historyIndex (historyIndex 1) % 100; lightHistory[lightIndex] currentLight; lightIndex (lightIndex 1) % 200; // 更新实时数值显示 updateDisplay(currentTemp, currentLight); } // 2. 定时更新波形图 if (now - lastGraphUpdate 100) { lastGraphUpdate now; updateLightGraph(); updateTempTrend(); graphSprite.pushSprite(150, 150); // 将精灵推送到屏幕指定位置 } // 3. 处理触摸 uint16_t tx, ty; if (tft.getTouch(tx, ty)) { handleTouch(tx, ty); delay(150); // 触摸去抖 } } void handleTouch(int x, int y) { if (x BTN_REC_X x BTN_REC_XBTN_W y BTN_REC_Y y BTN_REC_YBTN_H) { // 记录按钮被按下 logToFile(temperatureHistory[(historyIndex-1100)%100], lightHistory[(lightIndex-1200)%200]); drawButton(BTN_REC_X, BTN_REC_Y, TFT_GREEN, Logged!); delay(300); drawButton(BTN_REC_X, BTN_REC_Y, TFT_BLUE, Record); } else if (x BTN_CLR_X x BTN_CLR_XBTN_W y BTN_CLR_Y y BTN_CLR_YBTN_H) { // 清屏按钮被按下 clearGraphs(); } } void logToFile(float temp, uint16_t light) { char cmd[128]; sprintf(cmd, echo %lu,%.2f,%d /home/pi/env_log.csv, millis()/1000, temp, light); system(cmd); }6.3 项目调试与部署在开发过程中充分利用串口打印调试信息。将程序设置为系统服务后可以通过sudo journalctl -u my-arduino-app.service -f来实时查看程序日志。如果屏幕显示异常检查User_Setup.h配置和屏幕旋转设置。如果触摸不准运行触摸校准程序。这个项目只是一个起点。你可以在此基础上增加更多功能比如网络同步使用curl或一个 Python 后台进程将数据同步到云端数据库如 InfluxDB或可视化平台如 Grafana。阈值报警当温度或光照超过设定值时让 RGB LED 闪烁或播放提示音。远程控制在 reTerminal 上运行一个简单的 Web 服务器如使用ESP8266WebServer库的移植版通过浏览器远程查看数据或控制设备。通过这个完整的“菜谱”你应该已经掌握了使用 Arduino 驾驭 reTerminal E 系列板载外设的核心方法。从环境搭建到外设驱动从图形界面到传感器融合再到系统集成与项目实战这套组合拳能让你快速将创意转化为看得见、摸得着的交互式智能设备原型。记住硬件开发的乐趣在于动手和迭代多尝试多调试你会在 reTerminal 这块强大的画布上创造出更多有趣的作品。如果在实际操作中遇到任何问题回顾一下对应章节的“注意事项”和“实操心得”那里往往藏着解决问题的钥匙。