|
本帖最后由 zgm1996 于 2024-6-9 20:48 编辑
整个改造过程跨度好几个月,今年二月份就改完了,终于今天坐下来把过程写写,供有改造想法的各位朋友参考。
先上主角照片:
关于万年历的来历:
据说 2014 年有一次老爹老娘出去串门,在亲戚家楼下垃圾箱里一眼就看见它了,刚被扔出来,玻璃面板都没破,两个小人儿还挺好看的,果断领回家。
据说回家通电发现只是调时间的 4 个按键氧化了按下去没反应,于是老爹果断的拆下按键,去了附近修家电的铺子换了 4 个按键花了 5 枚华币。
(为什么是据说?因为当年还在上学。等我中午回家表已经挂在墙上了)
血亏啊!!!这样的按键我抽屉里有啊!!!
想改造的起因是在每一次停电又送电之后,这个万年历的时间都会变回 09 年 12 月。
您问会不会是纽扣电池没电了?不可能,绝对不可能,这货自打 2014 年到家,每次来电都要重新调一遍的。
所以这块表在我家工作了即将 10 年,次次停电次次调。
忍无可忍,必须搞它。换个主控,升级一下!
先拆开看看,极度简洁:
220V 转 12V 的变压器直接接到板子,经过 4 个 1N4007 构成的整流桥之后,到了两个像三极管一样的东西,仔细一看,两个并联的 78L05,发热量巨大,上面的电容都烤黑了。
两个 78L05 并联电流最大也就 200 mA,改的时候拆下来换成 7805。
主控是一个34脚小板上的牛屎芯,实现了年月日、星期、时分、秒闪烁、农历、温度与按键调整时间。重制也要复现这些功能。
有 6 个 PNP 三极管 S8550,用于驱动6条“线”上的数码管;测温用的玻璃封装的 NTC 热敏电阻;至于扬声器,压根就没响过。
充分利用互联网资源,找到了这位老哥的改造先例:
“古董万年历升级WiFi授时 STM32+ESP8266” https://blog.csdn.net/qq_19262979/article/details/104857420
但由于我没用过 STM32(真是惭愧,有时间一定补上这块短板),考虑将全部功能都放在 ESP8266 上实现。
其中文章提到了另一位老哥的农历转换:
“农历和阳历互转(c语言)” https://www.cnblogs.com/liyang31tg/p/4123171.html
可以修改移植到 ESP8266 上为我所用。
于是有了以下方向:
ESP8266 快速验证想法,用 Arduino C 写。
ESP8266 内部 RTC 误差大,挂一个 PCF8563 做 RTC。
测温度,数字方案有 DS18B20,模拟方案可以继续利用万年历自带的 NTC 热敏电阻。
鉴于 Arduino IDE 及其难用的代码编辑器和每次都无脑重新编译全部的文件极耗时间的问题,改用 VSCode + PlatformIO。
PlatformIO 下只重新编译变动的文件,而且 VSCode 的各种好功能(格式化、高亮、跟踪跳转)都可以用起来了
PlatformIO编译环境搭建就不写了,互联网玄学,部署时请备好极为充足的耐心 + 降压药 或 仅出于必要的科研目的使用一下国际互联网。
下面开始动手:
继续利用互联网资源。
框架程序参考了“ESP8266 NodeMCU NTP Client-Server: Get Date and Time (Arduino IDE)” https://RandomNerdTutorials.com/esp8266-nodemcu-date-time-ntp-client-server-arduino/
这位外国老哥的示例只有 WI-FI 连接和 NTP 授时,靠 delay 控制每 2 秒获取一次时间,但讲解十分详细。
在此基础上,逐步添加 DS18B20 测温、PCF8563 时钟模块、农历、OLED 显示等功能,拼拼凑凑就改出了一个的万年历雏形。
PlatformIO 和 Arduino IDE 区别在于:
1、PlatformIO 中子函数要写在 void setup() 和 void loop() ,编译时才不会报找不到的错误,好多 Arduino IDE 编译没问题的 *.ino 的程序换成 PlatformIO 都要调顺序。
2、PlatformIO 要写 #include <Arduino.h>
- // 结构体 disp_info:存储全部显示数据
- struct display_data
- {
- unsigned short year;
- unsigned char month;
- unsigned char day;
- unsigned char weekday;
- unsigned char hour;
- unsigned char minute;
- unsigned char second;
- int lunar_month;
- int lunar_day;
- int temperature;
- int adc;
- } disp_info;
复制代码
DS18B20初始化,设置为非阻塞模式,转换完成后等待读取。
- void ds18B20_init(){
- sensors.begin(); //启动DS18B20
- sensors.setWaitForConversion(false); //设置DS18B20为非阻塞模式
- }
复制代码
OLED 显示,12864的屏,屏芯片 SSD1315,使用了 U8G2 库,为了避免烧屏,增加了滚动显示,每秒上/下移动一行:
- void oled_display(){
- // 清屏,设置初始位置
- u8g2.clearBuffer(); //清除缓冲区,不清除屏幕
- u8g2.setCursor(0, place+10);
- /*---------------------- 第一行 -------------------------------*/
- //年月日
- u8g2.setFont(u8g2_font_profont15_tf); //字号8x10
- u8g2.print(disp_info.year%100); // 只取年份后两位
- u8g2.print("-");
- u8g2.print(disp_info.mouth);
- u8g2.print("-");
- u8g2.print(disp_info.day);
- //星期
- u8g2.setCursor(64, place+10); // 星期位置固定
- u8g2.print("<");
- u8g2.print(disp_info.weekday);
- u8g2.print("> ");
- //农历
- u8g2.setCursor(88, place+10);
- if (disp_info.lunar_mouth<10){ // 靠右对齐,月份为个位数时补一个空格
- u8g2.print(" ");//1个
- }
- u8g2.print(disp_info.lunar_mouth);
- u8g2.print('-');
- u8g2.println(disp_info.lunar_day);
-
- /*---------------------- 第二行 -------------------------------*/
- //时分秒
-
- u8g2.setFont(u8g2_font_profont29_tf);
- if (disp_info.hour<10){ // 小时居中
- u8g2.setCursor(10, place+35);
- }
- else{
- u8g2.setCursor(0, place+35);
- }
- u8g2.print(disp_info.hour);
- u8g2.print(':');
- if (disp_info.minute<10){ // 分钟补零
- u8g2.print(0);
- }
- u8g2.print(disp_info.minute);
- u8g2.print(':');
- if (disp_info.second<10){ // 秒补零
- u8g2.print(0);
- }
- u8g2.println(disp_info.second);
- /*---------------------- 第三行 -------------------------------*/
- //温度
- u8g2.setCursor(5, place+52);
- u8g2.setFont(u8g2_font_profont15_tf);
- // u8g2.print("T:");
- u8g2.print(disp_info.temperature);
- u8g2.print(char(176));u8g2.print("C");
-
- //光强
- u8g2.setCursor(64, place+52);
- u8g2.print("ADC:");
- u8g2.println(disp_info.adc);
- u8g2.sendBuffer(); // 显示本次数据
- //修改下一次显示位置及设置滚动方向
- if (count_flag==0){
- place++;
- if (place>11){
- count_flag=1;
- }
- }
- else{
- place--;
- if (place==0){
- count_flag=0;
- }
- }
- }
复制代码
不加OLED 用串口显示也可以:
- void Serial_print(){
- Serial.print(disp_info.year);
- Serial.print("-");
- Serial.print(disp_info.mouth);
- Serial.print("-");
- Serial.print(disp_info.day);
- //星期
- Serial.print(" <");
- Serial.print(disp_info.weekday);
- Serial.print("> ");
- //农历
- Serial.print(disp_info.lunar_mouth);
- Serial.print('-');
- Serial.println(disp_info.lunar_day);
-
- //时分秒
- Serial.print(disp_info.hour);
- Serial.print(':');
- if (disp_info.minute<10){ // 分钟补零
- Serial.print(0);
- }
- Serial.print(disp_info.minute);
- Serial.print(':');
- if (disp_info.second<10){ // 秒补零
- Serial.print(0);
- }
- Serial.println(disp_info.second);
- //温度与光强
- Serial.print("T: ");
- Serial.print(disp_info.temperature);
- Serial.print("ºC ");
- Serial.print("ADC: ");
- Serial.println(disp_info.adc);
-
- Serial.println(""); //分隔下次数据
- }
复制代码
初始化程序:
- void setup() {
- Rtc.Begin(); //初始化PCF8563
- Serial.begin(115200); // 启动串口 设置波特率115200
- oled_init(); //初始化 OLED
- ds18B20_init(); //初始化 ds18B20
- int connect_flag = wifi_connect();
- if (connect_flag==1){
- set_time();
- }
- timer1.attach(1,every_second);
- }
- void loop() {
- // 主程序为空,核心程序在 every_second()
复制代码
秒刷新程序:
- void every_second(){
- RtcDateTime now = Rtc.GetDateTime();
- disp_info.year=now.Year();
- disp_info.mouth=now.Month();
- disp_info.day=now.Day();
- disp_info.weekday=now.DayOfWeek();
- using namespace std;
- using namespace lunar;
- Date lunar_date = LuanrDate(disp_info.year, disp_info.mouth, disp_info.day);
- disp_info.lunar_mouth=lunar_date.month;
- disp_info.lunar_day=lunar_date.day;
- disp_info.hour=now.Hour();
- disp_info.minute=now.Minute();
- disp_info.second=now.Second();
- disp_info.temperature=sensors.getTempCByIndex(0); //取上次温度数据
- sensors.requestTemperatures(); //启动下次转换
- disp_info.adc=analogRead(sensorPin); //取ADC数据
- oled_display();
- Serial_print();
- }
复制代码
效果就是这样的:
如果只是 DIY 一个时钟当作摆件的话,到这儿就结束了,这一版本的源代码送上。
但下面才是重头戏,因为万年历的数码管要重新驱动起来继续利用。
(老娘说这个表晚上也能看见时间,不用点灯。所以这块表的家庭地位十分稳固,只能升级改造不能扔)。
分析一下万年历电路,拆掉主控,万用表打“二极管挡”,跑一遍数码管线路,得到以下的分布:
数码管采用共阳接法,主控的 1、2、3、32、33、34 各控制一个三极管基极作为“位线”驱动,每条“位线”驱动 3 个数码管(个别的有 2 个)。
每条“位线” 3 个数码管的各段引脚由原主控 4-10、11-17、31-20(10/16/17)直接控制。
各“位线”上的数码管“同名段”之间并在一起,个别用不到的“段线”用来控制其它位置的“笔画”。
(比如 2 组 34 线:月份 < 2,其余段线控制农历和温度的笔画;2 组 1 线:月份十位 < 4 等等)。
这样一来,要用到的也就不止一种共阳字符表了。
需要这么多IO,ESP8266 自己肯定不够用,请出著名的移位寄存器 74HC595 和著名的 3-8 译码器 74HC138 登场。
将 3 颗 74HC595 级联,用于控制数码管段,74HC138 用于控制 6 个三极管的基极,做位选。
数码管驱动电路原理图:
手搓 74HC595 和 74HC138 驱动板,把线焊上去:
下一步,就是针对 74HC595 和 74HC138 写驱动了。
直接放代码:74HC595.h,解释放在注释
- // 程序名称:康巴丝万年历 74HC595 三级联 + 74HC138 译码位选驱动
- // 作 者:zgm1996
- // 创建时间:2024/01/06 12:40:25
- // =================================================================================
- // 版 本:V1.0
- // 当前版本完成时间:2024年1月26日19:51:39
- // 变更内容:
- // 通过 ESP8266 + 74HC595 + 74HC138 测试
- //
- // 存在问题:秒中断闪烁过于明显!!!
- //
- // =================================================================================
- #include <Arduino.h>
- // 0-9,关,常规共阳数码管,0xff全关断
- static const unsigned char table[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0xff};
- // 特殊数码管--农历日期十位,0xff关断做消隐
- static const unsigned char lunar_ten_table[] = {0xff, 0xf6, 0x8c, 0x86};
- // 特殊数码管--小时十位,0xff直接关断做消隐
- static const unsigned char hour_ten_table[] = {0xff, 0xf9, 0xc4};
- // 秒灯所在段码
- static const unsigned char flash_table[] = {0xff, 0xf6};
- class HC595
- {
- public:
- HC595(int input_pin, int shift_clock_pin, int storage_clock_pin);//int input_pin, int shift_clock_pin, int storage_clock_pin, int b0, int b1, int b2
- //串行数据输入,移位寄存时钟,存储时钟
- void display();
- private:
- int _DS; // 串行数据输入
- int _SH_CP; // 移位寄存时钟
- int _ST_CP; // 存储时钟
- int _b0;
- int _b1;
- int _b2;
- void send_to_595(unsigned char Data);
- };
- HC595::HC595(int input_pin, int shift_clock_pin, int storage_clock_pin)
- {
- _DS = input_pin;
- _SH_CP = shift_clock_pin;
- _ST_CP = storage_clock_pin;
- pinMode(_DS, OUTPUT);
- pinMode(_SH_CP, OUTPUT);
- pinMode(_ST_CP, OUTPUT);
- _b0 = D0;
- _b1 = D4;
- _b2 = D8;
- pinMode(_b0, OUTPUT);
- pinMode(_b1, OUTPUT);
- pinMode(_b2, OUTPUT);
- }
- void HC595::send_to_595(unsigned char Data)
- {
- shiftOut(_DS, _SH_CP, MSBFIRST, Data); // 这个就是用MSBFIRST参数让0-7个针脚以高字节优先输出(LSBFIRST 低字节)是DS的参数,
- }
- /*===================================================
- 康巴斯万年历-数码管核心驱动程序
- ===================================================*/
- // 由全局结构体:“disp_info” 传入 “年,月,日,星期,时,分,秒,农历月,农历日,温度”
- void HC595::display()
- {
- // 按各显示位分解数据
- unsigned char year_1, year_2, month_1, month_2, date_1, date_2,
- hour_1, hour_2, flash_flag, flash, minute_1, minute_2,
- L_month_1, L_month_2, L_date_1, L_date_2,
- temp_1, temp_2;
- // 临时存储联合显示的中间数据
- unsigned char sendtemp;
- // 分解各显示位
- year_1 = disp_info.year % 1000 / 10; // 年月日
- year_2 = disp_info.year % 1000 % 10;
- month_1 = disp_info.month / 10;
- month_2 = disp_info.month % 10;
- date_1 = disp_info.day / 10;
- date_2 = disp_info.day % 10;
- hour_1 = disp_info.hour / 10; // 时分,秒灯指示
- hour_2 = disp_info.hour % 10;
- flash_flag = disp_info.second % 2;
- flash = flash_table[flash_flag]; // 秒灯闪烁控制
- minute_1 = disp_info.minute / 10;
- minute_2 = disp_info.minute % 10;
- L_month_1 = disp_info.lunar_month / 10; // 农历月日
- L_month_2 = disp_info.lunar_month % 10;
- L_date_1 = disp_info.lunar_day / 10;
- L_date_2 = disp_info.lunar_day % 10;
- temp_1 = disp_info.temperature / 10; // 温度
- temp_2 = disp_info.temperature % 10;
- //===================== line_1,位选-000 =================================
- // 第一线位选,控制:农历月份个位,分钟十位,日期十位
- digitalWrite(_ST_CP, LOW); // 准备接收
- send_to_595(table[L_month_2]);
- send_to_595(table[minute_1]);
- if (date_1 == 0)
- { // 取公历月份十位数,
- sendtemp = table[10]; // 对0进行消隐
- }
- else
- {
- sendtemp = table[date_1];
- }
- // 农历月份个位,笔画C段受公历日期十位数(G段,I/O_16)控制
- // C段码值 0x04(00000100),将农历月份个位与0x04按位与,共阳接法为0时,该位点亮
- // 则将该位映射到F段(00100000b)0x20并取反得0xdf,再按位与运算,附加到农历月份个位上
- if ((table[L_month_2] & 0x04) == 0)
- {
- sendtemp = sendtemp & 0xdf;
- }
- send_to_595(sendtemp);
- digitalWrite(_ST_CP, HIGH);
- digitalWrite(_b0, LOW);
- digitalWrite(_b1, LOW);
- digitalWrite(_b2, LOW);
- delayMicroseconds(3000);
- digitalWrite(_b0, HIGH);
- digitalWrite(_b1, HIGH);
- digitalWrite(_b2, HIGH);
- //===================== line_2 位选-001 =================================
- // 控制农历日期十位(特殊码表),小时个位,日期个位
- digitalWrite(_ST_CP, LOW); // 准备接收
- send_to_595(lunar_ten_table[L_date_1]);
- send_to_595(table[hour_2]);
- send_to_595(table[date_2]); // 位选110
- digitalWrite(_ST_CP, HIGH);
- digitalWrite(_b0, HIGH);
- digitalWrite(_b1, LOW);
- digitalWrite(_b2, LOW);
- delayMicroseconds(3000);
- digitalWrite(_b0, HIGH);
- digitalWrite(_b1, HIGH);
- digitalWrite(_b2, HIGH);
- //===================== line_3 位选-010 =================================
- // 第三线位选,控制月份个位,小时十位,农历日期个位
- digitalWrite(_ST_CP, LOW); // 准备接收
- send_to_595(table[L_date_2]);
- sendtemp = hour_ten_table[hour_1];
- // 农历日期个位笔画C段受小时十位(G段,I/O_10)控制
- // C段码值 0x04(00000100),将农历月份个位与0x04按位与,共阳接法为0时,该位点亮
- // 则将该位映射到G段(01000000b)0x40并取反得0x0xbf,再按位与运算,附加到小时十位上
- if ((table[L_date_2] & 0x04) == 0)
- {
- sendtemp = sendtemp & 0xbf;
- }
- send_to_595(sendtemp);
- send_to_595(table[month_2]); // 位选101
- digitalWrite(_ST_CP, HIGH);
- digitalWrite(_b0, LOW);
- digitalWrite(_b1, HIGH);
- digitalWrite(_b2, LOW);
- delayMicroseconds(3000);
- digitalWrite(_b0, HIGH);
- digitalWrite(_b1, HIGH);
- digitalWrite(_b2, HIGH);
- //===================== line_32 位选-100 =================================
- // 第四线位选,控制年份个位,星期
- digitalWrite(_ST_CP, LOW); // 准备接收
- send_to_595(0xff); // 用0xff填充最高位74HC595,无显示用处
- send_to_595(table[disp_info.weekday]);
- send_to_595(table[year_2]); // 位选100
- digitalWrite(_ST_CP, HIGH);
- digitalWrite(_b0, HIGH);
- digitalWrite(_b1, HIGH);
- digitalWrite(_b2, LOW);
- delayMicroseconds(3000);
- digitalWrite(_b0, HIGH);
- digitalWrite(_b1, HIGH);
- digitalWrite(_b2, HIGH);
- //===================== line_33 位选-100 =================================
- // 第五线位选,控制年份个位,秒灯,温度十位
- digitalWrite(_ST_CP, LOW); // 准备接收
- send_to_595(table[temp_1]);
- sendtemp = flash;
- // 温度十位笔画C段受flash(I/O_10)控制
- // C段码值 0x04(00000100),将农历月份个位与0x04按位与,共阳接法为0时,该位点亮
- // 则将该位映射到G段(01000000b)0x40并取反得0x0xbf,再按位与运算,附加到小时十位上
- if ((table[temp_1] & 0x04) == 0)
- {
- sendtemp = sendtemp & 0xbf;
- }
- send_to_595(sendtemp);
- send_to_595(table[year_1]); // 位选011
- digitalWrite(_ST_CP, HIGH);
- digitalWrite(_b0, LOW);
- digitalWrite(_b1, LOW);
- digitalWrite(_b2, HIGH);
- delayMicroseconds(3000);
- digitalWrite(_b0, HIGH);
- digitalWrite(_b1, HIGH);
- digitalWrite(_b2, HIGH);
- //===================== line_34 位选-101 =================================
- // 第六线位选,控制月份十位(附带农历月份十位),分钟个位,温度个位
- digitalWrite(_ST_CP, LOW); // 准备接收
- send_to_595(table[temp_2]);
- send_to_595(table[minute_2]);
- if (month_1 == 0)
- {
- sendtemp = table[10]; // 正常计算公历月份十位数,并对0进行消隐
- }
- else
- {
- sendtemp = table[month_1];
- }
- // 农历月份的十位数 1X月(b,c段)受公历月份的十位数(d-I/O_12,f-I/O_16)控制
- // 农历月份的十位数为1时,映射到(d-I/O_12,f-I/O_16)(11010111b)0xd7,再按位与运算,附加到小时十位上
- if (L_month_1 == 1)
- {
- sendtemp = sendtemp & 0xd7; // 将对应位置零
- }
- // 温度个位笔画C段受公历月份十位数(G段,I/O_17)控制
- // C段码值 0x04(00000100),将农历月份个位与0x04按位与,共阳接法为0时,该位点亮
- // 则将该位映射到G段(01000000b)0x40并取反得0xbf,再按位与运算,公历月份十位数上
- if ((table[temp_2] & 0x04) == 0)
- { // 按位与,C段值为0时点亮(共阳接法)
- sendtemp = sendtemp & 0xbf; //
- }
- send_to_595(sendtemp); // 位选010
- digitalWrite(_ST_CP, HIGH);
- digitalWrite(_b0, HIGH);
- digitalWrite(_b1, LOW);
- digitalWrite(_b2, HIGH);
- delayMicroseconds(3000);
- digitalWrite(_b0, HIGH);
- digitalWrite(_b1, HIGH);
- digitalWrite(_b2, HIGH);
- }
复制代码
点亮了。
把程序和前面“DIY小时钟”合并整理一下。
顺利的话我以为这就完了。
才怪。
每秒刷新时,有个明显的抖动。(鼠标出镜,在老数码之家拆过)
逐个部分排查,问题锁定在了 DS18B20 上。尽管已经设置成了非阻塞模式,但读出数据的时间仍然超出了可接受的范围。
果断换方案,改用 NTC 热敏电阻测温,用 ESP8266 的 ADC 。热敏电阻型号为 NTC_3950 50K。
继续利用互联网资源:
热敏电阻使用 Steinhart-Hart 方程计算温度,引用一张网上的图:
三个系数可由以下网站计算得出:
SRS Thermistor Calculator https://www.thinksrs.com/downloads/programs/therm%20calc/ntccalibrator/ntccalculator.html
- /*----------------------- NTC 电阻测温 ---------------------------------*/
- #include <math.h>
- int sensorPin = A0; // GPIO 17
- int adcValue = 0; // 数模转换值 0-1024
- unsigned int Rs = 47495; // Rs 实测值为 47.49k
- double V_REF = 1.017; // NodeMCU开发板自带分压电路,应修改参考电压
- // 将 NodeMCU 的 A0 引脚接至 VCC,测量 ESP12 核心板的 A0 电压 作为参考电压
- //+3.3V
- // ---
- // |
- // | | Rs,47.495K
- // |
- // |---------------------A0
- // |
- // |/| R2,NTC 3950 50k
- // |
- // |
- // -==-
- // GND
- // 利用Steinhart-Hart方程计算温度
- double Thermister(int val)
- {
- double V_NTC = (double)val / 1024;
- double R_NTC = (Rs * V_NTC) / (V_REF - V_NTC);
- R_NTC = log(R_NTC);
- double Temp = 1 / (0.0008494662974 + (0.0002191266040 + (0.0000001055140254 * R_NTC * R_NTC)) * R_NTC); // 开式温度
- Temp = Temp - 273.15; // 转摄氏度
- return Temp;
- }
复制代码
完美,不闪了!
做几处优化:
为了进一步减小不必要的时间开销,把中断程序中更新数据结构体的逻辑进行优化,按变化频次 “秒>>年” 分先后考虑,其余不变的直接 return 回去刷新数码管,不必再写到结构体。
- // 中断服务程序,每秒更新数据
- void IRAM_ATTR every_second()
- {
- DateTime now = Ext_RTC.now(); // 取当前时间
- disp_info.temperature = int(Thermister(analogRead(sensorPin)));
- if (disp_info.second != now.second()) // 秒发生变化
- {
- disp_info.second = now.second(); // 秒一定改变,用于更新闪烁
- if (disp_info.minute != now.minute())
- {
- disp_info.minute = now.minute(); // 更新分钟
- if (disp_info.hour != now.hour())
- {
- disp_info.hour = now.hour(); // 更新小时
- if (disp_info.day != now.day()) // 日期发生变化,判断年份是否变化
- {
- if (disp_info.year != now.year())
- { // 年份变了更新年,之后更新其它数据,因为农历依赖年份信息;
- // 年份不变直接更新其它数据
- disp_info.year = now.year();
- }
- disp_info.day = now.day(); // 更新日期、农历、星期
- disp_info.month = now.month();
- if (now.dayOfTheWeek() != 0)
- {
- disp_info.weekday = now.dayOfTheWeek();
- }
- else
- {
- disp_info.weekday = 8;
- }
- using namespace std; // 超出知识储备范围,后续在解释
- using namespace lunar; // 超出知识储备范围,后续在解释
- Date lunar_date = LuanrDate(disp_info.year, disp_info.month, disp_info.day);
- disp_info.lunar_month = lunar_date.month;
- disp_info.lunar_day = lunar_date.day;
- }
- else
- {
- return; // 日期不变直接返回
- }
- }
- else
- {
- return; // 小时不变直接返回
- }
- }
- else
- {
- return; // 分不变直接返回
- }
- }
- else
- {
- return; // 秒不变直接返回
- }
- }
复制代码
装上之后就不能用串口下载程序了,改用 Arduino OTA。
- void setup()
- {
- Ext_RTC_init();
- int connect_flag = wifi_connect();
- if (connect_flag == 1)
- {
- set_time();
- }
- ArduinoOTA.begin();
- pinMode(second_Irq, INPUT_PULLUP);
- attachInterrupt(digitalPinToInterrupt(second_Irq), every_second, RISING); // RISING: 上升沿触发
- }
- void loop()
- {
- ArduinoOTA.handle_noirq(second_Irq); // Arduino OTA 监听
- LED_disp.display();
- }
复制代码
这次编译下载还是需要串口的,下次就不用了。
再修改 platformio.ini,添加以下配置:(IP可以登录路由器做个绑定)
- upload_protocol = espota
- upload_port = 192.168.0.220
复制代码
最后编译下载,组装上去,只保留一个复位键,把 NTC 放在壳子外面。
上面板,大功告成!以后有时间在立创打个板子,就更好了。
(小声说:其实年初打了一版但74138控制位选的方案错了,原想把74138位选编进数码管H位那个用不到的小数点比特,能节省 ESP8266 3个IO,结果数码管点亮时序和延时冲突用不了……)
(才知道,不要直接Ctrl+V直接粘贴图片,应该用上传,不然帖子会超长,我改了好半天)
最终版:
谢谢大家观看,祝大家端午安康!
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
打赏
-
查看全部打赏
|