RRoy 发表于 2022-7-13 15:33:26

用ESP8266做一个迷你的时钟

本帖最后由 RRoy 于 2022-7-13 15:33 编辑




本周分享一个迷你但功能齐全的时钟项目,带有RGB效果,兼具温度监测功能。
第1步:材料准备



[*]NodeMCU (ESP8266)
[*]定制PCB板
[*]连接线
[*]电池 5v



构思


用NodeMCU显示时间,用Arduino监测温度;可以选择在每秒钟改变显示的颜色。

迷你LED的额定电压是3.0V到5.5V,16mA(每个LED)。

我们的NodeMCU有3.3V的稳压器,可以正常驱动所有的LED。

第2步:LED WS2812B 3030


这里使用了WS2812 NeoPixel Led,它带有集成的IC,这样我们就可以对每段进行单独寻址。不仅LED是可寻址的,而且还可以改变每个像素的颜色(改变0-255(8位值)的数字值)。

LED有4个引脚,此外,这些LED具有数据输入和数据输出功能,通过这些功能,我们可以把它们连接起来,显示文字或数据。


第3步:使用NeoPixel Led制作


要制作这个面板,首先我们可以仔细观察一下实际的液晶显示器。这样我们就可以复制段的排列,并为它编写代码。

在上图,各段被命名为A、B、C、D、E、F、G,为了连接所有的段,我们使用串联数据和平行电源的方法:所有的电源线,GND和VCC被并联到所有的LED上;数据输出被提供给串联的下一个LED的数据输入;把第一个面板的Dout连接到第二个面板的Din。


第4步:连接




为了连接小时和分钟的面板,我们在两者之间放一个小的PCB板,就是上图中的"Dash"。


第5步:NodeMCU/ESP8266


ESP8266集成了一个32位Tensilica处理器,标准的数字外围接口。

ESP8266具有板载Wi-Fi支持,利用它可以通过互联网调整时间而不需要任何RTC(实时时钟)模块。这样减少了连接,可以使整个项目变得更简单一些。

如果你使用下面的代码,那么可以在这个7段时钟中添加两个额外的功能。


第6步:温度和湿度


在13号针脚上添加一个DHT11传感器,在12号针脚上添加一个触觉按钮,这样我们就可以在屏幕上获得摄氏或华氏的温度值。

用一个10k电阻将按钮的12号针脚连接到5V,另一端连接到GND。也就是说,当按钮针脚被拉到GND时,显示器将显示温度读数。

如果没有这个温度传感器,代码也可以正常运行,所以如果你想保持尽可能简单的话,可以不需要这些连接。


第7步:亮度控制


通过在A0引脚上做一个电阻分压器网络,添加一个带有10k电阻的LDR传感器,可以相应地改变亮度。

白天的亮度高,晚上的亮度低。

如果你不想要可调节的亮度,下面的代码也可以在没有这些传感器的情况下正常运行,它会保持默认设置。


第8步:7段时钟




我在EasyEDA中设计了电路,这里使用了3个LED。因此,每块面板总共需要21个LED。

底层做了连接引脚,这样别人就看不到连接和布线了。

CPL、BOM和Gerber文件在GitHub仓库:

https://github.com/halfstudents/ESP8266-Wi-Fi-based-7-Segment-Display-clock

或者也可以在文末打包下载。


第9步:连接




使用上面的原理图连接NodeMCU。

这边用到的软件是Cirkit Designer,一个非常不错的软件。

平时你可以在学校演示的时候用这个线图、面包板电路以及创建一些自定义组件。另外,它最近还增加了代码编译、BOM和一些新的元件。

使用Cirkit Designer,我们可以绘制出逼真的电路图,这些电路图与物料清单相连接,这样就可以无缝订购电路中的部件。

Windows、Linux、Mac都可以使用,下载地址:https://www.cirkitstudio.com/download.html


第10步:代码部分

首先用librarie初始化代码:

#include <ESP8266WiFi.h>
#include <Adafruit_NeoPixel.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <TimeLib.h>
#include <DHT.h>
#include <Adafruit_Sensor.h>



定义所有Pixels、I/O引脚、传感器引脚:
#define PIXEL_PER_SEGMENT 3 // Number of LEDs in each Segment
#define PIXEL_DIGITS 4 // Number of connected Digits
#define PIXEL_PIN 2 // GPIO Pin
#define PIXEL_DASH 1 // Binary segment
#define LDR_PIN A0 // LDR pin
#define DHT_PIN 13 // DHT Sensor pin
#define BUTTON_PIN 12 // Button pin



