回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

【Arduino 动手做】3D打印的 7 段数字大时钟 简单

头像 驴友花雕 2025.07.11 4 0

3D-7 段数字时钟

这是我制作的另一个自制数字时钟的源代码和架构。这是 YouTube 视频的链接

请记住,打印所有部分需要很长时间,而且在日光下不是很亮。 您可以在此处从 Play Story 下载 Android 应用:https://play.google.com/store/apps/details?id=nl.leonvandenbeukel.BTDigitalClockApp

打印说明

为了获得更好的对比度,最好将以下部分打印为黑色:

  • 块之间
  • BewteenSegments
  • 点环
  • 点底
  • 中间
  • OuterRingSegments (外环分段)

其余部分可以用白色打印。


00.jpg01.jpg01-.jpg01-0.jpg01-1.jpg01-2.jpg01-3.jpg02.jpg03.jpg04.jpg

项目代码

 

代码
/*
 * MIT License
 * 
 * Copyright (c) 2018 Leon van den Beukel
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 * 
 * Source: 
 * https://github.com/leonvandenbeukel/3D-7-Segment-Digital-Clock
 * 
 * External libraries you need:
 * Adafruit Sensor Library:   https://github.com/adafruit/Adafruit_Sensor
 * Adafruit RTCLib:           https://github.com/adafruit/RTClib
 * FastLED:                   https://github.com/FastLED/FastLED
 * Timer Library:             https://github.com/JChristensen/Timer
 */

#include <DHT.h>
#include <DHT_U.h>
#include <FastLED.h>
#include <Wire.h>
#include "RTClib.h"
#include <SoftwareSerial.h>
#include "Timer.h"

#define DHTPIN 12
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

#define NUM_LEDS 30     
#define DATA_PIN 6
CRGB LEDs[NUM_LEDS];

SoftwareSerial BTserial(8, 9);
RTC_DS3231 rtc;
Timer t1;
Timer t2;
Timer t3;

String btBuffer;
CRGB colorCRGB = CRGB::Red;           // Change this if you want another default color, for example CRGB::Blue
CHSV colorCHSV = CHSV(95, 255, 255);  // Green
CRGB colorOFF  = CRGB(20,20,20);      // Color of the segments that are 'disabled'. You can also set it to CRGB::Black
volatile int colorMODE = 1;           // 0=CRGB, 1=CHSV, 2=Constant Color Changing pattern
volatile int mode = 0;                // 0=Clock, 1=Temperature, 2=Humidity, 3=Scoreboard, 4=Time counter
volatile int scoreLeft = 0;
volatile int scoreRight = 0;
volatile long timerValue = 0;
volatile int timerRunning = 0;

#define blinkDots   0                 // Set this to 1 if you want the dots to blink in clock mode, set it to value 0 to disable
#define hourFormat  24                // Set this to 12 or to 24 hour format
#define temperatureMode 'C'           // Set this to 'C' for Celcius or 'F' for Fahrenheit

