esp8266 天气时钟(esp8266天气时钟代码)

esp8266 天气时钟(esp8266天气时钟代码)前言 本文为手把手教学 ESP8266 著名开源项目 太空人 WiFi 天气时钟 不同的是本次项目采用的是 STM32 作为 MCU 两者开发过程中有因为各自芯片的特点 时钟频率 内存大小等 导致开发程序大不相同 很多地方需要特殊设计一下 而作者使用 STM32 开发的原因很简单 ESP8266 虽然计算能力等方面优于 STM32F1xx 但是弊端也很明显 其所具备的引脚和外设太少

大家好,我是讯享网,很高兴认识大家。



前言

本文为手把手教学ESP8266著名开源项目——太空人WiFi天气时钟,不同的是本次项目采用的是STM32作为MCU。


两者开发过程中有因为各自芯片的特点(时钟频率,内存大小等),导致开发程序大不相同,很多地方需要特殊设计一下。而作者使用STM32开发的原因很简单,ESP8266虽然计算能力等方面优于STM32F1xx,但是弊端也很明显。


其所具备的引脚和外设太少,扩展性一般(ESP32算是二者优点兼备)。加之网上ESP8266的太空人WiFi天气时钟已经开源的很完善了,所以尝试用STM32实现一下,也方便后续利用STM32拓展开发。(文末有代码开源!)

实验硬件

STM32F103ZET6;7针1.3寸TFT-LCD(240×240);ESP8266

硬件实物图:


讯享网

 效果图

引脚连接:

LCD显示引脚:
VCC –> 3.3V
GND –> GND
CLK –> PA5
DIN –> PA7
RES –> PB0
DC –> PB1
CS –> PA4

讯享网
讯享网ESP8266模块引脚:
VCC –> 3.3V
GND –> GND
RX–> PB10
TX –> PB11
RST –> PB9
EN –> PB7

一、ESP8266简介与使用

1.1 ESP8266简介

SP8266是一款超低功耗的UART-WiFi透传模块,拥有业内极富竞争力的封装尺寸和超低能耗技术,专为移动设备和物联网应用设计,可将用户的物理设备连接到Wi-Fi无线网络上,进行互联网或局域网通信,实现联网功能。

ESP8266是上海乐鑫信息科技(国产)设计的低功耗WiFi芯片,集成完整的TCP/IP协议栈和MCU(网上ESP8266型号很多,基本都具备联网功能,部分型号可以直接作为MCU使用)。

而ESP8266模块是深圳安信可公司基于ESP8266芯片研发(增加必要外围电路、串口flash、板载天线等)的串口WiFi模块,成本低、使用简便、功能强大。

1.2 硬件与网络的桥梁—ESP8266

ESP8266模块和串口蓝牙JDY-31模块一样,串口WiFi模块也是扩展单片机功能的又一神器。

小巧的 ESP8266 WiFi模块通过串口AT指令与单片机通讯,实现串口透传,非常好上手(部分型号ESP8266可以直接当MCU,无需再通过串口与其他MCU通讯)。

透传,又称透明传输,具体来说就是“输入即输出(如从WiFi模块串口输入的字符会透传到服务器端)”,数据不改变,不同协议之间的转换(如串口到WiFi、蓝牙等)由模块完成。

使用者无需关心内部具体实现,因此模块对于使用者是“透明的”、似乎不存在的(因为可无视中间的实现原理)。一个高度封装的模块,应该隐藏内部实现细节,仅对外提供使用接口。

 把硬件联网之后,就再也不是“玩单机”了。配合服务器端的Socket网络编程,可以玩许多东西。所以我觉得WiFi模块是连接软件(网络编程)与硬件(单片机)的桥梁,把所学的单片机(MCU)和Web知识联系起来了。

如今大火的物联网等概念都属于“智能硬件”,ESP8266等模块的出现大大减少了网络开发的难度系数,也进一步促进了技术下放。而且,通过学习ESP8266/ESP32等模块,可以熟悉大量TCP/IP等网络协议,对后续Linux系统板网络开发也是极具意义的。

1.3 ESP8266使用——AT指令

 AT指令最早在蓝牙模块上接触过,所谓AT指令实质上就是一些起控制作用的特殊字符串。模块可以通过AT指令控制搭配使用源代码API函数开发,总体开发速度快,难度较低。

说明:下面仅列举一些最常用的AT指令及用法,指令的详细参数及使用说明请参考官方文档:ESP8266 AT指令集。

基础AT指令

