Esp8266开发物联网小工具(一)

目标

我们将通过ESP8266连接Thinkphp开发的接收API,将DHT11温度传感器获取到的环境温度、湿度等数据实时发送至服务器,用户可通过设备和OLED触摸屏的实时数据界面查看实时环境温度。

硬件准备:

1)ESP8266-13 WIFI电路板

2)DHT11温湿度传感器

3)0.96”OLED(我使用的版本主控芯片是SSD1306、四线制SPI)

4)USB插座和5v至3.3V稳压器

5)USB-TTL串口下载模块

开发软件

arduino IDE

接下来我来介绍一下我们本次项目使用的控制器ESP8266

简介(来自官方)

  • 乐鑫智能互联平台ESP8266EX拥有高性能无线SOC,给移动平台
    设计师带来福音,它以最低成本提供最大实用性,为WiFi功能嵌入
    其他系统提供无限可能。

  • ·ESP8266EX是一个完整且自成体系的WiFi网络解决方案,能够
    立运行,也可以作为从机搭载于其他主机MCU运行。ESP8266EX
    在搭载应用并作为设备中唯一的应用处理器时,能够直接从外接闪存
    中启动。内置的高速缓冲存储器有利于提高系统性能,并减少内存需
    求。

    扫描二维码关注公众号,回复: 11456892 查看本文章
  • 另外一种情况是,ESP8266EX负责无线上网接入承担WiFi适配器(网卡使用)
    的任务时,可以将其添加到任何基于微控制器的设计中,连接简单易
    行,身需通过SPI/SDIO接口或|2C/UART口即可。

    性能

    • 802.11b/g/n
    • 内置低功耗32位CPU:可以兼作应用处理器
    • 内置10bit,高精度ADC
    • 内置TCP/管协议栈
    • 内置TR开关、balun、LNA、功率放大器和匹配网络
    • 内置PLL、稳压器和电源管理组件
    • 支持天线分集
    • STBC、1×1MIMO、2×1 MIMO
    • A-MPDU、A-MSDU的聚合和0.4s的保护间隔
    • [email protected],支持WPAWPA2安全模式
    • 支持STA/AP/STA+AP工作模式
    • 支持 Smart Config 功能(包括Android和iOS设备)
    • SDIO 2.0、(H)SPI、UART、I2C、12S、IR Remote Control、PWM、GPIO
    • 深度睡眠保持电流为10uA,关断电流小于5uA
    • 2ms 之内唤醒、连接并传递数据包
    • 802.11b模式下+20dBm的输出功率
    • 待机状态消耗功率小于1.0mW(DTIM3)
    • 工作温度范围:-40℃-125℃
    • 模细通过CC,CE,TELEC,WiFi Alliance及 SRRC认证

在这里插入图片描述

简要介绍一下这个ESP8266,它一共有三种工作模式,AP模式,STA模式,AP+STA模式,每种模式的使用情况介绍如下图:

img

