文章目录

  • 前言
  • 硬件制作
    • 电源管理
  • 软件抄作业
    • API解析
  • 结尾

前言

之前学习律动灯条的时候买了一块esp8266开发板以及1.44寸的tft屏幕,一直闲置,所以学习制作网上爆火的天气时钟。同时为了便携,制作成可充电版本(typec充电)

软件和硬件都在:!!!!!点击这里!!!!!!

硬件制作


因为有现成的esp8266开发板,所以就在画pcb的时候就没有自己做esp8266的外围电路。

TFT的接线为:
这对应的esp8266开发板的D0那一列。

对应TFT引脚:

这里的按键检测电路有问题,原来我以为可以程序设计该引脚为上拉状态,但是参考资料少,所以没找到。

最好设计为下图


这里的原理图和pcb都是修改后的,我自己做的板子有点问题,只好飞线处理了。


洗板水在学校,所以板子看上去黄黄的,松香没洗。

电源管理

这里尝试一节锂电池降压到3.3v后给板子供电,可能因为显示屏缘故,电压不够,所以用两节锂电池串联降压到5v后,从板子的VIN供电。

充电电路参考: 基于CS5090E的5V升压给两节锂电池8.4v充电电路

这里注意1117降压芯片降压后不能和充电电路的5v连在一起,这样电池降压后又给电池充电,形成了回路。1117受不了,我的冒烟了。所以后面用剪刀把板子的线路划断了,然后飞线走的。上面的原理图和pcb是修改后的

软件抄作业

软件抄作业自:使用esp8266点亮福利屏型号st7735的1.44的TFT屏

软件比较复杂,涉及到物联网的知识,而且arduino编程序都是用的封装好的库,所以不容易理解。包括但不限与json解析,TFT显示,NTP服务器、网络配置等等,比较复杂,我也是抄的作业然后自己修改了一下。软件也放在上面的开源资料里了。

增加了按键控制亮度的问题,实际中发现这个东西是电老虎

  if(digitalRead(D0)==LOW&&key_press==0){    lcd_light=lcd_light+20;analogWrite(LCD_BL_PIN,50);}

可以控制TFT的LED引脚(背光控制引脚)节省电。

API解析

因为农历生日常常记不住,所以我加了一个农历日期显示,这里就需要自己找API接口,来解析。

char n_nongli[30]   ="";
char n_shengxiao[1]   ="";
String nongli_show;
void nongli_get()
{const char* hosts = "lunarapi.top"; // http://lunarapi.top/lunar/getbydate?date=2022-08-02// Connect to APISerial.print("连接nongli服务器::::");Serial.println(hosts);// Use WiFiClient class to create TCP connectionsWiFiClient nongclient;const int httpPort = 80;if (!nongclient.connect(hosts, httpPort)) {Serial.println("连接失败");return;}// We now create a URI for the request//增加公历日期到url中String date;date=String(year())+"-";if(month()<10){date+="0"+String(month())+"-";}else{date+=String(month())+"-";}if(day()<10){date+="0"+String(day());}else{date+=String(day());}//Serial.println(date);String url = "/lunar/getbydate?date="+date;Serial.print("Requesting URL: ");Serial.println(url);// This will send the request to the servernongclient.print(String("GET ") + url + " HTTP/1.1\r\n" +"Host: " + hosts + "\r\n" +"Connection: close\r\n\r\n");delay(1000);// Read all the lines of the reply from server and print them to SerialString nong_data;while (nongclient.available()) {String line = nongclient.readStringUntil('\r');nong_data += line;}nongclient.stop();Serial.println();Serial.println("关闭连接");// Convert to JSONString json_nong_data;int jsonIndex;for (int i = 0; i < nong_data.length(); i++) {if (nong_data[i] == '{') {jsonIndex = i;break;}}// Get JSON datajson_nong_data = nong_data.substring(jsonIndex);Serial.println();Serial.println(json_nong_data);// String input;StaticJsonDocument<512> doc;//char state = 0;deserializeJson(doc, json_nong_data);JsonObject data = doc["data"];strcpy(n_nongli, data["lunarDateTime"]); //农历2021年3月2日nongli_show=n_nongli;Serial.println("nongli: ");Serial.println(nongli_show);
}

