ESP8266 控制舵机和 DHT11 传感器数据上传 OneNET 平台

一、硬件准备

  • Arduino 开发板
  • ESP8266 模块
  • DHT11 温湿度传感器
  • 舵机
  • 面包板
  • 跳线

二、软件准备

  • Arduino IDE
  • OneNET 平台账号

三、代码实现

// 引入 ESP8266.h 头文件,建议使用教程中修改后的文件
#include <ESP8266.h>
#include <dht11.h>
#include <SoftwareSerial.h>
#include <WiFi.h>
#include <Servo.h>

// 配置 ESP8266 WIFI 设置
#define SSID 'HONOR Play4T'    // 填写 2.4GHz 的 WIFI 名称,不要使用校园网
#define PASSWORD '12345678' // 填写自己的 WIFI 密码
#define HOST_NAME 'api.heclouds.com'  // API 主机名称,连接到 OneNET 平台,无需修改
#define DEVICE_ID '1099655073'       // 填写自己的 OneNET 设备 ID
#define HOST_PORT (80)                // API 端口,连接到 OneNET 平台,无需修改
String APIKey = 'IiJSs17atNND2C77wumz03w63hw='; // 与设备绑定的 APIKey
String cmdUrl = 'http://api.heclouds.com/cmds?device_id=1099655073';
#define INTERVAL_SENSOR 5000 // 定义传感器采样及发送时间间隔

// 创建 dht11 示例
dht11 DHT11;
// 创建舵机
Servo myservo;
int servoPin = 7;
int light = 0;
int servoPos = 0;
// 定义 DHT11 接入 Arduino 的管脚
#define DHT11PIN 4

// 定义 ESP8266 所连接的软串口
/*********************
 * 该实验需要使用软串口
 * Arduino 上的软串口 RX 定义为 D3,
 * 接 ESP8266 上的 TX 口,
 * Arduino 上的软串口 TX 定义为 D2,
 * 接 ESP8266 上的 RX 口.
 * D3 和 D2 可以自定义,
 * 但接 ESP8266 时必须恰好相反
 *********************/
SoftwareSerial mySerial(3, 2);
ESP8266 wifi(mySerial);

void handleCommand(String command) {
  Serial.print('Command received: ');
  Serial.println(command);

  if (command == '0') { // 控制舵机转到 0 度位置
    myservo.write(0);
    servoPos = 0;
    light = 0;
    Serial.println('Servo position: 0');
    myservo.write(servoPos);
  } else if (command == '1') { // 控制舵机转到 180 度位置
    myservo.write(180);
    servoPos = 180;
    light = 1;
    Serial.println('Servo position: 180');
    myservo.write(servoPos);
  } else {
    Serial.println('Invalid command');
  }
}

void setup() {
  mySerial.begin(115200); // 初始化软串口
  Serial.begin(9600);     // 初始化串口
  Serial.print('setup begin\r\n');

  myservo.attach(servoPin);
  myservo.write(0);
  
  // 以下为 ESP8266 初始化的代码
  Serial.print('FW Version: ');
  Serial.println(wifi.getVersion().c_str());

  if (wifi.setOprToStation()) {
    Serial.print('to station ok\r\n');
  } else {
    Serial.print('to station err\r\n');
  }

  // ESP8266 接入 WIFI
  if (wifi.joinAP(SSID, PASSWORD)) {
    Serial.print('Join AP success\r\n');
    Serial.print('IP: ');
    Serial.println(wifi.getLocalIP().c_str());
  } else {
    Serial.print('Join AP failure\r\n');
  }
  Serial.println('');
  Serial.print('DHT11 LIBRARY VERSION: ');
  Serial.println(DHT11LIB_VERSION);

  mySerial.println('AT+UART_CUR=9600,8,1,0,0');
  mySerial.begin(9600);
  Serial.println('setup end\r\n');
 
}