void setup () {

  // Initialize LED strip
  FastLED.delay(3000);

  // Check if you're LED strip is a RGB or GRB version (third parameter)
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(LEDs, NUM_LEDS);

  Serial.begin(9600);
  while (!Serial) { /* Wait until serial is ready */ }

  BTserial.begin(9600);
  Serial.println("BTserial started at 9600");

  dht.begin();

  if (!rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
    
  t1.every(1000 * 29, refreshDisplay); 
  t2.every(1000, refreshTimer);
  t3.every(50, updateHue);
  refreshDisplay();
}

void loop () {
  
  t1.update(); 
  t2.update();
  t3.update();

  if (BTserial.available())
  {
    char received = BTserial.read();
    btBuffer += received; 

    if (received == '|')
    {
        processCommand();
        btBuffer = "";
    }
  }
}

void updateHue() {
  if (colorMODE != 2)
    return;
    
  colorCHSV.sat = 255;
  colorCHSV.val = 255;
  if (colorCHSV.hue >= 255){
    colorCHSV.hue = 0;
  } else {
    colorCHSV.hue++;
  }
  refreshDisplay();
}

void refreshDisplay() {
  switch (mode) {
    case 0:
      displayClock();
      break;
    case 1:
      displayTemperature();
      break;
    case 2:
      displayHumidity();
      break;
    case 3:
      displayScoreboard();
      break;      
    case 4:
      // Time counter has it's own timer
      break;
    default:   
      break; 
  }
}

void refreshTimer() {

  if (mode == 0 && blinkDots == 1) {    
    displayDots(3);
  } else if (mode == 4 && timerRunning == 1 && timerValue < 6000) {
    timerValue++;

    int m1 = (timerValue / 60) / 10 ;
    int m2 = (timerValue / 60) % 10 ;
    int s1 = (timerValue % 60) / 10;
    int s2 = (timerValue % 60) % 10;
  
    displaySegments(0, s2); 
    displaySegments(7, s1);
    displaySegments(16, m2);    
    displaySegments(23, m1);  
    displayDots(0);  
    FastLED.show();
  }
}

void processCommand(){

  if (btBuffer.startsWith("RGBD")) {
    long R = getValue(btBuffer, ',', 1).toInt();
    long G = getValue(btBuffer, ',', 2).toInt();
    long B = getValue(btBuffer, ',', 3).toInt();
    long D = getValue(btBuffer, ',', 4).toInt();
    colorCRGB.red = R;
    colorCRGB.green = G;
    colorCRGB.blue = B;
    colorMODE = 0;
    if (D > 0) FastLED.setBrightness(D); 
  } else if (btBuffer.startsWith("HSVD")) {
    long H = getValue(btBuffer, ',', 1).toInt();
    long S = getValue(btBuffer, ',', 2).toInt();
    long V = getValue(btBuffer, ',', 3).toInt();
    long D = getValue(btBuffer, ',', 4).toInt();
    colorCHSV.hue = H;
    colorCHSV.sat = S;
    colorCHSV.val = V;
    colorMODE = 1;
    if (D > 0) FastLED.setBrightness(D);
  } else if (btBuffer.startsWith("RTC")) {
    long y = getValue(btBuffer, ',', 1).toInt();
    long m = getValue(btBuffer, ',', 2).toInt();
    long d = getValue(btBuffer, ',', 3).toInt();
    long h = getValue(btBuffer, ',', 4).toInt();
    long mm = getValue(btBuffer, ',', 5).toInt();
    long s = getValue(btBuffer, ',', 6).toInt();
    rtc.adjust(DateTime(y, m, d, h, mm, s));
    Serial.println("DateTime set");
  } else if (btBuffer.startsWith("CLOCK")) {
    mode = 0;    
  } else if (btBuffer.startsWith("TEMPERATURE")) {
    mode = 1;    
  } else if (btBuffer.startsWith("HUMIDITY")) {
    mode = 2;
  } else if (btBuffer.startsWith("SCOREBOARD")) {
    scoreLeft = getValue(btBuffer, ',', 1).toInt();
    scoreRight = getValue(btBuffer, ',', 2).toInt();
    mode = 3;    
  } else if (btBuffer.startsWith("STARTTIMER")) {
    timerValue = 0;
    timerRunning = 1;
    mode = 4;    
  } else if (btBuffer.startsWith("STOPTIMER")) {
    timerRunning = 0;
    mode = 4;    
  } else if (btBuffer.startsWith("CHANGINGPATTERN")) {
    colorMODE = 2;
  }
  
  refreshDisplay();
}

void displayClock() {   
  DateTime now = rtc.now();

  int h  = now.hour();
  if (hourFormat == 12 && h > 12)
    h = h - 12;
  
  int hl = (h / 10) == 0 ? 13 : (h / 10);
  int hr = h % 10;
  int ml = now.minute() / 10;
  int mr = now.minute() % 10;

  displaySegments(0, mr);    
  displaySegments(7, ml);
  displaySegments(16, hr);    
  displaySegments(23, hl);  
  displayDots(0);  
  FastLED.show();
}

void displayTemperature() {
  float tmp = dht.readTemperature(temperatureMode == 'F' ? true : false);

  if (isnan(tmp)) {
    Serial.println("Failed to read from DHT sensor!");
  } else {
    int tmp1 = tmp / 10;
    int tmp2 = ((int)tmp) % 10;
    displaySegments(23, tmp1);    
    displaySegments(16, tmp2);
    displaySegments(7,  10);    
    displaySegments(0, (temperatureMode == 'F' ? 14 : 11));
    displayDots(1);  
    FastLED.show();    
  }  
}

void displayHumidity() {
  float hum = dht.readHumidity();

  if (isnan(hum)) {
    Serial.println("Failed to read from DHT sensor!");
  } else {
    int hum1 = hum / 10;
    int hum2 = ((int)hum) % 10;
    displaySegments(23, hum1);    
    displaySegments(16, hum2);
    displaySegments(7,  10);    
    displaySegments(0,  12);
    displayDots(1);  
    FastLED.show();    
  }  
}

void displayScoreboard() {
  int s1 = scoreLeft % 10;
  int s2 = scoreLeft / 10;
  int s3 = scoreRight % 10;
  int s4 = scoreRight / 10;
  displaySegments(0, s3);    
  displaySegments(7, s4);
  displaySegments(16, s1);    
  displaySegments(23, s2);
  displayDots(2);  
  FastLED.show();  
}

void displayDots(int dotMode) {
  // dotMode: 0=Both on, 1=Both Off, 2=Bottom On, 3=Blink
  switch (dotMode) {
    case 0:
      LEDs[14] = colorMODE == 0 ? colorCRGB : colorCHSV;
      LEDs[15] = colorMODE == 0 ? colorCRGB : colorCHSV; 
      break;
    case 1:
      LEDs[14] = colorOFF;
      LEDs[15] = colorOFF; 
      break;
    case 2:
      LEDs[14] = colorOFF;
      LEDs[15] = colorMODE == 0 ? colorCRGB : colorCHSV; 
      break;
    case 3:
      LEDs[14] = (LEDs[14] == colorOFF) ? (colorMODE == 0 ? colorCRGB : colorCHSV) : colorOFF;
      LEDs[15] = (LEDs[15] == colorOFF) ? (colorMODE == 0 ? colorCRGB : colorCHSV) : colorOFF;
      FastLED.show();  
      break;
    default:
      break;    
  }
}

void displaySegments(int startindex, int number) {

  byte numbers[] = {
    0b00111111, // 0    
    0b00000110, // 1
    0b01011011, // 2
    0b01001111, // 3
    0b01100110, // 4
    0b01101101, // 5
    0b01111101, // 6
    0b00000111, // 7
    0b01111111, // 8
    0b01101111, // 9   
    0b01100011, // º              10
    0b00111001, // C(elcius)      11
    0b01011100, // º lower        12
    0b00000000, // Empty          13
    0b01110001, // F(ahrenheit)   14
  };

  for (int i = 0; i < 7; i++) {
    LEDs[i + startindex] = ((numbers[number] & 1 << i) == 1 << i) ? (colorMODE == 0 ? colorCRGB : colorCHSV) : colorOFF;
  } 
}

String getValue(String data, char separator, int index) {
  int found = 0;
  int strIndex[] = {0, -1};
  int maxIndex = data.length()-1;

  for(int i=0; i<=maxIndex && found<=index; i++){
    if(data.charAt(i)==separator || i==maxIndex){
        found++;
        strIndex[0] = strIndex[1]+1;
        strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }

  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}

【Arduino 动手做】3D打印的 7 段数字大时钟
项目链接:https://github.com/leonvandenbeukel/3D-7-Segment-Digital-Clock
项目作者:KCCP

项目视频:https://www.youtube.com/watch?v=tvGPeV5hQNM
项目代码:https://github.com/leonvandenbeukel/3D-7-Segment-Digital-Clock/blob/master/3D-7-Segment-Digital-Clock.ino
3D打印文件:https://github.com/leonvandenbeukel/3D-7-Segment-Digital-Clock/tree/master/STL

 

00186---.gif

评论

user-avatar
icon 他的勋章
    展开更多