跳到內容
  • 版面
  • 最新
  • 標籤
  • 熱門
  • World
  • 使用者
  • 群組
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • 預設 (Yeti)
  • 未使用主題設計
Collapse
品牌標誌
  1. 首頁
  2. ESP32教學與討論
  3. AHT15溫濕度感測器
  4. AHT15溫濕度感測器-NB-IoT

AHT15溫濕度感測器-NB-IoT

已排程 已置頂 已鎖定 已移動 AHT15溫濕度感測器
esp32arduino idenb-iotaht15溫濕度感測器
1 貼文 1 Posters 20 瀏覽
  • 從舊到新
  • 從新到舊
  • 最多點贊
回覆
  • 在新貼文中回覆
登入後回覆
此主題已被刪除。只有擁有主題管理權限的使用者可以查看。
  • adminA 離線
    adminA 離線
    admin
    寫於 最後由 編輯
    #1

    16ebee6ae62dba0a05c9aa7a49b8af4b-0.png 16ebee6ae62dba0a05c9aa7a49b8af4b-1.png 16ebee6ae62dba0a05c9aa7a49b8af4b-2.png 16ebee6ae62dba0a05c9aa7a49b8af4b-3.png 16ebee6ae62dba0a05c9aa7a49b8af4b-4.png 16ebee6ae62dba0a05c9aa7a49b8af4b-5.png 16ebee6ae62dba0a05c9aa7a49b8af4b-6.png 16ebee6ae62dba0a05c9aa7a49b8af4b-7.png 16ebee6ae62dba0a05c9aa7a49b8af4b-8.png 16ebee6ae62dba0a05c9aa7a49b8af4b-9.png 16ebee6ae62dba0a05c9aa7a49b8af4b-10.png 16ebee6ae62dba0a05c9aa7a49b8af4b-11.png 16ebee6ae62dba0a05c9aa7a49b8af4b-12.png 16ebee6ae62dba0a05c9aa7a49b8af4b-13.png 16ebee6ae62dba0a05c9aa7a49b8af4b-14.png 16ebee6ae62dba0a05c9aa7a49b8af4b-15.png 16ebee6ae62dba0a05c9aa7a49b8af4b-16.png 16ebee6ae62dba0a05c9aa7a49b8af4b-17.png 16ebee6ae62dba0a05c9aa7a49b8af4b-18.png 16ebee6ae62dba0a05c9aa7a49b8af4b-19.png 16ebee6ae62dba0a05c9aa7a49b8af4b-20.png 16ebee6ae62dba0a05c9aa7a49b8af4b-21.png 16ebee6ae62dba0a05c9aa7a49b8af4b-22.png 16ebee6ae62dba0a05c9aa7a49b8af4b-23.png 16ebee6ae62dba0a05c9aa7a49b8af4b-24.png 16ebee6ae62dba0a05c9aa7a49b8af4b-25.png 16ebee6ae62dba0a05c9aa7a49b8af4b-26.png

    //程式碼
    #include <Wire.h>
    #include "MatrixInt.h" //安裝方式:https://drive.google.com/file/d/1W5dv4GtC1vuxjfKtOHlABnVAjdWW0eGB/view?usp=sharing
    
    #define AHT15_ADDRESS 0x38 // AHT15 的 I2C 地址
    
    // ------ 以下修改成你MQTT設定 ------
    long WNB303Timeout = 10000; //返回0=Timeout
    
    //使用小霸王Matrix板
    int WNB303ResetPIN = 14;       //  設定 WNB303 重置腳位為輸出腳位
    int WNB303PowerPIN = 15;      //  設定 WNB303 電源控制腳位為輸出腳位
    
    // ------ 以下修改成你MQTT設定 ------
    String MQTTServer = "mqttgo.io";//免註冊MQTT伺服器
    String MQTTPort = "1883";//MQTT Port
    String MQTTUser = "";//不須帳密
    String MQTTPassword = "";//不須帳密
    String MQTTPubTopicT = "denny/room/Temp";//推播主題:推播溫度(記得改成你自己的Topic)
    String MQTTPubTopicH = "denny/room/Humi";//推播主題:推播濕度(記得改成你自己的Topic)
    long MQTTLastPublishTime = 0;//此變數用來記錄推播時間
    long MQTTPublishInterval = 10000;//每10秒推撥一次
    
    void setup() {
      Serial.begin(115200);       //  設定序列埠監控視窗的鮑率
      Serial2.begin(115200);      //  設定 WNB303 的鮑率
      Wire.begin(26, 27); // 開始第一組 I2C 通訊
      Wire1.begin(21, 22); // 開始第二組 I2C 通訊
      for (int i = 0; i <= 7; ++i) MatrixInt(i, 0);//關閉所有燈號
      pinMode(WNB303ResetPIN, OUTPUT);        //  設定 WNB303 電源控制腳位為輸出腳位
      pinMode(WNB303PowerPIN, OUTPUT);        //  設定 WNB303 重置腳位為輸出腳位
      delay(1000);
    
      Serial.println("\r\n\r\n======================\r\nSystem Starting....");
      String result = "";
      //  開啟 Modem 的電源,開啟關閉之間須間隔10秒(延時電路)
      WNB303Restart(10);
      //檢查網路註冊狀態,5分鐘內無法註冊,則重新啟動WNB303
      int tryCount = 0;
      while (1) {
        boolean resultb = WNB303CheckReg();
        Serial.print("WNB303CheckNetReg result="); Serial.println(resultb);
        if (resultb == false) {
          Serial.println("時間內無法註冊網路(" + String(tryCount) + ")");
          delay(10000);
        }
        else break;
        if (tryCount++ >= 30) { //無法註冊已經超過5分鐘
          tryCount = 0;
          WNB303Restart(30);
        }
      }
      //檢查網路訊號品質
      result = WNB303CheckRSSI();
      Serial.print("WNB303CheckRSSI result="); Serial.println(result);
      delay(10000);
    }
    
    void loop() {
    
      //檢查時間,傳輸步驟:檢查網路、讀取溫濕度、MQTT連線、推播、關閉
      if ((millis() - MQTTLastPublishTime) >= MQTTPublishInterval ) {
        MatrixInt(7, 1);
        //沒有網路,則重新啟動WNB303
        String result = "";
        //檢查網路狀態
        if (!(WNB303CheckReg())) {
          WNB303Restart(60); //60秒後重新檢測網路
          return;
        }else result = WNB303CheckRSSI();
        //讀取溫濕度
        float temperature = 0; float humidity = 0;
        ReadAHT(&temperature, &humidity, Wire1);
    
        //連線mqtt
        result = mqttConnect(MQTTServer, MQTTPort, MQTTUser, MQTTPassword);
        if (result == "OK") Serial.println("MQTT Connected");
        String payloadT =  String(temperature) ;
        String payloadH =  String(humidity);
        //推播訊息
        result = mqttPublish(MQTTPubTopicT, "0", "0", "0", payloadT);
        if (result == "OK") Serial.println("Data:\"" + payloadT + "\" Published to " + MQTTPubTopicT);
        result = mqttPublish(MQTTPubTopicH, "0", "0", "0", payloadH);
        if (result == "OK") Serial.println("Data:\"" + payloadH + "\" Published to " + MQTTPubTopicH);
        //關閉mqtt
        result = mqttDisconnect();
        if (result == "OK") Serial.println("MQTT Disconnected");
        MQTTLastPublishTime = millis(); //更新最後傳輸時間
        MatrixInt(7, 0);
      }
      delay(1000);
    }
    
    
    //連線mqtt
    String mqttConnect(String Host, String Port, String MQTTUser, String MQTTPassword) {
      //1.取得IP
      String result = "" ;
      String IP = AT2WNB303("AT+EDNS=\"" + Host + "\"", "+EDNS:");
      IP.trim(); IP = split( IP, ':', 1);
      if (IP.length() <= 7) return "Error: Can't Get IP";
      //2.建立連線
      result = AT2WNB303("AT+EMQNEW=\"" + IP + "\",\"" + Port + "\"" + "," + 60000  + "," + 1024, "+EMQNEW:");
      String mqttid = split( result, ':', 1);
      //Serial.print("MQTTCreate result="); Serial.println(mqttid);
      //以亂數為ClientID
      String  MQTTClientid = "NBIoT-" + String(random(1000000, 9999999));
      result = AT2WNB303("AT+EMQCON=" + mqttid + ",3,\"" + MQTTClientid + "\"" + "," + 60000  + ",0,0,\"" + MQTTUser + "\",\"" + MQTTPassword + "\"", "OK");
      //Serial.print("MQTTConnect result="); Serial.println(result);
      return result;
    }
    
    //推播訊息
    String mqttPublish(String Topic, String QoS, String retained, String dup , String Payload) {
      String result = "" ;
      String hexPayload = Str2Hex(Payload);
      String lenHexPayload = String(hexPayload.length());
      result = AT2WNB303("AT+EMQPUB=0," + Topic + "," + QoS + "," + retained + "," + dup + "," + lenHexPayload + "," + hexPayload, "OK");
      return result;
    }
    
    //關閉mqtt連線
    String mqttDisconnect() {
      String result = "" ;
      result = AT2WNB303("AT+EMQDISCON=0", "OK");
      return result;
    }
    
    //檢查網路註冊狀態 return true or false
    boolean WNB303CheckReg() {
      String result = "";
      boolean CEREG = false;
      result = AT2WNB303("AT+CEREG?", "+CEREG:");
      if (result.indexOf("0,1") >= 0 || result.indexOf("1,1") >= 0) { //註冊成功
        MatrixInt(5, 0);//亮紅燈
        MatrixInt(6, 1);//亮綠燈
        CEREG = true;
      }
      else {
        MatrixInt(5, 1);//亮紅燈
        MatrixInt(6, 0);//亮綠燈
        CEREG = false;
      }
      return CEREG;
    }
    
    //檢查網路訊號品質 return RSSI,當RSSI=0或99代表沒訊號
    int WNB303CheckRSSI() {
      String result = "";
      int RSSI = 0;
      result = AT2WNB303("AT+CESQ", "+CESQ:");
      //處理+CESQ:
      if (!(result == "-1")) {
        int CESQ = split(split(result, ':', 1), ',', 0).toInt();
        RSSI = CESQ - 111;
      }
      if (RSSI == -111 || RSSI == 210) RSSI = 0;
      MatrixLEDrssi(RSSI);
      return RSSI;
    }
    
    //重新啟動WNB303(單位為秒)
    void WNB303Restart(int dalayTime) {
      AT2WNB303("POWEROFF", "");
      delay(5000);
      AT2WNB303("POWERON", "");
      delay(dalayTime * 1000) ;
    }
    
    //HTTP GET
    String HTTPGET(String Protocol, String Host, String port, String Url) {
      //例如 http://x.x.x.x/update?api_key=xxxxx&field1=60
      //拆解成Protocol="http" host="x.x.x.x" port="80" Url="/update?api_key=CxxxxxxJ&field1=60"
      //1.轉換網址IP
      String result = "" ;
      String IP = AT2WNB303("AT+EDNS=\"" + Host + "\"", "+EDNS:");
      IP.trim(); IP = split( IP, ':', 1);
      if (IP.length() <= 7) return "Error: Can't Get IP";
      //2.建立連線
      String PIP = Protocol + "://" + IP + ":" + port + "/";
      int PIPlen = PIP.length();
      //Serial.println("PIP=" + PIP + ",len=" + String(PIPlen));
      result = AT2WNB303("AT+EHTTPCREATE=0," + String(PIPlen) + "," + String(PIPlen) + ",\"" + PIP + "\"", "+EHTTPCREAT");
      result.trim(); String clientid = split(result, ':', 1);
      if (result == "") return "Error: Can't Create Connection";
      else {
        //3.開啟連線
        result = AT2WNB303("AT+EHTTPCON=" + clientid, "OK");
        result.trim();
        if (!(result == "OK")) result = "Error: Can't Connect to Server";
        //4.組成網址並傳送
        int LenUrl = Url.length();
        Url = clientid + ",0," + String(LenUrl) + "," + Url + ",0,,0,,0,";
        Url = "0," + String(Url.length()) + "," + String(Url.length()) + "," + Url;
        result = AT2WNB303("AT+EHTTPSEND=" + Url, "OK");
        if (!(result == "OK")) result = "Error: Can't Send to Server";
      }
      delay(1000);
      //關閉連線
      AT2WNB303("AT+EHTTPDISCON=" + clientid, "OK");
      //Serial.println(result);
      delay(1000);
      AT2WNB303("AT+EHTTPDESTROY=" + clientid, "OK");
      //Serial.println(result);
      delay(1000);
      return result;
    }
    
    //HTTP POST
    String HTTPPOST(String Protocol, String Host, String port, String Url , String contType , String Data) {
      //1.轉換網址IP
      String result = "" ;
      String IP = AT2WNB303("AT+EDNS=\"" + Host + "\"", "+EDNS:");
      IP.trim(); IP = split( IP, ':', 1);
      if (IP.length() <= 7) return "Error: Can't Get IP";
      //2.建立連線
      String PIP = Protocol + "://" + IP + ":" + port + "/";
      int PIPlen = PIP.length();
      //Serial.println("PIP=" + PIP + ",len=" + String(PIPlen));
      result = AT2WNB303("AT+EHTTPCREATE=0," + String(PIPlen) + "," + String(PIPlen) + ",\"" + PIP + "\"", "+EHTTPCREAT");
      result.trim(); String clientid = split(result, ':', 1);
      if (result == "") return "Error: Can't Create Connection";
      else {
        //3.開啟連線
        result = AT2WNB303("AT+EHTTPCON=" + clientid, "OK");
        result.trim();
        if (!(result == "OK")) result = "Error: Can't Connect to Server";
        //4.組成網址並傳送
        int i = 0;
        String PostCommand[10];
        PostCommand[i++] = clientid + ",1," + Url.length() + "," + Url + ",0,," + contType.length() + "," + contType + ",";
        //Serial.println("command1=" + PostCommand[i - 1]);
        String hexData = Str2Hex(Data);
        int lenHexData = hexData.length();
        PostCommand[i++] = String(lenHexData) + ",";
        //Serial.println("command2=" + PostCommand[i - 1]);
        int num = 30;
        for (int n = 0; n < lenHexData; n = n + num) {
          String DataSend = "";
          if (n + num < lenHexData) {
            //切割字串
            DataSend = hexData.substring(n, n + num);
          } else if (lenHexData % num > 0) {
            int remainder = lenHexData % num;
            //切割字串
            DataSend = hexData.substring(n, n + remainder);
          }
          PostCommand[i++] = DataSend;
          //Serial.println("command2=" + PostCommand[i - 1]);
        }
        //求出每條命令長度
        int totalLenHexData = 0;
        for (int j = 0; j <= i - 1; j++) {
          totalLenHexData = totalLenHexData + PostCommand[j].length();
          PostCommand[j] = String(PostCommand[j].length()) + "," + PostCommand[j];
        }
        //完成命令組合
        for (int j = 0; j <= i - 1; j++) {
          if (j == 1) PostCommand[j] = "AT+EHTTPSEND=1," + String(totalLenHexData) + "," + PostCommand[j];
          else if (j == i - 1) PostCommand[j] = "AT+EHTTPSEND=0," + String(totalLenHexData) + "," + PostCommand[j];
          else PostCommand[j] = "AT+EHTTPSEND=1," + String(totalLenHexData) + "," + PostCommand[j];
          result = AT2WNB303(PostCommand[j], "OK");
          //Serial.println("POST" + String(j) + + ":" + result);
        }
    
      }
      delay(1000);
      //關閉連線
      AT2WNB303("AT+EHTTPDISCON=" + clientid, "OK");
      //Serial.println(result);
      delay(1000);
      AT2WNB303("AT+EHTTPDESTROY=" + clientid, "OK");
      //Serial.println(result);
      delay(1000);
      return result;
    }
    
    //將訊息傳到WNB303,並讀取回傳訊息 0代表timeout
    String AT2WNB303(String ATdata, String StartWith) {
      Serial.println("你的命令是:" + ATdata);
      if (ATdata.length() > 0) { //送出AT命令
        ATdata.trim();
        String command = ATdata;
        command.toUpperCase();
    
        if (command == "RESET") {  //重置 WNB303
          digitalWrite(WNB303ResetPIN, HIGH);
          delay(10000);
          digitalWrite(WNB303ResetPIN, LOW);
          return "RESET OK";
        }
        else if (command == "POWERON") {  //開啟 WNB303 的電源
          digitalWrite(WNB303PowerPIN, HIGH);
          return "POWERON OK";
        }
        else if (command == "POWEROFF") {  //關閉 WNB303 的電源
          digitalWrite(WNB303PowerPIN, LOW);
          return "POWEROFF OK";
        }
        else  {  //送出AT命令
          Serial2.println(ATdata);
        }
      }
      else return "";
      String result = "";
      //等候回應資料
      long StartTime = millis();
      while (1) {
        result = "";
        while (Serial2.available()) { //WNB303有資料回傳
          char c = Serial2.read();    //從WNB303讀取一個位元組
          result += c;                //將讀到的字元 c 加進字串 Xfer
          if (c == '\n') break;
        }
        result.trim();
        if (result.startsWith(StartWith)) break; //結尾OK返回
        if ((millis() - StartTime) >= WNB303Timeout ) { //Timeout返回
          result = "0";
          break;
        }
      }
      return result;
    }
    
    
    void ReadAHT(float *temperature, float *humidity, TwoWire& myWire) {
      uint8_t data[6];
    
      // 發送啟動和測量命令
      myWire.beginTransmission(AHT15_ADDRESS);
      myWire.write(0xAC);
      myWire.write(0x33);
      myWire.write(0x00);
      myWire.endTransmission();
    
      delay(80); // 等待 AHT15 完成測量
    
      // 讀取數據
      myWire.requestFrom(AHT15_ADDRESS, 6);
      for (int i = 0; i < 6; i++) {
        data[i] = myWire.read();
      }
    
      // 計算濕度和溫度
      *humidity = ((data[1] << 12) | (data[2] << 4) | data[3] >> 4) * 100.0 / (1 << 20);
      *temperature = (((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5]) * 200.0 / (1 << 20) - 50;
    }
    
    
    
    
    //字串轉HEX
    String Str2Hex(String msg) {
      String a = "";
      for (int i = 0; i < msg.length(); i++)  {
        a = a + String(msg.charAt(i), HEX);
      }
      return a;
    }
    
    //HEX轉字串
    String Hex2Str(String msg) {
      char input[msg.length() + 1];
      msg.toCharArray(input, msg.length() + 1);
      char c[sizeof(input)];
      String a = "";
      for (int i = 0; i < sizeof(input) - 1; i += 2) {
        char temp[3];
        temp[0] = input[i];
        temp[1] = input[i + 1];
        int val = ASCIIHexToInt(temp[0]) * 16 + ASCIIHexToInt(temp[1]);
        c[i] = toascii(val);
        a = a + String(c[i]);
      }
      return a;
    }
    
    //ASC轉INT
    int ASCIIHexToInt(char c) {
      int ret = 0;
      if ((c >= '0') && (c <= '9')) ret = (ret << 4) + c - '0';
      else ret = (ret << 4) + toupper(c) - 'A' + 10;
      return ret;
    }
    
    //split拆解,範例:String a1=split(“aa,bb,cc”,’,’,0);
    String split(String data, char separator, int index) {
      int found = 0;
      int strIndex[] = { 0, -1 };
      int maxIndex = data.length() - 1;
      for (int i = 0; i <= maxIndex && found <= index; i++) {
        if (data.charAt(i) == separator || i == maxIndex) {
          found++;
          strIndex[0] = strIndex[1] + 1;
          strIndex[1] = (i == maxIndex) ? i + 1 : i;
        }
      }
      return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
    }
    
    

    平台使用上有任何問題歡迎寄信至[email protected]詢問

    1 條回覆 最後回覆
    0
    • adminA admin 移動話題來自 ESP32教學與討論 的
    回覆
    • 在新貼文中回覆
    登入後回覆
    • 從舊到新
    • 從新到舊
    • 最多點贊


    風狂logo 藏碳logo 南台logo SDGS2 SDGS7 SDGS12
    • 登入

    • 沒有帳戶? 註冊

    Powered by NodeBB Contributors
    • 第一個貼文
      最後的貼文
    0
    • 版面
    • 最新
    • 標籤
    • 熱門
    • World
    • 使用者
    • 群組