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

WebServer CustomStepper

gerkimuyda

New member
while(!stepper.isDone()) {stepper.run();}
По поводу вашего решения: Задаем двигателю крутиться stepper.rotate(); - это постоянный поворот без окончания. Что получаем? На нас нападает сторожевой пес и кусает за попку!
Это кроме того, что мы блокируем работу всех остальных фоновых задач SDK (из видимых - вайфай отваливается).

Зачем городить костыли на захламленном неправильном коде, если проще написать сразу правильно?
Что нам надо? Зайти в цикл, пробежаться по нему и выйти вконце (без прерывания в середине).
Что делаем? Вставляем в него stepper.run(); чтобы работал наш моторчик.

Код:
void loop()  {
     if( !stepper.isDone() ) { stepper.run(); } // Для правильности и программной красоты вставим перед ним проверку.

/* Далее мы пишем код, в котором проверяем подключенность клиента и приход от него команд. Т.е. мы не блокируем работу цикла ожиданием команд,
    а выполняем блок действий ТОЛЬКО если есть команды, иначе - продолжаем работу цикла.
*/
  WiFiClient client = server.available();
   if( client ) {
      if( client.available() ) {
        String req = client.readStringUntil('\r');
        if( req.indexOf("/stepper/up") != -1 )   { /* тут выполняем stepper.disable(); чтобы прервать любые задачи двигателя и нужные нам новые настройки */ }
        /* другие блоки запросов */

       // Отдаем ответ на наш запрос
       client.print( String("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n") + respMsg );
     } //client.available
   } //client
} //loop()
@gerkimuyda очень тщательно проверил код - но разные замечания имеют разную степень влияния на конечный результат работы программы.
Поэтому я и говорю, что правильнее и проще с нуля написать код так, как он должен работать. Чем пытаться накостылять наставить костылей в этом глюкокоде. ;):)o_O

рискую получить кучу критики
Не переживайте. Мне очень нравится лаконичный и выдержанный стиль вашего общения на форуме. Также приятны совместные диалоги и попытки развязывания тех или иных вопросов.

Читал где-то что именно delay ибивает весь процесс, нужно использовать millis. Убрать delay , а правильно ли это будет? Или while заменить if.
delay - приостанавливает выполнение текущего кода на заданное время
millis - возвращает текущее время (со старта процессора)
Если перестроить саму структуру программы, избавившись от delay и white (тех участков, которые блокируют наш основной цикл) - это и будет правильным подходом.

Вот представим ситуацию, что вы в добавок к веб-клиенту решите подключить кнопки к вашему модулю, чтобы не только со смарта управлять поворотом жалюзи (или к чему будет прикреплен шаговый двигатель), но и с выключателя, расположенного возле окна. При старом подходе к алгоритму вы получите "затык" с ожиданием команд через http и полное игнорирование нажатий на кнопки! При новой структуре - вы можете продолжать спокойно работать и даже разобрать ситуацию, если пользователь зажмет кнопку "вверх" и при этом пошлет команду "вниз" (вдруг это хитрый способ блокировки управлением от баловства детей?) :cool:
 

gerkimuyda

New member
Не уверен, но вроде бы после '+ respMsg' необходимо добавить сакральные ' +"\r\n\r\n" '
С начала идут заголовки ответа (headers), потом само тело ответа, которое отделяется от заголовком двумя переводами строки (пустой строкой). В конце тела ответа можно не ставить перевод строки. В данном случае, оформление тела я возложил на respMsg. Которое может быть пустым (тогда ответ тоже будет пустым).

\r - carriage return (возврат каретки (курсора))
\n - new line ( новая строка)
Почему в паре? Когда мониторы еще были ламповыми, а принтеры - матричными, эти символы использовались для управления оформлением. Чтобы обновить текущую строку без перевода на новую (например вывести индикатор процентов выполненного), необходимо было перевести курсор на начало строки без перевода строки и поверх напечатать новую. А \n на принтере опускал позицию головки на следующую строку, но не возвращал ее в начало строки.
 
Последнее редактирование:

IgorFX

