查看: 2068|回复: 4

如何用ESP8266做一个天气预报,趣味与功能并存

[复制链接]
  • TA的每日心情
    郁闷
    2018-6-8 10:40
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2018-6-15 17:28 | 显示全部楼层 |阅读模式
    1、硬件
    用一个四博智联提供的nodemcu。一个OLED屏,一个USB线,4根杜邦线,可以上网的路由器,电脑。


         3V3---VCC
         GND---GND
         GPIO4(D2)---SDA
         GPIO5(D1)---SCL

    2、设置路由器
    把路由器账号设置为把路由器账号设置为
    账号:xh003
    密码:zxd+19901120=
    3、烧录程序
    打开ESP_TOOLS下载工具,选择8266.
    工具下载:http://bbs.doit.am/forum.php?mod ... 6&highlight=TOO

    点击START.等待烧录完成。

    烧录完成后复位一下nodemcu。等待10s左右。
    测试结果如下:



    Arduino代码如下:
    #include <ESP8266WiFi.h>
    #include <ArduinoJson.h>
    #include <Wire.h>
    #include "OLED.h"
    static const char logo[] PROGMEM={
    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0xff,0xe0,0xff,0x03,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0x1f,0x1c,0xf0,0x1f,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0x0f,0x00,0x80,0x7f,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0xff,0x01,0x00,0xfc,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0x07,0x00,0x00,0xfe,0x03,0x00,0xf8,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0x03,0x00,0x00,0xfc,0x07,0x00,0xf8,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0x01,0x00,0x00,0xf8,0x0f,0x00,0xf0,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xf0,0x1f,0x00,0xf0,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0xf0,0x1f,0x00,0xf0,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0xf0,0x1f,0x00,0xf0,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0xf0,0x1f,0x00,0xf0,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0xf0,0x3f,0x00,0xf0,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0x07,0x00,0x00,0x00,0xf0,0x1f,0x00,0xf8,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0x07,0x00,0x00,0x00,0xf0,0x0f,0x00,0xf8,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0x03,0x00,0x00,0x00,0xf8,0x03,0x00,0xfc,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xfc,0x00,0x00,0x7e,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x7f,0x00,0x00,0x7f,0xf8,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0x00,0x00,0x00,0x80,0x1f,0x00,0x80,0x7f,0xf8,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0x00,0x00,0x00,0xe0,0x07,0x00,0xc0,0x3f,0xf0,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0x00,0x00,0x00,0xf8,0x01,0x00,0xe0,0x3f,0xf0,0xff,0xff,0xff,0x7f,
    0xff,0xff,0x7f,0x00,0x00,0x00,0x7f,0x00,0x00,0xf8,0x3f,0xf0,0xff,0xff,0xff,0x7f,
    0xff,0xff,0x7f,0x00,0x00,0xe0,0x1f,0x00,0x00,0xfe,0x0f,0xf0,0xff,0xff,0xff,0x7f,
    0xff,0xff,0x7f,0x00,0x00,0xf8,0x03,0x00,0x80,0xff,0x0f,0xf8,0xff,0xff,0xff,0x7f,
    0xff,0xff,0x7f,0x00,0x00,0x7e,0x00,0x00,0xe0,0xff,0x01,0xf0,0xff,0xff,0xff,0x7f,
    0xff,0xff,0x7f,0x00,0x00,0x1f,0x00,0x00,0xf8,0xff,0x00,0xf8,0xff,0xff,0xff,0x7f,
    0xff,0xff,0x7f,0x00,0xc0,0x0f,0x00,0x00,0xfe,0x7f,0x00,0xfc,0xff,0xff,0xff,0x7f,
    0xff,0xff,0x7f,0x00,0xe0,0x03,0x00,0x80,0xff,0x1f,0x00,0xfe,0xff,0xff,0xff,0x7f,
    0xff,0xff,0x7f,0x00,0xf8,0x01,0x00,0xe0,0xff,0x07,0x00,0xfe,0xff,0xff,0xff,0x7f,
    0xff,0xff,0x7f,0x00,0x7c,0x00,0x00,0xfc,0xff,0x00,0x00,0xfc,0xff,0xff,0xff,0x7f,
    0xff,0xff,0x7f,0x00,0x3e,0x00,0x00,0xff,0x07,0x00,0x00,0xfc,0xff,0xff,0xff,0x7f,
    0xff,0xff,0x7f,0x00,0x0f,0x00,0xc0,0xff,0x07,0x00,0x00,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0x80,0x07,0x00,0xf0,0xff,0xff,0x0f,0xc0,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xc0,0x03,0x00,0xf8,0xff,0xff,0x3f,0xf8,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xc0,0x01,0x00,0xfe,0xf8,0xc7,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xe1,0x01,0x00,0x7f,0xc0,0x03,0x87,0x00,0xfe,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xe1,0x00,0xc0,0x7f,0x80,0x01,0x86,0x00,0xfe,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0x63,0x00,0xe0,0x7f,0x80,0x01,0x86,0x00,0xfe,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0x63,0x00,0xe0,0x7f,0x8c,0x31,0x86,0xc3,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0x67,0x00,0xc0,0x7f,0x8c,0x31,0x86,0x83,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0x6f,0x00,0xc0,0x7f,0x8c,0x31,0x86,0x83,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0x7f,0x00,0xc0,0x7f,0x8c,0x31,0x86,0x83,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0x7f,0x00,0xc0,0x7f,0x8c,0x31,0x86,0x83,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0x00,0x80,0x7f,0x80,0x01,0x86,0x83,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0x01,0x00,0x7f,0x80,0x01,0x86,0x83,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0x03,0x00,0x7c,0xc0,0x03,0x87,0x83,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0x07,0x00,0xf8,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0x0f,0x00,0xe0,0xff,0x7f,0xf0,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0xfe,0x07,0xfc,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
    0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f
    };
    //GPIO4(SDA) GPIO5(SCL)
    OLED display(4, 5);

    const char* ssid     = "xh003";         // XXXXXX -- 使用时请修改为当前你的 wifi ssid
    const char* password = "zxd+19901120=";         // XXXXXX -- 使用时请修改为当前你的 wifi 密码
    const char* host = "api.seniverse.com";
    const char* APIKEY = "wcmquevztdy1jpca";        //API KEY
    const char* city = "shenzhen";
    const char* language = "en";//zh-Hans 简体中文  会显示乱码

    const unsigned long BAUD_RATE = 115200;                   // serial connection speed
    const unsigned long HTTP_TIMEOUT = 5000;               // max respone time from server
    const size_t MAX_CONTENT_SIZE = 1000;                   // max size of the HTTP response

    // 我们要从此网页中提取的数据的类型
    struct UserData {
      char city[16];//城市名称
      char weather[32];//天气介绍(多云...)
      char temp[16];//温度
      char udate[32];//更新时间
    };

    WiFiClient client;
    char response[MAX_CONTENT_SIZE];
    char endOfHeaders[] = "\r\n\r\n";

    /**
    * @Desc 初始化操作
    */
    void setup() {
      WiFi.mode(WIFI_STA);     //设置esp8266 工作模式
      Serial.begin(BAUD_RATE);
      delay(10);
      Serial.println();
      Serial.println();
      Serial.print("Connecting to ");//写几句提示,哈哈
      Serial.println(ssid);
      WiFi.begin(ssid, password);   //连接wifi
      while (WiFi.status() != WL_CONNECTED) {
        //这个函数是wifi连接状态,返回wifi链接状态
        delay(100);
        Serial.print(".");
      }
      Serial.println("");
      Serial.println("WiFi connected");
      delay(100);
      Serial.println("IP address: ");
      Serial.println(WiFi.localIP());//WiFi.localIP()返回8266获得的ip地址
      client.setTimeout(HTTP_TIMEOUT);

    }

    /**
    * @Desc  主函数
    */

    void loop() {
       //初始化oled
      display.begin();

      //测试显示信息
      display.print("Hello DOIT",2,3);
      display.print("www.doit.am",4,3);
      delay(2*1000);
      display.clear();

      while (!client.connected()){
         if (!client.connect(host, 80)){
             Serial.println("connection....");
             delay(100);
         }
      }
      if (sendRequest(host, city, APIKEY) && skipResponseHeaders()) {
        clrEsp8266ResponseBuffer();
        readReponseContent(response, sizeof(response));
        UserData userData;
        if (parseUserData(response, &userData)) {
          printUserData(&userData);
        }
      }
      delay(300);//每5s调用一次
    }

    /**
    * @发送请求指令
    */
    bool sendRequest(const char* host, const char* cityid, const char* apiKey) {
      // We now create a URI for the request
      //心知天气
      String GetUrl = "/v3/weather/now.json?key=";
      GetUrl += apiKey;
      GetUrl += "&location=";
      GetUrl += city;
      GetUrl += "&language=";
      GetUrl += language;
      // This will send the request to the server
      client.print(String("GET ") + GetUrl + " HTTP/1.1\r\n" +
                   "Host: " + host + "\r\n" +
                   "Connection: close\r\n\r\n");
      Serial.println("create a request:");
      Serial.println(String("GET ") + GetUrl + " HTTP/1.1\r\n" +
                   "Host: " + host + "\r\n" +
                   "Connection: close\r\n");
      delay(100);
      return true;
    }

    /**
    * @Desc 跳过 HTTP 头,使我们在响应正文的开头
    */
    bool skipResponseHeaders() {
      // HTTP headers end with an empty line
      bool ok = client.find(endOfHeaders);
      if (!ok) {
        Serial.println("No response or invalid response!");
      }
      return ok;
    }

    /**
    * @Desc 从HTTP服务器响应中读取正文
    */
    void readReponseContent(char* content, size_t maxSize) {
      size_t length = client.peekBytes(content, maxSize);
      delay(100);
      Serial.println("Get the data from Internet!");
      content[length] = 0;
      Serial.println(content);
      Serial.println("Read data Over!");
      client.flush();//这句代码需要加上  不然会发现每隔一次client.find会失败
    }

    /**
    * @Desc 解析数据
    * 数据格式如下:
    * {
    *    "results": [
    *        {
    *            "location": {
    *                "id": "WX4FBXXFKE4F",
    *                "name": "北京",
    *                "country": "CN",
    *                "path": "北京,北京,中国",
    *                "timezone": "Asia/Shanghai",
    *                "timezone_offset": "+08:00"
    *            },
    *            "now": {
    *                "text": "多云",
    *                "code": "4",
    *                "temperature": "23"
    *            },
    *            "last_update": "2017-09-13T09:51:00+08:00"
    *        }
    *}
    */
    bool parseUserData(char* content, struct UserData* userData) {
    //    -- 根据我们需要解析的数据来计算JSON缓冲区最佳大小
    //   如果你使用StaticJsonBuffer时才需要
    //    const size_t BUFFER_SIZE = 1024;
    //   在堆栈上分配一个临时内存池
    //    StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
    //    -- 如果堆栈的内存池太大,使用 DynamicJsonBuffer jsonBuffer 代替
      DynamicJsonBuffer jsonBuffer;

      JsonObject& root = jsonBuffer.parseObject(content);

      if (!root.success()) {
        Serial.println("JSON parsing failed!");
        return false;
      }

      //复制我们感兴趣的字符串
      strcpy(userData->city, root["results"][0]["location"]["name"]);
      strcpy(userData->weather, root["results"][0]["now"]["text"]);
      strcpy(userData->temp, root["results"][0]["now"]["temperature"]);
      strcpy(userData->udate, root["results"][0]["last_update"]);
      //  -- 这不是强制复制,你可以使用指针,因为他们是指向“内容”缓冲区内,所以你需要确保
      //   当你读取字符串时它仍在内存中
      return true;
    }

    // 打印从JSON中提取的数据
    void printUserData( struct UserData* userData) {
      Serial.println("Print parsed data :");
      display.print("City: ",0,0);
      display.print(userData->city,0,6);
      display.print("Weat: ",2,0);
      display.print(userData->weather,2,6);
      display.print("Temp: ",4,0);
      display.print(userData->temp,4,6);
    // display.print("Last Updata : ",7,2);
    display.print(userData->udate,6,0);
    // display.print("\r\n");
    delay(4*1000);
    }

    // 关闭与HTTP服务器连接
    void stopConnect() {
      Serial.println("Disconnect");
      client.stop();
    }

    void clrEsp8266ResponseBuffer(void){
        memset(response, 0, MAX_CONTENT_SIZE);      //清空
    }
    esp8266-weather-station.ino

    11.18 KB, 下载次数: 7

    Arduino源码
    esp8266-weather-station.ino.nodemcu.bin

    262.06 KB, 下载次数: 9

    模组烧录文件


    该用户从未签到

    发表于 2018-8-15 09:28 | 显示全部楼层
    盗贴?大部分源码都是和博哥一样的
  • TA的每日心情
    奋斗
    2019-1-27 14:38
  • 签到天数: 33 天

    [LV.5]常住居民I

    发表于 2018-12-26 11:34 | 显示全部楼层
    你好,请问可以直接用arduino进行烧录可以吗
    ?我现在遇到了一个问题:Arduino:1.8.9 Hourly Build 2018/12/19 06:33 (Windows 10), 开发板:"Generic ESP8266 Module, 80 MHz, Flash, Enabled, ck, 26 MHz, 40MHz, QIO, 512K (no SPIFFS), 2, v2 Lower Memory, Disabled, None, Only Sketch, 115200"

    In file included from C:\Users\218\Desktop\arduino-nightly\libraries\WiFi\src/WiFi.h:32:0,

                     from C:\Users\218\Documents\Arduino\libraries\sketch_dec25b\sketch_dec25b\sketch_dec26a\sketch_dec26a.ino:2:

    C:\Users\218\Desktop\arduino-nightly\libraries\WiFi\src/WiFiServer.h:37:14: error: invalid abstract return type for member function 'WiFiClient WiFiServer::available(uint8_t*)'

       WiFiClient available(uint8_t* status = NULL);

                  ^

    In file included from C:\Users\218\Desktop\arduino-nightly\libraries\WiFi\src/WiFi.h:31:0,

                     from C:\Users\218\Documents\Arduino\libraries\sketch_dec25b\sketch_dec25b\sketch_dec26a\sketch_dec26a.ino:2:

    C:\Users\218\Desktop\arduino-nightly\libraries\WiFi\src/WiFiClient.h:27:7: note:   because the following virtual functions are pure within 'WiFiClient':

    class WiFiClient : public Client {

           ^

    In file included from C:\Users\218\Desktop\arduino-nightly\libraries\WiFi\src/WiFiClient.h:24:0,

                     from C:\Users\218\Desktop\arduino-nightly\libraries\WiFi\src/WiFi.h:31,

                     from C:\Users\218\Documents\Arduino\libraries\sketch_dec25b\sketch_dec25b\sketch_dec26a\sketch_dec26a.ino:2:

    C:\Users\218\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0-beta2\cores\esp8266/Client.h:29:21: note:         virtual int Client::connect(const IPAddress&, uint16_t)

             virtual int connect(CONST IPAddress& ip, uint16_t port) =0;

                         ^

    C:\Users\218\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0-beta2\cores\esp8266/Client.h:37:22: note:         virtual bool Client::flush(unsigned int)

             virtual bool flush(unsigned int maxWaitMs = 0) = 0;

                          ^

    C:\Users\218\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0-beta2\cores\esp8266/Client.h:38:22: note:         virtual bool Client::stop(unsigned int)

             virtual bool stop(unsigned int maxWaitMs = 0) = 0;

                          ^

    sketch_dec26a:23:12: error: cannot declare variable 'espClient' to be of abstract type 'WiFiClient'

    WiFiClient espClient;

                ^

    In file included from C:\Users\218\Desktop\arduino-nightly\libraries\WiFi\src/WiFi.h:31:0,

                     from C:\Users\218\Documents\Arduino\libraries\sketch_dec25b\sketch_dec25b\sketch_dec26a\sketch_dec26a.ino:2:

    C:\Users\218\Desktop\arduino-nightly\libraries\WiFi\src/WiFiClient.h:27:7: note:   since type 'WiFiClient' has pure virtual functions

    class WiFiClient : public Client {

           ^

    exit status 1
    cannot declare variable 'espClient' to be of abstract type 'WiFiClient'

    在文件 -> 首选项开启
    “编译过程中显示详细输出”选项
    这份报告会包含更多信息。
  • TA的每日心情
    奋斗
    2019-1-14 09:55
  • 签到天数: 4 天

    [LV.2]偶尔看看I

    发表于 2018-12-26 14:25 | 显示全部楼层
    哈哈,感觉可以哦,不错不错
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    热门推荐

    博哥零基础教你玩转ESP8266(十三) ESP8266WiFiGeneric库
    博哥零基础教你玩转ESP826
    帖子导航帖 博哥零基础教你玩转ESP8266(一) 重识ESP8266 博哥零基础教你玩转ESP8266
    求助!WeMos D1 WiFi怎么接0.96寸OLED?(ㄒoㄒ)
    求助!WeMos D1 WiFi怎么
    求助!WeMos D1 WiFi怎么接0.96寸OLED?(ㄒoㄒ) 想用WeMos D1 WiFi接收服务器的数据然
    串口发送16进制指令求助
    串口发送16进制指令求助
    我准备串口发出16进制指令到我的外置设备 代码如下图 我分别监控ARDUINO的tx口和USB口
    一文教你选择Arduino开发板,小白进
    一文教你选择Arduino开发
    笔者在2016年接触了Arduino,跳了万条坑,行了千里弯,到今天也算是Arduino的一
    大神们!1602显示屏上的MQ2浓度示数不是实时监测的何解
    大神们!1602显示屏上的MQ
    本人小白,刚刚接触arduino,长时间的查阅资料后,通过复制修改代码接线实现了DHT11实
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表