查看: 7646|回复: 23

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

[复制链接]
  • TA的每日心情
    开心
    2018-12-13 09:56
  • 签到天数: 553 天

    [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的每日心情
    开心
    2018-12-13 09:56
  • 签到天数: 553 天

    [LV.9]以坛为家II

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

    [LV.9]以坛为家II

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

    就在上面的心知天气  然后你自己注册就有了
    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2018-12-13 09:56
  • 签到天数: 553 天

    [LV.9]以坛为家II

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

    不是烧三段  而是三个文件是同一个工程来的
    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2018-12-13 10:46
  • 签到天数: 883 天

    [LV.10]以坛为家III

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

    [LV.9]以坛为家II

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

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

    本版积分规则

    热门推荐

    KittenBot杯第六届开源硬件开发大赛启动啦
    KittenBot杯第六届开源硬
    大赛简介: 第六届开源硬件开发大赛由Arduino中文社区发起 由KittenBot冠名赞助
    arduino温湿度无线传感控制系统
    arduino温湿度无线传感控
    求求你我真的不会,要挂科了,我快哭了真的。如何把功能1234合在一起,目前只会功能2
    请问大神们,这是怎么回事
    请问大神们,这是怎么回事
    出现了这个问题,不知道怎么改,求助大神
    [游戏发布]飞机大战
    [游戏发布]飞机大战
    飞机大战游戏,你可以通过按键控制飞机躲避障碍,直到30000分通关 你要控制飞
    一 个 维 信,改 变你 的 一 生
    一 个 维 信,改 变你 的
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表