我尝试在esp32上使用wifimanager库,如果门户网站在未连接wifi的情况下超时,是否可以在没有wifi的情况下进行处理?

问题描述 投票:0回答:1

我的项目有问题,我的项目需要可以使用 wifi 和非 wifi,我使用 wifimanager 库,并且我尝试修改这个库

#include <WiFiManager.h>
#include <Ticker.h>
#include <SD.h>
#include "FS.h"
#include <RTClib.h>
#include <Wire.h>
#include <TimeLib.h>  // Add the Time library to work with timestamps
#include <SPI.h>      // Include the SPI library required by the SD library
#include <PubSubClient.h>
#include <LiquidCrystal_I2C.h>
#include "Adafruit_seesaw.h"
#include <Adafruit_AHTX0.h>
#include "DFRobot_ESP_EC.h"           //https://github.com/GreenPonik/DFRobot_ESP_EC_BY_GREENPONIK.git
#include "DFRobot_ESP_PH_WITH_ADC.h"  //https://github.com/GreenPonik/DFRobot_ESP_PH_WITH_ADC_BY_GREENPONIK.git
#include "Adafruit_ADS1X15.h"         //https://github.com/GreenPonik/Adafruit_ADS1X15.git
#include "Wire.h"
#include "OneWire.h"
#include "DallasTemperature.h"
#include "EEPROM.h"

#define ONE_WIRE_BUS 15
#define LED 2
#define SW1 34
#define address 0x23  //I2C Address 0x23
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

DFRobot_ESP_PH_WITH_ADC ph;
DFRobot_ESP_EC ec;
Adafruit_ADS1115 ads;
Adafruit_ADS1115 ads2;
Ticker ticker;
RTC_DS3231 rtc;


