Управление сервой с web странички, проблемы с переключением режимов

Тема в разделе "Arduino & Shields", создана пользователем MaksXXI, 16 сен 2020.

  1. MaksXXI

    MaksXXI Нуб

    Доброго времени суток.
    Есть надобность управлять сервоприводом через Arduino Uno + Ethernet Shield+ сервопривод на 180 градусов(FS5106B), в таком режиме:
    При включении сервопривод уходит на цикл поворотов 60\120\180 градусов, до тех пор пока на Web сервер не придет команда остановится в одном из этих положений. После остановки нужна возможность опять включить повороты по циклу.
    В написании скетчей первый опыт, тапками просьба не кидать, лучше подскажите как сделать что бы серва после выхода из цикла поворотов и остановки в заданном положении не сваливалась опять в цикл поворотов. Проблема в области видимости переменной ServoState, вероятно есть в С++ какой то способ передать значение переменной из одной функции в другую, но я его не нашел.
    В дальнейшем количество приводов планируется увеличить, поэтому так же используется Multiservo Shield.

    Код (C++):
    #include <SPI.h>
    #include <Ethernet.h>
    #include <Multiservo.h>

    // введите ниже MAC-адрес и IP-адрес вашего контроллера;
    // IP-адрес будет зависеть от вашей локальной сети:
    byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
    IPAddress ip(192, 168, 1, 7);

    // инициализируем библиотеку Ethernet Server, указывая нужный порт
    // (по умолчанию порт для HTTP – это «80»):
    EthernetServer server(80);
    Multiservo myservo1;

    // задаем контакт и начальное состояние для сервы:
    String ServoState = "circle";
    int servo1 = 6;
    int delaycircle = 1000; // задержка при непрерывном вращении

    // задаем переменные для клиента:
    char linebuf[80];
    int charcount = 0;

    void runcircle() {
        myservo1.write(60);
        delay(delaycircle);
        myservo1.write(120);
        delay(delaycircle);
        myservo1.write(180);
        delay(delaycircle);
        myservo1.write(120);
        delay(delaycircle);
        ServoState = "circle";
       }

    void setup() {
        // подготавливаем сервы
        myservo1.attach(servo1);
        myservo1.write(60);

        // открываем последовательную коммуникацию на скорости 9600 бод:
        Serial.begin(9600);

        // запускаем Ethernet-коммуникацию и сервер:
        Ethernet.begin(mac, ip);
        server.begin();
        Serial.print("server is at ");  //  "сервер на "
        Serial.println(Ethernet.localIP());
    }

    // Показываем веб-страницу
    void dashboardPage(EthernetClient& client) {
        client.println("<!DOCTYPE HTML><html><head>");
        client.println("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"></head><body>");
        client.println("<h3>Servo Control - <a href=\"/\">Refresh</a></h3>");
        // генерируем кнопку для управления приводом:
        client.println("<h4>ServoState: " + ServoState + "</h4>");

        // если серва в 60, показать другие варианты        
        if (ServoState == "60") {
            client.println("<a href=\"/120gr\"><button>make 120</button></a>");
            client.println("<a href=\"/180gr\"><button>make 180</button></a>");
            client.println("<a href=\"/circle\"><button>make circle</button></a>");
        }

        // если серва в 120, показать другие варианты
        else if (ServoState == "120") {
            client.println("<a href=\"/60gr\"><button>make 60</button></a>");
            client.println("<a href=\"/180gr\"><button>make 180</button></a>");
            client.println("<a href=\"/circle\"><button>make circle</button></a>");
        }
        // если серва в 180, показать другие варианты
        else if (ServoState == "180") {
            client.println("<a href=\"/60gr\"><button>make 60</button></a>");
            client.println("<a href=\"/120gr\"><button>make 120</button></a>");
            client.println("<a href=\"/circle\"><button>make circle</button></a>");
        }
        // если серва в circle, показать другие варианты
        else if (ServoState == "circle") {
            client.println("<a href=\"/60gr\"><button>make 60</button></a>");
            client.println("<a href=\"/120gr\"><button>make 120</button></a>");
            client.println("<a href=\"/180gr\"><button>make 180</button></a>");
            client.println("<a href=\"/circle\"><button>make circle</button></a>");
        }
        client.println("</body></html>");
    }


    void loop() {
        delay(1000);
        if (ServoState = "circle") {
            runcircle();
            Serial.println("circle on loop");
        }

            // прослушиваем входящих клиентов:
        EthernetClient client = server.available();
        if (client) {
            Serial.println("new client");  //  8
            memset(linebuf, 0, sizeof(linebuf));
            charcount = 0;
            // HTTP-запрос заканчивается пустой строкой:
            boolean currentLineIsBlank = true;
            while (client.connected()) {
                if (client.available()) {
                    char c = client.read();
                    // считываем HTTP-запрос, символ за символом:
                    linebuf[charcount] = c;
                    if (charcount < sizeof(linebuf) - 1) charcount++;
                    // если вы дошли до конца строки (т.е. если получили
                    // символ новой строки), это значит,
                    // что HTTP-запрос завершен, и вы можете отправить ответ:
                    if (c == '\n' && currentLineIsBlank) {
                        dashboardPage(client);
                        break;
                    }
                    if (c == '\n') {
                        if (strstr(linebuf, "GET /60gr") > 0) {
                            myservo1.write(60);
                            String ServoState = "60";
                            Serial.println("Make 60");
                        }
                        else if (strstr(linebuf, "GET /120gr") > 0) {
                            myservo1.write(120);
                            String ServoState = "120";
                            Serial.println("Make 120");
                        }
                        else if (strstr(linebuf, "GET /180gr") > 0) {
                            myservo1.write(180);
                            String ServoState = "180";
                            Serial.println("Make 180");
                        }
                        else if (strstr(linebuf, "GET /circle") > 0) {
                            runcircle();
                            Serial.println("circle on ReadButton");
                            String ServoState = "circle";
                        }
                        // если получили символ новой строки...
                        currentLineIsBlank = true;
                        memset(linebuf, 0, sizeof(linebuf));
                        charcount = 0;
                    }
                    else if (c != '\r') {
                        // если получили какой-то другой символ...
                        currentLineIsBlank = false;
                    }
                }
            }
            // даем веб-браузеру время на получение данных:
            delay(1);
            // закрываем соединение:
            client.stop();
            Serial.println("client disonnected");  //  "Клиент отключен"
        }
    }
     
    [​IMG]

    Большое спасибо за любые советы!
     
  2. parovoZZ

    parovoZZ Гуру

    через глобальную переменную, через указатель, через стек..
     
  3. KindMan

    KindMan Гуру

    А в какой области видимости она у вас?
    Код (C++):

    // задаем контакт и начальное состояние для сервы:
    String ServoState = "circle";
    // и далее в функции loop ещё несколько строк типа
    String ServoState = "180";

     
    Это что значит?
     
  4. MaksXXI

    MaksXXI Нуб

    Переменная управляет текущим режимом работы приводов. Перед началом цикла она String ServoState = "circle" для того что бы при включении приводы работали по кругу через void runcircle(); . Далее рисуется веб страничка с кнопками переключения режимов, кнопка по клику меняет значение переменной, и по задумке это должно привести к смене режима работы сервопривода. Но так как в начале программы StateServo это глобальная переменная, а в блоках отрисовки кнопок она локальная, то в начале цикла loop всегда начинает крутится. Вопрос в том, как написать код, который при нажатии на кнопку make 60 передаст значение String ServoState = "60" в цикл loop
     
  5. b707

    b707 Гуру

    если Вы сами понимаете, что у вас в программе не одна переменная StateServo, а куча разных - зачем вы так делаете? Опишите одну глобальную переменную и в процедурах просто присваивайте ей значение, вместо того чтоб создавать кучу локальных переменных с тем же именем.

    А вообще. все это настолько элементарные понятия, разобранные в любом учебнике. что приходить с подобными вопросами на форум должно быть просто стыдно.
     
    MaksXXI нравится это.
  6. parovoZZ

    parovoZZ Гуру

    Сперва надо освоить построение алгоритмов, затем освоить желаемый язык программирования. А уже потом программировать. Только в такой последовательности и никак иначе.
     
  7. MaksXXI

    MaksXXI Нуб

    Спасибо за ответ по существу вопроса, сперва описать переменную, а потом присвоить ей значение, именно тот ответ за которым зашел на форум. Согласен вопрос нубский, но все с чего то начинают).
     
  8. MaksXXI

    MaksXXI Нуб

    Спасибо за разъяснение стратегии, но именно сейчас мне нужен более тактический ответ. Да, я взялся не за свое дело, но и не претендую на звание программиста, просто сисадмин в свободное время занялся ардуинкой, чего сразу вставать в позу?)
     
  9. KindMan

    KindMan Гуру

    Так вот не понятно, зачем зашли :) На свой вопрос сами и отвечаете. Зачем вам объявлять локальную StateServo, если можно использовать глобальную в любой функции?
    И да, алгоритм у вас не продуман изначально, как будут несколько серв у вас крутиться с delay'ями, по очереди? Пока они крутятся не иметь возможности ими управлять?