Помогите разобраться с сервером на ардуино и вводом цифр с клавиатуры одновременно
- Войдите на сайт для отправки комментариев
Пнд, 01/07/2019 - 21:48
Доброго времени суток. Задумал сделать автоматизацию калитки, но не могу разобраться с кодом. Хочу сделать на ардуино мега (+ ethernet шилд ) веб сервер по считыванию показаний с датчиков: геркон, клавиатура ну и электрозамок. На ардуине должен работать веб сервер, и в тоже время ардуинка будет отсылать запрос на локальный веб сервер о статусах датчиков. Но при одновременном считывании цифер с клавиатуры веб сервер подвисает и не работает.
//======================================================= // Имя устройства: Gate // Геркон положение двери: 0=закрыто; 1=открыто. // Кнопка звонка: 1=нажата. // Электрозамок: 1=открыть. // Клавиатура: ввод пароля 0123456789. //======================================================= //========== Настройки ================================== //#define DEV_NAME "Gate" // Название устройства //#define DEV_KEY "35bd29" // Уникальный ключ устройства //======================================================= //========== Библиотеки ================================= #include <SPI.h> #include <Ethernet.h> #include <SoftwareSerial.h> // Серийный порт #include <Keypad.h> //Клавиатура //======================================================= byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //физический мак адрес IPAddress ip(192,168,0,110); // IP адрес в сети IPAddress gateway(192,168,0,1); // internet access via router IPAddress subnet(255,255,255,0); //маска подсети IPAddress myserver (192,168,0,2);//(192, 168, 0, 2); // IP удаленного сервера EthernetServer server(80); //Порт сервера 80 EthernetClient client; String readString; //======================================================= const char* DEV_KEY = "35bd29"; // ключ шифрования const char* DEV_NAME = "Gate"; // наименование устройства // ################################геркон################################ int Door_Sensor_Pin = 4; // контакт для геркона int val = 0; // переменная для хранения состояния датчика геркона // ###################################################################### SoftwareSerial RfidReader(0, 1); // Rfid ридер pin RX and pin TX // ###################################################################### int Relay = 22; //Pin для подключения реле // ###################################################################### void setup() { //========================================================================== Ethernet.begin(mac, ip, subnet, gateway); server.begin(); Serial.begin(9600); Serial.println("Server/Client 1.0 test 24/06/19"); // keep track of what is loaded Serial.println("Send an g in serial monitor to test client"); // what to do to test client Serial.print(" DHCP assigned IP "); Serial.println(Ethernet.localIP()); //========================================================================== pinMode(Relay, OUTPUT); // ВЫХОД РЕЛЕ pinMode(Door_Sensor_Pin, INPUT); // ГЕРКОН установить Door_Sensor_Pin как вход } void loop() { WebSrv(); passCheck(); } //Функция клиента по отправке/принятию Get запроса с данными. void sendGET(String sTrg) { if (client.connect(myserver, 80)) { Serial.println("connected"); Serial.print("connected to "); Serial.println(client.remoteIP()); Serial.println(); Serial.println("GET " + sTrg + " HTTP/1.0"); client.println("GET " + sTrg + " HTTP/1.0"); client.println(); } else { Serial.println("Connection failed!"); Serial.println(); } while (client.connected() && !client.available()) delay(1); //waits for data while (client.connected() || client.available()) { //connected or data available char c = client.read(); Serial.print(c); } Serial.println(); Serial.println("Disconnecting."); Serial.println("=================="); Serial.println(); client.stop(); } // Функция открытия калитки void OpenDoor () { digitalWrite(Relay, HIGH); // реле включено delay(500); digitalWrite(Relay, LOW); // реле выключено } void WebSrv() { // check for serial input if (Serial.available() > 0) { byte inChar; inChar = Serial.read(); if (inChar == 'g') { sendGET("/arduino.txt"); // call sendGET function } } 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 //now output HTML data header if (readString.indexOf('?') >= 0) {//don't send new page client.println("HTTP/1.1 204 GSH"); client.println(); client.println(); } else { 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("<TITLE>Smart Device GATE v1.0</TITLE>"); client.println("</HEAD>"); client.println("<BODY>"); client.println("<H1>Smart device GATE v1.0 by Arduino</H1>"); client.println("Open gate: "); client.println("<a href=\"/?gateOpen\" target=\"inlineframe\">Open</a>"); //client.println("<a href=\"/?off\" target=\"inlineframe\">OFF</a>"); client.println(""); client.println("Status Gate: Close"); client.println("Bell button: Not pressed"); //client.println("<IFRAME name=inlineframe src=\"res://D:/WINDOWS/dnserror.htm\" width=1 height=1\">"); client.println("<IFRAME name=inlineframe style=\"display:none\" >"); client.println("</IFRAME>"); client.println("</BODY>"); client.println("</HTML>"); } //delay(1); //stopping client client.stop(); ///////////////////// control arduino pin if (readString.indexOf("gateOpen") > 0) //checks for on { // digitalWrite(4, HIGH); // set pin 4 high Serial.println("Gate OPEN"); OpenDoor(); } if (readString.indexOf("off") > 0) //checks for off { // digitalWrite(4, LOW); // set pin 4 low Serial.println("Led Off"); } //clearing string for next read readString = ""; } } } } }
/* Модуль работы с цифровой клавиатурой */ #define NUM_KEYS 6 // количество знаков в коде char key; char myarraw[NUM_KEYS] = { '2', '0', '1', '1', '8', '6'}; // массив с верным кодом char button_pressed[NUM_KEYS]; //массив для хранения нажатых кнопок int k=0; // счетчик нажатий int s=0; // счетчик совпадений нажатых кнопок с верными const byte ROWS = 4; // количество строк в матрице клавиатуры const byte COLS = 4; // количество столбцов char keys[ROWS][COLS] = { // таблица соответствия кнопок символам {'1','2','3','A'}, {'4','5','6','B'}, {'7','8','9','C'}, {'*','0','#','D'}}; byte rowPins[ROWS] = {12, 11, 10, 9}; // пины подключенных строк byte colPins[COLS] = {8, 7, 6, 5}; // пины подключенных столбцов Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); // создаем объект клавиатуры для работы с ней /*void setup() { Serial.begin(9600); Serial.print("Введите пароль:"); }*/ /*void loop (){ passCheck(); }*/ void passCheck(){ key = keypad.getKey(); // спрашиваем у клавиатуры, есть нажатая кнопка? if ( key != NO_KEY ){ // если она все-таки есть button_pressed [k] = key; //сохраняем эту кнопочку в массиве Serial.print(key); k = k + 1; // запоминаем сколько уже кнопок нажали if(k == NUM_KEYS){ // если нажали нужное количество кнопок for ( uint8_t i = 0; i < NUM_KEYS; i++){ // пройдемся по всему массиву if (button_pressed[i] == myarraw[i]){ // и проверим нажатые кнопки с верным кодом s = s + 1; // плюсуем счетчик совпадений } } if(s == NUM_KEYS){ //если у нас все кнопки совпали с кодом, то включаем реле Serial.println("открыто"); Serial.println(""); sendGET("/robots.txt"); k=0; //сбрасываем счетчик нажатий нашей переменной s=0; // сбрасываем счетчик совпадений нашей переменной } else { // если не все кнопки совпали с верным кодом Serial.println("ошибка доступа"); // включаем красный светик (пользователь ввел неверный код) //delay (5000); // ждем 5 секунд // гасим красн светик k=0; // обнуляем счетчики, чтобы начать все заново s=0; // } } } }
Первое что вижу это:
Ethernet.begin(mac, ip, subnet, gateway);
045
server.begin();
Если объявил переменную server, то и оперируй ей.
Мне кажется вместо этих двух строчек должна быть одна:
server.begin(mac, ip, subnet, gateway);
045
Но могу ошибаться, до Ethernet мне ещё далеко, а записи смущают точно.
Это разные объекты. Ethernet управляет общей конфигурацией чипа - адреса, маки, гейтвеи и пр. EthernetServer - виртуальный sockets set, который разруливает входящие коннекты (в чипе его нет, существует только в воображении программиста).
Получается тут ошибки нет?
Почему же нет... Если не работает, значит есть. Обычно хрень получается на строках типа 80 и 81.
А как её побороть? Хотя без подключения клавиатуры все работает.
Побороть - выявив. Выявить отладкой. Там, где есть нелинейность алгоритма и внешнее воздействие типа хаотически входящих данных, простым осмотром кода редко можно сходу проблему обнаружить. Надо заливать в железо, модель собирать и т.д. Или сидеть, втыкать в него долго и упорно. Может кому-то не лень будет - найдут.
Ну ведь функция loop она зацикливается и ждет завершения функции по порядку. А функция обработки клавиатуры ждет ввода с клавиатуры до 6 символов. Может она по этому зависает и ждет завершения функции?
Зависает при нажатии первой же кнопки ? Ожидания нет, функцию опроса оно вроде должно проскакивать и с нажатой кнопкой и без.
Мне кажется зависает сразу после запуска.
А если убрать
passCheck();
виснет ?Нет. Работает так как надо.
Если key = keypad.getKey(); заменить на key = NO_KEY; ?
Спасибо за совет. Доберусь до ардуинки и отпишусь.
Если key = keypad.getKey(); заменить на key = NO_KEY; ?
В этом случае работает только web server. Клавиатура по понятным причинам нет.
Но при этом клавиатура работает...
В Serial Monitor что написано?
20:31:10.233 ->
20:31:10.233 ->
20:31:10.233 ->
20:31:10.233 ->
20:31:10.233 ->
20:31:10.273 ->
20:31:10.273 ->
20:31:10.273 ->
20:31:10.273 ->
Очень быстро выдает...
Не вижу, из какого фрагмента кода это.
Вообщем все перепробовал. Как только функцию passCheck(); вставляю в любой части кода сервер виснет полностью...
Я же говорю - собирать надо. Так, в голове, не отследишь что куда и почем.
Пустые строки выдает клавиатура.... я ставил вывод в порт переменной key.
Ну вообщем заменил библиотеку на <Adafruit_Keypad.h> та же самая проблема. Но если убрать из блока setup вот это код customKeypad.begin(); в мониторе отображается:
19:34:32.639 -> 6 released
19:34:32.639 -> # released
19:34:32.679 -> 1 released
19:34:32.679 -> * released
19:34:32.679 -> # released
19:34:32.719 -> 1 released
19:34:32.719 -> * released
19:34:32.719 -> # released
19:34:32.759 -> 1 released
19:34:32.759 -> * released
19:34:32.759 -> # released
19:34:32.799 -> 4 pressed
19:34:32.799 -> * released
19:34:32.799 -> 2 pressed
19:34:32.799 -> 5 pressed
19:34:32.839 -> 3 pressed
19:34:32.839 -> 6 pressed
19:34:32.839 -> # released
19:34:32.879 -> 1 released
19:34:32.879 -> 4 released
19:34:32.879 -> * released
19:34:32.919 -> 5 released
19:34:32.919 -> 3 released
19:34:32.919 -> 6 released
19:34:32.919 -> # released
И при этом работает сервер в штатном режиме....
Вообщем копаю дальше....