接下来我来介绍一下我们本次项目使用的传感器DHT11温湿度传感器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E0qeg5MX-1593946859904)(https://techtutorialsx.files.wordpress.com/2016/04/dht11.png?w=197&h=153)]

DHT11可以测量温度和湿度,是简单环境监测项目的理想选择。它的温度分辨率为1ºC,相对湿度为1%。它的温度范围在0ºC到50ºC之间,湿度的测量范围取决于温度(您可以查看数据表中的详细信息)。

OLED

OLED,即有机发光二极管(OrganicLight-Emitting Diode),又称为有机电激光显示(OrganicElectroluminesence Display, OELD)。因为具备轻薄、省电等特性,因此从2003 年开始,这种显示设备在MP3播放器上得到了广泛应用,而对于同属数码类产品的DC 与手机,此前只是在一些展会上展示过采用OLED 屏幕的工程样品。自2007 年后,寿命得到很大提高,具备了许多LCD 不可比拟的优势。

img

接线

ESP8266 DHT11 OLED
GPIO_05 信号引脚
GPIO_14 SCL
GPIO_02 SDA

下面我们开始配置Arduino IDE使其支持ESP8266的开发

如前所述,我们假设使用Arduino IDE对ESP8266进行编程。如果您尚未将其配置为支持ESP8266板。Arduino有一些库可以简化我们与DHT11还有OLED的交互的任务。一个非常简单易用且与ESP8266配合使用的是Simple DHT传感器库OLED则是u8g2。可以通过Arduino IDE Library Manager轻松安装这两个库。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Tg3qy3tw-1593946859916)(https://techtutorialsx.files.wordpress.com/2016/04/dht11-esp8266-library1.png?w=640)]

温湿度获取编程:

要导入新安装的库,请在代码顶部添加以下include:

#include <SimpleDHT.h>

同时使用GPIO引脚的编号声明一个全局变量,以便于更改。在这种情况下,我们将使用GPIO5:

int DHTpin = 5;

要允许将数据发送到计算机,请在设置功能中启动串行连接:

Serial.begin(115200);

声明两个字节变量,一个用于温度,另一个用于湿度:

byte temperature;

byte humidity;

我们使用字节变量,因为DHT11在温度和湿度方面只有8位分辨率。

最后,在主循环函数中,读取值并通过串口发送它们:

if (simple_dht11_read(DHTpin, &temperature, &humidity, NULL)) {

   Serial.print("Failed.");

}else {

   Serial.print("温度: "); Serial.print(temperature); Serial.println("ºC");

   Serial.print("湿度: "); Serial.print(humidity); Serial.println("%");

}

delay(500);

打开Arduino IDE的串行监视器,应该会看到类似于图4的内容。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FPQdcSUe-1593946859922)(https://techtutorialsx.files.wordpress.com/2016/04/esp8266-dht11-readings.png?w=640)]

到这里我们就完成了ESP8266对温湿度的获取程序,下一步我们来点亮我们的OLED屏幕

#include <Arduino.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ D2, /* data=*/ D1, /* reset=*/ U8X8_PIN_NONE);   // 此处 D1 D2是对应焊接的脚针

void setup(void) {
  u8g2.begin();
}

void loop(void) {
  u8g2.clearBuffer();                    // clear the internal memory
  u8g2.setFont(u8g2_font_ncenB08_tr);    // choose a suitable font
  u8g2.drawStr(0,10,"Hello World!");    // write something to the internal memory
  u8g2.sendBuffer();                    // transfer internal memory to the display
  delay(1000);  
}

下载程序后是不是屏幕上出现了Hello World!呢?好奇心严重的小宝宝可能发现了这代码没法显示中文啊!!!!

下面我们来修改代码让他显示中文

/*
esp8266+oled显示屏
显示汉字项目
论坛地址:bbskali.cn
博客:blog.bbskali.cn
*/

#include <Arduino.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif



U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ D2, /* data=*/ D1, /* reset=*/ U8X8_PIN_NONE);   // All Boards without Reset of the Display


void setup(void) {
  u8g2.begin();
  u8g2.enableUTF8Print();        // enable UTF8 support for the Arduino print() function
}

void loop(void) {
  u8g2.setFont(u8g2_font_unifont_t_chinese2);  // use chinese2 for all the glyphs of "你好世界"
  u8g2.setFontDirection(0);
  u8g2.clearBuffer();
  u8g2.setCursor(0, 15);
  u8g2.print("你好世界");
  u8g2.setCursor(0, 30);
  u8g2.print("你好世界");        // Chinese "Hello World" 

  u8g2.sendBuffer();

  delay(1000);
}

到这里我们的OLED得编码工作也到了最后一步了,发送HTTP-post请求到我们的API。

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>

const char* ssid = "##设置能上网的wifi的名称##";      // wifi名
const char* password = "##wifi密码##";  // wifi密码

const char* host = "api.heclouds.com";  // 连接的主机域名
const int httpsPort = 443;  // https端口
String url = "";  // 请求的页面地址(后面代码中进行拼接)

String API_KEY = "##填写自己OneNet平台里的OneNet的api key##";  // onenet的 api key
String deviceId = "##OneNet里设备的ID##";    // onenet的 设备ID
String dataId = "led";    // 任意设置的数据名

void connectWifi();
void postDataToOnenet(float data);

void setup() {
  Serial.begin(115200);
}

void loop() {
  float data = 314;
  postDataToOnenet(data);
  delay(3000);
}

/**
 * 连接wifi
 */
