基于巴法云的esp8266实现温湿度、LED、sg90舵机和HC-RS04实现的小程序远程控制

该项目通过ESP8266实现温湿度、LED、舵机和超声波传感器的远程控制。使用巴法云作为服务器,通过TCP连接进行数据交互。代码中包含了DHT11传感器读取温湿度、LED开关控制、SG90舵机转动以及HC-SR04超声波测距功能,并解决了舵机消抖问题。
摘要由CSDN通过智能技术生成

基于巴法云的esp8266实现温湿度、LED、sg90舵机和HC-RS04实现的小程序远程控制


本项目想法已经在我脑海想了很久了,都没有时间去实现它,这次刚刚考完试就用了两天把它做了出来,希望对大家有帮助,有什么需要的可以在下面留言喔。

  • 其实这两天遇到的坑还是比较多的,就比如在数据传输的没能想到用cmd9进行获取返回值
  • 还有一个便是舵机消抖问题

具体代码.

#include <ESP8266WiFi.h>
#include <SimpleDHT.h>
#include <U8g2lib.h>
#include <Servo.h>

///*********************************************///

//巴法云的定义
#define TCP_SERVER_ADDR "bemfa.com"
#define TCP_SERVER_PORT "8344"
#define DEFAULT_STASSID  "123456"
#define DEFAULT_STAPSW "1234567890"
String UID = "xxxxx";
String TOPIC = "temp"; //用于传输温湿度的主题
//主题名字,可在控制台新建
String TOPIC2  = "Light002";  //用于led控制的主题
String TOPIC3  = "distance";  //用于HC-RS04控制的主题
String TOPIC4  = "servo";  //用于电机控制的主题

///*********************************************///

//DHT11引脚值
int pinDHT11 = D4;  //连接dht11的引脚
//单片机LED引脚值
int LED_Pin = D2;  //假设连接led的引脚
int pin1= D5;  //连接HC-RS04的 trig引脚
int pin2= D6;  //连接HC-RS04的echo引脚
int servopin = D7;   //电机引脚
volatile float item;       //物体距离

///*********************************************///
//led 控制函数
void turnOnLed();
void turnOffLed();

//电机控制函数
void turnleft();
void turnright();

//led状态状态
String my_led_status = "off";
//电机状态状态
String my_servo_status = "left";
float cm;

//电机状态之后的 防止状态没变 导致一直运行 防抖
bool my_servo_left =true;
bool my_servo_right =true;

///*********************************************///
//下面的2代表上传间隔是2秒
#define upDataTime 2*1000

SimpleDHT11 dht11(pinDHT11);
Servo myservo;  


//最大字节数
#define MAX_PACKETSIZE 512


//tcp客户端相关初始化,默认即可
WiFiClient TCPclient;
String TcpClient_Buff = "";
unsigned int TcpClient_BuffIndex = 0;
unsigned long TcpClient_preTick = 0;
unsigned long preHeartTick = 0;
unsigned long preTCPStartTick = 0;
bool preTCPConnected = false;

///*********************************************///
//相关函数初始化
//连接WIFI
void doWiFiTick();
void startSTA();

//TCP初始化连接
void doTCPClientTick();
void startTCPClient();
void sendtoTCPServer(String p);


///*********************************************///
/*
  *发送数据到TCP服务器
 */
