Официальный сайт компании Arduino по адресу arduino.cc
Ethernet W5100 + Buttons
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Чт, 22/09/2016 - 12:32
Здравствуйте.
Пытаюсь написать скетч по управлению внешними нагрузками через Web-интерфейс + физический выколючатель (вместо реле подключен светодиод). На данный момент работает либо переключение через web, либо через кнопки. Как заставить ардуино включать светодиод и с кнопки, и через веб?
В гугле нашел то, что мне нужно https://startingelectronics.org/articles/arduino/switch-and-web-page-but... , но не понимаю, как оно работает у товарища.
Можете подсказать, почему код обработки кнопки не работает?
Спасибо.
#include <SPI.h> #include <Ethernet.h> #include <Bounce2.h> #define BUTTON 6 #define LED 7 Bounce bouncer = Bounce(); int ledValue = LOW; byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; byte ip[] = { 10, 20, 30, 199 }; EthernetServer server(80); 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(BUTTON, INPUT); pinMode(LED, OUTPUT); bouncer.attach(BUTTON); bouncer.interval(5); digitalWrite(LED, LOW); } // start the Ethernet connection and the server: // Ethernet.begin(mac, ip, gateway, subnet); Ethernet.begin(mac, ip); server.begin(); Serial.print("server is at "); Serial.println(Ethernet.localIP()); } void loop() { // Create a client connection EthernetClient client = server.available(); if (client) { while (client.connected()) { if (client.available()) { char c = client.read(); //read char by char HTTP request if (readString.length() < 100) { //store characters to string readString += c; //Serial.print(c); } //if HTTP request has ended if (c == '\n') { Serial.println(readString); //print to serial monitor for debuging client.println("HTTP/1.1 200 OK"); //send new page client.println("Content-Type: text/html"); client.println(); client.println("<HTML>"); client.println("<HEAD>"); client.println("<meta name='apple-mobile-web-app-capable' content='yes' />"); client.println("<meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' />"); client.println("<link rel='stylesheet' type='text/css' href='http://randomnerdtutorials.com/ethernetcss.css' />"); client.println("<TITLE>Random Nerd Tutorials Project</TITLE>"); client.println("</HEAD>"); client.println("<BODY>"); client.println("<H1>Random Nerd Tutorials Project</H1>"); client.println("<hr />"); client.println("<br />"); client.println("<H2>Arduino with Ethernet Shield</H2>"); client.println("<br />"); client.println("<a href=\"/?button1on\"\">Turn On LED</a>"); client.println("<a href=\"/?button1off\"\">Turn Off LED</a><br />"); client.println("<br />"); client.println("<br />"); client.println("<a href=\"/?button2on\"\">Rotate Left</a>"); client.println("<a href=\"/?button2off\"\">Rotate Right</a><br />"); client.println("<p>Created by Rui Santos. Visit http://randomnerdtutorials.com for more projects!</p>"); 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(LED, HIGH); } if (readString.indexOf("?button1off") >0){ digitalWrite(LED, LOW); } //clearing string for next read readString=""; } } } } //----Код обработки кнопки---------------------- if ( bouncer.update() ) { //если считано значение 1 if ( bouncer.read() == HIGH) { //если свет был выключен, будем его включать if ( ledValue == LOW ) { ledValue = HIGH; //если свет был включен, будем выключать } else { ledValue = LOW; } //записываем значение вкл/выкл на пин со светодиодом digitalWrite(LED,ledValue); } } //------------------------- }
Ну, по уму она работать и не должна.
Первая ошибка (дальше не смотрел) состоит в том, что в сроках 86-91 Вы тупо манипулируете светодиодом не изменяя при этом переменную ledValue .
А в строках 100-113 Вы надеетесь, что ledValue адекватно отражает состояние светодиода.
Теперь проиграйте сценарий. Вот Вы включили светодиод из сети. ledValue при этом как была false, так и осталась. Теперь Вы давите на кнопку. Там проверяется значение ledValue и, поскольку она false, ещё раз включается уже итак включённый светодиод. На глаз этого не видно и Вам кажется, что кнопку проигнорировали.
1. Исправьте это
2. после строки 100 поставьте печать чего нибудь, чтобы видеть попадает ли программа туда
3. опишите поведение - будем думать
Спасибо за подсказку с дебагом! Только она и помогла разобраться, что и как работало.
На данный момент получилось сделать так:
Остается только один вопрос с редиректом client.println("<meta http-equiv=\"refresh\" content=\"3; url=http://10.20.30.199/\">");
Проблема вот в чем: когда пользователь нажимает на кнопку включения/отключения светодиода (на веб-форме), в адресной строке добавляется ?button1on или ?button1off. Если сделать автоматический рефреш страницы (чтобы обновлять статус лайбла LED is On/ LED is Off), то в GET запросе автоматически подставляется последнее значение и светодиод принимает значение от значения в адресной строке. Соответственно светодиод примет то значение, которое указано в GET-запросе. Придумал костыль в виде редиректа на стартовую страницу формы, чтобы управлять светодиодм также можно было и через обычную кнопку.
Скажите, пожалуйста, насколько данное решение можно применять в реальном использовании микроконтроллера? Можно ли это чем-нибудь заменить более правильным? Читал про arduino+ajax https://startingelectronics.org/tutorials/arduino/ethernet-shield-web-se... , но, как я понял, там придется делать авторефреш и держать кнопку нажатой по значению таймера, чтобы значение на веб-форме изменилось.
Не совсем понял, Вам нужно, чтобы актульное состояние кнопки отображалось на странице, даже если кнопку нажали офф-лайн?
Ну, для этого не надо свежать страницу целиком.
Давайте разделим вопрос и обсудим по частям:
1. Если таки (в других случаях) надо обновить страницу, но надо чтобы она точно загрузилась с сервера, а не взялась из кэша браузера, то это делается путём добавления случайного параметра на который страница никак не реагирует. Т.е. например, есть страница kaka.htm . Ну добавьте параметр со случайным значением и запрашивайте kaka.htm?a=321 - где 321 - случайное число, каждый раз разное. Всё, URL отличается - никаких кэшей - бкдет перегружаться.
2. В вашем случае перегружать страницу не надо. Достаточно сделать совсем маленькую вставочку типа adjax. Техника там такая же, но ajax - гормадный монстр, а мы сделаем крохотный его кусочек. Как это делается я уже здесь писал - смотрите. Кстати, в этой статье и техника вставки случайного параметра показана.