关于WiFi模式这里要说明一下,sta模式下模块相当于客户端,像我们手机平板一样是要去连接路由器的,而AP模式下模块相当于路由器,是发射WiFi被别人连的。

ESP8266支持两种模式并存(模块出厂默认的是AP模式) 。另外,扫描WiFi指令 AT+CWLAP 只能在sta模式下使用,否则会报ERRO错误, AT+CWJAP 和 AT+CWQAP 指令也同理。

sta模式连接WiFi演示

1. 发送 AT+CWMODE=1 指令配置模块为sta模式(参数1,2,3分别对应模式sta,AP和sta/AP)。

2. 发送 AT+CWLAP 指令扫描当前附近WiFi,模块会返回可用AP列表。

3. 使用 AT+CWJAP=“WiFi名称”,“WiFi密码” 连接到指定的路由器,比如我在图书馆的WiFi是 “Wang”,密码是“”,实际连接WiFi发送的指令就是 AT+CWJAP=“Wang”,“” 。

4. 返回的“WIFI CONNECTED”说明连接成功,“WIFI GOT IP”代表模块分配到了IP。

5. 最后可使用 AT+CWQAP 断开当前连接的WiFi。

TCP/IP相关AT指令

传输控制协议(英语:Transmission Control Protocol,缩写为 TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。

在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能,用户数据报协议(UDP)是同一层内另一个重要的传输协议。

在因特网协议族(Internet protocol suite)中,TCP层是位于IP层之上,应用层之下的中间层。不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。

我们常说互联网互联网,那两个连接到互联网的设备该如何相互“交流”呢?TCP连接就是其中一种最常用的方式。

TCP是面向连接的传输层协议,通信双方都要实现TCP协议,其中一方只需目标ip地址和端口号就能发起连接,连接一旦建立,就像在双方之间拉了一条管子,管子两端可进行全双工(双向同时收发)通信。

TCP是传输层协议,是在网络层IP协议的基础上封装而来。而这些封装的实现细节也是与我们无关,我们只需使用系统所提供的相关接口“拿来即用”,比如网络编程中的Socket。

ESP8266模块中也实现了TCP/IP协议栈,模块作为客户端可轻松使用AT指令向服务端发起TCP连接。连接TCP服务器并开启透传模式后,模块串口收到的数据就会通过TCP连接透传到服务端,这样就完成了数据从硬件串口通过网络到程序进程的传输,实现软硬结合。

AT 是最常用的指令,用于测试模块能否正常接受指令。在sscom中向串口发送指令 AT ,若收到模块返回的 OK 则说明模块的AT指令可正常工作。发送 AT+GMR 可查看AT指令及SDK的版本号,一般最新版指令会增加一些新功能,可随时关注官方的更新。

WiFi功能AT指令

WiFi是让硬件联网的基础,和其他功能一样,这里仅列举所需的常用指令,更详细指令说明还得查阅文档。

把WiFi模块和电脑连接,在sscom确定AT指令能正常使用后,就可以开始配置TCP连接了,具体步骤如下:

1. 根据上面“sta模式连接WiFi演示”一节把模块连上WiFi

3. 从“网络调试助手”得知本机IP和端口,输入指令 AT+CIPSTART=“TCP”,“192.168.43.140”,1234 (指令参数分别为连接类型、目标IP地址和端口号)向服务器发起TCP连接请求,握手成功并建立连接后,服务器端的“网络调试助手”就会显示客户端IP和端口信息,此时双方已做好收发数据的准备(根据实际需要连接的IP地址来)

4. 输入指令 AT+CIPMODE=1 开启透传模式

5. 输入命令 AT+CIPSEND 进入透传模式,此时模块会把所有串口收到的数据都从TCP端口发送至服务器,同样的,从服务器收到的数据也会从模块串口发送出去打印到sscom上。这样WiFi模块就真正成为了连接硬件与网络的桥梁,实现了串口到TCP的协议转换

以上其实就是大概本次项目需要使用到的指令,ESP8266配置代码如下:

void esp8266_config(void){    char str[200];    sprintf(str, “AT+CWJAP=\”%s\“,\”%s\“\r\n”, WIFI_NAME, WIFI_PSW);//    SendATCmd(“+++”, 500);        // 退出透传模式    SendATCmd(“AT\r\n”, 2000);      // 测试ESP01模块是否存在//    SendATCmd(“AT+GMR\r\n”,3000);  // 查看模块版本信息    SendATCmd(“AT+CWMODE=1\r\n”, 2000);  // 开启STA+AP模式 ==================        SendATCmd(“AT+RST\r\n”, 3000);      SendATCmd(str, 10000);  // 连接无线路由器或者手机热点,等待10秒 ============    SendATCmd(“AT+CIPMUX=0\r\n”, 2000);  // 关闭多连接    SendATCmd(“AT+CIPSTART=\“TCP\”,\“api.seniverse.com\”,80\r\n”, 2000);  // 连接心知  天气TCP服务器    SendATCmd(“AT+CIPMODE=1\r\n”, 500);  // 开启透传模式    SendATCmd(“AT+CIPSEND\r\n”, 500);    // 开始透传}

二、知心天气API使用

本项目为WiFi天气时钟,自然离不开需要从网页上读取天气信息。这里我们使用业内比较著名的知心天气。

2.1 登陆心知天气官网,注册

没有账号的朋友可以自己去注册一下,流程很简单。不商用的话,知心天气是免费的,还是比较良心的(网站响应率也很高)。

点击“立即免费试用”

点击免费版的“免费申请”

申请后可查看到自己的私钥(自行保存后面需要用到)

2.1 API函数的使用

目前,大部分网络数据调用都是习惯性的调用数据提供商的API接口函数。

重新点击“产品”—>“天气数据”,点击“查看API文档” 

点击”天气实况”,打开对应的API接口文档 

查看天气实况的接口地址,以及返回的数据结果示例(自行保存后面需要用到)

1)上述知心天气API接口函数的寻找和使用通用性很高,大部分网络数据读取的流程与之类似。

2)嵌入式开发大部分情况下一般都是C语言进行开发的,由于C语言的局限性,没有直接的字典类型处理(python)