New member
@gerkimuyda вы прям в воду глядите... т.е. в код))) это управление рулонной шторой). Будут и кнопки и фоторезистор. На 433Мгц управление думаю уже по пинам и питанию не пройдёт. У Wemos по 3,3 в проблема там стаб или микросхема дохнет( номинал 600мА, с учетом КНР /2 так и выходит из строя))
По коду теперь все понятно, огромное спасибо.
Есть ещё вопрос по поводу драйвера uln2003 довольно таки большой и прожорливый. Для Wemos есть шилд tb6612fng но там все рассчитано на два коллекторных двигателя и все это по i2c. Видео есть и код. Но как реализованно. Шилд можно перепрошить но это слишком сложно для меня по крайней мере. Или всё-таки можно скетчем обойтись?IMG_4682.JPGIMG_4681.JPG
 
Последнее редактирование:

gerkimuyda

New member
В схемотехнике я не так силен, как в программировании. Тут уж пусть другие товарищи подсказки сделают.
 

IgorFX

New member
Код:
void loop()  {
     if( !stepper.isDone() ) { stepper.run(); } // Для правильности и программной красоты вставим перед ним проверку.

/* Далее мы пишем код, в котором проверяем подключенность клиента и приход от него команд. Т.е. мы не блокируем работу цикла ожиданием команд,
    а выполняем блок действий ТОЛЬКО если есть команды, иначе - продолжаем работу цикла.
*/
  WiFiClient client = server.available();
   if( client ) {
      if( client.available() ) {
        String req = client.readStringUntil('\r');
        if( req.indexOf("/stepper/up") != -1 )   { /* тут выполняем stepper.disable(); чтобы прервать любые задачи двигателя и нужные нам новые настройки */ }
        /* другие блоки запросов */

       // Отдаем ответ на наш запрос
       client.print( String("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n") + respMsg );
     } //client.available
   } //client
} //loop()
Данный код не работает...страница не доступна. Если убрать if( client.available() ) то страница доступна...но все осталось как прежде делает шаг и все.
 

kab

New member
Код:
void loop()  {
     if( !stepper.isDone() ) { stepper.run(); } // Для правильности и программной красоты вставим перед ним проверку.

/* Далее мы пишем код, в котором проверяем подключенность клиента и приход от него команд. Т.е. мы не блокируем работу цикла ожиданием команд,
    а выполняем блок действий ТОЛЬКО если есть команды, иначе - продолжаем работу цикла.
*/
  WiFiClient client = server.available();
   if( client ) {
      if( client.available() ) {
        String req = client.readStringUntil('\r');
        if( req.indexOf("/stepper/up") != -1 )   { /* тут выполняем stepper.disable(); чтобы прервать любые задачи двигателя и нужные нам новые настройки */ }
        /* другие блоки запросов */

       // Отдаем ответ на наш запрос
       client.print( String("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n") + respMsg );
     } //client.available
   } //client
} //loop()
Данный код не работает...страница не доступна. Если убрать if( client.available() ) то страница доступна...но все осталось как прежде делает шаг и все.
Вы не совсем поняли, Вам надо взять первоначальный Ваш текст и поменять некоторые строчки по образцу, показанному @gerkimuyda. Перед проверкой поместите переработанный текст в сообщение - надо будет проверить, как Вы справились с заданием :):):).

После этого я еще покажу, где надо подправить - жизнь идет вперёд - появляются новые идеи
 

gerkimuyda

New member
Да, kab совершенно верно говорит: Если вы внимательно посмотрите мой код, то поймете, что это всего-лишь шаблон (или образец), построенный из вашего кода, и его необходимо поправить под себя. У меня двигателей нету, чтобы обкатать на практике ваш код. А по поводу http-сервера - есть и другие способы реализации его (примеров много в Ардуине). Я даже не проверял работоспособность, а просто скопировал ваши строчки. Попробуйте подходящий для вас пример из библиотеки esp8266.
И помните, что часто проблемы с библиотеками бывают уже решены и требуют только обновления версии. Поэтому всегда проверяйте, что у вас последняя версия (это касается и http-сервера и SDK в библиотеке esp8266 для ардуины). https://github.com/esp8266/Arduino/releases/download/2.4.0-rc2/package_esp8266com_index.json
 

