Доброго времени суток. Есть надобность управлять сервоприводом через 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"); // "Клиент отключен" } } Большое спасибо за любые советы!
А в какой области видимости она у вас? Код (C++): // задаем контакт и начальное состояние для сервы: String ServoState = "circle"; // и далее в функции loop ещё несколько строк типа String ServoState = "180"; Это что значит?
Переменная управляет текущим режимом работы приводов. Перед началом цикла она String ServoState = "circle" для того что бы при включении приводы работали по кругу через void runcircle(); . Далее рисуется веб страничка с кнопками переключения режимов, кнопка по клику меняет значение переменной, и по задумке это должно привести к смене режима работы сервопривода. Но так как в начале программы StateServo это глобальная переменная, а в блоках отрисовки кнопок она локальная, то в начале цикла loop всегда начинает крутится. Вопрос в том, как написать код, который при нажатии на кнопку make 60 передаст значение String ServoState = "60" в цикл loop
если Вы сами понимаете, что у вас в программе не одна переменная StateServo, а куча разных - зачем вы так делаете? Опишите одну глобальную переменную и в процедурах просто присваивайте ей значение, вместо того чтоб создавать кучу локальных переменных с тем же именем. А вообще. все это настолько элементарные понятия, разобранные в любом учебнике. что приходить с подобными вопросами на форум должно быть просто стыдно.
Сперва надо освоить построение алгоритмов, затем освоить желаемый язык программирования. А уже потом программировать. Только в такой последовательности и никак иначе.
Спасибо за ответ по существу вопроса, сперва описать переменную, а потом присвоить ей значение, именно тот ответ за которым зашел на форум. Согласен вопрос нубский, но все с чего то начинают).
Спасибо за разъяснение стратегии, но именно сейчас мне нужен более тактический ответ. Да, я взялся не за свое дело, но и не претендую на звание программиста, просто сисадмин в свободное время занялся ардуинкой, чего сразу вставать в позу?)
Так вот не понятно, зачем зашли На свой вопрос сами и отвечаете. Зачем вам объявлять локальную StateServo, если можно использовать глобальную в любой функции? И да, алгоритм у вас не продуман изначально, как будут несколько серв у вас крутиться с delay'ями, по очереди? Пока они крутятся не иметь возможности ими управлять?