项目使用过程中直接使用知心天气自带的API函数,项目大致流程:开启STA模式后,成功连上WiFi后,通过TCP协议去访问执行天气网站的服务器,在发送特定的API接口函数,服务器响应后返回需要的结果信息。

三、UART串口通讯

STM32作为MCU与ESP8266直接的通讯就是简单的UART(串口)通信,这一点依旧与蓝牙模块很类似。

使用方法:通过串口UARTx_TX连接ESP8266的UART_RX,然后单片机通过串口发送AT指令集。

ESP8266后续从服务器接受的数据信息也从ESP8266的UART_TX传输给单片机UARTx_RX。后续只需要使用自己的方法去解析串口接收到的数据,即可得到自己想要的数据信息。

四、CubeMX配置

RCC配置外部高速晶振(精度更高)—HSE

SYS配置:Debug设置成Serial Wire(否则可能导致芯片自锁)

GPIO配置:此处模拟使用SPI通信,并且设置ESP8266的EN和RST

RTC配置:年月日,时分秒

UART1和UART3配置:MCU分别与电脑和ESP8266通讯(记得开启串口通信中断)

时钟树配置 

工程配置

五、代码与解析

5.1 TFT-LCD显示代码

LCD显示部分其实都是非常基础的操作,不熟悉的可以去看看笔者另一篇文章了解一下。作者这里主要把工程中不一样的地方指出来一下。

5.1.1 UI设计

 WiFi天气时钟中最要的点——UI设计,需要去设计很多界面图标,作者这里耗费了超级多的时间,翻遍了GitHub和视觉中国。

最后找到了差不多符合作者要求的UI库(有需要的可以评论区留下邮箱),如下:

 5.1.2 GIF动图实现

目前,由于STM32自身内存的缘故,其实STM32是不太适合实现GIF动图的。所以,网上这方面的资料和代码都很少。目前,较为主流的方法:(1)enWin或者Lvgl库实现GIF动图;(2)从SD卡读取数据去显示。

作者这里用了一直笨方法去实现了GIF显示,就是去循环遍历GIF动图的每一帧。

使用GIF分离器去分离GIF动图的每一帧;

再利用Image2Lcd 2.9(激活成功教程版)去提前图模;

将取模代码变为2维数组,第一维度为帧数,第二维度为每帧图片的取模。

之后循环显示该GIF数组的每一帧,即可实现GIF动图显示。

代码:

讯享网void showimage4(const unsigned char p) {  int i;   unsigned char picH,picL;   Address_set(180,146,228,195);  for(i=0;i<4950;i++)    {        picL=(p+i2);        picH=(p+i2+1);              LCD_WR_DATA(picH<<8|picL);             }  }  for(int a=0;a<11;a++){    showimage4(gImage_1[a]);}