调整时间,使用Wi-Fi连接互联网到ESP8266:

WiFi.begin(ssid, password);
Serial.print("Connecting.");
while ( WiFi.status() != WL_CONNECTED )


Pixel上的时间设置:

void disp_Time() {
clearDisplay();
writeDigit(0, Hour / 10);
writeDigit(1, Hour % 10);
writeDigit(2, Minute / 10);
writeDigit(3, Minute % 10);
writeDigit(4, Second / 10);
writeDigit(5, Second % 10);
disp_Dash();

面板显示的颜色设置:

if (index == 0 || index == 1 ) color = strip.Color(0, Brightness, 0);
if (index == 2 || index == 3 ) color = strip.Color(0, Brightness, 0);
if (index == 4 || index == 5 ) color = strip.Color(Brightness, 0, 0);

完整代码:

#include <ESP8266WiFi.h>
#include <Adafruit_NeoPixel.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <TimeLib.h>
#include <DHT.h>
#include <Adafruit_Sensor.h>

#define PIXEL_PER_SEGMENT3   // Number of LEDs in each Segment
#define PIXEL_DIGITS       4   // Number of connected Digits
#define PIXEL_PIN          2   // GPIO Pin
#define PIXEL_DASH         1    // Binary segment

#define LDR_PIN       A0    // LDR pin
#define DHT_PIN       13    // DHT Sensor pin
#define BUTTON_PIN    12    // Button pin

// Uncomment the type of sensor in use
#define DHT_TYPE    DHT11   // DHT 11
//#define DHT_TYPE    DHT22   // DHT 22 (AM2302)
//#define DHT_TYPE    DHT21   // DHT 21 (AM2301)

#define TIME_FORMAT      12    // 12 = 12 hours format || 24 = 24 hours format

Adafruit_NeoPixel strip = Adafruit_NeoPixel((PIXEL_PER_SEGMENT * 7 * PIXEL_DIGITS) + (PIXEL_DASH * 2), PIXEL_PIN, NEO_GRB + NEO_KHZ800);
DHT dht(DHT_PIN, DHT_TYPE);

// set Wi-Fi SSID and password
const char *ssid   = "Hackster";
const char *password = "*************";

WiFiUDP ntpUDP;
// 'time.nist.gov' is used (default server) with +1 hour offset (3600 seconds) 60 seconds (60000 milliseconds) update interval
NTPClient timeClient(ntpUDP, "time.nist.gov", 19800, 60000); //GMT+5:30 : 5*3600+30*60=19800

int period = 2000;   //Update frequency
unsigned long time_now = 0;
int Second, Minute, Hour;

// set default brightness
int Brightness = 40;
// current temperature, updated in loop()
int Temperature;

bool Show_Temp = false;

//Digits array
byte digits = {
//abcdefg
0b1111110,   // 0
0b0110000,   // 1
0b1101101,   // 2
0b1111001,   // 3
0b0110011,   // 4
0b1011011,   // 5
0b1011111,   // 6
0b1110000,   // 7
0b1111111,   // 8
0b1110011,      // 9
0b1001110,   // C
0b1000111,   // F
};

//Clear all the Pixels
void clearDisplay() {
for (int i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, strip.Color(0, 0, 0));
}
strip.show();
}

void setup() {
Serial.begin(115200);
strip.begin();
strip.show();

dht.begin();
pinMode(BUTTON_PIN, INPUT);

WiFi.begin(ssid, password);
Serial.print("Connecting.");
while ( WiFi.status() != WL_CONNECTED ) {
    delay(500);
    Serial.print(".");
}
Serial.println("connected");
timeClient.begin();
delay(10);
}

void loop() {
if (WiFi.status() == WL_CONNECTED) { // check WiFi connection status
    int sensor_val = analogRead(LDR_PIN);
    Brightness =40;
    timeClient.update();
    int Hours;
    unsigned long unix_epoch = timeClient.getEpochTime();   // get UNIX Epoch time
    Second = second(unix_epoch);                            // get seconds
    Minute = minute(unix_epoch);                            // get minutes
    Hours= hour(unix_epoch);                              // get hours

    if (TIME_FORMAT == 12) {
      if (Hours > 12) {
      Hour = Hours - 12;
      }
      else
      Hour = Hours;
    }
    else
      Hour = Hours;
}

if (digitalRead(BUTTON_PIN) == LOW) {
    Show_Temp = true;
}
else
    Show_Temp = false;

if (Show_Temp) {
    Temperature = dht.readTemperature();
    Serial.println(Temperature);
    clearDisplay();
    writeDigit(0, Temperature / 10);
    writeDigit(1, Temperature % 10);
    writeDigit(2, 10);
    strip.setPixelColor(28, strip.Color(Brightness, Brightness,Brightness));
    strip.show();
    delay(3000);
    clearDisplay();
    Show_Temp = false;
}
while (millis() > time_now + period) {
    time_now = millis();
    disp_Time();   // Show Time
}
}

