天天看點

基于OneNet平台智慧農業大棚(esp32)

esp32功能介紹

ESP32是一款WiFi和藍牙系統級晶片(SoC),具有行業領先的射頻性能、低功耗和高度內建的優勢。ESP32內建了完整的發射/接收射頻功能,包括天線開關,射頻balun,功率放大器,低噪放大器,過濾器,電源管理子產品和先進的自校準電路。自校準電路實作了動态自動調整以消除外部電路的缺陷。ESP32帶有2個32位、LX6 CPU,主頻高達240MHz,采用7級流水線架構。ESP32還內建了豐富的模拟傳感和數字接口。

ESP32的超低功耗射頻架構和擁有專利的省電技術延長了實際應用的電池續航時間。

ESP32完全符合WiFi 802.11b/g/n/e/i和藍牙4.2的标準,內建了WiFi/藍牙/BLE射頻和低功耗技術,并且支援開放性的實時作業系統RTOS。ESP32所內建的調整緩存幫助提高系統性能并且優化系統存儲。靈活的RAM/ROM劃分架構則允許使用者自定義以滿足特殊要求和使用情況。

ESP32可作為獨立應用程式或是主機MCU的從裝置。作為從裝置,ESP32通過SPI/SDIO或I2C/UART接口提供WiFi和藍牙功能。

硬體

esp32—wroom-32

溫濕度傳感器(工業級 485)

光線傳感器(工業級 485)

二氧化碳傳器(工業級 485)

土壤PH傳感器(工業級 485)

TDS傳感器子產品(工業級 485)

RS484轉TTl

接線端子1進6

12V電源

基于OneNet平台智慧農業大棚(esp32)
基于OneNet平台智慧農業大棚(esp32)
基于OneNet平台智慧農業大棚(esp32)

開發環境

下載下傳安裝Arduino IDE:

https://www.arduino.cc/en/Main/Software

Arduino IDE中添加ESP32開發闆資料:

安裝完成後選擇:檔案>首選項>附加開發闆管理器網址 中加入Arduino for esp8266的位址 https://dl.espressif.com/dl/package_esp32_index.json

完成網址添加後就可以在:工具>開發闆>開發闆管理器 中搜尋并下載下傳esp32開發闆資料包。

工具

modus協定校驗碼計算(RS485)

序列槽調試助手(用于修改傳感器ID)

網絡調試助手(TCP透傳調試)

接線

esp32 RS484轉TTl
5V VCC
GND GND
GPIO17 RX
GPIO16 TX
基于OneNet平台智慧農業大棚(esp32)

資料采集協定:Modbus協定

OneNet:HTTP協定

程式

/*
 * POST Data 1.1
 * 
 */

 /************TCP**********************************/
#include <WiFi.h>
const char *ssid = "test";//WIFI
const char *password = "12345678";//WIFI密碼
const char* serverIP = "183.230.40.33"; //欲通路的位址
uint16_t serverPort = 80;         //伺服器端口号
String url = "http://api.heclouds.com/devices/526038005/datapoints?type=3";//網址 裝置ID
String api="NkjCsVzErzqKLv8pKlWMIG6e8DE=";//api-key
String post;//http請求
int Content_Length;
WiFiClient client; //聲明一個用戶端對象,用于與伺服器進行連接配接
/****************************************************/


/************資料采集*********************************/
size_t data_get[5][8]={//指令      id
  {1,3,0,1,0,2,149,203},//TDS值    1
  {2,3,0,8,0,1,5,251},//土壤ph值    2
  {3,3,0,0,0,6,196,42},//溫濕度     3
  {4,3,0,5,0,1,148,94},//CO2       4
  {5,3,0,7,0,2,116,78}//光照        5
  };
//傳感器資料
long tsd_value=0,co2_value=0,lig_value=0;
float ph_value=0,tem_value=0,hum_value=0;
String string1,string2,string3,string4;
int value = 0;
static unsigned long time_=0;//定義初始發送時間為0
static unsigned long time_out=0;//定義逾時發送時間為0
/****************************************************/

void setup()
{
    Serial2.begin(9600);//初始化波特率9600 資料收發序列槽
    Serial.begin(9600);//                 調試列印序列槽
    Serial.println();
    
   ;
    Serial.print("Connecting to ");
    Serial.println(ssid);

    WiFi.begin(ssid, password);//連接配接到網絡

    while (WiFi.status() != WL_CONNECTED) {//等待網絡連接配接成功
        delay(500);
        Serial.print(".");
    }

    Serial.println("");
    Serial.println("WiFi connected");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());//列印子產品IP

}