unsigned long net_time1 = millis(); // 数据上传服务器时间
unsigned long net_time2 = millis(); // 获取命令时间
void loop() {

  if (net_time1 > millis())
    net_time1 = millis();
 
  if (millis() - net_time1 > INTERVAL_SENSOR) // 发送数据时间间隔
  {

    int chk = DHT11.read(DHT11PIN);

    Serial.print('Read sensor: ');
    switch (chk) {
      case DHTLIB_OK:
        Serial.println('OK');
        break;
      case DHTLIB_ERROR_CHECKSUM:
        Serial.println('Checksum error');
        break;
      case DHTLIB_ERROR_TIMEOUT:
        Serial.println('Time out error');
        break;
      default:
        Serial.println('Unknown error');
        break;
    }

    float sensor_hum = (float)DHT11.humidity;
    float sensor_tem = (float)DHT11.temperature;
    Serial.print('Humidity (%): ');
    Serial.println(sensor_hum, 2);

    Serial.print('Temperature (oC): ');
    Serial.println(sensor_tem, 2);
    Serial.println('');

    if (wifi.createTCP(HOST_NAME, HOST_PORT)) { // 建立 TCP 连接,如果失败,不能发送该数据
      Serial.print('create tcp ok\r\n');
      char buf[10];

      // 拼接发送 data 字段字符串
      String jsonToSend = '{"Temperature":';
      dtostrf(sensor_tem, 1, 2, buf);
      jsonToSend += '"' + String(buf) + '"';
      jsonToSend += ',"Humidity":';
      dtostrf(sensor_hum, 1, 2, buf);
      jsonToSend += '"' + String(buf) + '"';
      jsonToSend += ',"light":';
      jsonToSend += '"' + String(light) + '"';
      jsonToSend += '}';

      // 拼接 POST 请求字符串
      String postString = 'POST /devices/';
      postString += DEVICE_ID;
      postString += '/datapoints?type=3 HTTP/1.1';
      postString += '\r\n';
      postString += 'api-key:';
      postString += APIKey;
      postString += '\r\n';
      postString += 'Host:api.heclouds.com\r\n';
      postString += 'Connection:close\r\n';
      postString += 'Content-Length:';
      postString += jsonToSend.length();
      postString += '\r\n';
      postString += '\r\n';
      postString += jsonToSend;
      postString += '\r\n';
      postString += '\r\n';
      postString += '\r\n';

      const char *postArray = postString.c_str(); // 将 str 转化为 char 数组

      Serial.println(postArray);
      wifi.send((const uint8_t *)postArray, strlen(postArray)); // send 发送命令,参数必须是这两种格式,尤其是 (const uint8_t*)
      Serial.println('send success');

      if (wifi.releaseTCP()) { // 释放 TCP 连接
        Serial.print('release tcp ok\r\n');
      } else {
        Serial.print('release tcp err\r\n');
      }
      postArray = NULL; }// 清空数组,等待下次传输数据
else {
        Serial.print('create tcp err\r\n');
      }
    Serial.println('');
    net_time1 = millis();
  } 

  // 从 OneNET 服务器获取命令
  if (millis() - net_time2 > 10000) { // 获取命令时间间隔
    if (wifi.createTCP(HOST_NAME, HOST_PORT)) { // 建立 TCP 连接,如果失败,不能获取命令
      Serial.print('create tcp ok\r\n');

      // 拼接 GET 请求字符串
      String cmdString = 'GET '; cmdString += cmdUrl; cmdString += ' HTTP/1.1'; cmdString += '\r\n';
      cmdString += 'api-key:'; cmdString += APIKey; cmdString += '\r\n'; cmdString += 'Host:api.heclouds.com\r\n';
      cmdString += 'Connection:close\r\n'; cmdString += '\r\n'; cmdString += '\r\n'; cmdString += '\r\n';

      const char *cmdArray = cmdString.c_str(); // 将 str 转化为 char 数组

      Serial.println(cmdArray);
      wifi.send((const uint8_t *)cmdArray, strlen(cmdArray)); // send 发送命令,参数必须是这两种格式,尤其是 (const uint8_t*)

      // 等待服务器回复
      String recvBuf = '';
      
      while (true) {
        int len = wifi.recv((uint8_t *)mySerial_buf, sizeof(mySerial_buf), 1000); // 接收数据
        if (len <= 0) {
          Serial.println('recv timeout');
          break;
        } else {
          mySerial_buf[len] = '\0';
          Serial.print(mySerial_buf);
          recvBuf += String(mySerial_buf);
        }
      }

      cmdArray = NULL;

      // 解析命令
      int pos = recvBuf.indexOf('"cmd":"');
      if (pos >= 0) {
        int endPos = recvBuf.indexOf('"', pos + 8);
        if (endPos >= 0) {
          String command = recvBuf.substring(pos + 7, endPos);
          handleCommand(command);
        }
      }

      if (wifi.releaseTCP()) { // 释放 TCP 连接
        Serial.print('release tcp ok\r\n');
      } else {
        Serial.print('release tcp err\r\n');
      }
    } else {
      Serial.print('create tcp err\r\n');
    }

    Serial.println('');
    net_time2 = millis();
  }
}

