You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 00:37:07