
前面我们学了舵机、超声波、红外遥控Arduino 已经能动、能看、能遥控了。但有个问题一直没解决——所有数据只能靠串口监视器看你得连电脑才能知道 Arduino 在干什么。今天这篇我们要给 Arduino 装上一块OLED 显示屏让它能独立显示文字、数字、图形彻底摆脱电脑的束缚。学完这篇你会完成三个项目文字显示在 OLED 上显示自定义文字和实时数据图形绘制画线、画圆、画矩形制作简易仪表盘综合项目智能测距仪超声波测距 OLED 实时显示做成一个独立的小设备一、OLED 显示屏是什么OLED有机发光二极管是一种自发光显示技术和 LCD 不同它不需要背光每个像素自己发光。OLED 的优势自发光黑色区域完全不亮对比度极高超薄模块非常薄适合嵌入各种项目低功耗只点亮需要的像素省电响应快刷新速度快适合动态显示常见规格Arduino 最常用的 OLED 模块是0.96 英寸 128×64 像素有蓝色、白色、双色上黄下蓝等颜色可选。二、通信方式I2C我们使用的 OLED 模块通过I2C 协议与 Arduino 通信只需要 4 根线引脚接到作用VCC5V或 3.3V供电GNDGND接地SCLA5I2C 时钟线SDAA4I2C 数据线I2C 是一种总线协议多个设备可以共用 SCL 和 SDA 两根线。每个设备有自己的地址Arduino 通过地址来区分它们。查找 I2C 地址OLED 模块的 I2C 地址通常是0x3C或0x3D。如果不确定可以用 I2C 扫描程序查找#include Wire.h void setup() { Serial.begin(9600); Wire.begin(); Serial.println( I2C 地址扫描 ); for (byte address 1; address 127; address) { Wire.beginTransmission(address); if (Wire.endTransmission() 0) { Serial.print(找到设备地址: 0x); Serial.println(address, HEX); } } Serial.println(扫描完成); } void loop() {}上传后打开串口监视器它会列出所有连接在 I2C 总线上的设备地址。三、安装必要的库需要安装两个库Adafruit SSD1306OLED 驱动库Adafruit GFX Library图形绘制库安装步骤菜单工具 → 管理库搜索Adafruit SSD1306安装搜索Adafruit GFX Library安装四、硬件清单元件数量作用Arduino Uno1块主控板面包板1块搭建电路0.96寸 OLEDI2C1个显示屏HC-SR04 超声波模块1个综合项目测距杜邦线若干连接元件五、电路接线OLED 接线VCC→ 接 5VGND→ 接 GNDSCL→ 接 Arduino 的A5SDA→ 接 Arduino 的A4HC-SR04 接线综合项目用VCC→ 接 5VGND→ 接 GNDTrig→ 接 Arduino 的D9Echo→ 接 Arduino 的D10六、实验一显示文字在 OLED 上显示Hello, Arduino!和实时更新的计数器。#include Wire.h #include Adafruit_GFX.h #include Adafruit_SSD1306.h // 屏幕参数 #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 // 没有复位引脚设为 -1 // 创建显示对象 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, Wire, OLED_RESET); int counter 0; void setup() { Serial.begin(9600); // 初始化 OLED if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println(OLED 初始化失败); for (;;); // 初始化失败停在这里 } Serial.println(OLED 初始化成功); // 清屏 display.clearDisplay(); // 设置文字大小1~5数字越大字越大 display.setTextSize(1); // 设置文字颜色SSD1306_WHITE 表示点亮像素 display.setTextColor(SSD1306_WHITE); // 设置光标位置x, y display.setCursor(0, 0); // 输出文字 display.println(Hello, Arduino!); display.println(----------------); display.println(OLED 显示测试); // 将缓冲区内容刷新到屏幕 display.display(); } void loop() { // 清屏 display.clearDisplay(); display.setTextSize(2); display.setCursor(0, 10); display.println(Counter:); display.setTextSize(3); display.setCursor(20, 35); display.println(counter); // 刷新显示 display.display(); counter; delay(500); }代码解读display.begin(SSD1306_SWITCHCAPVCC, 0x3C)初始化 OLED参数是 I2C 地址display.clearDisplay()清空屏幕只是清空缓冲区还没显示display.setTextSize(n)设置文字大小1 是最小数字越大字越大display.setCursor(x, y)设置下一个文字的起始位置display.println()写入文字到缓冲区display.display()把缓冲区的内容真正刷新到屏幕上注意所有display.println()只是写入缓冲区必须调用display.display()才会在屏幕上显示。这样设计是为了提高刷新效率——你可以一次性准备好所有内容再一次性刷新。七、实验二图形绘制OLED 不仅能显示文字还能画各种图形。我们用 Adafruit GFX 库提供的绘图函数来画。#include Wire.h #include Adafruit_GFX.h #include Adafruit_SSD1306.h #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, Wire, OLED_RESET); void setup() { display.begin(SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay(); // 画矩形边框 display.drawRect(0, 0, 128, 64, SSD1306_WHITE); // 画填充矩形 display.fillRect(5, 5, 40, 20, SSD1306_WHITE); // 画圆形 display.drawCircle(90, 32, 20, SSD1306_WHITE); // 画填充圆形 display.fillCircle(45, 45, 12, SSD1306_WHITE); // 画直线 display.drawLine(65, 45, 120, 45, SSD1306_WHITE); // 画三角形 display.drawTriangle(70, 55, 85, 45, 100, 55, SSD1306_WHITE); // 显示文字 display.setTextSize(1); display.setCursor(8, 8); display.setTextColor(SSD1306_BLACK); // 在白色背景上用黑色字 display.println(GFX); display.setTextColor(SSD1306_WHITE); display.setCursor(70, 58); display.println(Shapes); display.display(); } void loop() {}常用绘图函数函数作用drawPixel(x, y, color)画一个点drawLine(x1, y1, x2, y2, color)画直线drawRect(x, y, w, h, color)画矩形边框fillRect(x, y, w, h, color)画填充矩形drawCircle(x, y, r, color)画圆形边框fillCircle(x, y, r, color)画填充圆形drawTriangle(x1,y1, x2,y2, x3,y3, color)画三角形drawRoundRect(x, y, w, h, radius, color)画圆角矩形坐标系左上角是 (0, 0)x 向右增大y 向下增大。屏幕右下角是 (127, 63)。八、综合项目智能测距仪把超声波和 OLED 结合起来做一个独立的测距仪——不需要连电脑开机就能实时显示距离。#include Wire.h #include Adafruit_GFX.h #include Adafruit_SSD1306.h #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, Wire, OLED_RESET); const int trigPin 9; const int echoPin 10; void setup() { Serial.begin(9600); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); // 初始化 OLED display.begin(SSD1306_SWITCHCAPVCC, 0x3C); display.clearDisplay(); // 开机画面 display.setTextSize(2); display.setCursor(10, 10); display.println(Smart); display.setCursor(10, 35); display.println(Ranger); display.display(); delay(1500); } void loop() { // 测量距离 float distance measureDistance(); // 清屏 display.clearDisplay(); // 画边框 display.drawRect(0, 0, 128, 64, SSD1306_WHITE); // 标题 display.setTextSize(1); display.setCursor(30, 5); display.println(Distance Meter); // 分隔线 display.drawLine(0, 16, 128, 16, SSD1306_WHITE); // 显示距离大字体 display.setTextSize(3); display.setCursor(10, 25); display.print(distance, 1); // 保留1位小数 // 单位 display.setTextSize(2); display.setCursor(95, 30); display.print(cm); // 状态指示 display.setTextSize(1); display.setCursor(5, 55); if (distance 20) { display.println([!!!] DANGER); } else if (distance 50) { display.println([!!] WARNING); } else if (distance 100) { display.println([!] CAUTION); } else { display.println([OK] SAFE); } // 刷新显示 display.display(); delay(200); } float measureDistance() { digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); long duration pulseIn(echoPin, HIGH, 30000); if (duration 0) return 999.9; // 超时返回 999.9 return duration / 58.0; }效果开机显示 Smart Ranger 启动画面1.5 秒后进入测距模式测距模式实时显示距离数值大字体下方显示安全状态状态判断 20cm显示DANGER20~50cm显示WARNING50~100cm显示CAUTION 100cm显示SAFE这就是一个完整的独立设备了——不需要电脑不需要串口开机即用。九、OLED 显示技巧自定义大数字默认字体最大只有 5 号如果想要更大的数字可以手动绘制像素点阵或者使用 U8g2 库支持更多字体。显示中文Adafruit SSD1306 默认不支持中文。要显示中文需要准备中文字库取模工具生成将字库数据存入 Arduino 的 Flash 存储用display.drawBitmap()绘制中文显示比较复杂因为 Arduino Uno 的 Flash 空间有限32KB放不下完整的中文字库。如果需要中文显示建议使用 U8g2 库它内置了多种中文字体。动态刷新技巧如果整个屏幕都刷新会有闪烁感。可以只刷新变化的部分// 只清除数字区域不重绘边框和标题 display.fillRect(10, 25, 80, 25, SSD1306_BLACK); display.setTextSize(3); display.setCursor(10, 25); display.print(distance, 1); display.display();十、常见问题排查QOLED 什么都不显示检查 I2C 地址是否正确用扫描程序确认检查 SCL 接 A5SDA 接 A4确认display.begin()没有返回 falseQ显示内容模糊或有残影每次刷新前先调用display.clearDisplay()如果只更新部分内容确保清除区域覆盖了旧内容Q屏幕亮度太低可以在setup()中调整对比度display.ssd1306_command(SSD1306_SETCONTRAST); display.ssd1306_command(255); // 0~255255 最亮Q刷新速度太慢减少display.display()的调用频率或者只刷新变化的区域。十一、本篇小结回顾一下今天学到的核心知识OLED 原理自发光显示高对比度低功耗I2C 通信只需 SCL SDA 两根线通过地址区分设备Adafruit SSD1306 库初始化、清屏、设置光标、输出文字、刷新显示Adafruit GFX 库画点、线、矩形、圆形、三角形等图形缓冲区机制先写入缓冲区再一次性刷新到屏幕综合项目超声波 OLED 独立测距仪OLED 显示屏让 Arduino 项目从只能看串口升级为自带屏幕的独立设备。下一篇我们学习温湿度传感器 DHT11——让 Arduino 能够感知环境温度和湿度做一个气象站。