void connectWifi(){
    Serial.println();
    Serial.print("connecting to ");
    Serial.println(ssid);

  WiFi.mode(WIFI_STA);    // 设置wifi模式
  WiFi.begin(ssid, password);   // 连接wifi
  while (WiFi.status() != WL_CONNECTED) { //判断连接状态
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

  Serial.print("requesting URL: ");
  Serial.println(url);

  // 发送POST请求
  // 组拼url地址
  url = "/devices/" + deviceId + "/datapoints";
  // 组拼HTTPS请求的Header
  String jsonStr = String("") + "{'datastreams':[{" +
            "'id':'" + dataId + "'" +
            ",'datapoints':[{" +
            "'value':" + data +
            "}]}]}";
  String getStr = String("POST ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "User-Agent: arduino\r\n" +
               "api-key:" + API_KEY + "\r\n" +
               "Connection: close\r\n";
  client.print(getStr);   // 发送Headers头
  client.print(String("") + "Content-Length:" + jsonStr.length() + "\r\n\r\n"); // 发送Header头-数据内容长度(注意:\r\n\r\n是结尾)
  client.print(jsonStr);  // 发送json数据

  Serial.println("request sent");

  Serial.println("==========");
  Serial.println("send was:");
  Serial.println(jsonStr);   // 打印发送的请求数据
  String line = client.readStringUntil('\n');
  Serial.println("reply was:");
  Serial.println(line);   // 打印接受到的数据
  Serial.println("==========");
###### }

到这里我们基础的小功能就都开发完成了!!!

下面我们进行最后一步将我们之前的代码整合到一起完成我们的想dome。

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266mDNS.h>
#include <SimpleDHT.h>
#include <Arduino.h>
#include <U8g2lib.h>

String url = "192.168.199.228:5000";  // 请求的页面地址(后面代码中进行拼接)
const char* host = "192.168.199.228";  // 连接的主机域名
const int httpsPort = 5000;  // https端口


String API_KEY = "123";  //  api key
String dataId = "07140401";    // 任意设置的数据名

#define USE_SERIAL Serial
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
#define SCL 14
#define SDA 2
#ifndef STASSID
#define STASSID "************"
#define STAPSK  "************"
#endif
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);
ESP8266WiFiMulti WiFiMulti;
int pinDHT11 = 5;
SimpleDHT11 dht11(pinDHT11);
byte temperature;
byte humidity;
const char *ssid = STASSID;
const char *password = STAPSK;

ESP8266WebServer server(80);

const int led = 13;

void handleRoot() {
  digitalWrite(led, 1);
  char temp[400];
  int sec = millis() / 1000;
  int min = sec / 60;
  int hr = min / 60;

  snprintf(temp, 400,

           "<html>\
  <head>\
    <meta http-equiv='refresh' content='5'/>\
    <title>ESP8266 Demo</title>\
    <style>\
      body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }\
    </style>\
  </head>\
  <body>\
    <h1>这里是ESP8266!</h1>\
    <p>运行时间: %02d:%02d:%02d</p>\
    <img src=\"/test.svg\" />\
  </body>\
</html>",

           hr, min % 60, sec % 60
          );
  server.send(200, "text/html", temp);
  digitalWrite(led, 0);
}

void handleNotFound() {
  digitalWrite(led, 1);
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";

  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }

  server.send(404, "text/plain", message);
  digitalWrite(led, 0);
}


void setup(void) {
  u8g2.begin();//oled初始化
  u8g2.enableUTF8Print(); //初始换OLED中文语言类库
  u8g2.setFont(u8g2_font_wqy15_t_chinese2); //设置中文字体 
  u8g2.setFontDirection(0);
  u8g2.clearBuffer();// 清除内存
  u8g2.setCursor(0, 15);//设置写入位置
  u8g2.print("系统启动中");
  u8g2.sendBuffer();// 将内存传输到显示器
  delay(100);
  pinMode(led, OUTPUT);
  digitalWrite(led, 0);
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  u8g2.setFontDirection(0);
  u8g2.clearBuffer();// 清除内存
  u8g2.setCursor(0, 15);//设置写入位置
  u8g2.print("网络连接中");
  u8g2.sendBuffer();// 将内存传输到显示器
    Serial.print("网络连接失败");
  }

  Serial.println("");
  Serial.print("接入WiFi名称:");
  Serial.println(ssid);
  Serial.print("获取IP地址");
  u8g2.setFontDirection(0);
  u8g2.clearBuffer();// 清除内存
  u8g2.setCursor(0, 15);//设置写入位置
  u8g2.print("IP地址为:");
  u8g2.setCursor(0, 40);
  u8g2.print(WiFi.localIP());
  u8g2.sendBuffer();// 将内存传输到显示器
  delay(500);
  Serial.println(WiFi.localIP());

  if (MDNS.begin("esp8266")) {
    Serial.println("MDNS服务启动成功");
  }

  server.on("/", handleRoot);
  server.on("/test.svg", drawGraph);
  server.on("/inline", []() {
    server.send(200, "text/plain", "this works as well");
  });
  server.onNotFound(handleNotFound);
  server.begin();
  Serial.println("HTTP服务启动成功");
}