IgorFX

New member
Да, kab совершенно верно говорит: Если вы внимательно посмотрите мой код, то поймете, что это всего-лишь шаблон (или образец), построенный из вашего кода, и его необходимо поправить под себя. У меня двигателей нету, чтобы обкатать на практике ваш код. А по поводу http-сервера - есть и другие способы реализации его (примеров много в Ардуине). Я даже не проверял работоспособность, а просто скопировал ваши строчки. Попробуйте подходящий для вас пример из библиотеки esp8266.
И помните, что часто проблемы с библиотеками бывают уже решены и требуют только обновления версии. Поэтому всегда проверяйте, что у вас последняя версия (это касается и http-сервера и SDK в библиотеке esp8266 для ардуины). https://github.com/esp8266/Arduino/releases/download/2.4.0-rc2/package_esp8266com_index.json
Ответ сервера закрывает соединение и рушит процесс stepper.run(). Закомментировал все работает.
Код:
void loop() 
{
  if( !stepper.isDone() )
    {
    stepper.run();
    }
    WiFiClient client = server.available();
    if( client )
      {
          String respMsg = "";
          Serial.println("new client");
          String req = client.readStringUntil('\r');       
          Serial.println(req);
          if( req.indexOf("/window/up") != -1 )  
            {
            stepper.setDirection(STOP);
            stepper.setDirection(CW);
            stepper.rotate(12);
            respMsg = "OK: MOTOR Going Up"; 
            }
          if( req.indexOf("/window/down") != -1 )  
             stepper.setDirection(STOP);
            stepper.setDirection(CCW);
            stepper.rotate(12);
            respMsg = "OK: MOTOR Going Down";   
            }
//      client.print( String("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n") + respMsg );
   }//client
} //loop()
 

IgorFX

New member
Код:
void loop()  {
     if( !stepper.isDone() ) { stepper.run(); } // Для правильности и программной красоты вставим перед ним проверку.
  WiFiClient client = server.available();
   if( client ) {
     " if( client.available() ) {"
        String req = client.readStringUntil('\r');
        if( req.indexOf("/stepper/up") != -1 )
{
digitalWrite(BUILD_IN_LED, HIGH);
}
       client.print( String("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n") + respMsg );
     "} //client.available"
   } //client
} //loop()
Сeрвер не доступен, если мы уберем строки выделенные кавычками все работает но только одно действие и ответ мы получим. попробуйте)
 

gerkimuyda

New member
Я вот вчера в другой теме приводил самый простой рабочий код сервера:
Код:
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
ESP8266WebServer server(80);
void handleRoot() { server.send(200, "text/html", "<!DOCTYPE HTML>\r\n<html>Hello!</html>"); }
void setup() {
  WiFi.begin("ssid", "password");
  server.on("/", handleRoot);
  server.begin();
}
void loop() {  server.handleClient(); }
Никаких проблем с ним. Попробуйте. (Для каждого запроса создаете свою отдельную функцию и делаете привязку ее к запросу)
 

IgorFX

New member
Я вот вчера в другой теме приводил самый простой рабочий код сервера:
Код:
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
ESP8266WebServer server(80);
void handleRoot() { server.send(200, "text/html", "<!DOCTYPE HTML>\r\n<html>Hello!</html>"); }
void setup() {
  WiFi.begin("ssid", "password");
  server.on("/", handleRoot);
  server.begin();
}
void loop() {  server.handleClient(); }
Никаких проблем с ним. Попробуйте. (Для каждого запроса создаете свою отдельную функцию и делаете привязку ее к запросу)
Сегодня начал разбирать похожий пример. А отдельными функциями это огород, они итак в библиотеке прописаны(пробовал кстати отдельно под каждое действие прописать).
Обновил библиотеки с гитхаба все тоже самое. Надо я так думаю в самих WiFi.h и webserver.h покопаться.

Хотя нет в данном примере к каждому запросу и прописывается функция. А в теле исполняем клиента.
 
Последнее редактирование:
Сверху Снизу