void disp_Time() {
clearDisplay();
writeDigit(0, Hour / 10);
writeDigit(1, Hour % 10);
writeDigit(2, Minute / 10);
writeDigit(3, Minute % 10);
writeDigit(4, Second / 10);
writeDigit(5, Second % 10);
disp_Dash();
strip.show();
}

void disp_Dash() {
int dot, dash;
for (int i = 0; i < 2; i++) {
    dot = 2 * (PIXEL_PER_SEGMENT * 7) + i;
    for (int j = 0; j < PIXEL_DASH; j++) {
      dash = dot + j * (2 * (PIXEL_PER_SEGMENT * 7) + 2);
      Second % 2 == 0 ? strip.setPixelColor(dash, strip.Color(0,Brightness ,0)) : strip.setPixelColor(dash, strip.Color(0, Brightness,0));
    }
}
}

void writeDigit(int index, int val) {
byte digit = digits;
int margin;
if (index == 0 || index == 1 ) margin = 0;
if (index == 2 || index == 3 ) margin = 1;
if (index == 4 || index == 5 ) margin = 2;
for (int i = 6; i >= 0; i--) {
    int offset = index * (PIXEL_PER_SEGMENT * 7) + i * PIXEL_PER_SEGMENT + margin * 2;
    uint32_t color;
    if (digit & 0x01 != 0) {
      if (index == 0 || index == 1 ) color = strip.Color(Brightness, 0,Brightness);
      if (index == 2 || index == 3 ) color = strip.Color(Brightness, 0,Brightness);
      if (index == 4 || index == 5 ) color = strip.Color(Brightness, 0,0);
    }
    else
      color = strip.Color(0, 0, 0);

    for (int j = offset; j < offset + PIXEL_PER_SEGMENT; j++) {
      strip.setPixelColor(j, color);
    }
    digit = digit >> 1;
}
}


第11步:完整电路图



第12步:PCB设计




这是主要的PCB设计,用于显示数字和其他字母。

这个项目涉及到的所有文件,可以在文末打包下载。


第13步:故障处理



[*]“Din”与“Dout”是串联在一起的,如果接反了或从哪里断开了,整个装置就会停止工作。
[*]如上图所示,连接“Dash”部分。
[*]确保所有的连接都焊接好了,干焊会导致数据值和颜色的改变。
[*]在焊接的时候,注意PCB温度不要太高。


原文链接:https://www.instructables.com/ES ... ment-Display-Clock/

GitHub仓库链接:https://github.com/halfstudents/ ... gment-Display-clock

项目作者:sainisagar7294



糖醋花生 发表于 2022-7-17 18:09:44

@ASH腻你好像很爱加精华呀

糖醋花生 发表于 2022-7-17 18:10:47

3D打印件呢???

糖醋花生 发表于 2022-7-18 17:34:53

有人么

peter3 发表于 2022-7-21 15:13:12

感觉还缺少一个外壳,这样的光太刺眼了,无法直视把。

peter3 发表于 2022-7-21 15:14:23

另外,建议下个版本可以把esp8266贴在钟的pcb的背面,不然esp8266还要放外面

8U7U3ZxTTS3T 发表于 2022-7-21 23:35:33

厉害!也可以用Nano.

俺是胡胡 发表于 2022-7-22 09:13:12

厉害,颜值爱了

派大星ym 发表于 2022-7-29 11:13:14

厉害厉害   8266yyds

发表于 2022-7-29 11:23:55

peter3 发表于 2022-7-21 15:14
另外,建议下个版本可以把esp8266贴在钟的pcb的背面,不然esp8266还要放外面

裘老师你入驻DF啦?

发表于 2022-7-29 11:25:44

这个PCB是用立创EDA设计的不?
页: [1]
查看完整版本: 用ESP8266做一个迷你的时钟