Программный последовательный конфликт с Wi-Fi на ESP8266

Я пытаюсь использовать ESP8266 (Wemos D1 mini) для чтения данных из последовательного порта 19,2 КБ и сообщать о результатах через Wi-Fi. Программирование осуществляется через Arduino IDE. Код для чтения порта работает нормально, если Wi-Fi не включен. Как только Wi-Fi включен, я теряю символы из входного потока. Я видел несколько сообщений в разных местах, которые указывают на проблемы с одновременным использованием SoftwareSerial и WiFi, по-видимому, связанные с конфликтами времени. Моя последняя попытка звонка

WiFi.disconnect();

перед кодом, который считывает символы из последовательного потока, а затем вызывает

WiFi.reconnect();

после чтения последовательного потока, но перед выполнением вызовов для отправки данных через Интернет. Это не сработало.

Мой код читает из последовательного порта в (блокирующем) цикле, что, по мнению других сообщений, является проблемой. Это не проблема, если нет подключения к объекту Wi-Fi. Я мог бы реструктурировать код, чтобы создать неблокирующее чтение, но это потребует значительных усилий (и сделает код намного сложнее для понимания), поэтому, прежде чем пойти по этому пути, мне интересно, есть ли другое решение.

, 👍2

Обсуждение

Почему бы не использовать аппаратный UART?, @Majenko

Если я правильно понимаю, UART0 подключен к интерфейсу USB, который я использую для прошивки и отладочных сообщений. UART1 предназначен только для отправки, и я пытаюсь прочитать данные., @Llaves

попробуйте бета-версию (2.5) ядра arduino esp8266. у него есть улучшения в SoftwareSerial, @Juraj


2 ответа


2

WiFi использует прерывания. Много. SoftwareSerial плохо работает с прерываниями. На Arduino все прерывания отключены, пока SoftwareSerial выполняет свою работу. Я не знаю, как это реализовано на ESP8266 и как прерывания работают на ESP8266, поэтому не могу комментировать, как это обойти.

Однако, если вы не можете использовать один из аппаратных каналов UART, возможно, вам нужно начать мыслить нестандартно. Под «коробкой» я подразумеваю «ESP8266».

Возможно, ESP8266 не для вас. Это отличный чип для создания интерфейса WiFi, но для чего-то другого он не годится. Ему просто не хватает внутренней периферии, чтобы быть полезным. Возможно, обновление до ESP32 будет для вас хорошим вариантом (это старший брат ESP8266). Он имеет гораздо более богатый набор периферийных устройств.

Также не бойтесь использовать более одного микроконтроллера. Если ESP8266 не имеет нужного вам интерфейса, добавьте к нему еще один MCU, который имеет нужный вам интерфейс, а затем заставьте их взаимодействовать, используя любой интерфейс, который у вас есть доступный (I2S, SPI, и т. д). Да, это означает больше программирования и более сложный проект, но изучение таких вещей, безусловно, откроет больше возможностей для будущих проектов.

,

3

Как уже отмечалось, существуют конфликты между Wi-Fi и SoftwareSerial. Попытка в вопросе отключить WiFi - это шаг в правильном направлении, но недостаточный. Вам действительно придется отключить Wi-Fi. Задача состоит в том, чтобы надежно отключить Wi-Fi, а затем снова запустить его. Эта проблема подробно обсуждалась в репозитории Git ESP8266/Arduino здесь и некоторые называют ее «Проблема 644». . Пример реализации кода для обеспечения надежности представлен здесь.

Вот как выглядят функции включения/выключения. Однако я настоятельно рекомендую вам перейти к приведенному выше коду и скопировать его оттуда, а не сюда.

extern "C" {
#include "user_interface.h"
#define WIFI_RETRIES 25

int conn_tries = 0;
bool WiFiOff() {
    WiFi.disconnect();
    WiFi.mode(WIFI_OFF);
    WiFi.forceSleepBegin();
    yield();

    /* 
     * It can take a while for the ESP to disconnect, so we need
     * to give it a couple of seconds before returning a fail.
     */
    while ((WiFi.status() == WL_CONNECTED)
           && (conn_tries++ < WIFI_RETRIES)) {
        delay(100);
#ifdef DEBUG
        Serial.print(".");
#endif
    }
    if (WiFi.status() != WL_CONNECTED)
        return (true);
    else
        return (false);
}

/*
 * Turn the WiFi back on again with forceSleepWake().
 * NOTE:-  =Your= SSID and password must be in the
 *         user_config.h file.
 */
bool WiFiOn() {
    conn_tries = 0;


    WiFi.forceSleepWake();
    WiFi.mode(WIFI_STA);
    wifi_station_connect();
    WiFi.begin("corazon_del_bosque", "");

    /* 
     * It may take a while for the ESP to re-connect, depending
     * upon external factors (e:- has the access-point moved out
     * of range since we were last connected?).  This loop will
     * give us a reasonable time to re-connect without blocking
     * permanently.
     */
    while ((WiFi.status() != WL_CONNECTED)
           && (conn_tries++ < WIFI_RETRIES)) {
        delay(100);
#ifdef DEBUG
        Serial.print(".");
#endif
    }
    if (WiFi.status() == WL_CONNECTED)
        return (true);
    else
        return (false);
}

Я использую этот код в своей программе через Arduino IDE. Автор использовал его в PlatformIO. Другие системы сборки могут иметь другие требования.

,