void loop(void) {
  server.handleClient();
  MDNS.update();
  ws();


}

void ws() {
  int err = SimpleDHTErrSuccess;
  if ((err = dht11.read(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) {
    Serial.print("Read DHT11 failed, err="); Serial.println(err);delay(1000);
    return;
  }
  u8g2.setFontDirection(0);
  u8g2.clearBuffer();// 清除内存
  u8g2.setCursor(0, 15);//设置写入位置
  u8g2.print("温度");
  u8g2.print((int)temperature);
  postData(temperature,"温度");
  u8g2.print(" *C, ");
  u8g2.setCursor(0, 40);
  u8g2.print("湿度");
  u8g2.print((int)humidity);
  postData(humidity,"湿度");
  u8g2.print(" H");
  u8g2.sendBuffer();// 将内存传输到显示器
  Serial.print("Sample OK: ");
  Serial.print((int)temperature); Serial.print(" *C, "); 
  Serial.print((int)humidity); Serial.println(" H");
  delay(1500);
}

void drawGraph() {
  String out = "";
  char temp[100];
  out += "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width=\"400\" height=\"150\">\n";
  out += "<rect width=\"400\" height=\"150\" fill=\"rgb(250, 230, 210)\" stroke-width=\"1\" stroke=\"rgb(0, 0, 0)\" />\n";
  out += "<g stroke=\"black\">\n";
  int y = rand() % 130;
  for (int x = 10; x < 390; x += 10) {
    int y2 = rand() % 130;
    sprintf(temp, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" stroke-width=\"1\" />\n", x, 140 - y, x + 10, 140 - y2);
    out += temp;
    y = y2;
  }
  out += "</g>\n</svg>\n";

  server.send(200, "image/svg+xml", out);
}
void postData(float data,String type){
  // Use WiFiClientSecure class to create TLS connection
  WiFiClient client;          // HTTP
  //WiFiClientSecure client;    // HTTPS
  Serial.print("connecting to ");
  Serial.println(host);
  if (!client.connect(host, httpsPort)) {   // 判断连接情况
    Serial.println("connection failed");
    return;
  }
  Serial.print("requesting URL: ");
  Serial.println(url);
  // 发送POST请求
  // 组拼url地址
  //url = "/devices/" + deviceId + "/datapoints";
  // 组拼HTTPS请求的Header
  String jsonStr = String("") + "{'"+type+"':[{" +
            "'id':'" + dataId + "'" +
            ",'data':[{" +
            "'value':" + data +
            "}]}]}";
  String getStr = String("POST ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "User-Agent: arduino\r\n" +
               "api-key:" + API_KEY + "\r\n" +
               "Connection: close\r\n";
  client.print(getStr);   // 发送Headers头
  client.print(String("") + "Content-Length:" + jsonStr.length() + "\r\n\r\n"); // 发送Header头-数据内容长度(注意:\r\n\r\n是结尾)
  client.print(jsonStr);  // 发送json数据
  Serial.println("request sent");
  Serial.println("==========");
  Serial.println("send was:");
  Serial.println(jsonStr);   // 打印发送的请求数据
  String line = client.readStringUntil('\n');
  Serial.println("reply was:");
  Serial.println(line);   // 打印接受到的数据
  Serial.println("==========");
}

到这里我们的硬件全部工作都已经完成了,接下来我们使用Thinkphp写一个简单的api来接收ESP8266发送的信息吧!

猜你喜欢

转载自blog.csdn.net/weixin_41450123/article/details/107143234