ESP32开发板I2C OLED显示屏运行自定义程序无输出求助
问题描述
编写了如下ESP32程序,意图通过RTC模块获取时间,在I2C OLED显示屏上展示太阳和月亮的移动轨迹,但显示屏始终黑屏,无任何内容输出。已确认硬件及连接无故障,运行时钟示例程序时显示屏可正常显示时间和日期,无法定位问题原因。
#include <Adafruit_GFX.h> #include <Adafruit_SH110X.h> #include <ThreeWire.h> #include <RtcDS1302.h> ThreeWire myWire(4,5,2); // IO, SCLK, CE RtcDS1302<ThreeWire> Rtc(myWire); #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels #define i2c_Address 0x3c // initialize with the I2C addr 0x3C Typically eBay OLED's #define OLED_RESET -1 // QT-PY / XIAO Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // define the sunrise and sunset times int sunrise_hour = 6; int sunset_hour = 18; void setup() { Rtc.Begin(); delay(250); // wait for the OLED to power up display.begin(i2c_Address, true); // Address 0x3C default display.clearDisplay(); display.setTextSize(1); display.setTextColor(SH110X_WHITE); display.setCursor(2, 2); display.println("Calendar"); display.display(); } void loop() { // get the current date and time unsigned int year, month, day; unsigned int hour, minute, second; RtcDateTime now = Rtc.GetDateTime(); year = now.Year(); month = now.Month(); day = now.Day(); hour = now.Hour(); minute = now.Minute(); second = now.Second(); // clear the display and set the cursor to the top left corner display.clearDisplay(); display.setCursor(0, 0); // calculate the position of the sun based on the current time int sun_x = (hour * 12) + (minute / 5); // 12 pixels per hour, 1 pixel every 5 minutes int sun_y = (SCREEN_HEIGHT / 2) - abs(6 - minute % 12); // move up and down in a sine wave pattern // calculate the position of the moon based on the current time int moon_x = (hour * 12) + (minute / 5); int moon_y = (SCREEN_HEIGHT / 2) + abs(6 - minute % 12) + 20; // move down in a sine wave pattern // check if it's before sunrise or after sunset if (hour < sunrise_hour || hour >= sunset_hour) { // draw the moon int moon_size = 8; int moon_color = SH110X_WHITE; display.fillCircle(moon_x, moon_y, moon_size, moon_color); } else { // draw the sun int sun_size = 10; int sun_color = SH110X_WHITE; display.fillCircle(sun_x, sun_y, sun_size, sun_color); } // display the changes on the OLED display.display(); delay(1000); // wait for 1 second }
问题排查与解决
图形位置超出屏幕可视范围:
原代码中sun_x和moon_x的计算方式为hour * 12 + minute /5,当hour超过10时,x坐标就会超过屏幕宽度128(比如10*12=120,加上minute/5就会超出),导致图形画在屏幕外无法看到。需要将24小时的时间范围映射到0-127的像素区间,修改计算式:// 太阳x坐标:将24小时映射到128像素宽度,包含分钟的细分 int sun_x = (hour * SCREEN_WIDTH)/24 + (minute * SCREEN_WIDTH)/(24*60); // 月亮x坐标同理 int moon_x = (hour * SCREEN_WIDTH)/24 + (minute * SCREEN_WIDTH)/(24*60);同时
moon_y的计算(SCREEN_HEIGHT / 2) + abs(6 - minute % 12) +20会导致y坐标最高达到32+6+20=58,加上月亮大小8后总高度66,超出屏幕高度64,部分或全部图形被裁切。可调整偏移量:int moon_y = (SCREEN_HEIGHT / 2) + abs(6 - minute % 12) + 10;RTC有效性未验证:
虽然时钟示例正常,但当前程序未验证RTC是否成功获取到有效时间,若RTC返回异常时间(比如hour为无效值),会导致逻辑判断错误。可在setup()中添加验证:void setup() { Rtc.Begin(); // 新增RTC有效性检查 if (!Rtc.IsDateTimeValid()) { delay(250); display.begin(i2c_Address, true); display.clearDisplay(); display.setTextSize(1); display.setTextColor(SH110X_WHITE); display.setCursor(2, 2); display.println("RTC Error"); display.display(); while(1); // 停在此处提示错误 } // 原有OLED初始化代码 delay(250); display.begin(i2c_Address, true); display.clearDisplay(); display.setTextSize(1); display.setTextColor(SH110X_WHITE); display.setCursor(2, 2); display.println("Calendar"); display.display(); }临时调试方法:
在loop()中添加时间文本显示,确认程序是否正确获取到RTC时间,以及图形位置计算是否合理:// 在draw太阳/月亮的代码后添加 display.setCursor(0, 0); display.print(hour); display.print(":"); display.print(minute); display.print(" | "); display.print("Sun:("); display.print(sun_x); display.print(","); display.print(sun_y); display.print(")");
内容的提问来源于stack exchange,提问作者Savad
相关产品推荐
相关产品推荐

