Arduino utiliza ESP8266 y DHT11 para mostrar los valores de temperatura y humedad.

Código completo, es mejor modificar el tamaño de SERIAL_RX_BUFFER_SIZE.

#include <SoftwareSerial.h>

#define DHT11_PIN (5)      //SCL引脚内部和ANALOG5相连,实际是PC5端口
byte dht11_dat[5];         //存储dht11的5字节数据

SoftwareSerial mySerial = SoftwareSerial(11, 12);

char ok[] = "OK";
char ipd[] = "+IPD,";
char rdy[] = "ready";
char GET[] = "GET /";
char SEND[] = ">";

int headlength;
char Header[]  = "HTTP/1.1 200 OK\r\n\
Server: nginx/1.10.3 (Ubuntu)\r\n\
Date: Wed, 08 Apr 2020 09:29:22 GMT\r\n\
Content-Type: text/plain\r\n\
Content-Length: 42\r\n\
Connection: keep-alive\r\n\
Last-Modified: Tue, 18 Sep 2018 03:55:48 GMT\r\n\
Accept-Ranges: bytes\r\n\
\r\n";

void setup()
{
  DDRC |= _BV(DHT11_PIN);   //Data Direction Register(数据方向寄存器)
  PORTC |= _BV(DHT11_PIN);  //数据寄存器


  mySerial.begin(9600);
  mySerial.println(Header);

  Serial.begin(115200);
  Serial.print(F("AT+RST\r\n"));
  if (waitForStr(rdy, 5000) == true)
    mySerial.println(F("ready ok"));

  Serial.println(F("ATE0"));           //disable echo
  if (waitForStr(ok, 1000) == true)
    mySerial.println(F("ATE0 ok"));

  Serial.println(F("AT+CWMODE=2"));    //station, AP is 3
  if (waitForStr(ok, 1000) == true)
    mySerial.println(F("AT+CWMODE=2 ok"));

  Serial.println(F("AT+CIPMUX=1"));
  if (waitForStr(ok, 1000) == true)
    mySerial.println(F("AT+CIPMUX=1 ok"));

  Serial.println(F("AT+CIPSERVER=1,8080"));
  if (waitForStr(ok, 1000) == true)
    mySerial.println(F("AT+CIPSERVER=1,8080 ok"));

  headlength = getStrLength(Header);
}


void loop()
{
  delay(1000);                              //最快1s读一次传感器的数据
  byte ret = read_dht11();
  if (ret != 0)
  {
    mySerial.println("dht11 error!");
    return ;
  }

  static char mux;                          //记录连接的通道号
  if (waitForStr(ipd, 1000) == true)        //有新的连接接入
  {
    mux = Serial.read();                    //ipd字符串下一个字节就是连接通道号
    if (waitForStr(GET, 1000) == true)      //有新的GET请求
    {
      //组建Body
      char Body[64];
      int bodylength = 0;
      sprintf(Body, "Current humdity = %2d.%1d%%\r\ntemperature=%2d.%1dC", dht11_dat[0], dht11_dat[1], dht11_dat[2], dht11_dat[3]);
      bodylength = getStrLength(Body);
      //调试串口打印 组建的数据的内容及长度
      //Header中的Content-Length必须设置成和这里的bodylength一样,否则浏览器不能正确解析,导致解析失败
      mySerial.println(Body);
      mySerial.print(F("Body length:"));
      mySerial.println(bodylength);
      //AT+CIPSEND=x,y 进入透传模式进行回复,x为通道号,y为要返回的数据长度
      Serial.print(F("AT+CIPSEND="));
      Serial.print(mux);
      Serial.print(",");
      Serial.println(headlength + bodylength);

      if (waitForStr(SEND, 1000) == true)   //出现'>'符号开始发送,发送头和体
      {
        Serial.print(Header);
        Serial.println(Body);
        if (waitForStr(ok, 10000) != true)    mySerial.println(F("send timeout"));

        //强制断开该连接
        Serial.print(F("AT+CIPCLOSE="));
        Serial.println(mux);
        if (waitForStr(ok, 1000) != true)     mySerial.println(F("close failed"));

      }
      else
      {
        mySerial.println(F("no >"));
      }
    }
    else
      mySerial.println(F("no GET"));
  }
  else
    mySerial.println(F("no connect"));
}
















/*---------------------------------------------------------------------------------------------------------------*/



int getStrLength(char* str) {
  int i = 0;
  while (str[i] != '\0') {
    i++;
  }
  return i;
}


bool waitForStr(char* str, long timeout) {
  long intime = millis();
  int i = 0, j = 0, cur = 0, index = 0;
  int len = getStrLength(str);
  bool ret = true;
  char* temp = new char(len);
  while (str[i] != '\0') {
    while (j - cur < len) {
      if (timeout > 0)
        if (millis() - intime > timeout) {
          ret = false;
          goto OUT;
        }
      if (Serial.available()) {
        index = j % len;
        temp[index] = Serial.read();
        j++;
      }
    }
    index = (cur + i) % len;
    if (str[i] == temp[index])
      i++;
    else
      i = 0, cur++;
  }
OUT:
  delete temp;
  return ret;
}




