Мгновенная реакция на нажатие кнопки в Веб-сервере W5100
- Войдите на сайт для отправки комментариев
Пнд, 19/03/2018 - 14:52
Доброго времени суток, уважаемые форумчане!
Перед мной возникла задача организации управления электронным блоком котлов через интернет
Решено было использовать Arduino UNO +W5100 и блок реле 4шт.
С сетевыми делами все ясно, но только не могу понять как сделать так, чтобы нажатие на кнопку в веб браузере мнговенно включало реле.
скетч
#include <SPI.h>
#include <Ethernet.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define MQ_PIN A0
float mqValue;
float mqPercents;
#define PIN_RELAY1 4 // пин, используемый для подключения реле
#define PIN_RELAY2 5 // пин, используемый для подключения реле
#define PIN_RELAY3 6 // пин, используемый для подключения реле
#define PIN_RELAY4 7 // пин, используемый для подключения реле
OneWire oneWire(2); // вход датчиков 18b20
DallasTemperature ds(&oneWire);
DeviceAddress sensor1 = {0x28, 0xFF, 0x82, 0x1C, 0x02, 0x17, 0x05, 0xD8};
DeviceAddress sensor2 = {0x28, 0xFF, 0x6E, 0x09, 0x03, 0x17, 0x04, 0x6F};
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // MAC address Ethernet шилда
IPAddress ip(192, 168, 171, 17); // IP address Ethernet шилда
byte gateway[] = { 192, 168, 171, 14 }; // Адрес основного шлюза (роутера локальной сети) Смотреть в настройках роутера.
byte subnet[] = { 255, 255, 255, 0 }; // Маска подсети. В локальной сети можно на любом компе зайти в центр упр. сет. -> параметры адаптера.
EthernetServer server(80); // create a server at port 80
void setup() {
{
pinMode(PIN_RELAY1, OUTPUT);// Объявляем пин реле как выход
pinMode(PIN_RELAY2, OUTPUT);
pinMode(PIN_RELAY3, OUTPUT);
pinMode(PIN_RELAY4, OUTPUT);
digitalWrite(PIN_RELAY1, LOW); // Выключаем реле -
digitalWrite(PIN_RELAY2, LOW);
digitalWrite(PIN_RELAY3, LOW);
digitalWrite(PIN_RELAY4, LOW);
}
Serial.begin(9600);
while (!Serial) ;
Ethernet.begin(mac, ip);
server.begin();
Serial.println(Ethernet.localIP());
ds.begin();
}
void loop() {
mqValue = analogRead(MQ_PIN);
mqPercents = mqValue/1024*100;
ds.requestTemperatures(); // считываем температуру с датчиков
float t1=ds.getTempC(sensor1);
float t2=ds.getTempC(sensor2);
// Serial.print("Sensor 1: ");
// Serial.print(ds.getTempC(sensor1)); // отправляем температуру
// Serial.println("C");
// Serial.print("Sensor 2: ");
// Serial.print(ds.getTempC(sensor2));
// Serial.println("C");
// Serial.println();
Serial.print(t1);
Serial.print(t2);
delay(1000);
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
if (c == '\n' && currentLineIsBlank) {
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html;charset=utf-8");
client.println("Connection: close");
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<meta http-equiv=\"refresh\" content=\"3\">");
client.println("<html><head><title>Карла Маркса. Корпус №7</title> </head>");
client.println("<body><CENTER><H2>Температура котлов Navien, корпус №7</H2></BR><H1>");
client.println("<body><H2>Уровень загазованности помещения:</H2><H1>");
client.println(mqPercents);
client.println("%, ");
client.println(mqValue);
client.println("ppm.");
client.println("<body><H2>Температура котла №1:</H2><H1>");
client.println(t1);
client.println("C");
client.println("<input type=submit value=\"+1 градус\"></form>");
if (client.print("<input type=hidden name=cmd>"));
{
digitalWrite(PIN_RELAY1, HIGH);
delay(500);
digitalWrite(PIN_RELAY1, LOW);
}
client.println("<input type=submit value=\"-1 градус\"></form>");
if (client.print("<input type=hidden name=cmd>"));
{
digitalWrite(PIN_RELAY2, HIGH);
delay(500);
digitalWrite(PIN_RELAY2, LOW);
}
client.println("<body><H2>Температура котла №2:</H2><H1>");
client.println(t2);
client.println("C");
client.println("<input type=submit value=\"+1 градус\"></form>");
if (client.print("<input type=hidden name=cmd value=1>"));
{
digitalWrite(PIN_RELAY3, HIGH);
delay(500);
digitalWrite(PIN_RELAY3, LOW);
}
client.println("<input type=submit value=\"-1 градус\"></form>");
if plen=es.ES_fill_tcp_data_p(buf,plen,PSTR("<input type=hidden name=cmd value=1>"));
{
digitalWrite(PIN_RELAY4, HIGH);
delay(500);
digitalWrite(PIN_RELAY4, LOW);
}
client.println("</html>");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
delay(1);
client.stop();
Serial.println("client disonnected");
}
}
Как сделать рабочие кнопки в веб сервере
Кнопки должны срабатывать мгновенно - включать реле на 500 мсекунд
Буду очень признателен за советы
никак.
WEB-протокол не предназаначен для Реал-Тайм систем.
Мгновенно, кстати, это сколько в секундах/миллисекундах/наносекундах?
Наверное я неверно выразился, под словом "мгновенно" я имел ввиду чтобы при нажатии кнопки с веб сервера сразу уходила команда на включение реле.
В примерах управления реле через веб-интерфейс, что мне попадались, надо было поставить галочку, потом нажать выполнить и тд.
Можно ли сделать так чтобы достаточно было только нажатия на кнопку?
И вообще как програмируются кнопки на веб сервере, точнее их функциональные возможности при срабатывании????
Можно-то можно, сделайте эту кнопку "сабмитом для формы", запрос на сервер будет уходить сразу. Только о какой мгновенности Вы говорите, если у Вас в loop торчат блокирующие функции (стр. 57-58), которые вместе работают целых полторы секунды?
ШTopo, странный какой-то у вас HTML. Он хоть что-то делает?
Температуру и загазованость показывает нормально, а кнопки ничего не делают - в этом то и главная проблема
Реле срабатывают поочередно и все(((
Под словом "мгновенно" имелось ввиду срабатываение кнопки только при нажатии на нее,
А можно по подробнее как использовать Submit???
client.println("<input type=submit value=\"-1 градус\"></form>");
Написал я что то с эти словом, но реле срабатывают сами по себе поочередно, без нажатия
Читайте вот здесь, начиная с фразы "Для отправки данных на сервер предназначена специальная кнопка Submit".
Но, лучше, читайте всё - пользы будет больше.
Что то я не пойму, как сказать Ардуине, что кнопка на веб сервере нажата?
Ну, как сказать... Попробуйте заорать на ардуину - может дойдет до нее.
Сабмит постит поля формы на вебсервер. Т.е. на ардуину прилетает строка с именами полей и их значениями. Ваше задание - распарсить эту строку и сделать ардуиной красиво, если прилетевшее поле равно чему-то нужному. Можете сделать что-то вроде <input hidden> и тогда это поле не будет показано в браузере, но при сабмите его значение полетит на ардуину.
Вы прочитали про HTML? Так прочитайте! Ну, поймите Вы, нельзя делать что-то в среде, о которой ничего не знаете!
Пишете в тэге form адрес Вашей ардуины, а запрос сам на неё пойдёт, когда submit Нажмёте
<form action="h t t p : / / moya.arduina.home</a>"> <!-- тут могут быть всякие элементы формы. Все они будут переданы странице h t t p : / / moya.arduina.home --> <input type="submit">Дави на меня!</p> </form>Разумеется, адрес правильный укажите в аттибуте action
Разумеется, адрес правильный укажите в аттибуте action
да бесполезно - следующий вопрос будет "А где мне взять адрес?"
Правильно сказал Дракула (вроде?) - "Ардуина, это игрушка. Но игрушка для программистов."
ТС, пока вы не станете программистом, хотя бы на любительском уровне - ничего дельного у вас с ардуиной не выйдет. Так что приготовтесь много учиться. Либо забросьте эту затею.
ПОшел немного другим путем.
Решил использовать гиперссылки
Вроде все заработало, но есть один маленкий и неприятный момент - при обновлении страницы реле самопроизвольно начинабт включатся, то первое, то 4-е
вот код
#include <SPI.h> #include <Ethernet.h> #include <OneWire.h> #include <DallasTemperature.h> #define MQ_PIN A0 float mqValue; float mqPercents; int led1 = 4; int led2 = 5; int led3 = 6; int led4 = 7; OneWire oneWire(2); // вход датчиков 18b20 DallasTemperature ds(&oneWire); DeviceAddress sensor1 = {0x28, 0xFF, 0x82, 0x1C, 0x02, 0x17, 0x05, 0xD8}; DeviceAddress sensor2 = {0x28, 0xFF, 0x6E, 0x09, 0x03, 0x17, 0x04, 0x6F}; int pos = 0; byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address byte ip[] = { 192, 168, 171, 17 }; // ip in lan (that's what you need to use in your browser. ("192.168.1.178") byte gateway[] = { 192, 168, 171, 14 }; // internet access via router byte subnet[] = { 255, 255, 255, 0 }; //subnet mask EthernetServer server(80); //server port String readString; void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } pinMode(led1, OUTPUT); pinMode(led2, OUTPUT); pinMode(led3, OUTPUT); pinMode(led4, OUTPUT); // start the Ethernet connection and the server: Ethernet.begin(mac, ip, gateway, subnet); server.begin(); Serial.print("server is at "); Serial.println(Ethernet.localIP()); } void loop() { digitalWrite(led1, LOW); digitalWrite(led2, LOW); digitalWrite(led3, LOW); digitalWrite(led4, LOW); mqValue = analogRead(MQ_PIN); mqPercents = mqValue/1024*100; ds.requestTemperatures(); // считываем температуру с датчиков float t1=ds.getTempC(sensor1); float t2=ds.getTempC(sensor2); // Serial.print("Sensor 1: "); // Serial.print(ds.getTempC(sensor1)); // отправляем температуру // Serial.println("C"); // Serial.print("Sensor 2: "); // Serial.print(ds.getTempC(sensor2)); // Serial.println("C"); // Serial.println(); Serial.print(t1); Serial.print(t2); delay(1000); // Create a client connection EthernetClient client = server.available(); if (client) { while (client.connected()) { if (client.available()) { char c = client.read(); if (readString.length() < 100) { readString += c; } if (c == '\n') { Serial.println(readString); //html file client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html;charset=utf-8"); client.println("<HTML>"); client.println("<HEAD>"); client.println("<meta http-equiv=\"refresh\" content=\"100\">"); client.println("<html><head><title>Карла Маркса. Корпус №7</title> </head>"); client.println("<body><CENTER><H2>Температура котлов Navien, корпус №7</H2></BR><H1>"); client.println("<body><H2>Уровень загазованности помещения:</H2><H1>"); client.println(mqPercents); client.println("%, "); client.println(mqValue); client.println("ppm."); client.println("<body><H2>Температура котла №1:</H2><H1>"); client.println(t1); client.println("C"); client.println("<a href=\"/?button1on\"\">+1 градус</a>"); client.println("<a href=\"/?button2on\"\">-1 градус</a>"); client.println("<body><H2>Температура котла №2:</H2><H1>"); client.println(t2); client.println("C"); client.println("<a href=\"/?button3on\"\">+1 градус</a>"); client.println("<a href=\"/?button4on\"\">-1 градус</a>"); client.println("<br />"); client.println("</BODY>"); client.println("</HTML>"); delay(1); //stopping client client.stop(); //controls the Arduino if you press the buttons if (readString.indexOf("?button1on") >0){ digitalWrite(led1, HIGH); delay(500); digitalWrite(led1, LOW); } if (readString.indexOf("?button2on") >0){ digitalWrite(led2, HIGH); delay(500); digitalWrite(led2, LOW); } if (readString.indexOf("?button3on") >0){ digitalWrite(led3, HIGH); delay(500); digitalWrite(led3, LOW); } if (readString.indexOf("?button4on") >0){ digitalWrite(led4, HIGH); delay(500); digitalWrite(led4, LOW); } //clearing string for next read readString=""; } } } } }В чем может быть причина???
А что в монитор порта печатается?
Можно протокол монитора порта скопипастить и чётко написать что именно включалось в моменты обновлений?
Включал поочередно 1 реле, затем 2, 3, 4
после нажал обновил страницу и сразу включилось 4-е реле (2 раза обновлял и 2 раза включалось реле)
Как будто думает что я кнопку нажимаю
вот данные с монитора порта:
видимо после обновления страницы он повторно отсылает последний запрос. как эт этого избавится то?
Это нормальное поведение браузера. Можно сделать редирект страницы на саму себя если пришли данные методом GET.
Это нормальное поведение браузера. Можно сделать редирект страницы на саму себя если пришли данные методом GET.
Или добавить свою кнопку обновить на страницу, которая будет ссылаться на саму страницу/
Включал поочередно 1 реле, затем 2, 3, 4
после нажал обновил страницу и сразу включилось 4-е реле (2 раза обновлял и 2 раза включалось реле)
Вот это то, чего я хотел услышать. А то раньше Вы писали другое
при обновлении страницы реле самопроизвольно начинабт включатся, то первое, то 4-е
Понимаете, то что влкючается не какое попало, а то, которое Вы последним включали, это правильно, так и должно быть.
Более того, Вы же печатаете лог, чего ж Вы в него не смотрите? (кстати, вставляйте с номерами строк, ну что вы - новички все такие). Вот смотрите
Строки 1-2 - это Ваш первый запрос на button1on.
Строки 3-4 - это Ваш второй запрос на button2on.
Строки 5-6 - это Ваш третий запрос на button3on.
Строки 7-8 - это Ваш четвёртый запрос на button4on.
А вот теперь два Ваших обновления - строки 9-10 и 11-12. Они тоже просят button4on - смотрите это написано в строках 9 и 11! Вы читайте то, что сами же печатаете!
Т.е. это совершенно нормальное поведение. Если ничего не предпринимать, то "по умолчанию" так и должно быть.
Теперь увидел - в дискуссии рождается истина)
Если ничего не предпринимать, то "по умолчанию" так и должно быть.
Что можно предпринять???
Можно ли сделать условия о отмене всех запросов при обновлении страницы?
Страницу необходимо обновлять каждые 10 секунд, для получения актуальных данных
Что можно предпринять???
Вам уже сказали в постах №№ #17 и #18.
Это нормальное поведение браузера. Можно сделать редирект страницы на саму себя если пришли данные методом GET.
Или добавить свою кнопку обновить на страницу, которая будет ссылаться на саму страницу/
Что такое редирект? Я чайник и сленг програмистов нихт ферштейн))
Кнопку делать мне не надо. Все равно при нажатии будет срабатывать одна из релюшек.
Тем более у мен страница должна обновлятся каждые 10 сек для получения актуальных данных о температуре и загазованности.
Как сделать редирект страницы на саму себя если пришли данные методом GET.
Где прочесть про это?
https://ru.wikipedia.org/wiki/HTTP
сленг програмистов нихт ферштейн))
И в гугле тоже забанирен! Достаточно набрать в гугле: редирект html
Как первый же результат будет - http://ab-w.net/HTML-guide/HTML-redirect.php
редирект результатов не принес
все равно последний запрос обрабатывается при обновлении страницы.
В редиректе указал ссылку на ip адресс ардуины.
Проверил работоспособность - вел другой Ip-шник по истечении 10 сек браизер переходил на него.
Однако при указании ссылки на ip адресс ардуины при обновлении срабатывает последнее нажатая ссылка.
Возникли следующие мысли.
ПРи обработке гиперссылок используется переменные:
?button1on
?button2on
?button3on
?button4on
При нажатии они становятся >0
можно ли их насильно после выполнения сделать =0??
Т.е. при обновлении страницы и запуске цикла все переменные будут =0, т.е типа не нажатые?
редирект результатов не принес
Код и лог печати в студию, иначе - кофейная гуща.
Решил все таки вернутся к использованию кнопок
#include <SPI.h> #include <Ethernet.h> #include <OneWire.h> #include <DallasTemperature.h> #define MQ_PIN A0 float mqValue; float mqPercents; byte cmd; int led = 4; int led2 = 5; int led3 = 6; int led4 = 7; OneWire oneWire(2); // вход датчиков 18b20 DallasTemperature ds(&oneWire); DeviceAddress sensor1 = {0x28, 0xFF, 0x82, 0x1C, 0x02, 0x17, 0x05, 0xD8}; DeviceAddress sensor2 = {0x28, 0xFF, 0x6E, 0x09, 0x03, 0x17, 0x04, 0x6F}; int pos = 0; byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address byte ip[] = { 192, 168, 171, 17 }; // ip in lan (that's what you need to use in your browser. ("192.168.1.178") byte gateway[] = { 192, 168, 171, 14 }; // internet access via router byte subnet[] = { 255, 255, 255, 0 }; //subnet mask EthernetServer server(80); //server port String readString; void setup() { // Open serial communications and wait for port to open: Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } pinMode(led, OUTPUT); pinMode(led2, OUTPUT); pinMode(led3, OUTPUT); pinMode(led4, OUTPUT); // start the Ethernet connection and the server: Ethernet.begin(mac, ip, gateway, subnet); server.begin(); Serial.print("server is at "); Serial.println(Ethernet.localIP()); } void loop() { byte cmd=0; digitalWrite(led, LOW); digitalWrite(led2, LOW); digitalWrite(led3, LOW); digitalWrite(led4, LOW); mqValue = analogRead(MQ_PIN); mqPercents = mqValue/1024*100; ds.requestTemperatures(); // считываем температуру с датчиков float t1=ds.getTempC(sensor1); float t2=ds.getTempC(sensor2); // Serial.print("Sensor 1: "); // Serial.print(ds.getTempC(sensor1)); // отправляем температуру // Serial.println("C"); // Serial.print("Sensor 2: "); // Serial.print(ds.getTempC(sensor2)); // Serial.println("C"); // Serial.println(); Serial.print(t1); Serial.print(t2); delay(1000); // Create a client connection EthernetClient client = server.available(); if (client) { while (client.connected()) { if (client.available()) { char c = client.read(); if (readString.length() < 100) { readString += c; } if (c == '\n') { Serial.println(readString); //html file client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html;charset=utf-8"); client.println(); client.println("<HTML>"); client.println("<HEAD>"); client.println("<meta http-equiv=\"refresh\" content=\"10\">"); client.println("<html><head><title>Карла Маркса. Корпус №7</title> </head>"); client.println("<body><CENTER><H2>Температура котлов Navien, корпус №7</H2></BR><H1>"); client.println("<body><H2>Уровень загазованности помещения:</H2><H1>"); client.println(mqPercents); client.println("%, "); client.println(mqValue); client.println("ppm."); client.println("<body><H2>Температура котла №1:</H2><H1>"); client.println(t1); client.println("C"); client.println("<input type=hidden name=cmd value=1>"); client.println("<input type=submit value=\"+1 градус\"></form>"); client.println("<input type=hidden name=cmd value=2>"); client.println("<input type=submit value=\"-1 градус\"></form>"); client.println("<body><H2>Температура котла №2:</H2><H1>"); client.println(t2); client.println("C"); client.println("<input type=hidden name=cmd value=3>"); client.println("<input type=submit value=\"+1 градус\"></form>"); client.println("<input type=hidden name=cmd value=4>"); client.println("<input type=submit value=\"-1 градус\"></form>"); client.println("<br />"); client.println("</BODY>"); client.println("</HTML>"); delay(1); //stopping client client.stop(); //controls the Arduino if you press the buttons if (byte cmd=1){ digitalWrite(led, HIGH); delay(300); digitalWrite(led, LOW); } if ( byte cmd=2){ digitalWrite(led2, HIGH); delay(300); digitalWrite(led2, LOW); } if (byte cmd=3){ digitalWrite(led3, HIGH); delay(300); digitalWrite(led3, LOW); } if (byte cmd=4){ digitalWrite(led4, HIGH); delay(300); digitalWrite(led4, LOW); } //clearing string for next read readString=""; } } } } }Sadman писал о "Т.е. на ардуину прилетает строка с именами полей и их значениями. Ваше задание - распарсить эту строку и сделать ардуиной красиво, если прилетевшее поле равно чему-то нужному. Можете сделать что-то вроде <input hidden> и тогда это поле не будет показано в браузере, но при сабмите его значение полетит на ардуину."
Как распарсить строку?
Я использовал код:
Сначало объявил переменную cmd как число
затем на веб сервер выводим кнопку и скрытий элемент, при нажатии переменная cmd принимает значени 1 (если я правильно оформил все по синтаксу):
client.println("<input type=hidden name=cmd value=1>"); client.println("<input type=submit value=\"+1 градус\"></form>");Затем задаем условие:
if (byte cmd=1){ digitalWrite(led, HIGH); delay(300); digitalWrite(led, LOW); }Но ничего не работает.
Господа форумчане, что я делаю не так то?
В строках №№ 111, 114, 120, 123 вижу закрывающие тэги "</form>", но что-то не нашёл к ним открывающих. Вы как вообще это делали и где именно указывали адрес Вашей страницы?
А в строке 97 необходимо явно указать URL, иначе она так и будет рефрешить с последним параметром (как у Вас и раньше было).
Про кривой HTML код, Вам уже неоднократно писали.
Затем задаем условие:
Что же этот if(), по-вашему, должен делать?
Что же этот if(), по-вашему, должен делать?
Провеярть действительно ли cmd=1 имеет тип byte. Угадал?
Что же этот if(), по-вашему, должен делать?
Провеярть действительно ли cmd=1 имеет тип byte. Угадал?
Может проверяет удалось ли в принципе создать переменную?
Может проверяет удалось ли в принципе создать переменную?
а какая, кстати, у нее будет область видимости? до закрывающей скобки условия или больше?
Таки
до закрывающей скобки условия