ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Arduino UNO电位器OLED舵机联动实验:模拟输入、PWM与显示详解

Arduino UNO电位器OLED舵机联动实验:模拟输入、PWM与显示详解 Arduino UNO 接电位器、OLED 和 SG90 舵机做联动验证是一个特别适合新人把三个知识点串起来的实验模拟输入读取、角度映射、PWM 舵机控制还有 I2C 屏幕显示。这个实验最终能实现的效果就是旋转电位器舵机跟着转角度OLED 实时显示当前角度值。如果你已经会单独点亮 OLED也单独转过舵机但还没有把它们组合成一个系统这个小项目恰恰能帮你补上“数据链路”这一步。我发现很多新手做到一半会卡住而且卡住的原因往往不在代码而在供电、共地、电位器量程、OLED 地址这类前置问题上。这篇文章按实际落地顺序写从器件选择、接线、库安装、代码拆解到故障排查尽量把每条判断依据都写清楚。做完之后你可以进一步把显示改成条形指示、加入按键校准、扩展成 ESP32 或 STM32 版本思路都能复用。1. 这个联动验证到底在解决什么问题1.1 三个元器件的职责边界电位器本质上是一个可调电阻接成类似分压电路之后中间抽头输出的电压会随着旋钮位置变化。Arduino UNO 的 A0 到 A5 引脚可以读取 0 到 5V 之间的电压并且内部把它量化为 0 到 1023 的数字量。SG90 是常见的小型模拟舵机接收频率大约 50Hz 的 PWM 信号用脉冲宽度来表示目标角度。对 Arduino UNO 来说通常不需要自己去算每个角度对应的脉宽用官方 Servo 库的servo.write(angle)就能把 0 到 180 度转换成对应的控制信号。OLED 模块承担的是反馈显示。这里用最常见也最适合这种实验的 0.96 寸 I2C SSD1306 屏。使用 I2C只要接两根信号线加电源线和地线就能完成通信对节约引脚很有帮助。1.2 数据链路是怎么串起来的联动系统的核心链路可以简化成电位器电压变化Arduino 的 ADC 把电压变成数字读数再把 0 到 1023 的读数映射到 0 到 180 的角度范围然后驱动舵机转动同时把角度值显示在 OLED 上。这三步看起来简单但每一步都有容易出问题的地方。例如电位器如果没接好ADC 读数不变化如果映射没加边界限制角度可能超出 0 到 180如果舵机供电不足转动时会抖动甚至整个主板复位如果 OLED 地址不对屏幕一直不显示内容。做联动验证真正要练的不是记住某个引脚能接哪个模块而是学会快速判断“问题到底出在模拟读取、逻辑转换、PWM 输出还是显示刷新”哪一层。1.3 这个项目适合谁做如果你的情况符合下面任意一条这个实验值得完整跑一遍刚学完 Arduino 数字输出还不太理解analogRead和map。尝试过 SG90 舵机但舵机只能在某个角度来回摆不知道怎么把旋钮和它关联起来。学会驱动 OLED 显示固定文字但不会根据传感器数值动态刷新。准备后续接触 ESP32、STM32、MicroPython 或 RTOS但希望先用最简单的 Arduino 逻辑打通概念。我更建议你把第一次测试拆成三步先把 OLED 单独显示成功再把舵机单独转到 90 度都正常之后才接电位器做联动。这样一旦出错你知道问题来自哪个部分而不是整块电路都连在一起时无从下手。2. 接线前先设计电位器的电学接入方式比哪根线更重要2.1 器件准备与基本参数确认先列一下我这次使用的器件供参考Arduino UNO 主板一块。10K 旋转电位器一个。SG90 舵机一个。0.96 寸 OLED 显示屏一块接口是 I2C控制芯片以 SSD1306 为主。面包板、跳线若干。OLED 有 I2C 版本也有 SPI 版本。如果你手里是 SPI 接口接法完全不同。下面内容按最常用 I2C 版本讲解。SG90 虽然型号很多常见参数大体接近红色线接电源正极、棕色线接地、橙色或黄色线接信号。实际引脚颜色可能因为厂商不同有差异所以接线前先看舵机上的标签不确定就不要凭颜色强行通电。2.2 Arduino UNO 接线表电位器有 3 个引脚通常左右两侧分别接 5V 和 GND中间抽头接 Arduino 的模拟输入。OLED 有 VCC、GND、SCL、SDA 四个引脚。SG90 有两根电源线加一根信号线。整体连接参考如下器件引脚Arduino UNO 引脚电位器左端例如顺时针最小端5V电位器右端例如逆时针最大端GND电位器中间抽头VoutA0OLEDVCC5VOLEDGNDGNDOLEDSCLA5OLEDSDAA4SG90 电源正极红/红色线外部 5V 电源或 UNO 5VSG90 电源负极棕/黑色线GND必须和 Arduin?共地SG90 信号线橙/黄色线D9我建议把电位器的两侧接成标准分压结构也就是左边接 5V右边接 GND中间抽头接 A0。如果你把两端的电源接反代码逻辑通常变成“向右转角度反而变小”这不会烧板但会干扰判断。2.3 SG90 的供电问题要提前想清楚SG90 这种小舵机启动瞬间和带动负载时会有一小段电流需求。只做一个旋转电位器联动测试时如果舵机不带额外负载很多 Uno 板可以直接从 5V 引脚给舵机供电同时用 USB 口给板子供电也能跑起来。但这里的问题在边界情况。如果舵机转动时碰到障碍物或者后续你用程序让它连续高频动作电流会高于普通 GPIO 能提供的水平。常见现象是舵机刚动一下Arduino 重启。OLED 突然花屏或熄灭。舵机发抖位置不准。这些大概率不是代码问题而是舵机电源吃掉了太多电流把整个板的电压拖下去了。更可靠的做法是给舵机准备独立 5V 电源然后把舵机电源的负极和 Arduino 的 GND 接到一起。共地非常重要。Arduino 通过 PWM 信号线告诉舵机要转到哪个角度信号线上比较的是电压差如果不共地Arduino 说“这是 0V”舵机侧的参考地却是别的电压控制信号就失去了意义。2.4 I2C OLED 接线最容易忽略的事SSD1306 的 I2C OLED 模块大多数会引出了 4 个引脚VCC、GND、SCL、SDA。其中 SCL 接 Arduino 的 A5SDA 接 A4。这个答案在任何 IDE 示例里都能看到但实际接线时很多人会把 SCL 和 SDA 接反或者把 VCC 和 GND 接反。接反之后OLED 可能不发亮也可能发亮但显示乱码。只要没有长期接反 VCC 和 GND通常模块不会立刻损坏但建议在上电前用万用表确认一下供电两端没有短路。另一个问题是OLED 模块上的 I2C 地址可能是 0x3C 或 0x3D不同商家的模块默认值不一样。代码里写的地址如果和模块不一致display.begin会失败屏幕没有反应。这个地址问题很常见后面我会专门写一个扫描程序。OLED 显示区域的每个像素点是由控制芯片的显示缓冲区决定的。不要用“通电后灯亮没亮”来判断 OLED 是否正常。SSD1306 的输出需要接收初始化指令如果主控没有正确初始化有些模块上电后并不会有稳定的完整画面。亮斑、半边显示、整体偏暗都不能作为接线成功的判定标准。3. Arduino IDE 环境准备、库安装与 I2C 探测3.1 先设置好板卡类型和端口连接 Arduino UNO 后在 Arduino IDE 的“工具-开发板”里选择 Arduino Uno。端口选择方面Windows 一般显示 COM 端口macOS 显示 /dev/cu.usbmodem 这样的设备节点。这一步骤似乎简单会影响后续编译和上传。选错板子时即使编译成功也可能出现无法上传或者主频配置不匹配的问题。如果上传时报找不到端口先检查 USB 线。很多短线只能供电不能传输数据。这类问题排在代码错误之前排查。3.2 安装 Adafruit SSD1306 和 Adafruit GFX 库OLED 显示驱动不用自己造轮子。Adafruit 提供了 SSD1306 驱动库而 SSD1306 库依赖 Adafruit GFX 图形库。在 Arduino IDE 的“工具-管理库”中分别搜索并安装Adafruit SSD1306Adafruit GFX安装结束后最好重启一次 IDE。IDE 有时在安装库之后不会马上识别新文件导致编译时报找不到头文件误导新人以为是代码问题。舵机控制不需要额外安装因为 Arduino IDE 内置了 Servo 库。文件顶部写#include Servo.h就能使用。如果你使用 U8g2 这类 OLED 库也能实现显示但它和 Adafruit 库的字库、API 不完全一致。为了避免把问题混在一起本文示例以 Adafruit SSD1306 为主线。你用另一套库也能学通思路只是代码里的函数名需要替换。3.3 用 I2C 扫描器确认 OLED 地址接线完成后先上传一个最简单的 I2C 扫描器确认 Arduino 能不能发现 OLED。代码逻辑是用Wire库遍历 1 到 127 号地址看哪些设备有回应。#include Wire.h void setup() { Wire.begin(); Serial.begin(9600); Serial.println(I2C Scanner); } void loop() { byte error, address; int nDevices 0; for (address 1; address 127; address) { Wire.beginTransmission(address); error Wire.endTransmission(); if (error 0) { Serial.print(I2C device found at address 0x); if (address 16) Serial.print(0); Serial.println(address, HEX); nDevices; } } if (nDevices 0) { Serial.println(No I2C device found); } delay(1000); }正常情况串口会打印类似I2C device found at address 0x3C的信息。如果没有发现设备先不要改代码按这个顺序排查SDA、SCL 是否分别接到 A4、A5。VCC、GND 是否反接。OLED 模块是否正常上电。有没有其他 I2C 设备占用同一组引脚。换一根短一点的杜邦线长线在 I2C 通信中也容易引起不稳定。这个扫描器值得保留以后接新传感器时还能用。4. 读取、映射、控制和显示核心代码拆解4.1 依赖与引脚声明完整示例代码顶部会包含四个组件I2C 通信、OLED 驱动、图形库和舵机库。#include Wire.h #include Adafruit_GFX.h #include Adafruit_SSD1306.h #include Servo.h #define OLED_ADDR 0x3C #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, Wire, OLED_RESET); Servo myServo; const int potPin A0; const int servoPin 9;OLED_RESET设为 -1表示没有使用专用复位引脚由库自行处理。假如你的 OLED 驱动板带 RST 引脚想手动控制复位可以把 -1 改成实际引脚号。myServo是一个舵机对象。Servo 库支持一个 UNO 同时控制多个舵机但每个舵机需要分配不同引脚。D9 和 D10 方向通常可用于此类实验但要注意 DMA 或定时器资源的边界后面如果你把舵机接到 D5 上代码也能编译只是不同引脚对应的定时器资源不同要查一下当前板卡支持范围。4.2 setup 里的初始化顺序有讲究当 OLED 初始化失败时如果继续往后跑屏幕不会显示任何有效内容。下面代码用一个死循环让程序停住同时用串口提示错误。void setup() { Serial.begin(9600); if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) { Serial.println(OLED init failed); while (1); } display.clearDisplay(); display.setTextColor(SSD1306_WHITE); display.setTextSize(2); display.setCursor(10, 8); display.print(Init OK); display.display(); myServo.attach(servoPin); myServo.write(0); delay(200); }这里有一个值得注意的细节先把 OLED 初始化再把舵机 attach。很多人习惯一上来就 attach但实际跑的时候如果 OLED 初始化失败程序还继续动作串口和屏幕都没有提示你会误以为代码逻辑有问题。舵机write(0)的目的是让程序启动后先把舵机拉到 0 度位置。这里不建议直接write(90)或write(180)因为舵机臂可能在通电瞬间先跳到一个不确定位置。先把目标角度定义成明确值之后再根据电位器读数改变角度逻辑更可控。delay(200)给舵机一点运动时间。追求稳定时可以在主循环里用millis()做时间管理而不是用阻塞式 delay。4.3 主循环里的模拟读取、滤波和映射主循环不是每秒钟都要做一次完整的显示与舵机刷新。显示和舵机需要一定的刷新间隔而电位器读数变化越快越容易出现毛刺和抖动。我的做法是设置一个固定的刷新周期例如 50 毫秒。只有到达刷新时间才读取电位器、计算角度、控制舵机并刷新 OLED。unsigned long previousMillis 0; const unsigned long refreshInterval 50; void loop() { unsigned long currentMillis millis(); if (currentMillis - previousMillis refreshInterval) { previousMillis currentMillis; long sum 0; for (int i 0; i 8; i) { sum analogRead(potPin); } int rawValue sum / 8; int angle map(rawValue, 0, 1023, 0, 180); angle constrain(angle, 0, 180); myServo.write(angle); updateDisplay(angle); } }每次刷新读 8 次模拟值取平均能减少一部分 ADC 抖动。代价是每次刷新会多花一点时间但对电位器这种缓慢变化的对象来说完全够用。map函数能把 0 到 1023 的 ADC 读数映射到 0 到 180 度。问题是真实电位器两端的电压不一定恰好是 0V 和 5V所以“向左转到尽头显示 8 度向右转到尽头显示 172 度”很常见。后面第 5 节专门讲怎么校准。4.4 OLED 显示函数OLED 的显示缓冲区需要先清屏再写内容最后调用display()才能真正把内容刷到屏幕上。void updateDisplay(int angle) { display.clearDisplay(); display.setTextSize(2); display.setCursor(10, 8); display.print(Angle:); display.setCursor(20, 30); display.print(angle); display.print( deg); display.drawRect(10, 52, 108, 8, SSD1306_WHITE); display.fillRect(10, 52, map(angle, 0, 180, 0, 108), 8, SSD1306_WHITE); display.display(); }画一个横向进度条可以帮助你更直观地判断当前角度。电位器向左转时角度变小白色填充条变短向右转填充条变长。文字和图形同时变化这时才算是完整的联动反馈。注意fillRect的宽度在角度等于 0 时会变成 0这没问题。如果你把角度值映射到进度条宽度时忘了用constrain在极端情况下宽度可能是负数Adafruit GFX 画出来的东西就可能出现异常所以主循环里的边界限制很重要。4.5 完整示例代码汇总把上面的段落整合成一份可直接烧录的代码#include Wire.h #include Adafruit_GFX.h #include Adafruit_SSD1306.h #include Servo.h #define OLED_ADDR 0x3C #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, Wire, OLED_RESET); Servo myServo; const int potPin A0; const int servoPin 9; const unsigned long refreshInterval 50; unsigned long previousMillis 0; void updateDisplay(int angle) { display.clearDisplay(); display.setTextSize(2); display.setCursor(10, 8); display.print(Angle:); display.setCursor(20, 30); display.print(angle); display.print( deg); display.drawRect(10, 52, 108, 8, SSD1306_WHITE); display.fillRect(10, 52, map(angle, 0, 180, 0, 108), 8, SSD1306_WHITE); display.display(); } void setup() { Serial.begin(9600); if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) { Serial.println(OLED init failed); while (1); } display.clearDisplay(); display.setTextColor(SSD1306_WHITE); display.setTextSize(2); display.setCursor(10, 8); display.print(Init OK); display.display(); myServo.attach(servoPin); myServo.write(0); previousMillis millis(); delay(200); } void loop() { unsigned long currentMillis millis(); if (currentMillis - previousMillis refreshInterval) { previousMillis currentMillis; long sum 0; for (int i 0; i 8; i) { sum analogRead(potPin); } int rawValue sum / 8; int angle map(rawValue, 0, 1023, 0, 180); angle constrain(angle, 0, 180); myServo.write(angle); updateDisplay(angle); } }如果你的 OLED 地址不是 0x3C把#define OLED_ADDR 0x3C改成扫描到的地址。如果屏幕显示方向和你预期不一样通常是电位器两端接反了交换 5V 和 GND。4.6 为什么不能每循环都刷新清屏简单写法可能是每轮循环都执行 clear、画字、write 舵机。实际上也能跑但会产生两个问题舵机控制信号会被高频重复写尤其在delay没有控制好时读数和刷新抖动会让舵机轻微发颤。OLED 清屏再写的操作会占用一定时间导致主循环节奏不稳定。更重要的是如果每轮循环都display.clearDisplay()你在串口打印调试信息的节奏也会和显示不同步。代码里设置 20Hz 或 10Hz 刷新率完全够用肉眼看起来已经足够平滑。5. 电位器量程校准和舵机角度边界5.1 为什么 ADC 读数不一定刚好是 0 和 1023很多新手看到map(rawValue, 0, 1023, 0, 180)就默认电位器转到最左会输出 0 度转最右会输出 180 度。实际上电位器的电器行程和机械行程未必完全重合接线接触电阻、面包板内阻、Arduino 模拟引脚内部结构都可能让两端读数偏离满量程。举个例子如果电位器左端接 5V但左端阻值并不是严格为 0那么中间抽头电压不会等于 5V。代码就会把它当成小于 1023 的值最终角度可能停在 178 度而不是 180 度。另外面板可调电位器两端如果接反读数也可能直接从这边开始跑。所以第一次启动时不要盯着舵机是否转到位先看串口打印的原始 ADC 值。5.2 在串口里确认真实边界调试时可以暂时用下面的调试代码代替联动刷新打印原始 ADC 值void loop() { int raw analogRead(potPin); Serial.print(raw ); Serial.println(raw); delay(200); }打开串口监视器把波特率设为 9600然后慢慢旋转电位器记录下最大值和最小值。很多 10K 电位器实际测出来可能是顺时针最小时后24逆时针最大后1018如果直接使用固定 0 到 1023舵机永远不会到 0 度和 180 度。验证时当然也能通过但如果你希望更精确可以把代码改成const int rawMin 20; const int rawMax 1018; int angle map(rawValue, rawMin, rawMax, 0, 180); angle constrain(angle, 0, 180);这里constrain依然不能省略。因为map是线性缩放当电位器读数偶尔低于rawMin或高于rawMax时angle会小于 0 或大于 180。舵机收到超出范围的write参数时有些库会把它当作合法角度范围外处理导致舵机试图转到非标位置甚至碰到机械限位发出卡卡声。5.3 Servo.write 并不是直接控制占空比Servo.write(angle)是用角度来配置脉宽。对于常见模拟舵机信号周期大约是 20mswrite(0)产生的脉宽很短write(180)产生的脉宽较长。这里不建议新手直接去查微秒数并调用writeMicroseconds。你确实能用下面这种方式写myServo.writeMicroseconds(1500);但不同舵机的中间值未必精确对应 1500 微秒。用角度模式更直观也更适合本实验。如果你想追求精确转动应该测量舵机臂在 0、90、180 度时实际到的位置再手动微调映射范围。舵机转动时一旦遇到机械阻力会持续尝试到达目标位置并产生抖动和电流。这个实验只是验证联动不要让舵机臂去顶住其他物体避免电流过大。5.4 显示角度和实际角度不一致如果你发现 OLED 上显示 90但舵机臂并不像垂直方向大概率是安装角度或舵机中位设置问题。还有一种可能是你先把手动设成了myServo.write(0)但舵机臂是随便拧上去的所以物理位置和程序角度没有校准关系。解决方法是启动时先让舵机转到 0 度再把舵机臂与舵机输出轴按合理方向安装。或者把舵机臂拆下来把程序主角度跑到 90 度后再装臂。这样显示值和物理位置才会一致。6. 什么才叫联动验证成功判断标准要具体化6.1 三个观察点都出现才算是跑通第一个观察点是电位器读数变化。旋转电位器时串口打印的数值跟随变化OLED 和舵机也跟随变化。第二个观察点是舵机角度变化。电位器转小圈舵机角度变小转大圈舵机角度变大。舵机不能在原地发抖也不能出现刚转一会儿就重启的现象。第三个观察点是 OLED 显示内容。OLED 上角度数值实时变化进度条长度至少视觉上能对应舵机位置。如果舵机已经转到左边屏幕却还显示 90 度说明刷新逻辑或映射逻辑没有同步。如果三个观察点全部符合可以判定联动验证成功。之后再去调刷新周期、加按键、改串口打印格式都不迟。6.2 建议的验证步骤建议按下面顺序执行每步都有明确结果先跑 I2C 扫描器串口能看到 OLED 地址。看不到就先把接线处理掉。上传不带动舵机的测试代码确认 OLED 能显示Init OK。注释掉 OLED 相关代码单独让舵机转到某个角度确认舵机供电和能力正常。加入电位器读取串口打印raw值和映射后的angle确认逻辑正确。最后把myServo.write(angle)和updateDisplay(angle)放回主循环。这套顺序看起来繁琐但能减少“代码看着没问题硬件一接电就各种怪现象”的挫败感。特别是 OLED 和舵机同时工作后如果复位不稳定往往会同时出现两个问题这时很难一次定位。6.3 OLED 刷新的一个判断细节当角度从 45 度变到 46 度舵机转动非常小OLED 显示可能因为刷新率太低而看起来不变。可以把刷新间隔调成 20ms或者加入串口打印辅助观察。但刷新率调高之后要留意 Arduino UNO 在每次 OLED 清屏和画图之间的时间开销。毕竟 ATmega328P 性能有限Adafruit GFX 绘制一条线段时要逐个像素地更新缓冲区。对这个小项目完全没压力但如果你后续想同时跑更多任务就要评估主循环耗时。建议在代码关键位置使用millis()做时间测量把一次循环总耗时打印出来。这比凭感觉判断“卡不卡”要准确得多。7. 常见故障排查先供电再接线最后看日志7.1 典型故障与排查顺序下面表格里的问题基本就是硬件开发中最常见的几类。现象优先排查方向说明OLED 无显示SDA/SCL 接反、地址错误、VCC/GND 接反先跑 I2C 扫描器OLED 显示乱码或花屏接线松动、地线不共地、I2C 线过长缩短跳线重新按压排针舵机不动信号线引脚、供电、共地先单独驱动到固定角度测试舵机抖动供电电流不足、刷新间隔太短单独供电或把刷新间隔调大主板复位SG90 耗电拉低电压给舵机独立 5V 电源并共地角度范围只有一小段电位器量程映射不对用串口读取真实 ADC 边界显示数值跳变ADC 噪声、电位器接触不良多次采样平均检查面包板接触上电前先看电源。如果舵机和 OLED 都从 UNO 5V 引脚取电同时 USB 口供电质量又一般就可能出现主板复位或 OLED 亮屏后又被拉灭的现象。更稳妥的硬件结构是把 SG90 接到外部 5VOLED 继续接 UNO 5V两个电源都共地。这里的“外部电源”不需要特别复杂。很多 5V USB 电源模块就可以给舵机供电关键是电源负极要和 Arduino GND 连接。如果不共地控制信号永远不正常。7.2 OLED “通电就亮吗”与模块常见的误解SSD1306 OLED 和普通 LCD 不太一样每个像素是自发光器件主控通过 I2C 向控制芯片写入显示缓冲区数据才能控制哪些像素点亮。有人以为只要插上电源OLED 就应该显示漂亮菜单。其实没有初始化时模块很可能显示不出任何完整内容或者只有某个区域发亮。正确做法是用代码初始化并写内容不要依赖“通电默认效果”。另外I2C OLED 模块的漂移问题也容易和显示花屏混在一起。Arduino UNO 的 I2C 引脚一般有内部上拉或板载上拉电阻但当你使用长杜邦线连接时信号波形可能畸变。如果花屏时有时无先换短线再检查 SDA、SCL 是否被其他器件占用。7.3 舵机卡住、发抖、启动跳变怎么办舵机在 setup 阶段从当前位置跳到目标位置这是常见现象。比如你先手动把舵机臂拧到 90 度程序一启动舵机立刻跳到 0 度。这不是故障而是舵机在执行目标角度。如果你不希望上电瞬间舵机乱跳可以把舵机臂在启动后延迟一段时间再执行大幅度动作或者在硬件上先不给舵机供电等程序稳定后再接通舵机电源。发抖则优先怀疑供电。很多 SG90 实验出现间歇性重启不是代码死循环而是电源电流不足。可以用万用表测舵机电源端的电压启动瞬间如果电压掉到 4V 以下就需要加强供电了。这个判断比反复改代码更快。7.4 后续扩展方向这个联动验证做完后你可以做几个扩展难度逐步增加把 OLED 上的数字显示改成更精细的弧形仪表盘。加入两个电位器分别控制舵机的角度和 OLED 进度条阈值。加入按键长按按键后进入校准模式让 OLED 提示用户转动电位器两端。把固定刷新间隔改成可配置参数观察不同刷新率对舵机和 OLED 的影响。把代码移植到 ESP32 或 STM32 上理解不同平台的 ADC 精度、PWM 定时器和 I2C 驱动差异。很多项目看着功能多本质仍然是“传感器读取、数值映射、执行器输出、界面显示”这个循环。你把这个 Arduino UNO 版本的电位器、OLED、SG90 联动验证跑通一次后面换平台换器件思维路径也基本一致。这套联动里最需要先跑稳的其实不是 OLED 显示也不是舵机能不能转到某个角度而是电源、共地、刷新周期和映射边界。把这几个基础点想清楚你会少走很多弯路。
返回列表