/*---------------------------------------------------------------------------------------------------------------*/

/*
  从DHT11中读取一个byte的数据
*/
byte read_dht11_dat()
{
  byte i = 0;
  byte result = 0;
  for (i = 0; i < 8; i++) {

    while (!(PINC & _BV(DHT11_PIN))); // wait for 50us          //#define _BV(bit) (1 << (bit))
    delayMicroseconds(30);

    if (PINC & _BV(DHT11_PIN))
      result |= (1 << (7 - i));
    while ((PINC & _BV(DHT11_PIN))); // wait '1' finish
  }
  return result;
}

/*
  从DHT11中读取一次数据
*/
byte read_dht11()
{
  byte dht11_in;        //存储当前端口读取的值
  byte i;
  // start condition
  // 1. pull-down i/o pin from 18ms
  PORTC &= ~_BV(DHT11_PIN); //拉低
  delay(18);
  PORTC |= _BV(DHT11_PIN);  //拉高
  delayMicroseconds(40);

  DDRC &= ~_BV(DHT11_PIN);
  delayMicroseconds(40);

  dht11_in = PINC & _BV(DHT11_PIN);

  if (dht11_in) {
    //Serial.println("dht11 start condition 1 not met");
    return 1;
  }
  delayMicroseconds(80);

  dht11_in = PINC & _BV(DHT11_PIN);

  if (!dht11_in) {
    //Serial.println("dht11 start condition 2 not met");
    return 2;
  }
  delayMicroseconds(80);
  // now ready for data reception
  for (i = 0; i < 5; i++)
    dht11_dat[i] = read_dht11_dat();

  DDRC |= _BV(DHT11_PIN);
  PORTC |= _BV(DHT11_PIN);

  byte dht11_check_sum = dht11_dat[0] + dht11_dat[1] + dht11_dat[2] + dht11_dat[3];
  // check check_sum
  if (dht11_dat[4] != dht11_check_sum)
  {
    //Serial.println("DHT11 checksum error");
    return 3;
  }
  return 0;
}

Pero el siguiente ciclo personalmente considera que está escrito un poco más estandarizado, y debería ser similar al anterior, pero a veces el navegador no espera respuesta.

void loop()
{
  mySerial.print(F("current time:"));
  mySerial.println(millis());
  char Body[64];
  int bodylength = 0;

  delay(1000);                              //最快1s读一次传感器的数据
  int ret = read_dht11();
  if (ret != 0)
  {
    mySerial.print(F("dht11 error:"));
    mySerial.println(ret);
    return ;
  }

  static char mux;                          //记录连接的通道号
  if (waitForStr(ipd, 1000) != true)        //无新的连接接入,直接超时退出
  {
    mySerial.println(F("no connect"));
    return;
  }
  //有新的连接,开始读取通道号,ipd字符串下一个字节就是连接通道号
  mux = Serial.read();
  if (waitForStr(GET, 1000) != true)        //不是GET请求,直接断开连接
  {
    mySerial.println(F("no GET"));
    goto close_ipd;
  }

  //组建Body
  sprintf(Body, "Current humdity = %2d.%1d%%\r\ntemperature=%2d.%1dC", dht11_dat[0], dht11_dat[1], dht11_dat[2], dht11_dat[3]);
  bodylength = getStrLength(Body);
  //调试串口打印 组建的数据的内容及长度
  //Header中的Content-Length必须设置成和这里的bodylength一样,否则浏览器不能正确解析,导致解析失败
  mySerial.println(Body);
  mySerial.print(F("Body length:"));
  mySerial.println(bodylength);

  //AT+CIPSEND=x,y 进入透传模式进行回复,x为通道号,y为要返回的数据长度
  Serial.print(F("AT+CIPSEND="));
  Serial.print(mux);
  Serial.print(",");
  Serial.println(headlength + bodylength);

  if (waitForStr(SEND, 1000) != true)       //没有进入透传模式,一般是不会进这里的,做错误检查,但还是要释放连接
  {
    mySerial.println(F("no >"));
    goto close_ipd;
  }
  //出现'>'符号开始发送,发送头和体
  Serial.print(Header);
  Serial.println(Body);
  if (waitForStr(ok, 10000) != true)        //发送超时,或者可能是数据包长度不对,退出透传模式,并断开连接
  {
    mySerial.println(F("send timeout"));
    Serial.println("+++");
    goto close_ipd;
  }

close_ipd:
  //强制断开该连接
  Serial.print(F("AT+CIPCLOSE="));
  Serial.println(mux);
  if (waitForStr(ok, 1000) != true)         //强制断开连接失败……怎么可能失败……
    mySerial.println(F("close failed"));
}
Publicado 340 artículos originales · ganó 78 · 230,000 vistas +

Supongo que te gusta

Origin blog.csdn.net/qq_27508477/article/details/105427056
Recomendado
Clasificación