ESP8266 Аналоговое чтение мешает Wi-Fi?

Краткая версия: У меня есть программа, которая подключает мой ESP8266 к WIFI, поэтому я могу управлять подключенным к нему реле через Интернет или кнопкой. У меня тоже есть датчик на дверь. Это программное обеспечение работает отлично, если я добавлю к нему светочувствительный резистор (который подключен правильно, так как я получаю от него показания) и начинаю считывать данные, я теряю соединение WIFI. У кого-нибудь есть идеи, почему это происходит?

Длинная версия:

Итак, эта программа работает на моем Esp8266.

#include <ESP8266WiFi.h>

IPAddress ip(192, 168, 0, 150);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);

const char* ssid = "mySSID";
const char* password = "myPSW";
const char* host = "192.168.0.228";

const int buttonPin = 0;
const int relayPin =  4;
const int doorPin = 5;
const int ldrPin = A0;


//целое ldrState;
// int серийный счетчик = 0;
//целое число ldrMin = 0;
//инт ldrMax = 1024;
int buttonState = 0;
int doorState = 0;
byte Main_Light_State_Begin;
bool Main_Light_State;
bool doorNotified = false;
bool button_action_taken = false;
bool Main_Light_DBR = true;
String HTTP_Get_Response;

WiFiServer server(80);

//Функции
String HTTP_Get(char* Adress, String URL, bool Last_Line_Bool) {
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(Adress, httpPort)) {
    Serial.println("connection failed");
    return "Failed";
  }

  Serial.print("Requesting URL: ");
  Serial.println(URL);
  Serial.println("at adress");
  Serial.println(Adress);
  client.print(String("GET ") + URL + " HTTP/1.1\r\n" +
               "Host: " + Adress + "\r\n" +
               "Connection: close\r\n\r\n");
  delay(10);

  String Response;
  String Last_Line;

  while (client.available()) {
    String line = client.readStringUntil('\r');
    Serial.print(line);
    Response = Response + line;
  }
  return Response;

  Serial.println();
  Serial.println("closing connection");

}

void setup() {
  Serial.begin(115200);
  delay(1000);

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);



  WiFi.begin(ssid, password);
  WiFi.config(ip, gateway, subnet);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  server.begin(); -
  Serial.println("Server started");

  Serial.println(WiFi.localIP());
  pinMode(relayPin, OUTPUT);
  pinMode(buttonPin, INPUT);
  pinMode(doorPin, INPUT);
// pinMode(ldrPin, INPUT);
}

void loop() {
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("Wifi NOT Connected");
  }
  //Датчики
  buttonState = digitalRead(buttonPin);
  doorState = digitalRead(doorPin);
  //ldrState = map(analogRead(ldrPin), ldrMin, ldrMax, 0, 100);
  //Serial.println(analogRead(ldrPin));
// если (serialCount == 1000) {
// Serial.println(ldrState);
// серийный счет = 0;
// } еще {
// серийный счет++;
// }

  //дверной датчик
  if (doorState == HIGH) {
    if (doorNotified == false) {
      Serial.println("DOOR");
      HTTP_Get_Response = HTTP_Get("192.168.0.228", "/index.php/?door_opened=true", false);
      doorNotified = true;
    }
  } else if (doorState == LOW) {
    if (doorNotified == true) {
      doorNotified = false;
      delay(500);
    }
    else {
      doorNotified = false;
    }
  }

  //Кнопка
  if (buttonState == LOW) {
    if (button_action_taken == false) {
      if (Main_Light_State == true) {
        Serial.println("SWITCH");
        Main_Light_State = false;
        digitalWrite(relayPin, HIGH);
        delay(500);
        Main_Light_DBR = false;
      }
      else if (Main_Light_State == false) {
        Serial.println("SWITCH");
        Main_Light_State = true;
        digitalWrite(relayPin, LOW);
        delay(500);
        Main_Light_DBR = false;
      }
      button_action_taken = true;
    }
  } else if (buttonState == HIGH) {
    if (button_action_taken == true) {
      button_action_taken = false;
      delay(500);
    }
    else {
      button_action_taken = false;
    }

  }
  //Main_Light_State
  if (Main_Light_State == true) {
    digitalWrite(relayPin, LOW);
    if (Main_Light_DBR == false) {
      HTTP_Get_Response = HTTP_Get("192.168.0.228", "/index.php/?main_light_on_dbr=true", false);
      Main_Light_DBR = true;
    }

  } else if (Main_Light_State == false) {
    digitalWrite(relayPin, HIGH);
    if (Main_Light_DBR == false) {
      HTTP_Get_Response = HTTP_Get("192.168.0.228", "/index.php/?main_light_off_dbr=true", false);
      Main_Light_DBR = true;
    }
  }

  WiFiClient client = server.available();
  if (!client) {
    return;
  }

  Serial.println("new client");
  while (!client.available()) {
    delay(1);
  }

  String req = client.readStringUntil('\r');
  Serial.println(req);
  client.flush();

  if (req.indexOf("/main_light/on") != -1) {
    Main_Light_State = true;
    Main_Light_DBR = false;
  } else if (req.indexOf("/main_light/off") != -1) {
    Main_Light_State = false;
    Main_Light_DBR = false;
  } else if (req.indexOf("/main_light/switch") != -1) {
    Serial.println("SWITCH");
    if (Main_Light_State == true) {
      Main_Light_State = false;
    }
    else if (Main_Light_State == false) {
      Main_Light_State = true;
    }
    Main_Light_DBR = false;
  } else if (req.indexOf("/main_light/state") != -1) {

  } else {
    Serial.println("invalid request");
    client.stop();
    return;
  }

  client.flush();

  String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";
  s += (Main_Light_State) ? "1" : "0";

  client.print(s);
  delay(1);
  Serial.println("Client disonnected");
}

