About ESP8266-NodeMCU and onenet communication transmission learning summary (2)

About ESP8266-NodeMCU and onenet communication transmission learning summary (2)

1. Updated some functions and code optimizations and comments

​ Added the network control of the motor (which will be used for door lock control and curtain control in the future). The process is a bit bumpy. I wanted to use an ESP8266-NodeMCU to realize the overall function, but I found that this board could not do other things while controlling the motor. Multithreading is also pseudo multithreading. It is not easy to use, so I plan to use two development boards, one is responsible for communication connection and data transmission, and the other is used for the following hardware control. The result is feasible and easy to implement, but not willing to waste resources, and try to put it Implementation on a development board should be considered a success in the end, but it seems that the motor is very hot and needs to be optimized. ps: It’s strange that the official arduino motor library just ran away. If you have the same problem, bloggers would like to share their experience.

The motor used here is 28BYJ-48. Some people here may complain why the 42 motor is not used. The reason is that I only have this, and I collected it from my classmates. . .

Having said so much, it is better to look at the code directly (the code specification is a bit spicy, I hope it does not affect reading):

/**
 * author: topthemaster
 * time: 2021.1.10
 * 
 */
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "AccelStepper.h"
#include <Ticker.h>
#include <ArduinoJson.h>
#define PRODUCT_ID    "396066" //产品名
#define API_KEY    "tx6WM==zmW21Z2pt4susBRlHMuY="//产品密钥
#define DEVICE_ID "666259032"//设备名
#define TOPIC     "ceshitopic1"//订阅主题
WiFiClient wifiClient;
Ticker ticker;
Ticker ticker2;
int count=0;//ticker1控制 数据上传下发的间隔时间(s)
int count2=0;//ticker2控制 电机转动的时间(s)
AccelStepper stepper1(4, D0, D2, D1, D3);//电机引脚
String door ="close";//默认检测门关闭
PubSubClient mqttClient(wifiClient);
const char* ssid = "Fishing WiFi ";//wifi名
const char* password = "zheshiyigewifi";//wifi密码
const char* mqttServer = "183.230.40.39";//onenet地址
const uint16_t mqttPort = 6002;//mqtt接口端口
String doorLock="close";//默认门锁指令关闭
char msgJson[75];//存json下发信息数据
char msg_buf[200];//存json上传数据及标识位
//初始化
void setup() {
  stepper1.setMaxSpeed(500);   // 设置电机最大速度为500
  stepper1.setSpeed(0);      // 初始化电机速度为300
  pinMode(LED_BUILTIN, OUTPUT);     // 设置板上LED引脚为输出模式
  digitalWrite(LED_BUILTIN, HIGH);  // 启动后关闭板上LED
  pinMode(D5, OUTPUT);
  pinMode(D6, INPUT_PULLUP);
  digitalWrite(D5, LOW);
  digitalWrite(D6, LOW);
  Serial.begin(9600);
  WiFi.mode(WIFI_STA);
  connectWifi();
  mqttClient.setServer(mqttServer,mqttPort);
  // 设置MQTT订阅回调函数
  mqttClient.setCallback(receiveCallback);
  connectMQTTServer();
  ticker.attach(1, addCount);

}