ESP8266.h(AT控制):

#ifndef ESP8266_Hmeta” style=“box-sizing: border-box;”>#define ESP8266_H comment” style=“box-sizing: border-box;”>//#include “stdint.h” //uint8_t aRxBuffer_rx1;      //接收中断缓冲//uint8_t aRxBuffer_rx3;      //接收中断缓冲 //typedef struct {//  uint16_t size;//  uint8_t buf[1022]; // 接收缓冲数组//} UART_RXDATA; //UART_RXDATA g_uart1_rx;//UART_RXDATA g_uart3_rx; //char Data_buff[1022]; //char weather[10];        //存储天气 //uint8_t temperature[2]={0,0};     //储存最高气温和最低气温//uint8_t temp = 0; //需要连接的wifi账号和密码,需要修改,且WiFi频段不支持5GHz#define WIFI_NAME “Wang”#define WIFI_PSW    “” 心知天气api,注意key=后面需要替换成自己账号的密钥//char *get=“GET https://api.seniverse.com/v3/weather/daily.json?key=SkV9zIBpwJAOixrJZ&location=chongqing&language=en&unit=crn”; //void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);void SendATCmd(char *cmd, int waitms); void esp8266_config(void);  #endif

ESP8266.h(AT控制):

讯享网#ifndef ESP8266_Hmeta” style=“box-sizing: border-box;”>#define ESP8266_H comment” style=“box-sizing: border-box;”>//#include “stdint.h” //uint8_t aRxBuffer_rx1;      //接收中断缓冲//uint8_t aRxBuffer_rx3;      //接收中断缓冲 //typedef struct {//  uint16_t size;//  uint8_t buf[1022]; // 接收缓冲数组//} UART_RXDATA; //UART_RXDATA g_uart1_rx;//UART_RXDATA g_uart3_rx; //char Data_buff[1022]; //char weather[10];        //存储天气 //uint8_t temperature[2]={0,0};     //储存最高气温和最低气温//uint8_t temp = 0; //需要连接的wifi账号和密码,需要修改,且WiFi频段不支持5GHz#define WIFI_NAME “Wang”#define WIFI_PSW    “” 心知天气api,注意key=后面需要替换成自己账号的密钥//char *get=“GET https://api.seniverse.com/v3/weather/daily.json?key=SkV9zIBpwJAOixrJZ&location=chongqing&language=en&unit=crn”; //void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);void SendATCmd(char *cmd, int waitms); void esp8266_config(void);  #endif

ESP8266.c:

#include “esp8266.h”#include “usart.h”#include <stdio.h>#include <string.h>#include <stdlib.h>#include “lcd.h”  void SendATCmd(char *cmd, int waitms) { // 发送AT指令给串口3  if (NULL != cmd)  {    HAL_UART_Transmit(&huart3, (uint8_t *)cmd, strlen(cmd), 0xFFFF);      if (waitms > 0)      HAL_Delay(waitms);  // 延时等待ESP01模块应答时间  }} void esp8266_config(void){    char str[200];    sprintf(str, “AT+CWJAP=\”%s\“,\”%s\“\r\n”, WIFI_NAME, WIFI_PSW);//    SendATCmd(“+++”, 500);        // 退出透传模式    SendATCmd(“AT\r\n”, 2000);      // 测试ESP01模块是否存在//    SendATCmd(“AT+GMR\r\n”,3000);  // 查看模块版本信息    SendATCmd(“AT+CWMODE=1\r\n”, 2000);  // 开启STA+AP模式 ==================        SendATCmd(“AT+RST\r\n”, 3000);      SendATCmd(str, 10000);  // 连接无线路由器或者手机热点,等待10秒 ============    SendATCmd(“AT+CIPMUX=0\r\n”, 2000);  // 关闭多连接    SendATCmd(“AT+CIPSTART=\“TCP\”,\“api.seniverse.com\”,80\r\n”, 2000);  // 连接心知天气TCP服务器    SendATCmd(“AT+CIPMODE=1\r\n”, 500);  // 开启透传模式    SendATCmd(“AT+CIPSEND\r\n”, 500);    // 开始透传      SendATCmd(“GET https://api.seniverse.com/v3/weather/daily.json?key=SkV9zIBpwJAOixrJZ&location=zhenjiang&language=en&unit=crn”, 2000);} 

注意,key=后面尽量换成自己的密钥,location=后面也可以换成自己所在城市的字母。

5.2.2 ESP8266信息解码

这部分作者取巧,使用了字符串对比和指针取值的操作。

