亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

Arduino Nano 七段数码管时钟 - DS3231 RTC 与 LDR 自动亮度

所需组件与材料

组件数量备注
Arduino Nano R3 (或 Uno)1主控板
Adafruit 1.2" 4位 七段数码管 + I2C 背包 (绿色)1HT16K33 驱动,I2C 地址 0x70
DS3231 RTC 模块1带 CR1220 纽扣电池座,比 DS1307 更精准且含温度传感器
光敏电阻 (LDR)1配合 100kΩ 电阻分压
100kΩ 电阻1LDR 分压用
面包板 & 杜邦线若干
CR1220 纽扣电池1RTC 备用电源

所需软件

项目特点

接线指南

模块引脚Arduino Nano
DS3231 / 七段管 (共用 I2C)VCC5V
GNDGND
SDAA4
SCLA5
LDR 分压电路LDR 一端5V
LDR 另一端A0 (模拟输入)
100kΩ 电阻A0 与 GND 之间

RTC 初始化(设置时间)

首次使用需将 DS3231 时间设置为当前时间。可使用 Adafruit 的 ds3231_set_time 示例,或通过串口发送指令。时间将写入 RTC 并由纽扣电池维持,断电不丢失。

完整代码 (v1.1 修正版)

// MyClock v1.1 - Ingo Lohs
// Hardware: Arduino Uno/Nano (ATmega328P)
// Libraries: Wire, Adafruit_GFX, Adafruit_LEDBackpack

#include <Wire.h>
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"

#define DS3231_I2C_ADDRESS 0x68

int ldr_sensor = A0;
int ldr_value = 0;
int brightness_matrix = 15;
int threshold_brightness = 400;  // 环境光阈值,需实测调整
int blinkrate_value = 0;
int delay_matrix_time = 20000;   // 时间显持续 20 秒 (单位 ms)
int delay_matrix_temp = 2000;    // 温度显示 2 秒
int blinky_dot = 2;

Adafruit_7segment matrix = Adafruit_7segment();

byte decToBcd(byte val) { return (val / 10 * 16) + (val % 10); }
byte bcdToDec(byte val) { return (val / 16 * 10) + (val % 16); }

void setup() {
  Serial.begin(9600);
  Wire.begin();
  matrix.begin(0x70);
}

void loop() {
  lightBrightness();
  matrixBlinkrate();
  displayTime();
  displayTemp();
}

void lightBrightness() {
  ldr_value = analogRead(ldr_sensor);
  Serial.print("LDR: "); Serial.println(ldr_value);
  // LDR 值越小 = 光线越强
  if (ldr_value <= threshold_brightness) {
    brightness_matrix = 15;  // 白天最高亮
  } else {
    brightness_matrix = 0;   // 夜间最暗
  }
}

void matrixBlinkrate() {
  matrix.blinkRate(blinkrate_value);
}

void displayTime() {
  matrix.setBrightness(brightness_matrix);
  matrix.clear();

  for (uint16_t i = 0; i < delay_matrix_time / 1000; i++) {  // 简化:每秒更新一次
    byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
    getDateDs3231(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);

    // 夏/冬令时自动切换 (欧洲规则:周日 dayOfWeek == 1)
    // 夏令时:3 月最后一个周日 2:00 -> 3:00
    if ((dayOfWeek == 1) && (dayOfMonth >= 25) && (month == 3) && (hour == 2)) {
      setDS3231time(second, minute, 3, dayOfWeek, dayOfMonth, month, year);
    }
    // 冬令时:10 月最后一个周日 3:00 -> 2:00 (year=1 标记夏令时)
    if ((dayOfWeek == 1) && (dayOfMonth >= 25) && (month == 10) && (hour == 1) && (year != 1)) {
      setDS3231time(second, minute, hour, dayOfWeek, dayOfMonth, month, 1);
    }
    if ((dayOfWeek == 1) && (dayOfMonth >= 25) && (month == 10) && (hour == 3) && (year == 1)) {
      setDS3231time(second, minute, 2, dayOfWeek, dayOfMonth, month, 0);
    }

    // 显示时分 HH:MM
    if (hour > 9) {
      matrix.writeDigitNum(0, hour / 10, false);
      matrix.writeDigitNum(1, hour % 10, false);
    } else {
      matrix.writeDigitNum(1, hour, false);
    }

    // 左侧双点随秒数上下翻转:前 30 秒显下点,后 30 秒显上点
    if (second <= 30) blinky_dot = 10;  // 下点 + 中间冒号
    else blinky_dot = 6;                // 上点 + 中间冒号
    matrix.writeDigitRaw(2, blinky_dot);

    matrix.writeDigitNum(3, minute / 10, false);
    matrix.writeDigitNum(4, minute % 10, false);
    matrix.writeDisplay();

    // 中间冒号每秒闪烁
    delay(500);
    matrix.drawColon(false);
    matrix.writeDisplay();
    delay(500);
  }
}