void loop() {
  if (mqttClient.connected()) { // 如果开发板成功连接服务器
    // 每隔2秒钟发布一次信息  
    // 保持心跳 若电机正在运转,暂时不发信息(由于mcu没有多线程,不能同时运转电机和上传下发数据)
    if(count>=2)
    {  
      if(count2==0)
      { Serial.print("门锁和门状态");
        Serial.print(doorLock);
        Serial.print(door);
        pubMQTTmsg();
        mqttClient.loop();
        count=0;
      }
    }
    
  } else {                  // 如果开发板未能成功连接服务器
    connectMQTTServer();    // 则尝试连接服务器
  }

  //电机控制
  if(doorLock=="close"&&door=="open")
  {
   stepper1.setSpeed(-500);
   Serial.print("1");
   
   ticker2.attach(1, controlDoor);
   
   door="close";
  }
   else if(doorLock=="open"&&door=="close")
   {stepper1.setSpeed(500);
    ticker2.attach(1, controlDoor);
    door="open";
   }
   stepper1.runSpeed();
   
}
//ticker2控制 电机运转时间
void controlDoor(){
  count2++;
  Serial.print("ticker调用");
   if (count2 >= 6) {
    stepper1.setSpeed(0);
    count2=0;
    ticker2.detach();  // 使用detach来停止ticker对象定时调用函数
    Serial.print("ticker.detach()");
  }
}
//连接mqtt服务器
void connectMQTTServer(){
  String clientId = DEVICE_ID;
  String productId=PRODUCT_ID;
  String apiKey=API_KEY;
  // 连接MQTT服务器
  if (mqttClient.connect(clientId.c_str(),productId.c_str(),apiKey.c_str())) { 
    Serial.println("MQTT Server Connected.");
    Serial.println("Server Address: ");
    Serial.println(mqttServer);
    Serial.println("ClientId:");
    Serial.println(clientId);
    subscribeTopic(); // 订阅指定主题
  } else {
    Serial.print("MQTT Server Connect Failed. Client State:");
    Serial.println(mqttClient.state());
    delay(3000);
  }   
}
// 订阅指定主题
void subscribeTopic(){
 
  // 建立订阅主题。主题名称以Taichi-Maker-Sub为前缀,后面添加设备的MAC地址。
  // 这么做是为确保不同设备使用同一个MQTT服务器测试消息订阅时,所订阅的主题名称不同
  String topicString = "temperature";
  char subTopic[topicString.length() + 1];  
  strcpy(subTopic, topicString.c_str());
  
  // 通过串口监视器输出是否成功订阅主题以及订阅的主题名称
  if(mqttClient.subscribe(subTopic)){
    Serial.println("Subscrib Topic:");
    Serial.println(subTopic);
  } else {
    Serial.print("Subscribe Fail...");
  }  
}
  //获取下发指令topic 指定主题 payload 下发信息,以字节存储 length 下发信息长度
void receiveCallback(char* topic, byte* payload, unsigned int length) {
  
  Serial.print("Message Received [");
  Serial.print(topic);
  Serial.print("] ");
  String receivePassage;
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
    receivePassage+=(char)payload[i];
  }
  Serial.println("----"+receivePassage+"----");
  Serial.print("Message Length(Bytes) ");
  Serial.println(length);
  ///
  receivePassage="";
  
  //测试下发数据
  if ((char)payload[0] == 'L') {     // 如果收到的信息以“1”为开始
    if((char)payload[1] == '0')
    {
    digitalWrite(BUILTIN_LED, LOW);  // 则点亮LED。
    Serial.println("LED ON");
    }
    else if((char)payload[1] == '1')
    {                           
    digitalWrite(BUILTIN_LED, HIGH); // 否则熄灭LED。
    Serial.println("LED OFF");
    }
  }else if((char)payload[0] == 'D') {     // 如果收到的信息以“1”为开始
    if((char)payload[1] == '1')
    doorLock="open";
    else if((char)payload[1] == '2')
    doorLock="close";
    }
    
   //
    
  
}

//对指定主题上传信息
void pubMQTTmsg(){
  //onenet数据点上传系统主题
  String topicString = "$dp";
  char publishTopic[topicString.length() + 1];  
  strcpy(publishTopic, topicString.c_str());
  //json数据转换为数组
  DynamicJsonDocument doc(64);
  bool pinState = !digitalRead(BUILTIN_LED);
  bool doorState = !digitalRead(D6);
  doc["led"] = pinState;
  doc["door"] = doorState;

  serializeJson(doc, Serial);
  // 建立发布信息。温度
  String jsonCode;  
  serializeJson(doc, jsonCode);
  Serial.print("json Code: ");Serial.println(jsonCode); 
  String messageString = jsonCode; 
  char publishMsg[messageString.length() + 1];   
  strcpy(publishMsg, messageString.c_str());
  int json_len=strlen(publishMsg);
  memset(msg_buf,0,200);
  msg_buf[0]=char(0x03);
  msg_buf[1]=char(json_len>>8);
  msg_buf[2]=char(json_len &0xff);
  memcpy(msg_buf+3,publishMsg,json_len);
  // 实现ESP8266向主题发布信息
  if(mqttClient.publish(publishTopic, (uint8_t*)msg_buf,3+json_len)){
    Serial.println("Publish Topic:");Serial.println(publishTopic);
    String msg_bufTotal;
    for(int i=0;i<sizeof(msg_buf)/sizeof(msg_buf[0]);i++)
    {
      msg_bufTotal+=msg_buf[i];
    }
    Serial.println("Publish message:");Serial.println(msg_bufTotal);    
  } else {
    Serial.println("Message Publish Failed."); 
  }
}
void addCount(){
  count++;
}
void connectWifi(){
 
  WiFi.begin(ssid, password);
 
  //等待WiFi连接,成功连接后输出成功信息
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi Connected!");  
  Serial.println(""); 
}

Later, wait until the hardware needs to be purchased to be updated.

Guess you like

Origin blog.csdn.net/TOPthemaster/article/details/112427199