四、代码说明

  1. 代码中包含了 ESP8266.h、dht11.h、SoftwareSerial.h、WiFi.h 和 Servo.h 这五个库文件,需要在 Arduino IDE 中安装这些库文件。
  2. 代码中定义了 WIFI 的 SSID 和 PASSWORD,以及 OneNET 平台的 HOST_NAME、DEVICE_ID 和 APIKey,需要根据自己的实际情况进行修改。
  3. 代码中定义了传感器采样及发送时间间隔 INTERVAL_SENSOR,可以根据自己的需求进行修改。
  4. 代码中定义了 DHT11 传感器接入 Arduino 的管脚 DHT11PIN,需要根据自己的实际情况进行修改。
  5. 代码中定义了 ESP8266 所连接的软串口 mySerial,需要根据自己的实际情况进行修改。
  6. 代码中定义了舵机控制函数 handleCommand,可以根据自己的需求进行修改。
  7. 代码中定义了数据上传服务器时间 net_time1 和 获取命令时间 net_time2,用于控制数据上传和命令获取的时间间隔。

五、连接电路

  • 将 ESP8266 模块的 TX 脚连接到 Arduino 的 D3 脚,RX 脚连接到 Arduino 的 D2 脚。
  • 将 DHT11 传感器的信号脚连接到 Arduino 的 D4 脚,VCC 脚连接到 Arduino 的 5V 脚,GND 脚连接到 Arduino 的 GND 脚。
  • 将舵机的信号脚连接到 Arduino 的 D7 脚,VCC 脚连接到 Arduino 的 5V 脚,GND 脚连接到 Arduino 的 GND 脚。

六、上传代码

将代码上传到 Arduino 开发板,并打开串口监视器,可以看到 ESP8266 的状态信息,以及传感器采集到的数据和上传到 OneNET 平台的数据。

七、OneNET 平台操作

  1. 在 OneNET 平台上创建设备,并将设备 ID 和 APIKey 填写到代码中。
  2. 在 OneNET 平台上添加数据流,并设置数据流的名称和数据类型。
  3. 在 OneNET 平台上添加命令,并设置命令的名称和命令类型。

八、使用说明

  • 当程序运行时,ESP8266 模块会连接到 WIFI 网络,并将 DHT11 传感器采集到的数据上传到 OneNET 平台。
  • 当 OneNET 平台下发命令时,ESP8266 模块会根据命令控制舵机的旋转角度。

九、注意事项

  • ESP8266 模块需要使用教程中修改后的 ESP8266.h 头文件,才能正常工作。
  • DHT11 传感器需要连接到 Arduino 的 D4 脚,才能正常工作。
  • 舵机需要连接到 Arduino 的 D7 脚,才能正常工作。
  • OneNET 平台的设备 ID 和 APIKey 需要根据自己的实际情况进行修改。
  • 数据上传和命令获取的时间间隔可以根据自己的需求进行修改。

十、扩展功能

  • 可以添加其他传感器,例如光线传感器、压力传感器等,并将数据上传到 OneNET 平台。
  • 可以添加其他控制功能,例如控制 LED 灯的亮灭、控制电机等。
  • 可以使用 MQTT 协议将数据上传到 OneNET 平台,提高数据上传的效率。

本教程介绍了 ESP8266 模块的基本操作,希望能够帮助你入门 ESP8266 开发。

ESP8266 控制舵机和 DHT11 传感器数据上传 OneNET 平台

原文地址: https://www.cveoy.top/t/topic/oLbm 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录