• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Проблема с созданием точки доступа

DMENUX

New member
Очень странная ситуация, но когда я создаю точку доступа в методе setup, а в методе loop постоянно вывожу текст на дисплей - то точка доступа или исчезает или к ней невозможно подключиться. Если после создания точки доступа в методе setup вывести что-то на дисплей, а в методе loop убрать весь код для вывода текста на дисплей - то точка доступа будет работать без проблем, но мне необходимо выводить постоянно обновляющиеся данные. Для работы с дисплеем использую библиотеку iarduino_OLED_txt, т.к с ее помощью можно легко вывести русский текст на дисплей.
 

CodeNameHawk

Moderator
Команда форума
Код в лооп должен выполнятся "быстро", примерно так, вошли в лооп, нарисовали, отработали логику и вышли из лооп.
 

DMENUX

New member
вот мой код loop:
C++:
void loop()
{
  if (getBatteryPercentage() >= 1)
  {
    webServer.handleClient();
    //displayMenuOptions(getMenuOptions());
    //displayCursor(5, getCurrentCursorYCoord());
    //displayScrollBar(115, getCurrentScrollBarYCoord());

    if (mainMenuConfigured == true)
    {
      drawString(20, 7, "Charge: " + String(getBatteryPercentage()) + "% ");  
    }

    if (apInfoMenuConfigured == true)
    {
      drawString(20, 3, "Devices: " + String(WiFi.softAPgetStationNum()) + " ");
    }

    if (systemMenuConfigured == true)
    {
      drawString(20, 1, String(getBatteryVoltage(), 2) + "V");
      drawString(20, 2, String((float)ESP.getFreeHeap() / 1024, 2) + "(kb)");
      drawString(20, 3, getWorkingTimeStr());
    }

    if (curMenuOptions.size() > 0)
    {
      if (upButtonIsPress())
      {
        cursorYCoord--;
        if (curMenuOptions.size() > maxMenuOptionsOnScreen)
        {
          if (cursorYCoord < 0)
          {
            if (menuOffset > 0)
            {
              menuOffset--;
              cursorYCoord = 0;
            }
            else
            {
              menuOffset = curMenuOptions.size() - maxMenuOptionsOnScreen;
              cursorYCoord = (int)maxMenuOptionsOnScreen - 1;
            }
          }
          else if ((size_t)cursorYCoord + menuOffset > ((size_t)curMenuOptions.size() - 1))
          {
            menuOffset = 0;
            cursorYCoord = 0;
          }
          else if (cursorYCoord > (int)maxMenuOptionsOnScreen - 1)
          {
            menuOffset++;
            cursorYCoord = (int)maxMenuOptionsOnScreen - 1;
          }
        }
        else
        {
          if (cursorYCoord < 0)
          {
            cursorYCoord = curMenuOptions.size() - 1;
          }
          else if ((size_t)cursorYCoord > ((size_t)curMenuOptions.size() - 1))
          {
            cursorYCoord = 0;
          }
        }
      }

      if (downButtonIsPress())
      {
        cursorYCoord++;
        if (curMenuOptions.size() > maxMenuOptionsOnScreen)
        {
          if (cursorYCoord < 0)
          {
            if (menuOffset > 0)
            {
              menuOffset--;
              cursorYCoord = 0;
            }
            else
            {
              menuOffset = curMenuOptions.size() - maxMenuOptionsOnScreen;
              cursorYCoord = (int)maxMenuOptionsOnScreen - 1;
            }
          }
          else if ((size_t)cursorYCoord + menuOffset > ((size_t)curMenuOptions.size() - 1))
          {
            menuOffset = 0;
            cursorYCoord = 0;
          }
          else if (cursorYCoord > (int)maxMenuOptionsOnScreen - 1)
          {
            menuOffset++;
            cursorYCoord = (int)maxMenuOptionsOnScreen - 1;
          }
        }
        else
        {
          if (cursorYCoord < 0)
          {
            cursorYCoord = curMenuOptions.size() - 1;
          }
          else if ((size_t)cursorYCoord > ((size_t)curMenuOptions.size() - 1))
          {
            cursorYCoord = 0;
          }
        }
      }

      if (selectButtonIsPress() || selectButtonIsHold())
      {
        if (curMenuOptions.size() > maxMenuOptionsOnScreen)
        {
          curMenuOptions[cursorYCoord + menuOffset].optionFunc();
        }
        else
        {
          curMenuOptions[cursorYCoord].optionFunc();
        }
      }
    }
  }
  else
  {
    webServer.stop();
    WiFi.disconnect(true);
    WiFi.softAPdisconnect(true);

    clearDisplay();
    drawString(20, 3, "Need charging");
    while (true)
    {
      millisDelay(200);
      if (getBatteryPercentage() >= 5)
      {
        configureMainMenu();
        break;
      }
      yield();
    }

    createAccessPoint(apSsid, apPassword);
    startWebServer();
  }
}
 