网上都是利用的心知天气的API,但是访问几次就被限制了,或者还要花钱买,我找到另外一个不要钱的,但是访问时需要在url上加上公历的日期。例子如下
http://lunarapi.top/lunar/getbydate?date=2022-08-02

TFT农历显示:

    nongli_get();clk.createSprite(120, 18);clk.fillSprite(0x0000);clk.loadFont(nonglifont_15); clk.setTextDatum(ML_DATUM);clk.setTextColor(0xFFFF, 0x0000);clk.drawString("农历:"+nongli_show,1,9);clk.pushSprite(5,108);clk.deleteSprite();clk.unloadFont(); //释放加载字体资源

这里又涉及到字库的问题了,需要下载一个软件,同时还要转码。

具体操作在:TFT_eSPI添加各种字库

ESP8266之TFT_eSPI库的自定义字体

上图软件在放在开头的资源包里面了。

结尾

时间不够,没有时间去画一个3D的外壳了。

通过做这个,对与网络API接口应用有了一个新的理解,同时因为不学网页开发,所以对json解析也不是很清楚,模仿别人代码试着解析理解了一下。

有兴趣可以把esp8266开发板和TFT集合在一块PCB板子上,就会更加小巧了。

arduino还是比较强大的,有各种库,但是不是专攻的话,不容易理解,因为封装的太好了,而且查找源文件还要到本地的库里面找。

最重要的是,编程不通过,可能是库的版本不对,我把所有库(比较大100多M)也一起发到资源包里面。还是编程不方便。

下面是软件:
主要的NTP时间获取:

oid digitalClockDisplay()
{clk.setColorDepth(8);/***中间时间区***///时分clk.createSprite(75, 28);clk.fillSprite(bgColor);clk.loadFont(FxLED_32);clk.setTextDatum(ML_DATUM);clk.setTextColor(timehmfontColor, bgColor);clk.drawString(hourMinute(),1,14,7); //绘制时和分clk.unloadFont();clk.pushSprite(10,19);clk.deleteSprite();//秒clk.createSprite(40, 28);clk.fillSprite(bgColor);clk.loadFont(FxLED_32);clk.setTextDatum(ML_DATUM);clk.setTextColor(timesfontColor, bgColor); clk.drawString(":"+num2str(second()),1,14);clk.unloadFont();clk.pushSprite(83,19);clk.deleteSprite();/***中间时间区***//***底部***/clk.loadFont(zkyyt12);clk.createSprite(30, 16);clk.fillSprite(bgColor);//星期clk.setTextDatum(ML_DATUM);clk.setTextColor(weekfontColor, bgColor);clk.drawString(week(),1,8);clk.pushSprite(2,89);clk.deleteSprite();//月日clk.createSprite(49,16);clk.fillSprite(bgColor);clk.setTextDatum(ML_DATUM);clk.setTextColor(monthfontColor, bgColor);  clk.drawString(monthDay(),1,8);clk.pushSprite(36,89);clk.deleteSprite();clk.unloadFont();/***底部***/}//星期
String week(){String wk[7] = {"日","一","二","三","四","五","六"};String s = "周" + wk[weekday()-1];return s;
}//月日
String monthDay(){String s = String(month());s = s + "月" + day() + "日";return s;
}
//时分
String hourMinute(){String s = num2str(hour());backLight_hour = s.toInt();s = s + ":" + num2str(minute());return s;
}String num2str(int digits)
{String s = "";if (digits < 10)s = s + "0";s = s + digits;return s;
}void printDigits(int digits)
{Serial.print(":");if (digits < 10)Serial.print('0');Serial.print(digits);
}
//------------------------------------------------------------------------------------//NTP部分的代码,包含2个函数------------------------------------------------------------/*-------- NTP code ----------*/const int NTP_PACKET_SIZE = 48; // NTP时间在消息的前48字节中
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packetstime_t getNtpTime()
{IPAddress ntpServerIP; // NTP server's ip addresswhile (Udp.parsePacket() > 0) ; // discard any previously received packets//Serial.println("Transmit NTP Request");// get a random server from the poolWiFi.hostByName(ntpServerName, ntpServerIP);//Serial.print(ntpServerName);//Serial.print(": ");//Serial.println(ntpServerIP);sendNTPpacket(ntpServerIP);uint32_t beginWait = millis();while (millis() - beginWait < 1500) {int size = Udp.parsePacket();if (size >= NTP_PACKET_SIZE) {Serial.println("可以呀,小伙子,NTP同步成功啦!!!");Udp.read(packetBuffer, NTP_PACKET_SIZE);  // read packet into the bufferunsigned long secsSince1900;// convert four bytes starting at location 40 to a long integersecsSince1900 =  (unsigned long)packetBuffer[40] << 24;secsSince1900 |= (unsigned long)packetBuffer[41] << 16;secsSince1900 |= (unsigned long)packetBuffer[42] << 8;secsSince1900 |= (unsigned long)packetBuffer[43];//Serial.println(secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR);return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;}}//ESP.restart(); //时间获取失败直接重启Serial.println("NTP同步失败,别气馁,下次会成功的...");return 0; // 无法获取时间时返回0
}// 向NTP服务器发送请求
void sendNTPpacket(IPAddress &address)
{// set all bytes in the buffer to 0memset(packetBuffer, 0, NTP_PACKET_SIZE);// Initialize values needed to form NTP request// (see URL above for details on the packets)packetBuffer[0] = 0b11100011;   // LI, Version, ModepacketBuffer[1] = 0;     // Stratum, or type of clockpacketBuffer[2] = 6;     // Polling IntervalpacketBuffer[3] = 0xEC;  // Peer Clock Precision// 8 bytes of zero for Root Delay & Root DispersionpacketBuffer[12] = 49;packetBuffer[13] = 0x4E;packetBuffer[14] = 49;packetBuffer[15] = 52;// all NTP fields have been given values, now// you can send a packet requesting a timestamp:Udp.beginPacket(address, 123); //NTP requests are to port 123Udp.write(packetBuffer, NTP_PACKET_SIZE);Udp.endPacket();
}

初始化和主循环:

void setup() {Serial.begin(115200);EEPROM.begin(1024);if(EEPROM.read(BL_addr)>0&&EEPROM.read(BL_addr)<100)LCD_BL_PWM = EEPROM.read(BL_addr); pinMode(LCD_BL_PIN, OUTPUT);analogWrite(LCD_BL_PIN, 150);pinMode(Button, INPUT);tft.begin(); /* TFT init */tft.invertDisplay(1);//反转所有显示颜色:1反转,0正常tft.fillScreen(0x0000);tft.setTextColor(TFT_WHITE, 0x0000);// 设置屏幕显示的旋转角度,参数为:0, 1, 2, 3// 分别代表 0°、90°、180°、270°//根据实际需要旋转tft.setRotation(4); TJpgDec.setJpgScale(1);TJpgDec.setSwapBytes(true);TJpgDec.setCallback(tft_output);targetTime = millis() + 1000; Serial.print("正在连接WIFI ");Serial.println(ssid);WiFi.begin(WiFi.SSID().c_str(),WiFi.psk().c_str());TJpgDec.setJpgScale(1);TJpgDec.setSwapBytes(true);TJpgDec.setCallback(tft_output);tft.fillScreen(0x0000);while (WiFi.status() != WL_CONNECTED) {loading(70);  if(loadNum>=94){SmartConfig();   break;}}delay(10); while(loadNum < 94) //让动画走完{ loading(1);}Serial.print("本地IP: ");Serial.println(WiFi.localIP());//Serial.println("启动UDP");Udp.begin(localPort);//Serial.print("端口号: ");//Serial.println(Udp.localPort());//Serial.println("等待同步...");setSyncProvider(getNtpTime);setSyncInterval(setNTPSyncTime*60); //NTP网络同步频率,单位秒。//绘制一个视口tft.fillScreen(0x0000);tft.fillRoundRect(0,0,128,128,0,bgColor);//实心矩形//绘制线框tft.drawFastHLine(0,0,128,xkColor);tft.drawFastHLine(0,18,128,xkColor);tft.drawFastHLine(0,106,128,xkColor);tft.drawFastVLine(80,0,18,xkColor);tft.drawFastHLine(0,88,128,xkColor);tft.drawFastVLine(32,88,18,xkColor);tft.drawFastVLine(85,88,18,xkColor);int TCityCODE = 0;for(int cnum=5;cnum>0;cnum--){          TCityCODE = TCityCODE*100;TCityCODE += EEPROM.read(CC_addr+cnum-1); delay(5);}if(TCityCODE>=101000000 && TCityCODE<=102000000) cityCode = String(TCityCODE);  elsegetCityCode();  //获取城市代码                  getCityWeater();    // get_Bstation_follow();// fanspush();  nonli_show();       pinMode(D0,INPUT);}
unsigned long nongliTime = 0;
unsigned long weaterTime = 0;
void loop() {key_state();if (now() != prevDisplay) {prevDisplay = now();digitalClockDisplay();}if(millis() - weaterTime > 300000){ //5分钟更新一次天气 millis()五十天后溢出weaterTime = millis();getCityWeater();   // nonli_show();     }if(millis() - nongliTime > 21600000){ //5分钟更新一次天气nongliTime = millis();  nonli_show();     }scrollBanner();weatherWarning();imgAnim();Serial_set();}

城市信息获取:

//CityCode文件夹内的js文件搜索可得String cityCode = "101250101";// 发送HTTP请求并且将服务器响应通过串口输出
void getCityCode(){String URL = "http://wgeo.weather.com.cn/ip/?_="+String(now());//创建 HTTPClient 对象HTTPClient httpClient;
httpClient.begin(wificlient,URL); //设置请求头中的User-AgenthttpClient.setUserAgent("Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1");httpClient.addHeader("Referer", "http://www.weather.com.cn/");//启动连接并发送HTTP请求int httpCode = httpClient.GET();Serial.print("Send GET request to URL: ");Serial.println(URL);//如果服务器响应OK则从服务器获取响应体信息并通过串口输出if (httpCode == HTTP_CODE_OK) {String str = httpClient.getString();int aa = str.indexOf("id=");if(aa>-1){//cityCode = str.substring(aa+4,aa+4+9).toInt();cityCode = str.substring(aa+4,aa+4+9);Serial.println(cityCode); getCityWeater();}else{Serial.println("获取城市代码失败");  }} else {Serial.println("请求城市代码错误:");Serial.println(httpCode);}//关闭ESP8266与服务器连接httpClient.end();
}

其他相关代码在资源包里,整体挺多的,放不下了。

【立创开源】ESP8266制作的1.44寸TFT显示屏太空人天气时钟(st7735)(增加农历显示)(抄作业)相关推荐

  1. ESP8266驱动1.44寸TFT屏幕(例程问题)

    ESP8266驱动1.44寸TFT屏幕(例程问题) 一.接线说明 二.引脚对应 D1 - 5 D2 - 4 D3 - 0 三.修改例程 将D1.D2.D3改成5.4.0然后编译上传即可 .D2.D3改 ...

  2. ESP32 SPI驱动1.44寸TFT彩屏(5)

    TFT-LCD 即薄膜晶体管液晶显示器.其英文全称为:Thin Film Transistor-Liquid Crystal Display. TFT-LCD 与无源 TN-LCD.STN-LCD 的 ...

  3. Esp8266+TFT太空人天气时钟

    开源项目,只对动手能力有要求,有现成程序 b站演示视频: https://www.bilibili.com/video/BV1ND4y1W7oS/?spm_id_from=333.999.0.0 效果 ...

  4. NodeMCU-ESP8266使用TFT_eSPI库驱动IC为ST7735的1.44寸TFT屏幕(TFT_eSPI详解)

    文章目录 1. TFT_eSPI 驱动TFT屏幕 2. TFT_eSPI详解 2.1 文件配置 2.2 类.常用函数 2.1.1 TFT_eSPI类 2.1.2 Sprite 类 3. OVERLAP ...

  5. esp32 cam 1.44寸TFT彩屏 ST7735S驱动 TFT_eSPI库驱动

    ESP32 CAM引脚与TFT1.44(ST7735S)引脚接线 ESP32 CAM TFT 1.44 5V VCC GND GND GND NC NC 5V BLC D14 SCL D15 SDA ...

  6. 树莓派驱动1.44寸TFT液晶并实时显示摄像头图像

    ** 需要什么 ** 一块lcd ,市面上大多数为spi ,i2c驱动的lcd,我这块是比赛剩下的模拟8080端口驱动.区别不大,仅需改动发送数据的函数 一个摄像头,我这里使用的是某宝17块钱买来的o ...

  7. 1.44寸TFT-LCD显示屏取模教程

    目录 1.软件包:点击下载 2.LCD_ASCLL码取模教程 3.LCD汉字取模教程 4.LCD图片取模教程 1.软件包:点击下载 2.LCD_ASCLL码取模教程 (1).打开取模软件 (2).左上 ...

  8. ESP32 驱动ST7789 240*240 1.3寸 TFT 显示屏

    百问网LVGL中文开发手册 STM32之littlevGL系列教程: 图形用户界面(GUI) 微雪课堂 正点原子手把手教你学littleVGL[轻量级开源GUI]-基于STM32_哔哩哔哩_bilib ...

  9. ESP8266与STC8H8K单片机联动——天气时钟

    基于ESP8266与STC单片机的天气时钟(包括DS18B20.TFT.串口.外部中断.ESP8266.STC.API等) 文章目录 基于ESP8266与STC单片机的天气时钟(包括DS18B20.T ...

  10. STM32系列(HAL库)——F103C8T6点亮1.44寸TFT-LCD彩屏

    1.软件准备 (1)编程平台:Keil5 (2)CubeMX (3)中景园屏幕资料链接:点击跳转        提取码:8888 2.硬件准备 (1)1.44寸TFT彩屏 (2)F1的板子,本例使用经 ...

最新文章

  1. python二维列表排序
  2. linux kernel中的中断处理流程
  3. mysql索引执行计划_第六章· MySQL索引管理及执行计划
  4. 大数据时代,一名优秀的开发者应具备怎样的特质?
  5. Java IO篇:什么是 Proactor 网络模型?
  6. 【uni-app】分享
  7. G6 图可视化引擎——入门教程——元素及其配置
  8. Java UnknownHostException –服务器的无效主机名–如何解决?
  9. JSON转换为excel工具
  10. VC皮肤库SkinSharp 1 0 6 6的使用
  11. S3C2440的SPI控制器
  12. 实现自动文本摘要(python,java)
  13. sublime text 3 3143
  14. rails用generate为两个模型创建has_and_belongs_to_many中间表
  15. 19.docker attach
  16. 已处理证书链,但是在不受信任提供程序信任的根证书中终止 - Windows 7安装.Net Framework 4.7.2时出现此问题
  17. openwrt路由器samba拒绝访问
  18. 2021年N1叉车司机新版试题及N1叉车司机证考试
  19. C++中文件后缀的区别:cxx、cpp和txx,c、cc和cpp、hpp和h等
  20. Linux如何下载mysql?Mysql高级超级详细+避坑,欢迎收藏点赞~~~~

热门文章

  1. 关于INTERVAL 函数的使用
  2. Git用户手册--Git 内部原理
  3. CISCO路由器交换机简介及Packet+Tracer使用说明
  4. 《物联网技术》课程笔记——第一章 物联网概述
  5. matlab 直方图
  6. android 涨潮动画加载_这是迪士尼动画片《长发公主》中王国的原型,涨潮时才浮出海面...
  7. java设计模式之假设要实现一个RPG游戏系统框架的部分功能
  8. 正面管教php_我就这样走进正面管教
  9. 【1月7日】议程正式公布!年度AIoT产业盛典重磅来袭!
  10. 新计算机的word无法输入文字,Win10专业版系统为什么不能给电脑Word输入中文汉字...