strstr()函数:

讯享网      char p;      p =  strstr(Data_buff,“text_day”);        //查找天气          sscanf(p+11,”%[^\“]”,weather);  //      LCD_ShowString(40,80,(uint8_t)weather);            p = strstr(Data_buff,“high”);                //查找气温      temperature[0]=atoi(p+7);      p = strstr(Data_buff,“low”);      temperature[1]=atoi(p+6);//      LCD_ShowxNum2(45,40,temperature[1],2,24,0);      LCD_ShowxNum2(160,207,temperature[0],2,24,0);       //温度      value = (temperature[1]+temperature[0])/2;      LCD_ShowxNum2(52,160,value,2,24,0);              //湿度      p = strstr(Data_buff,“humidity”);      humidity=atoi(p+11);      LCD_ShowxNum2(132,160,humidity,2,24,0);      LCD_ShowNew(161,160,’%’,24,0);            if((strstr(weather,“Overcast”)) || (strstr(weather,“Mostly Cloudy”)) || (strstr(weather,“Partly Cloudy”)) || strstr(weather,“Cloudy”))        {        Overcast();      }      if((strstr(weather,“Sunny”)) || (strstr(weather,“Clear”)) || (strstr(weather,“Fair”)))      //ÇçÌì      {        Sunny();      }      if((strstr(weather,“Shower”)))              {        Shower();      }      if((strstr(weather,“Thundershower”)) || (strstr(weather,“Thundershower with Hail”)))          {        Thundershower();      }      if((strstr(weather,“Light rain”)) || (strstr(weather,“Moderate Rain”)))            {        smallrain();      }      if((strstr(weather,“Heavy Rain”)) || (strstr(weather,“Storm”)) || (strstr(weather,“Heavy Storm”)) || (strstr(weather,“Severe Storm”)))          {        Bigrain();      }      if((strstr(weather,“Ice Rain”)) || (strstr(weather,“Sleet”)) || (strstr(weather,“Snow Flurry”)) || (strstr(weather,“Light Snow”)) || (strstr(weather,“Moderate Snow”)) || (strstr(weather,“Heavy Snow”)) || (strstr(weather,“Snowstorm”)))          {        snow();      }      

5.3 RTC代码

rtcdisplay.h:

#ifndef RTCDISPLAY_Hmeta” style=“box-sizing: border-box;”>#define RTCDISPLAY_H function” style=“box-sizing: border-box;”>void RTC_display(); #endif

rtcdisplay.c:

讯享网#include “rtcdisplay.h”#include “rtc.h”#include “lcd.h” RTC_DateTypeDef GetData;  //获取日期结构体RTC_TimeTypeDef GetTime;   //获取时间结构体 void RTC_display()        //RTC DISPLAY{      /* Get the RTC current Time /    HAL_RTC_GetTime(&hrtc, &GetTime, RTC_FORMAT_BIN);    / Get the RTC current Date /    HAL_RTC_GetDate(&hrtc, &GetData, RTC_FORMAT_BIN);      / Display date Format : yy/mm/dd ///    OLED_ShowNum(0,0,2000+GetData.Year,4,16);      //year//    OLED_ShowStr(35,30,“.”,2);//    OLED_ShowNum(45,0,GetData.Month,2,16);        //month//    OLED_ShowStr(60,30,“.”,2);//    OLED_ShowNum(70,0,GetData.Date,2,16);          //date      / Display time Format : hh:mm:ss */    LCD_ShowxNum2(15,75,GetTime.Hours,2,60,0);        //hour//    LCD_ShowNew(75,65,‘:’,60,0);    LCD_ShowxNum2(105,75,GetTime.Minutes,2,60,0);      //min    LCD_ShowxNum2(180,105,GetTime.Seconds,2,32,0);      //seconds }

这里RTC的时钟显示,作者也去网上找了专门的LED数字字体,如果需要LED数字字体库的也可以评论留言,作者把安装脚本发你。

六、项目效果

https://download.csdn.net//download/black_sneak/

END

本系列课程为“如何开发一个ROS人机交互软件“系列的第三讲,灵活运用Qt的信号与槽机制,并与ROS进行通信;通过多个例子,介绍如何在Qt中订阅与发布ROS的话题,并将ROS的话题消息在Qt中进行可视化显示。

(扫描二维码可查看课程详情)

点击“阅读原文”即可查看课程

小讯
上一篇 2025-06-12 19:06
下一篇 2025-04-23 20:46

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/149077.html