unsigned long intervals[] = {
  1000U,     //0
  2000U,     //1
  3000U,     //2
  5000U,     //3
  10000U,    //4
  15000U,    //5
  20000U,    //6
  25000U,    //7
  60000U,    //8
  1800000U,  //9
};           //this defines the interval for each task in milliseconds
unsigned long last[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
bool calibrationIsRunning = false;

float voltage, phValue, ecValue, temperature = 25;

float lastTemperature;

const int relayPin = 33;
const int relay1Pin = 32;
const int relay2Pin = 26;
bool wifiConnected = false;
bool relayState = false;
bool ecButtonPressed = false;  // ตัวแปรเก็บสถานะการกดปุ่ม EC
bool phButtonPressed = false;
bool wifiButtonPressed = false;          // ตัวแปรเก็บสถานะการกดปุ่ม PH
const unsigned long debounceDelay = 50;  // Adjust this as necessary
volatile bool resetWifiFlag = false;
const int chipSelect = 5;  // Choose an appropriate pin number for your hardware setup

unsigned long lastInterruptTime = 0;
int i = 0;
bool readSerial(char result[]) {
  while (Serial.available() > 0) {
    char inChar = Serial.read();
    if (inChar == '\n') {
      result[i] = '\0';
      Serial.flush();
      i = 0;
      return true;
    }
    if (inChar != '\r') {
      result[i] = inChar;
      i++;
    }
    delay(1);
  }
  return false;
}


LiquidCrystal_I2C lcd(0x27, 20, 4);
Adafruit_seesaw ss;

Adafruit_AHTX0 aht;
sensors_event_t humidity, temp;

uint8_t buf[4] = { 0 };
uint16_t data, data1;
float Lux;
float tempC;

// MQTT Broker
const char *mqtt_broker = "174.138.17.96";
const char *topic = "relay/control";
const char *mqtt_username = "emqx";
const char *mqtt_password = "public";
const int mqtt_port = 1883;
const char *topic_tem = "tem";
const char *topic_capa = "capa";
const char *topic_light = "light";
const char *topic_temp = "temp";
const char *topic_humid = "humid";
const char *topic_ph = "ph";
const char *topic_ec = "ec";

WiFiClient espClient;
PubSubClient client(espClient);
WiFiManager wm;

char result_tem[10];
char result_temp[10];
int light_data;
char result_humid[10];
char result_ph[10];
char result_ec[10];

const int buttonPin = 35;
const int buttonPinWifi = 4;
const int buttonPinEC = 16;
const int buttonPinPH = 17;



void IRAM_ATTR buttonInterrupt() {
  // Restart the board
  esp_restart();
}

void tick() {
  digitalWrite(LED, !digitalRead(LED));
}

void configModeCallback(WiFiManager *myWiFiManager) {
  Serial.println("Entered config mode");
  Serial.println(WiFi.softAPIP());
  Serial.println(myWiFiManager->getConfigPortalSSID());
  ticker.attach(0.2, tick);
}

void Wifi_Reset_begin() {
  Serial.println("Wifi Reset? Pls. waiting 3S..");
  lcd.clear();
  lcd.print("WiFi Reset in 3 Sec");
  lcd.setCursor(0, 1);
  delay(3000);
  Serial.println("WiFi Reset Setting OK ");
  lcd.clear();
  lcd.print("WiFi Reset Success");
  lcd.setCursor(0, 1);
  WiFiManager wm;
  wm.resetSettings();
  ESP.restart();
}
void IRAM_ATTR buttonInterruptWifi() {
  // Get the current time
  unsigned long interruptTime = millis();

  // If interrupts come faster than 50ms, assume it's a bounce and ignore
  if (interruptTime - lastInterruptTime > debounceDelay) {
    resetWifiFlag = true;
  }

  lastInterruptTime = interruptTime;
}
void setup() {
  Serial.begin(115200);
  Wire.begin();
  rtc.begin();
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  aht.begin();
  Serial.println("seesaw Soil Sensor example!");
  ss.begin(0x36);
  EEPROM.begin(64);
  ads.setGain(GAIN_ONE);
  ads.begin();
  ads2.begin(0x49);
  ph.begin(10);  //we store 2 value from the start address (10 & 14)
  ec.begin(20);  //we store 2 value from the start address (20 & 24)
  pinMode(relayPin, OUTPUT);
  digitalWrite(relayPin, HIGH);
  pinMode(relay1Pin, OUTPUT);
  pinMode(relay2Pin, OUTPUT);
  pinMode(SW1, INPUT_PULLUP);
  ticker.attach(1, tick);
  pinMode(buttonPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(buttonPin), buttonInterrupt, FALLING);
  pinMode(buttonPinEC, INPUT_PULLUP);
  pinMode(buttonPinPH, INPUT_PULLUP);
  pinMode(buttonPinWifi, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(buttonPinWifi), buttonInterruptWifi, FALLING);
  WiFiManager wm;
  wm.setAPCallback(configModeCallback);
  lcd.begin();
  // turn on LCD backlight
  lcd.backlight();
  lcd.print("Please");
  lcd.setCursor(0, 1);
  lcd.print("Connect WiFi");
  // Set software serial baud to 115200;
  wm.setConnectTimeout(20);
  wm.setConfigPortalTimeout(180);
unsigned long wifiTimeout = millis() + 300000; // 5 minutes timeout
  while (!wifiConnected && millis() < wifiTimeout) {
    if (wm.autoConnect("SMART FARM")) {
      wifiConnected = true;
    } else {
      delay(1000); // Wait for a moment before retrying the WiFi connection
    }
  }

  if (!wifiConnected) {
    Serial.println("Failed to connect to WiFi within 5 minutes. Proceeding without WiFi.");
  } else {
    // If WiFi connection was successful, detach the ticker.
    ticker.detach();
    Serial.println("");
    Serial.println("WiFi connected.");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
    lcd.clear();
    lcd.print("WiFi Connected");
    lcd.setCursor(0, 1);

    // Connecting to the MQTT broker only if WiFi is connected.
    client.setServer(mqtt_broker, mqtt_port);
    client.setCallback(callback);

    while (!client.connected()) {
      String client_id = "esp32-client-";
      client_id += String(WiFi.macAddress());
      Serial.printf("The client %s connects to the public mqtt broker\n", client_id.c_str());
      if (client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
        Serial.println("Public emqx mqtt broker connected");
        digitalWrite(relay1Pin, HIGH);
        digitalWrite(relay2Pin, LOW);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Connecting success");
        lcd.clear();
        client.subscribe("relay/control");
      } else {
        digitalWrite(relay2Pin, HIGH);
        digitalWrite(relay1Pin, LOW);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Failed connecting to MQTT");
        Serial.print("Failed with state ");
        Serial.print(client.state());
        lcd.clear();
      }
    }
  }
}

// publish and subscribe
//client.publish(topic, "100");

void callback(char *topic, byte *payload, unsigned int length) {
  String message = "";
  for (int i = 0; i < length; i++) {
    message += (char)payload[i];
  }
  if (message == "ON") {
    digitalWrite(relayPin, LOW);
    Serial.println("รดน้ำ");
    relayState = true;
    client.publish("relay/status", "รดน้ำ");
  } else if (message == "OFF") {
    digitalWrite(relayPin, HIGH);
    Serial.println("หยุดรดน้ำ");
    relayState = false;
    client.publish("relay/status", "หยุดรดน้ำ");
  }
  Serial.print("Message arrived in topic: ");
  Serial.println(topic);
  Serial.print("Message:");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  Serial.println("-----------------------");
}
void Ec() {

  float ecVoltage, temperature = 25;
  unsigned long now = millis();
  if (!ads.begin()) {
    ecValue = 0;
    Serial.println(F("First ADS1115 not found. Returning to loop..."));
    return;
  }
  if (now - last[0] >= intervals[0])  //1000ms interval
  {
    last[0] = now;
    if (calibrationIsRunning) {
      Serial.println(F("[main]...>>>>>> calibration is running, to exit send exitph or exitec through serial <<<<<<"));
      //water temperature
      temperature = tempC;
      //EC
      ecVoltage = ads.readADC_SingleEnded(0) / 10;
      Serial.print(F("[EC Voltage]... ecVoltage: "));
      Serial.println(ecVoltage);
      ecValue = ec.readEC(ecVoltage, temperature);  // convert voltage to EC with temperature compensation
      Serial.print(F("[EC Read]... EC: "));
      Serial.print(ecValue);
      Serial.println(F("ms/cm"));
      lcd.clear();
      lcd.print("EC COLLECT");
      lcd.setCursor(0, 1);
      lcd.print("ecValue");
    }

    char cmd[10];
    if (readSerial(cmd)) {
      strupr(cmd);
      if (calibrationIsRunning || strstr(cmd, "EC")) {
        calibrationIsRunning = true;
        Serial.println(F("[]... >>>>>calibration is now running PH and EC are both reading, if you want to stop this process enter EXITPH or EXITEC in Serial Monitor<<<<<"));
        if (strstr(cmd, "EC")) {
          ec.calibration(ecVoltage, temperature, cmd);  //EC calibration process by Serail CMD
        }
      }
      if (strstr(cmd, "EXITEC")) {
        calibrationIsRunning = false;
      }
    }
  }
  if (now - last[3] >= intervals[3])  //5000ms interval
  {
    last[3] = now;
    if (!calibrationIsRunning) {
      //temperature = getWaterTemperature(); // read your temperature sensor to execute temperature compensation
      /*Serial.print("temperature:");
      Serial.print(temperature, 1);
      Serial.println("^C");*/

      ecVoltage = ads.readADC_SingleEnded(0) / 10;
      Serial.print("ecVoltage:");
      Serial.println(ecVoltage, 4);

      ecValue = ec.readEC(ecVoltage, temperature);  // convert voltage to EC with temperature compensation
      Serial.print("EC:");
      Serial.print(ecValue, 4);
      Serial.println("ms/cm");

      dtostrf(ecValue, 6, 2, result_ec);
      client.publish(topic_ec, result_ec);
    }
  }
}

void Ph() {

  float phVoltage, temperature = 25;
  unsigned long now = millis();
  if (!ads2.begin(0x49)) {
    phValue = 0;
    Serial.println(F("Second ADS1115 not found. Returning to loop..."));
    return;
  }

  if (now - last[0] >= intervals[0])  //1000ms interval
  {
    last[0] = now;
    if (calibrationIsRunning) {
      Serial.println(F("[main]...>>>>>> calibration is running, to exit send exitph or exitec through serial <<<<<<"));
      //water temperature
      temperature = tempC;
      //pH
      phVoltage = ads2.readADC_SingleEnded(1) / 10;
      Serial.print(F("[pH Voltage]... phVoltage: "));
      Serial.println(phVoltage);
      phValue = ph.readPH(phVoltage, temperature);
      Serial.print(F("[pH Read]... pH: "));
      Serial.println(phValue);
      lcd.clear();
      lcd.print("PH COLLECT");
      lcd.setCursor(0, 1);
      lcd.print("phValue");
    }

    char cmd[10];
    if (readSerial(cmd)) {
      strupr(cmd);
      if (calibrationIsRunning || strstr(cmd, "PH")) {
        calibrationIsRunning = true;
        Serial.println(F("[]... >>>>>calibration is now running PH and EC are both reading, if you want to stop this process enter EXITPH or EXITEC in Serial Monitor<<<<<"));
        if (strstr(cmd, "PH")) {
          ph.calibration(phVoltage, temperature, cmd);  //PH calibration process by Serail CMD
        }
      }
      if (strstr(cmd, "EXITPH")) {
        calibrationIsRunning = false;
      }
    }
  }
  if (now - last[3] >= intervals[3])  //5000ms interval
  {
    last[3] = now;
    if (!calibrationIsRunning) {
      //temperature = getWaterTemperature(); // read your temperature sensor to execute temperature compensation
      /*Serial.print("temperature:");
      Serial.print(temperature, 1);
      Serial.println("^C");*/
      phVoltage = ads2.readADC_SingleEnded(1) / 10;  // read the voltage
      Serial.print("phVoltage:");
      Serial.println(phVoltage, 4);
      phValue = ph.readPH(phVoltage, temperature);  // convert voltage to pH with temperature compensation
      Serial.print("pH:");
      Serial.println(phValue, 4);
      dtostrf(phValue, 6, 2, result_ph);
      client.publish(topic_ph, result_ph);
    }
  }
}

void Soil() {
  if (!ss.begin(0x36)) {
    tempC = 25;
    //Serial.println(F("soil temp sensor not find"));
    return;
  }
  float tempC = ss.getTemp();
  uint16_t capread = ss.touchRead(0);
  char stringcapread[6];
  /*Serial.println("*C");
    Serial.print("Capacitive: ");
    Serial.println(capread);
  itoa(capread, stringcapread, 10);*/

  Serial.print("Temperature: ");
  Serial.print(tempC);
  dtostrf(tempC, 6, 2, result_tem);
  client.publish(topic_tem, result_tem);
  delay(100);
  client.publish(topic_capa, stringcapread);
  //Serial.print("Temperature: ");
  //Serial.print(tempC);
  //delay(100);
}

void Light() {
  readReg(0x10, buf, 2);  //Register Address 0x10
  data = buf[0] << 8 | buf[1];
  Lux = (((float)data) / 1.2);
  /*Serial.print("LUX:");
    Serial.print(Lux);
    Serial.print("lx");
    Serial.print("\n");*/
  char msg[50];
  snprintf(msg, 50, "%.2f lx", Lux);
  client.publish(topic_light, msg);
}
uint8_t readReg(uint8_t reg, const void *pBuf, size_t size) {
  if (pBuf == NULL) {
    Serial.println("pBuf ERROR!! : null pointer");
  }
  uint8_t *_pBuf = (uint8_t *)pBuf;
  Wire.beginTransmission(address);
  Wire.write(&reg, 1);
  if (Wire.endTransmission() != 0) {
    return 0;
  }
  delay(20);
  Wire.requestFrom(address, (uint8_t)size);
  for (uint16_t i = 0; i < size; i++) {
    _pBuf[i] = Wire.read();
  }
  return size;
}

void Tempera() {
  aht.getEvent(&humidity, &temp);  // วัดค่าอุณหภูมิและความชื้น
  /*Serial.print(temp.temperature);
  Serial.print("                ");
  Serial.println(humidity.relative_humidity);*/

  dtostrf(temp.temperature, 6, 2, result_temp);
  client.publish(topic_temp, result_temp);

  dtostrf(humidity.relative_humidity, 6, 2, result_humid);
  client.publish(topic_humid, result_humid);
  //delay(1000);
}




String getCurrentTimestamp() {
  DateTime now = rtc.now();
  char timestampBuffer[20];
  sprintf(timestampBuffer, "%04d-%02d-%02d %02d:%02d:%02d",
          now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second());
  return String(timestampBuffer);
}


// Update logData function to accept individual values for data logging
void writeLogData(fs::FS &fs, const char *path, const char *data) {
  if(!SD.begin(5)){
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();

  if(cardType == CARD_NONE){
    Serial.println("No SD card attached");
    return;
  }

  Serial.print("SD Card Type: ");
  if(cardType == CARD_MMC){
    Serial.println("MMC");
  } else if(cardType == CARD_SD){
    Serial.println("SDSC");
  } else if(cardType == CARD_SDHC){
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }

  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);

  Serial.println("SD card initialized successfully!");
  Serial.printf("Writing log data to file: %s\n", path);

  File file = fs.open(path, FILE_APPEND);
  if (!file) {
    Serial.println("Failed to open file for writing");
    return;
  }
  if (file.println(data)) {
    Serial.println("Log data written");
  } else {
    Serial.println("Write failed");
  }
  file.close();
}
void display() {

  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print("Temp:");
  lcd.print(temp.temperature);

  lcd.setCursor(0, 2);
  lcd.print("Humid:");
  lcd.print(humidity.relative_humidity);

  lcd.setCursor(0, 0);
  lcd.print("Lux:");
  lcd.print(Lux);
}

void reconnectWIFI() {
  if (WiFi.status() != WL_CONNECTED) {
    // Perform reconnection attempts or other handling

    // Example: Disconnect and reconnect
    WiFi.disconnect();
    wm.autoConnect("AutoConnectAP");
  }
}
void loop() {
  if (digitalRead(buttonPinEC) == LOW) {
    if (!ecButtonPressed) {
      ecButtonPressed = true;
      Ec();

      if (ecValue == 0) {
        lcd.clear();
        lcd.print("EC NOT CONNECTED");
        lcd.setCursor(0, 1);
        lcd.print("EC Value: 0");
      } else {
        lcd.clear();
        lcd.print("EC COLLECT");
        lcd.setCursor(0, 1);
        lcd.print(ecValue);
      }
    }
  } else {
    ecButtonPressed = false;
  }

  if (digitalRead(buttonPinPH) == LOW) {
    if (!phButtonPressed) {
      phButtonPressed = true;
      Ph();

      if (phValue == 0) {
        lcd.clear();
        lcd.print("PH NOT CONNECTED");
        lcd.setCursor(0, 1);
        lcd.print("PH Value: 0");
      } else {
        lcd.clear();
        lcd.print("PH COLLECT");
        lcd.setCursor(0, 1);
        lcd.print(phValue);
      }
    }
  } else {
    phButtonPressed = false;
  }

  if (!ecButtonPressed && !phButtonPressed) {
    Tempera();
    reconnectWIFI();
    Soil();
    Light();
    display();
    // Assuming you have sensor readings in variables: temperature, humidity, Lux, phValue, ecValue
    DateTime now = rtc.now();
    char timestampBuffer[20];
    sprintf(timestampBuffer, "%04d-%02d-%02d %02d:%02d:%02d",
            now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second());
    String timestamp = getCurrentTimestamp();
    String logData = timestamp + "," + String(temperature) + "," + String(humidity.relative_humidity) + "," + String(Lux) + "," + String(phValue) + "," + String(ecValue);
    writeLogData(SD, "/datalog.txt", logData.c_str());
  }
  if (resetWifiFlag) {
    resetWifiFlag = false;
    Wifi_Reset_begin();
    ESP.restart();
  }
  delay(600);
}

我尝试在 wifimanager.cpp 中进行修改,但它不起作用

arduino mqtt wifi esp32 wifimanager
1个回答
0
投票

首先,您发布的代码太多,您应该提取问题所在,在本例中就是涉及Wifimanager的问题。

我认为你的代码过于复杂,我过去使用过WiFiManager,有很多方法可以做你想做的事情。

我将为您提供一个解决方案,您可以扩展该解决方案以完成更聪明的事情,其想法是将连接逻辑的一部分转移到主循环中,这样您也可以根据需要轻松地包括重新连接尝试。 阅读我在代码中添加的注释并添加缺少的内容。

bool wifiConnected = 0;
unsigned long connectionCheck = 300000; //5 minutes

void startMqtt(){
  //put all your mqtt setup/connecting stuff here
}

void setup(){

   // here add only the code to start the WiFiManager with a 5 min timeout
  //also set the WiFimanager to be in non-blocking mode
  WiFiPortal.setConfigPortalBlocking(false);

  // don't do any setup of the mqtt, put that into a separate function  startMqtt()

}

void loop(){

   //if we are in the first 5 minutes when the WiFiManager is running the portal
   if(millis() <= connectionCheck){
      
       WiFiPortal.process(); //you have to keep the WiFiManager running here as we are in a non-blocking mode

     // if we are still not connected to the WiFi
     if (WiFi.status() != WL_CONNECTED){
        //don't run anything, exit the loop
        return;

     }else{ 
       //we are connected but it can be at anytime in the first 5 minutes
       // but we only want to setup the mqtt once
       if(wifiConnected == 0){
         connectionCheck = millis();
         wifiConnected = 1;
         startMqtt();
       }
     }

   }


   //put whatever code you need here it will run either if the WiFi is connected in the first 5 minutes or if it doesn't get connected after 5 minutes



    ///you can also do another check maybe after some time and if WiFi not connected try reconnecting again
    
    if(millis() - connectionCheck > 30000){//maybe check every 30 seconds
       if (WiFi.status() != WL_CONNECTED){

          // 1. restart the WiFiManager
          
          // 2. close the mqtt

           wifiConnected = 0;

           connectionCheck = millis() + 300000; //we will reset this to 5 minutes in the future as we will restart the WiFi portal so the check at the begining of the loop will work again
           

       }else{

         connectionCheck = millis();

        } 

    }

}
© www.soinside.com 2019 - 2024. All rights reserved.