Со строками, которые я прокомментировал выше, все работает нормально. У меня есть светочувствительный резистор, подключенный (правильно, я получаю от него правильные измерения) к A0. С того момента, как я раскомментирую строки, связанные с этим LDR, и, таким образом, начну читать данные из него, я потеряю соединение с Wi-Fi. Кто-нибудь понял, почему это так? Спасибо!

, 👍8

Обсуждение

*Какой* ESP8266? Есть много версий, каждая с разными способностями и возможностями., @Majenko

@Majenko Тот, у которого на борту серийный чип и регулятор мощности. (Diymall NodeMCU Devkit 1.0 CP2102 IIC SPI для MAC OS от Apple https://www.amazon.co.uk/dp/B00XJG7GEK/ref=cm_sw_r_other_awd_UnhOwbBSFS1GS), @JanG

Я наткнулся на это, когда искал информацию о проблемах с аналоговым чтением. Я думаю, что «более элегантное решение» может иметь несколько проблем. Проблема 1. Если чтение и обработка сенсора занимает менее 1 мс, цикл может вернуться, и вы получите несколько запусков AnalogRead в течение одной миллисекунды — не желаемый результат. Учитывая, что сам AnalogRead(A0) занимает всего около 70 микросекунд, если обработка быстрая, вы можете легко выполнить 10 или около того AnalogRead(A0) за эту миллисекунду. Проблема 2. Если есть другие вещи, выполнение которых занимает несколько миллисекунд (например,, @farmerkeith


3 ответа


Лучший ответ:

8

Я обнаружил, что это было вызвано многократным считыванием аналогового PIN-кода за короткий период времени. я заменил

  ldrState = map(analogRead(ldrPin), ldrMin, ldrMax, 0, 100);
  Serial.println(analogRead(ldrPin));
  if (serialCount == 1000) {
    Serial.println(ldrState);
    serialCount = 0;
  } else {
    serialCount ++;
  }

с этим:

if (serialCount == 10000) {
  ldrState = map(analogRead(ldrPin), ldrMin, ldrMax, 0, 100);
  Serial.println(ldrState);
  serialCount = 0;
} else {
  serialCount ++;
}

Хотя я думал об этом подходе раньше, моя ошибка заключалась в том, что я все еще считывал датчик каждый раз, когда код зацикливался, я просто не выводил его на последовательный монитор до каждого сотого цикла.

Это по-прежнему дает мне показания несколько раз в секунду, что намного больше, чем мне нужно. Во всяком случае, теперь я знаю, что не могу считывать аналоговый вывод ESP8266 много раз в секунду, иначе Wi-Fi отключится (по крайней мере, при использовании его с Arduino IDE)

,

Это отлично работает, только что возникла именно такая проблема 4 года спустя. Кто-нибудь знает, зарегистрирована ли это ошибка? Наверное, так и должно быть., @Archimaredes


6

Это старый вопрос, на который уже дан ответ, но я хотел бы предложить немного более элегантное решение (IMO!):

В моем методе, который считывает аналоговые данные, я проверяю и читаю только каждые 50 миллисекунд:

void readAnalogSensor() {
   if( millis() % 50 != 0 )
       return;
   .
   .  // Ваш датчик считывает и обрабатывает здесь
   .
}

Это позволяет избежать необходимости вести счетчик циклов и кажется более детерминированным — значение счетчика циклов не обязательно будет постоянно увеличиваться в зависимости от того, что еще происходит в цикле. Доступные значения миллисекунд также полезны, если вам нужно реализовать код для устранения дребезга кнопок.

,

Ух ты, действительно прошло много времени, чувак, мне пора вернуться к этому проекту! Это действительно более элегантное решение, спасибо!, @JanG

Если по какой-то причине основной цикл работает очень медленно и цикл переходит от ...49 к ...51, это приводит к пропуску analogRead. Вот почему я считаю решение «serialCount» более надежным., @Wouterr


2

Вот что я обычно делаю, чтобы повторять через определенные промежутки времени:

void readAnalogSensor(){
  if (millis()<taskTime) return; // время еще не истекло
  taskTime += 50; // устанавливаем время следующего исполнения
  // .... больше кода для задачи, которая выполняется каждые 50 мс
}

Для этого требуется длинная переменная без знака taskTime. Вы также можете использовать константу вместо 50.
taskTime должно быть установлено на некоторое значение, близкое к millis() в конце setup(), иначе будет быстрая последовательность выполнения в то время как taskTime догоняет millis().

,

Спасибо. Я хотел избежать выполнения арифметических действий при каждом проходе цикла, но кажется, что это невозможно без возникновения ошибки опрокидывания., @farmerkeith