void sendtoTCPServer(String p){
  
  if (!TCPclient.connected()) 
  {
    Serial.println("Client is not readly");
    return;
  }
  TCPclient.print(p);   //将数据发送到巴法云中
  Serial.println("刚刚发送到云端的数据为:");
  Serial.println(p);
}
///*********************************************///
/*
  *初始化和服务器建立连接
*/
void startTCPClient(){
  if(TCPclient.connect(TCP_SERVER_ADDR, atoi(TCP_SERVER_PORT))){
    Serial.print("\nConnected to server:");
    Serial.printf("%s:%d\r\n",TCP_SERVER_ADDR,atoi(TCP_SERVER_PORT));
    String tcpTemp="";
    tcpTemp = "cmd=1&uid="+UID+"&topic="+TOPIC2+"&msg="+my_led_status+"\r\n";         //这里可以随便写一个主题,主要是测试与服务器的连接状态
    sendtoTCPServer(tcpTemp);
    preTCPConnected = true;
    preHeartTick = millis();
    TCPclient.setNoDelay(true);
  }
  else{
    Serial.print("Failed connected to server:");
    Serial.println(TCP_SERVER_ADDR);
    TCPclient.stop();
    preTCPConnected = false;
  }
  preTCPStartTick = millis();
}
///*********************************************///
/*
  *检查数据,发送数据
*/
void doTCPClientTick(){
 //检查是否断开,断开后重连
   if(WiFi.status() != WL_CONNECTED) return;

  if (!TCPclient.connected()) {//断开重连

  if(preTCPConnected == true){

    preTCPConnected = false;
    preTCPStartTick = millis();
    Serial.println();
    Serial.println("TCP Client disconnected.");
    TCPclient.stop();
  }
  else if(millis() - preTCPStartTick > 1*1000)//重新连接
    startTCPClient();
  }
  else
  {
    if (TCPclient.available()) {//收数据
      char c =TCPclient.read();
      TcpClient_Buff +=c;
      TcpClient_BuffIndex++;
      TcpClient_preTick = millis();
      if(TcpClient_BuffIndex>=MAX_PACKETSIZE - 1){
        TcpClient_BuffIndex = MAX_PACKETSIZE-2;
        TcpClient_preTick = TcpClient_preTick - 200;
      }
      preHeartTick = millis();   
    }   
    if(millis() - preHeartTick >= upDataTime){//上传数据
      preHeartTick = millis();

      /*****************获取DHT11 温湿度*****************/
      // read without samples.
      byte temperature = 0;
      byte humidity = 0;
      int err = SimpleDHTErrSuccess;
      if ((err = dht11.read(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) {
        Serial.print("Read DHT11 failed, err="); Serial.println(err);delay(1000);
        return;
      }      
      /*********************数据上传*******************/
      /*
        数据用#号包裹,以便app分割出来数据,&msg=#23#80#on#\r\n,即#温度#湿度#按钮状态#,app端会根据#号分割字符串进行取值,以便显示
        如果上传的数据不止温湿度,可在#号后面继续添加&msg=#23#80#data1#data2#data3#data4#\r\n,app字符串分割的时候,要根据上传的数据进行分割
      */
      String upstr = "";
      String upstr1 = "";
      String upstr2 = "";
      String upstr3 = "";

      //发送数据   温湿度及距离用cmd2 发送无需返回值    而需要返回值的  这种情况需要是服务器端操控单片机的话 使用cmd9
      upstr = "cmd=2&uid="+UID+"&topic="+TOPIC+"&msg=#"+temperature+"#"+humidity+"#\r\n";
      upstr1 = "cmd=9&uid="+UID+"&topic="+TOPIC2+"\r\n";
      upstr2 = "cmd=2&uid="+UID+"&topic="+TOPIC3+"&msg="+item+"\r\n";
      upstr3 = "cmd=9&uid="+UID+"&topic="+TOPIC4+"\r\n"; 
        
      sendtoTCPServer(upstr);
      sendtoTCPServer(upstr1);
      sendtoTCPServer(upstr2);
      sendtoTCPServer(upstr3); 
      upstr = "";
      upstr1 = "";
      upstr2 = "";
      upstr3 = "";
    }
  }
  if((TcpClient_Buff.length() >= 1) && (millis() - TcpClient_preTick>=200))
  {//data ready
    TCPclient.flush();
    Serial.println("Buff");
    Serial.println(TcpClient_Buff);
    //TcpClient_Buff.indexOf判断返回值中是否有这些字符   本人建议最好加上主题
    if((TcpClient_Buff.indexOf("servo&msg=right") > 0)) {
     String my_servo1_status = "right";
      turnright();
    }else if((TcpClient_Buff.indexOf("servo&msg=left") > 0)) {
      String my_servo1_status = "left";
      turnleft();
    } 
    if((TcpClient_Buff.indexOf("Light002&msg=on") > 0)) {
      String my_led1_status = "off";
      turnOffLed();
    }else if((TcpClient_Buff.indexOf("Light002&msg=off") > 0)) {
      String my_led1_status = "on";
     turnOnLed();
   } 
   TcpClient_Buff="";
   TcpClient_BuffIndex = 0;
  }
  item = checkdistance_2_3();
  }
//打开灯泡
void turnOnLed(){
  Serial.println("Turn on");
  digitalWrite(LED_Pin,LOW);
  my_led_status = "on";
}
//关闭灯泡
void turnOffLed(){
  Serial.println("Turn off");
  digitalWrite(LED_Pin,HIGH);
  my_led_status = "off";
 
}
//打开电机
void turnleft(){
  Serial.println("Turn left");
   my_servo_status ="left";
   if(my_servo_left==true){          //解决待机问题的消抖
    servopulse(180);   //引用脉冲函数
    delay(1000);
    my_servo_left=false;
   }else{
      my_servo_right=true;
    }
  }
void turnright(){
  Serial.println("Turn right");
  my_servo_status ="right";
 if(my_servo_right==true){     //解决待机问题的消抖
    servopulse(0);   //引用脉冲函数
    delay(1000);
    my_servo_right=false;
 }else{
  my_servo_left=true;
  }
}

void startSTA(){
  WiFi.disconnect();
  WiFi.mode(WIFI_STA);
  WiFi.begin(DEFAULT_STASSID, DEFAULT_STAPSW);
}

//*********************************************************************
void doWiFiTick(){
  static bool startSTAFlag = false;
  static bool taskStarted = false;
  static uint32_t lastWiFiCheckTick = 0;
  if (!startSTAFlag) {
    startSTAFlag = true;
    startSTA();
    Serial.printf("Heap size:%d\r\n", ESP.getFreeHeap());
  }
  //未连接1s重连
  if ( WiFi.status() != WL_CONNECTED ) {
    if (millis() - lastWiFiCheckTick > 1000) {
      lastWiFiCheckTick = millis();
    }
  }
  //连接成功建立
  else {
    if (taskStarted == false) {
      taskStarted = true;
      Serial.print("\r\nGet IP Address: ");
      Serial.println(WiFi.localIP());
      startTCPClient();
    }
  }
}

//*********************************************************************
float checkdistance_2_3() {         //获取物体距离函数
  digitalWrite(pin1, LOW);
  delayMicroseconds(pin1);
  digitalWrite(pin1, HIGH);
  delayMicroseconds(10);
  digitalWrite(pin1, LOW);
  float distance = pulseIn(pin2, HIGH) / 58.00;
  delay(10);
  return distance;
}
float iif(bool expression, float truePart, float falsePart)
{
  return expression ? truePart : falsePart;
}


//*********************************************************************
//消抖
void servopulse(int angle)//定义一个脉冲函数
{
  //发送50个脉冲
  for (int i = 0; i < 50; i++) {
    int pulsewidth = (angle * 11) + 500; //将角度转化为500-2480的脉宽值
    digitalWrite(servopin, HIGH);   //将舵机接口电平至高
    delayMicroseconds(pulsewidth);  //延时脉宽值的微秒数
    digitalWrite(servopin, LOW);    //将舵机接口电平至低
    delayMicroseconds(20000 - pulsewidth);
  }
  //  delay(20);
}
// 初始化,相当于main 函数
void setup() {
 myservo.attach(servopin); 
   pinMode(pin1, OUTPUT);
  pinMode(pin2, INPUT);
  Serial.begin(115200);
  //初始化引脚为输出
	pinMode(LED_Pin,OUTPUT);
}
//循环
void loop() {
  doWiFiTick();
 doTCPClientTick();
}

在这里插入图片描述

  • 0
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

归想

谢谢大家支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值