void loop()
{
   //擷取數組長度
   int len=sizeof(data_get)/sizeof(size_t);
   int len2=sizeof(data_get[0])/sizeof(size_t);
   int len_data=len/len2;

    if(millis()-time_>200){//當系統時間大于200ms 0.2s采集一個傳感器資料
     for(int j=0;j<8;j++){
      Serial2.write(data_get[value][j]);//向傳感器發送指令 
     }
      time_=millis();
    }
    
     
  
  
  if(Serial2.available()){
       value++;//累加 為下一條指令發送
       
       size_t counti = Serial2.available();//序列槽緩沖器 傳回的是緩沖區準确的可讀位元組數
       uint8_t sbuf[counti];
       Serial2.readBytes(sbuf, counti);//從序列槽讀取指定長度counti的字元到緩存數組sbuf。數組
//       Serial.write(sbuf,counti);
       delay(50);
       switch (sbuf[0]){//判斷傳感器ID
       case 1:string1=tohex(int(sbuf[3]));
              string2=tohex(int(sbuf[4]));
              tsd_value=todec(string1,string2);
              Serial.print("tds: ");
              Serial.println(tsd_value);
              break;
       case 2:string1=tohex(int(sbuf[3]));
              string2=tohex(int(sbuf[4]));
              ph_value=((float)todec(string1,string2))/10;
              Serial.print("ph: ");
              Serial.println(ph_value);
              break;
       case 3:string1=tohex(int(sbuf[3]));
              string2=tohex(int(sbuf[4]));
              hum_value=((float)todec(string1,string2))/10;
              string1=tohex(int(sbuf[5]));
              string2=tohex(int(sbuf[6]));
              tem_value=((float)todec(string1,string2))/10;
              Serial.print("tem: ");
              Serial.print(tem_value);
              Serial.print("  hum: ");
              Serial.println(hum_value);
              break;
       case 4:string1=tohex(int(sbuf[3]));
              string2=tohex(int(sbuf[4]));
              co2_value=((float)todec(string1,string2));
              Serial.print("CO2: ");
              Serial.println(co2_value);
              break;
       case 5:string1=tohex(int(sbuf[3]));
              string2=tohex(int(sbuf[4]));
              string3=tohex(int(sbuf[5]));
              string4=tohex(int(sbuf[6]));
              lig_value=((float)todec_lig(string1,string2,string3,string4));
              Serial.print("light: ");
              Serial.println(lig_value);
              break;
       }
       
  }

  if(millis()-time_out>4000){//采集逾時處理
    value=5;
    time_out=millis();
  }
  if(value==len_data){//判斷當指令均已發送後
    value=0;//置0  
    Serial.print("connecting to ");//列印連接配接伺服器IP
    Serial.println(serverIP);

    // Use WiFiClient class to create TCP connections
    if (!client.connect(serverIP, serverPort)) {//判斷是否連接配接伺服器
        Serial.println("connection failed");
        return;
    }else{//連接配接成功
       Serial.println("connection succ");
       Serial.println();
       String data_value="{\"tem\":"+String(tem_value)+",\"hum\":"+String(hum_value)
          +",\"lig\":"+String(lig_value)+",\"tds\":"+String(tsd_value)
          +",\"CO2\":"+String(co2_value)+",\"soil_ph\":"+String(ph_value)
          +",\"ec\":"+String(tsd_value/0.47)+"}\r\n\r\n";
       Content_Length=data_value.length();
       post=String("POST ")+url+" HTTP/1.1\r\n"+"api-key: "+api+"\r\n"
          +"Host:api.heclouds.com\r\n"+"Connection:close\r\n"+"Content-Length:"
          +String(Content_Length)+"\r\n\r\n"+data_value;
//          +"{\"tem\":"+String(tem_value)+",\"hum\":"+String(hum_value)
//          +",\"lig\":"+String(lig_value)+",\"tds\":"+String(tsd_value)
//          +",\"CO2\":"+String(co2_value)+",\"soil_ph\":"+String(ph_value)
//          +"}\r\n\r\n";
      
          
          Serial.println(Content_Length);
           Serial.print(post);//序列槽列印HTTP請求
           client.print(post);//向伺服器發送HTTP請求
   
      }
  }
  
  while(client.available()) {//判斷WIFI是否有資料
        String line = client.readStringUntil('\r');//讀取WIFI資料賦給line
        Serial.print(line);//列印line
          
    }
   
}

void init_data(){//初始化所有資料,當傳感器未采集到資料時,值為0;
  tsd_value=0;
  ph_value=0;
  hum_value=0;
  tem_value=0;
  co2_value=0;
  lig_value=0;
}
 
//字元串合并,轉為long資料  
long todec(String string1,String string2){ 
       String str=string1+string2;//合并兩個字元串
       int str_len = str.length() + 1;//str字元串長度
       char char_array[str_len];//建立字元數組
       str.toCharArray(char_array, str_len);//将str轉為char數組
       long iOut;
       iOut = strtol(char_array, NULL, 16);//将char_array數組以16為long權值 轉為long資料
       return iOut;
}

//字元串合并(光照,轉為long資料
long todec_lig(String string1,String string2,String string3,String string4){   
       String str=string1+string2+string3+string4;
       int str_len = str.length() + 1;
       char char_array[str_len];
       str.toCharArray(char_array, str_len);
       long iOut;
       iOut = strtol(char_array, NULL, 16);
       return iOut;
}


//十進制轉十六進制
String tohex(int n) {
  if (n == 0) {
    return "00"; //n為0
  }
  String result = "";
  char _16[] = {
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
  };
  const int radix = 16;
  while (n) {
    int i = n % radix;          // 餘數
    result = _16[i] + result;   // 将餘數對應的十六進制數字加入結果
    n /= radix;                 // 除以16獲得商,最為下一輪的被除數
  }
  if (result.length() < 2) {
    result = '0' + result; //不足兩位補零
  }
  return result;
}

           

效果

https://open.iot.10086.cn/iotbox/appsquare/appview?openid=30ae21ae9de8f1c5b337b4393497dc9d

繼續閱讀