查看: 8942|回复: 24

《博哥OLED系列》- 8266+心知天气+OLED

[复制链接]
  • TA的每日心情
    开心
    2019-2-21 09:05
  • 签到天数: 609 天

    [LV.9]以坛为家II

    发表于 2017-9-26 00:06 | 显示全部楼层 |阅读模式
    本帖最后由 单片机菜鸟 于 2017-9-26 00:06 编辑

    一、前言       
          接着上一篇最后说道,博哥准备给ESP8266 天气接口加入OLED显示,那么这篇就是为了实现这个承诺。接下来就直接撸代码吧。


    二、撸代码

    实验前提:博哥这里是用Mega2560来测
          1.首先,在你的ESP8266上烧录以下代码,无非就是调用心知天气接口:
          

    kittenblock中小学创客名师推荐的图形化编程软件

    /**
    * 日期:2017/09/25
    * 功能:wifi+weather+oled   8266端
    * 作者:单片机菜鸟
    * 16X16点阵显示 取模方式 阴码+逐行式+顺向
    **/
    #include <ESP8266WiFi.h>
    #include <ArduinoJson.h>
    //#define DEBUG 是否启用debug功能
    
    #ifdef DEBUG
    #define DebugPrintln(message)    Serial.println(message)
    #define DebugPrint(message)    Serial.print(message)
    #else
    #define DebugPrintln(message)
    #define DebugPrint(message)
    #endif
    #define LED 2
    
    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
    
    const char* host = "api.seniverse.com";
    const char* APIKEY = "wcmquevztdy1jpca";        //API KEY
    const char* city = "guangzhou";
    const char* language = "en";//zh-Hans 简体中文  会显示乱码
    
    WiFiClient client;
    char response[MAX_CONTENT_SIZE];
    char endOfHeaders[] = "\r\n\r\n"; 
    unsigned int flag = HIGH;//默认当前灭灯
    long lastTime = 0;
    // 请求服务间隔
    long Delay = 20000;
    
    // 我们要从此网页中提取的数据的类型
    struct UserData {
      char city[16];//城市名称
      char weather[32];//天气介绍(多云...)
      char temp[16];//温度
      char udate[32];//更新时间
    };
    
    /**
    * @Desc 初始化操作
    */
    void setup()   {                
      Serial.begin(BAUD_RATE);
      pinMode(LED,OUTPUT);
      digitalWrite(LED, HIGH);
      if(!autoConfig()){
        smartConfig();
        while (WiFi.status() != WL_CONNECTED) {
        //这个函数是wifi连接状态,返回wifi链接状态
           delay(500);
           DebugPrint(".");
        }
      }
      DebugPrintln("IP address: ");
      DebugPrintln(WiFi.localIP());//WiFi.localIP()返回8266获得的ip地址
      lastTime = millis();
    }
    
    void loop() {
      while (!client.connected()){
         if (!client.connect(host, 80)){
             flag = !flag;
             digitalWrite(LED, flag);
             delay(500);
         }
      }
    
      if(millis()-lastTime>=Delay){
             //每间隔20s左右调用一次
         lastTime = millis();
         if (sendRequest(host, city, APIKEY) && skipResponseHeaders()) {
           clrEsp8266ResponseBuffer();
           readReponseContent(response, sizeof(response));
           UserData userData;
           if (parseUserData(response, &userData)) {
              sendtoArduino(&userData);
           }
         }
      }
    
      if(Serial.available()>0){
          char ch = Serial.read();
          if(ch == '1'){
            smartConfig();
            delay(1000);
            digitalWrite(LED, LOW);
          }
       }
    }
    
    /**
    * @发送请求指令
    */
    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");
      DebugPrintln("create a request:");
      DebugPrintln(String("GET ") + GetUrl + " HTTP/1.1\r\n" +
                   "Host: " + host + "\r\n" +
                   "Connection: close\r\n");
      delay(1000);
      return true;
    }
     
    /**
    * @Desc 跳过 HTTP 头,使我们在响应正文的开头
    */
    bool skipResponseHeaders() {
      // HTTP headers end with an empty line
      bool ok = client.find(endOfHeaders);
      if (!ok) {
        DebugPrintln("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);
      DebugPrintln("Get the data from Internet!");
      content[length] = 0;
      DebugPrintln(content);
      DebugPrintln("Read data Over!");
      client.flush();//这句代码需要加上  不然会发现每隔一次client.find会失败
    }
      
    // 关闭与HTTP服务器连接
    void stopConnect() {
      client.stop();
    }
     
    void clrEsp8266ResponseBuffer(void){
        memset(response, 0, MAX_CONTENT_SIZE);      //清空
    }
    
    /**
    * 自动连接20s 超过之后自动进入SmartConfig模式
    */
    bool autoConfig(){
      WiFi.mode(WIFI_STA);     //设置esp8266 工作模式
      WiFi.begin();
      delay(2000);//刚启动模块的话 延时稳定一下
      DebugPrintln("AutoConfiging ......");
      for(int i=0;i<20;i++){
        int wstatus = WiFi.status();
        if (wstatus == WL_CONNECTED){
          DebugPrintln("AutoConfig Success");
          DebugPrint("SSID:");
          DebugPrintln(WiFi.SSID().c_str());
          DebugPrint("PSW:");
          DebugPrintln(WiFi.psk().c_str());
          digitalWrite(LED, LOW);
          return true;
        }else{
          DebugPrint(".");
          delay(1000);
          flag = !flag;
          digitalWrite(LED, flag);
        } 
      }
      DebugPrintln("AutoConfig Faild!");
      return false;
    }
    
    /**
    * 开启SmartConfig功能
    */
    void smartConfig()
    {
      WiFi.mode(WIFI_STA);
      delay(2000);
      DebugPrintln("Wait for Smartconfig");
      // 等待配网
      WiFi.beginSmartConfig();
      while (1){
        delay(500);
        flag = !flag;
        digitalWrite(LED, flag);
        if (WiFi.smartConfigDone()){
          //smartconfig配置完毕
          DebugPrintln("SmartConfig Success");
          DebugPrint("SSID:");
          DebugPrintln(WiFi.SSID().c_str());
          DebugPrint("PSW:");
          DebugPrintln(WiFi.psk().c_str());
          digitalWrite(LED, LOW);
          WiFi.setAutoConnect(true);  // 设置自动连接
          break;
        }
      }
    }
    
    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 sendtoArduino(const struct UserData* userData) {
      StaticJsonBuffer<300> jsonBuffer;
      // StaticJsonBuffer 在栈区分配内存   它也可以被 DynamicJsonBuffer(内存在堆区分配) 代替
      // DynamicJsonBuffer  jsonBuffer;
      //创建根,也就是顶节点
      JsonObject& root = jsonBuffer.createObject();
      root["city"] = userData->city;
      root["weather"] = userData->weather;
      root["temp"] = userData->temp;
      root["time"] = userData->udate;
      root.printTo(Serial);//单行打印
    }


       2.第二步,在Arduino板子上烧录以下代码(分为三个文件),楼主这里是Mega2560.
       

    kittenblock中小学创客名师推荐的图形化编程软件

    /**
    * 日期:2017/09/25
    * 功能:wifi+weather+oled   arduino端
    * 作者:单片机菜鸟
    * 16X16点阵显示 取模方式 阴码+逐行式+顺向
    **/
    
    #include <SoftwareSerial.h>
    #include <ArduinoJson.h>
    #include <Wire.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_SSD1306.h>
    #include "code.cpp"
    
    #define OLED_RESET 4
    #define LOGO16_GLCD_HEIGHT 16 
    #define LOGO16_GLCD_WIDTH  16 
    
    #if (SSD1306_LCDHEIGHT != 64)
    #error("Height incorrect, please fix Adafruit_SSD1306.h!");
    #endif
    
    #define DEBUG //是否开启debug功能
    //#define UNO      //uncomment this line when you use it with UNO board
    #define MEGA    //uncomment this line when you use it with MEGA board
    
    #ifdef UNO
     SoftwareSerial mySerial(10,11);
    #endif
      
    #ifdef UNO
    #define WifiSerial  Serial
    #define MyDebugSerial mySerial
    #endif
       
    #ifdef MEGA
    #define WifiSerial Serial1
    #define MyDebugSerial Serial
    #endif  
    
    #ifdef DEBUG
    #define DBGLN(message)    MyDebugSerial.println(message)
    #else
    #define DBGLN(message)
    #endif
    
    #ifdef UNO 
    #define PIN_KEY 7// 按键
    #else
    #define PIN_KEY 6  
    #endif 
    
    Adafruit_SSD1306 display(OLED_RESET);
    
    const unsigned long BAUD_RATE = 115200;                   // serial connection speed
    const size_t MAX_CONTENT_SIZE = 300;                   // max size of the HTTP response
    char response[MAX_CONTENT_SIZE];
    
    // 定义记录按键当前状态的变量
    int state_btn;
    // 定义记录按键最近一次状态变化的变量,并初始化状态为LOW。
    int lastButtonState = LOW;
    // 定义记录最近一次抖动的时间变量,并初始化时间为0毫秒。
    long lastDebounceTime = 0;
    // 定义延迟抖动的时间变量
    long debouncdDelay = 60;
    
    // 我们要从此网页中提取的数据的类型
    struct UserData {
      char city[16];//城市名称
      char weather[32];//天气介绍(多云...)
      char temp[16];//温度
      char udate[32];//更新时间
    };
    
    /**
    * @Desc 初始化操作
    */
    void setup()   {
      pinMode(PIN_KEY,INPUT);
      WifiSerial.begin(BAUD_RATE);
      #ifdef DEBUG
        #ifdef UNO
          MyDebugSerial.begin(9600);//软串口9600稳定
        #else
          MyDebugSerial.begin(BAUD_RATE);
        #endif
      #endif
      delay(500);
      DBGLN("Arduino Init End");
                      
      // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
      display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3D (for the 128x64)
      display.clearDisplay();   // clears the screen and buffer
      //显示欢迎界面
      display.ShowCN_16(0,16, Welcome_16x16,sizeof(Welcome_16x16)/32,WHITE);
      display.ShowCN_16(48,32, Author_16x16,sizeof(Author_16x16)/32,WHITE);
      display.display();
    }
    
    void loop() {
      if(WifiSerial.available()>0){
        clrEsp8266ResponseBuffer();
        int data_size = ReceiveMessage(response, sizeof(response));
        if(data_size>0){
          //开始解析数据
          UserData userData;
          if(parseData(response,&userData)){
            showWeather(&userData);
          }
        }
      }
      checkButton();
    }
    
    /**
    * 读取串口缓冲区里面的数据
    */
    int ReceiveMessage(char* content, size_t maxSize){
      size_t length = WifiSerial.readBytes(content, maxSize);
      delay(100);
      content[length] = 0;
      WifiSerial.flush();
      DBGLN(content);
      return length;
    }
    
    /**
     * 数据格式如下:
     * {"city":"Guangzhou","weather":"Cloudy","temp":"28","time":"2017-09-25T22:40:00+08:00"}
     */
    bool parseData(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()) {
        DBGLN("JSON parsing failed!");
        return false;
      }
     
      //复制我们感兴趣的字符串
      strcpy(userData->city, root["city"]);
      strcpy(userData->weather, root["weather"]);
      strcpy(userData->temp, root["temp"]);
      strncpy(userData->udate, root["time"],10);
      //  -- 这不是强制复制,你可以使用指针,因为他们是指向“内容”缓冲区内,所以你需要确保
      //   当你读取字符串时它仍在内存中
      return true;
    }
    
    /**
    * 检查按键功能 进入一键配置模式
    */
    void checkButton(){
      int buttonState = digitalRead(PIN_KEY);//读取当前按键状态
      if(buttonState != lastButtonState){
         //如果按键发生了变化  则重新设置最近一次抖动的时间
         //方法millis()可以获取当前时间,单位统一为毫秒。
         lastDebounceTime = millis();  
      }
       
      // 判断按键按下状态时间间隔是否大于延迟抖动的时间长度。
      if(millis()-lastDebounceTime>debouncdDelay){
        // 判断当前的按键状态是否和之前有所变化
        if(buttonState != state_btn){
           // 如果发生了变化,
           // 则更新按键状态变量。
           state_btn = buttonState;
           if(state_btn == HIGH){
            //再次确认是否真的按下了按键
             DBGLN("smartconfig");
             WifiSerial.write('1');
           }
        }
      }
      // 更新按键最近一次状态变化的变量
      lastButtonState = buttonState;
    }
    
    void clrEsp8266ResponseBuffer(void){
        memset(response, 0, MAX_CONTENT_SIZE);      //清空
    }
    
    // 打印从JSON中提取的数据
    void showWeather(struct UserData* userData) {
      display.clearDisplay();
      display.setTextSize(1);
      display.setTextColor(WHITE);
      
      display.ShowCN_16(0,0, City_16x16,sizeof(City_16x16)/32,WHITE);
      display.setCursor(sizeof(City_16x16)/2+8,4);
      display.print(userData->city);
      
      display.ShowCN_16(0,16, Weather_16x16,sizeof(Weather_16x16)/32,WHITE);
      display.setCursor(sizeof(Weather_16x16)/2+8,18);
      display.print(userData->weather);
      
      display.ShowCN_16(0,32, Temp_16x16,sizeof(Temp_16x16)/32,WHITE);
      display.setCursor(sizeof(Temp_16x16)/2+8,36);
      display.print(userData->temp);
      display.print(" C");
      
      display.ShowCN_16(0,48, Date_16x16,sizeof(Date_16x16)/32,WHITE);
      display.setCursor(sizeof(Date_16x16)/2+8,52);
      
      display.print(userData->udate);
      display.display();
    }

       

    kittenblock中小学创客名师推荐的图形化编程软件

    #include "code.h"
    #include <avr/pgmspace.h>
    
    /**
    *@Desc 中文字模
    *欢迎来到心知天气
    */
    static const uint8_t PROGMEM Welcome_16x16[] ={
    0x00,0x80,0x00,0x80,0xFC,0x80,0x04,0xFC,0x05,0x04,0x49,0x08,0x2A,0x40,0x14,0x40,
    0x10,0x40,0x28,0xA0,0x24,0xA0,0x45,0x10,0x81,0x10,0x02,0x08,0x04,0x04,0x08,0x02,//欢
    0x00,0x00,0x20,0x80,0x13,0x3C,0x12,0x24,0x02,0x24,0x02,0x24,0xF2,0x24,0x12,0x24,
    0x12,0x24,0x12,0xB4,0x13,0x28,0x12,0x20,0x10,0x20,0x28,0x20,0x47,0xFE,0x00,0x00,//迎
    0x01,0x00,0x01,0x00,0x01,0x00,0x7F,0xFC,0x01,0x00,0x11,0x10,0x09,0x10,0x09,0x20,
    0xFF,0xFE,0x03,0x80,0x05,0x40,0x09,0x20,0x31,0x18,0xC1,0x06,0x01,0x00,0x01,0x00,//来
    0x00,0x04,0xFF,0x84,0x08,0x04,0x10,0x24,0x22,0x24,0x41,0x24,0xFF,0xA4,0x08,0xA4,
    0x08,0x24,0x08,0x24,0x7F,0x24,0x08,0x24,0x08,0x04,0x0F,0x84,0xF8,0x14,0x40,0x08,//到
    0x00,0x00,0x02,0x00,0x01,0x00,0x00,0x80,0x00,0x80,0x04,0x00,0x04,0x08,0x24,0x04,
    0x24,0x04,0x24,0x02,0x44,0x02,0x44,0x12,0x84,0x10,0x04,0x10,0x03,0xF0,0x00,0x00,//心
    0x20,0x00,0x20,0x00,0x20,0x7C,0x7E,0x44,0x48,0x44,0x88,0x44,0x08,0x44,0x08,0x44,
    0xFF,0x44,0x08,0x44,0x14,0x44,0x14,0x44,0x22,0x7C,0x22,0x44,0x42,0x00,0x80,0x00,//知
    0x00,0x00,0x3F,0xF8,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xFF,0xFE,0x01,0x00,
    0x02,0x80,0x02,0x80,0x04,0x40,0x04,0x40,0x08,0x20,0x10,0x10,0x20,0x08,0xC0,0x06,//天
    0x10,0x00,0x10,0x00,0x3F,0xFC,0x20,0x00,0x4F,0xF0,0x80,0x00,0x3F,0xF0,0x00,0x10,
    0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x0A,0x00,0x0A,0x00,0x06,0x00,0x02//气
    }; 
    
    static const uint8_t PROGMEM Author_16x16[] ={
    0x10,0x10,0x08,0x20,0x04,0x40,0x3F,0xF8,0x21,0x08,0x21,0x08,0x3F,0xF8,0x21,0x08,
    0x21,0x08,0x3F,0xF8,0x01,0x00,0x01,0x00,0xFF,0xFE,0x01,0x00,0x01,0x00,0x01,0x00,//单0
    0x00,0x40,0x10,0x40,0x10,0x40,0x10,0x40,0x10,0x40,0x1F,0xFC,0x10,0x00,0x10,0x00,
    0x10,0x00,0x1F,0xE0,0x10,0x20,0x10,0x20,0x10,0x20,0x20,0x20,0x20,0x20,0x40,0x20,//片1
    0x10,0x00,0x11,0xF0,0x11,0x10,0x11,0x10,0xFD,0x10,0x11,0x10,0x31,0x10,0x39,0x10,
    0x55,0x10,0x55,0x10,0x91,0x10,0x11,0x12,0x11,0x12,0x12,0x12,0x12,0x0E,0x14,0x00,//机2
    0x08,0x20,0x08,0x20,0xFF,0xFE,0x08,0x20,0x00,0x10,0x00,0xF8,0x3F,0x00,0x11,0x10,
    0x08,0x20,0x01,0x00,0x7F,0xFC,0x05,0x40,0x09,0x20,0x31,0x18,0xC1,0x06,0x01,0x00,//菜3
    0x01,0x00,0x02,0x00,0x1F,0xF0,0x10,0x10,0x12,0x10,0x11,0x10,0x11,0x50,0x10,0x20,
    0x10,0x00,0x1F,0xFC,0x00,0x04,0x00,0x04,0x7F,0xE4,0x00,0x04,0x00,0x28,0x00,0x10,//鸟4
    }; 
    
    static const uint8_t PROGMEM City_16x16[] ={
    0x20,0x28,0x20,0x24,0x20,0x20,0x27,0xFE,0x24,0x20,0xFC,0x20,0x24,0x24,0x27,0xA4,
    0x24,0xA4,0x24,0xA8,0x24,0xA8,0x3C,0x90,0xE6,0x92,0x49,0x2A,0x08,0x46,0x10,0x82,//城/0
    
    0x02,0x00,0x01,0x00,0x00,0x00,0x7F,0xFC,0x01,0x00,0x01,0x00,0x01,0x00,0x3F,0xF8,
    0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x28,0x21,0x10,0x01,0x00,0x01,0x00//市/1
    }; 
    
    static const uint8_t PROGMEM Temp_16x16[] ={
    0x10,0x00,0x10,0x00,0x3F,0xFC,0x20,0x00,0x4F,0xF0,0x80,0x00,0x3F,0xF0,0x00,0x10,
    0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x0A,0x00,0x0A,0x00,0x06,0x00,0x02,//气/0
    
    0x00,0x00,0x23,0xF8,0x12,0x08,0x12,0x08,0x83,0xF8,0x42,0x08,0x42,0x08,0x13,0xF8,
    0x10,0x00,0x27,0xFC,0xE4,0xA4,0x24,0xA4,0x24,0xA4,0x24,0xA4,0x2F,0xFE,0x00,0x00//温/1
    }; 
    
    static const uint8_t PROGMEM Weather_16x16[] ={
    0x00,0x00,0x3F,0xF8,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xFF,0xFE,0x01,0x00,
    0x02,0x80,0x02,0x80,0x04,0x40,0x04,0x40,0x08,0x20,0x10,0x10,0x20,0x08,0xC0,0x06,//天/0
    
    0x10,0x00,0x10,0x00,0x3F,0xFC,0x20,0x00,0x4F,0xF0,0x80,0x00,0x3F,0xF0,0x00,0x10,
    0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x0A,0x00,0x0A,0x00,0x06,0x00,0x02//气/1
    }; 
    
    static const uint8_t PROGMEM Date_16x16[] ={
    0x00,0x00,0x1F,0xF0,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x1F,0xF0,
    0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x1F,0xF0,0x10,0x10,//日/0
    
    0x22,0x00,0x22,0x7C,0x7F,0x44,0x22,0x44,0x22,0x44,0x3E,0x7C,0x22,0x44,0x22,0x44,
    0x3E,0x44,0x22,0x7C,0x22,0x44,0xFF,0x44,0x04,0x84,0x22,0x84,0x41,0x14,0x82,0x08,//期/1
    }; 
    
    
    
    
    

    kittenblock中小学创客名师推荐的图形化编程软件

    #ifndef _CODE_H
    #define _CODE_H
    
    #if ARDUINO <100
      #include <WProgram.h>
    #else
      #include <Arduino.h>
    #endif
    
    #endif


    C~]B2@RX`T8G90Z(3PZ8OK5.png
       
        正常效果应该是以下两个图:

        W53}MX1%MS4CV73F6F~5MDE.jpg
        N6T2LO_0RN]A0MPFNIB$]{A.jpg
      这一篇就讲到这里了,相对比较简单。其实复杂的显示效果都是由这些简单的慢慢实现的。。。
    打赏作者鼓励一下!

    该用户从未签到

    发表于 2017-10-1 01:20 | 显示全部楼层
    博哥强无敌
  • TA的每日心情
    开心
    2017-10-19 17:48
  • 签到天数: 45 天

    [LV.5]常住居民I

    发表于 2017-10-1 09:38 | 显示全部楼层
    请问城市代码的key在哪里申请呢?谢谢

    该用户从未签到

    发表于 2017-10-1 16:31 | 显示全部楼层
    请问一下 Mega2560 如何烧三段代码,是把三段代码复制粘贴在一起烧吗
  • TA的每日心情
    开心
    2019-2-21 09:05
  • 签到天数: 609 天

    [LV.9]以坛为家II

     楼主| 发表于 2017-10-1 18:33 | 显示全部楼层
    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2019-2-21 09:05
  • 签到天数: 609 天

    [LV.9]以坛为家II

     楼主| 发表于 2017-10-1 18:34 | 显示全部楼层
    Peter58 发表于 2017-10-1 09:38
    请问城市代码的key在哪里申请呢?谢谢

    就在上面的心知天气  然后你自己注册就有了
    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2019-2-21 09:05
  • 签到天数: 609 天

    [LV.9]以坛为家II

     楼主| 发表于 2017-10-1 18:34 | 显示全部楼层
    lovepqmagic_6 发表于 2017-10-1 16:31
    请问一下 Mega2560 如何烧三段代码,是把三段代码复制粘贴在一起烧吗

    不是烧三段  而是三个文件是同一个工程来的
    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2019-2-21 08:40
  • 签到天数: 932 天

    [LV.10]以坛为家III

    发表于 2017-10-1 20:53 | 显示全部楼层
    现在网络越来越发达了,比单独玩arduino好玩多了。
  • TA的每日心情
    开心
    2019-2-21 09:05
  • 签到天数: 609 天

    [LV.9]以坛为家II

     楼主| 发表于 2017-10-1 21:12 | 显示全部楼层
    老胖熊 发表于 2017-10-1 20:53
    现在网络越来越发达了,比单独玩arduino好玩多了。

    所以利用好各种模块也是一种王道
    打赏作者鼓励一下!
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    热门推荐

    博哥零基础教你玩转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 )
    快速回复 返回顶部 返回列表