void displayTemp() {
  matrix.setBrightness(brightness_matrix);
  matrix.clear();

  byte temp = get3231Temp();
  int abs_temp = abs(temp);

  // 显示温度,支持负数
  if (temp < 0) matrix.writeDigitRaw(0, 0x40);  // 负号
  if (temp <= -10) matrix.writeDigitRaw(2, 0x0C); // 十位负号位置调整

  if (temp >= 10 || temp <= -10) matrix.writeDigitNum(0, abs_temp / 10, false);
  matrix.writeDigitNum(1, abs_temp % 10, false);
  matrix.writeDigitRaw(3, 0x63);  // '°' 符号
  matrix.writeDigitRaw(4, 0x39);  // 'C' 符号
  matrix.writeDisplay();

  Serial.print("Temperature C: "); Serial.println(get3231Temp());
  delay(delay_matrix_temp);
}

void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year) {
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0);
  Wire.write(decToBcd(second));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));
  Wire.write(decToBcd(dayOfWeek));    // 1=周日, 7=周六
  Wire.write(decToBcd(dayOfMonth));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.endTransmission();
}

void getDateDs3231(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year) {
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}

float get3231Temp() {
  byte tMSB, tLSB;
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x11);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 2);
  if (Wire.available() >= 2) {
    tMSB = Wire.read();
    tLSB = Wire.read();
    float temp3231 = (tMSB & 0x7F);           // 符号位处理
    temp3231 += ((tLSB >> 6) * 0.25);         // 小数部分 0.25 度分辨率
    if (tMSB & 0x80) temp3231 = -temp3231;    // 负温度
    return temp3231;
  } else {
    Serial.println("DS3231 Sensor Error - cant read temperature");
    matrix.print(0xBEEF, HEX);
    matrix.writeDisplay();
    delay(5000);
    return 0;
  }
}

进阶扩展建议

源码仓库

GitHub - ILohs/MySketches

制造工艺

  1. Arduino POV 时钟:自制视觉暂留 LED 显示器
  2. 复古 Numitron 管时钟:Arduino Nano 驱动,低温可靠省电
  3. 用 Adafruit 60 LED NeoPixel 环形灯和 Arduino 制作时尚挂钟
  4. 自制 Arduino 伊斯兰祷告时间实时时钟
  5. 自制大尺寸LED主时钟带闹钟功能 — 12米外清晰可见
  6. Arduino Due 驱动 3.2″ TFT 实现温度监测与实时时钟
  7. Arduino Nano + 摇杆控制双步进电机:Visuino 图形化教程
  8. DIY Arduino 智能手表:打造属于你的 Apple Watch 风格腕表
  9. 用 Arduino Pro Mini 与 DS1302 RTC 打造精准七段数码管时钟
  10. Arduino Nano 手持盖革计数器:DIY 核辐射检测仪
  11. 手把手打造Arduino Nano喂食机器人
  12. 用 DS1302 RTC 和 Arduino UNO 制作可靠闹钟