news 2026/9/5 19:37:36

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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 数字输出,还不太理解analogReadmap
  • 尝试过 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
电位器中间抽头VoutA0
OLEDVCC5V
OLEDGNDGND
OLEDSCLA5
OLEDSDAA4
SG90 电源正极红/红色线外部 5V 电源或 UNO 5V
SG90 电源负极棕/黑色线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 的 A5,SDA 接 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 SSD1306
  • Adafruit 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)是用角度来配置脉宽。对于常见模拟舵机,信号周期大约是 20ms,write(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 建议的验证步骤

建议按下面顺序执行,每步都有明确结果:

  1. 先跑 I2C 扫描器,串口能看到 OLED 地址。看不到就先把接线处理掉。
  2. 上传不带动舵机的测试代码,确认 OLED 能显示Init OK
  3. 注释掉 OLED 相关代码,单独让舵机转到某个角度,确认舵机供电和能力正常。
  4. 加入电位器读取,串口打印raw值和映射后的angle,确认逻辑正确。
  5. 最后把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 接到外部 5V,OLED 继续接 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 显示,也不是舵机能不能转到某个角度,而是电源、共地、刷新周期和映射边界。把这几个基础点想清楚,你会少走很多弯路。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/5 19:35:03

一个人+49个AI员工:多Agent协作如何重塑游戏开发工作流

一个人 49 个 AI 员工&#xff1a;组建完整游戏工作室 &#xff5c;SSP Github Daily 1. “一个人开公司”已经从概念变成可复制的工程方案 我第一次看到“一个人 49 个 AI 员工组建游戏工作室”这个标题时&#xff0c;第一反应是又一个噱头。但真正顺着 SSP 那条 GitHub D…

作者头像 李华
网站建设 2026/9/5 19:30:10

Matlab实现Attention-LSTM时间序列预测:原理、代码与避坑指南

简介&#xff1a;本资源是一份面向人工智能初学者与时间序列建模实践者的MATLAB教学型项目&#xff0c;聚焦于提升LSTM在复杂时序预测任务中的关键信息捕捉能力。通过将注意力机制嵌入LSTM网络&#xff0c;有效缓解传统RNN对长程依赖建模不足的问题&#xff0c;适用于电力负荷预…

作者头像 李华
网站建设 2026/9/5 19:29:41

Intel核显本地部署大模型:Ollama量化调参与踩坑全攻略

先说实话&#xff1a;我这台电脑没有独立显卡&#xff0c;只有一块不算新的 Intel 核显。前阵子被“本地大模型”这几个字挠得心痒&#xff0c;想在自己机器上部署一套能离线对话、能接 API 的模型&#xff0c;结果照着网上大量“默认你有 N 卡”的教程一路硬踩&#xff0c;翻车…

作者头像 李华
网站建设 2026/9/5 19:27:06

从零搭建AI编程工作流:工具选型、关键节点与实战避坑指南

这两年&#xff0c;我花在AI编程上的时间越来越多&#xff0c;手里的“AI编程工作流”也换了好几茬工具。一开始我觉得&#xff0c;所谓AI编程不就是打开对话框提问、把代码复制过来、再手动粘进项目里吗&#xff1f;直到我被一段又一段“看起来对但跑不起来”的代码反复折磨后…

作者头像 李华
网站建设 2026/9/5 19:26:04

DA1459x双核蓝牙SoC开发实战:从最小广播到稳定连接排查指南

一次做入门级双核蓝牙 SoC DA1459x 系列开发实战演示时&#xff0c;QA 环节里第一个问题非常典型&#xff1a;示例工程编译通过&#xff0c;固件也烧进去了&#xff0c;板子上的 LED 在闪&#xff0c;手机却一直搜不到设备。问的人第一反应是去改广播间隔、换调试工具&#xff…

作者头像 李华