DMENUX

New member
вот код drawString():
C++:
void drawString(uint8_t x, uint8_t y, String text)
{
  display.print(text.c_str(), x, y);
}
 

DMENUX

New member
если закоментить эти строчки - то точка доступа будет работать
C++:
if (mainMenuConfigured == true)
{
  drawString(20, 7, "Charge: " + String(getBatteryPercentage()) + "% ");
}

if (apInfoMenuConfigured == true)
{
  drawString(20, 3, "Devices: " + String(WiFi.softAPgetStationNum()) + " ");
}

if (systemMenuConfigured == true)
{
  drawString(20, 1, String(getBatteryVoltage(), 2) + "V");
  drawString(20, 2, String((float)ESP.getFreeHeap() / 1024, 2) + "(kb)");
  drawString(20, 3, getWorkingTimeStr());
}
 

DMENUX

New member
и проблема тут не в частом считывании аналогового пина, считывание происходит раз в 3 секунды.
вот код для получения приблизительного уровня заряда батареии:
C++:
float getBatteryVoltage()
{
  if (firstAnalogReadCompleted == false)
  {
    float voltage = (analogRead(batteryPin) * maxVoltage) / 1023.0;
    lastBatteryVoltage = voltage;
    batteryMillis = millis();
    firstAnalogReadCompleted = true;
    return voltage;
  }
  else if (millis() - batteryMillis >= 3000)
  {
    float voltage = (analogRead(batteryPin) * maxVoltage) / 1023.0;
    lastBatteryVoltage = voltage;
    batteryMillis = millis();
    return voltage;
  }
  else
  {
    return lastBatteryVoltage;
  }
}

int getBatteryPercentage()
{
  float volt = getBatteryVoltage();
  int percents = (int)roundf((volt - minVoltage) / (maxVoltage - minVoltage) * 100);
  if (percents > 100)
  {
    percents = 100;
  }
  else if (percents < 0)
  {
    percents = 0;
  }
  return percents;
}
 

CodeNameHawk

Moderator
Команда форума
Проблема в том, что в коде нет коментов.
По идее должен выполняться всегда, пока запущен веб сервер.
И самое очевидное займитесь отладкой, проверьте что сколько времени занимает, включите отладку сети в ардуиноиде.
 

esp340

Active member
Для работы с дисплеем использую библиотеку iarduino_OLED_txt,
вот код drawString():
C++:
void drawString(uint8_t x, uint8_t y, String text)
{
  display.print(text.c_str(), x, y);
}
Выбрось эти стринги и возьми нормальныеую трусы библиотеку http://arduino.ru/forum/proekty/aso...lya-oled-displeya-128kh64-s-kirillitsei-utf-8
 

DMENUX

New member
Выбрось эти стринги и возьми нормальныеую трусы библиотеку http://arduino.ru/forum/proekty/aso...lya-oled-displeya-128kh64-s-kirillitsei-utf-8
переход на эту библиотеку не помог решить проблему, однако эта библиотека куда лучше написана чем iarduino_OLED_txt и в целом она мне больше понравилась, так что я останусь на ней
 

DMENUX

New member
Как вы это определяете?
Точка доступа даже не появляется в списке активных wifi сетей, т.к ей что-то сильно мешает. Я бы мог предположить, что слишком частая отправка данных на дисплей каким-то образом мешает работе точки доступа, как и слишком частое считывания аналогового пина, но если сделать считывания пина раз в три секунды - не проблема, то с отправкой данных на дисплей так не прокатит. Не стоит так сильно замедлять дисплей. Я понимаю, что можно использовать куда меньшую задержку и для считывания пина и для отправки данных на дисплей, но если для дисплея требуется задержка больше 20мс - то это совершено не вариант.
Когда я пишу "задержка" я имею ввиду это:
C++:
unsigned long prevMillis = 0;
bool firstAnalogReadCompleted = false;

void t()
{
  if (firstAnalogReadCompleted == false)
  {
    // analogRead();
    prevMillis = millis();
    firstAnalogReadCompleted = true;
  }
  else if (millis() - prevMillis >= 3000)
  {
    // analogRead();
    prevMillis = millis();
  }
}
 

CodeNameHawk

Moderator
Команда форума
как и слишком частое считывания аналогового пина,
Была информация, что "частая" работа с аналоговым входом мешает работе есп, но у вас в тестовом скетче нет работы с ним, а вывод на экран должен работать.
 

DMENUX

New member
Была информация, что "частая" работа с аналоговым входом мешает работе есп, но у вас в тестовом скетче нет работы с ним, а вывод на экран должен работать.
Верно, в тестовом скетче нет работы с аналоговым входом. Я привел его как возможную аналогию проблемы с дисплеем. То есть как слишком частое считывание A0 мешает есп, так возможно слишком частая передача данных по i2c мешает работе esp
 
Сверху Снизу