Официальный сайт компании Arduino по адресу arduino.cc
Сопряжение 2 скетчей
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Доброго времени суток.
В программировании Ардуино я новичок, но тем не менее хочу попробовать осуществить управление готовым скетчем при помощи веб интерфейса. Суть в том, что имеется скетч (полностью рабочий)и к нему надо так же привинтить аналоговое управление через web-страничку, чтобы можно было изменять ход циклов на ходу. Изначально всё управлялось через COM-порт посредством C++ или Python. Точно сказать не могу потому как расшифровать готовую программу у меня знаний не хватит. И в целом занялся этим делом потому как с Web-программированием я более-менее знаком ну и так для меня будет проще вносить поправки в скетч/web-страничку. А собственно проблема в том, то я не могу понять как мне по запросу с браузера заставить работать определённый цикл в программе. По нажатию "Start" (HTTP_req, "pin=01") должен выполняться "case '1'", по нажатию "Stop"(HTTP_req, "pin=02" "case 'g'" из цикла void ReadSerial(){switch (Serial.read())......} (находится в конце скетча).
Собственно сам скетч:
#include <SPI.h> #include <Ethernet.h> #include <SD.h> #define REQ_BUF_SZ 80 // Входы #define keycell 22 // Ключ в лебёдке #define keycollar 24 // Ошейник #define keychair 26 // Эл стул #define keyout 28 // Выходная дверь #define noise A0 // Вход от датчика шума #define button A1 // Кнопка на газ.камере // Выходы #define volt 30 // Стрелочный индикатор #define screen_open 32 // Экран открыть #define screen_close 34 // Экран закрыть #define blades 36 // Лезвия #define lamp 38 // Освещение #define mp3 40 // Плеер в душевой #define collar 42 // Запуск ошейника #define door_chamber 44 // Дверь газкамеры #define smoke 46 // Дыммашина #define fire 48 // Пол в газкамере #define door_out 31 // Выходная дверь из квеста #define limit 250 // Предел микроамперметра с учётом -10 #define v 1 // Шаг стрелки амперметра #define timeScreen 3200 // Время движения экрана на потолке #define timeSpeed 20 // Задержка между измерениями датчика шума (влияет на сорость) #define beep A9 // Бузер #define GND A8 // Земля бузера File webFile; char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string char req_index = 0; // index into HTTP_req buffer byte mac[] = { 0x78, 0xAC, 0xC0, 0xC0, 0x26, 0x75}; IPAddress ip( 10, 10, 35, 140); EthernetServer server(80); int sign = 0; int amper = 0; int a = 0; int var = v; int low = 640; int high = 665; int long beepTime = 0; int p = 0; int u = 0; int f = 0; int fl = 0; bool game = false; bool cell_lable = true; bool collar_lable = true; bool chair_lable = true; bool chamber_lable = false; bool button_lable = true; bool svet = false; bool beep_lable = false; bool p01; bool p02; bool p03; bool p04; bool p05; bool p06; bool p07; bool p08; bool p09; bool p10; bool p11; bool p12; bool p13; bool p14; bool p15; bool p16; int pd; void setup() { pinMode(37, OUTPUT); setup_in(); setup_out(); res_logic(); res_rele(); Serial.begin(9600); SD.begin(4); Ethernet.begin(mac, ip); server.begin(); } void res_logic() { game = false; cell_lable = true; collar_lable = true; chair_lable = true; chamber_lable = false; button_lable = true; svet = false; amper = 0; var = v; beep_lable = false; beepTime = 0; p = 0; u = 0; } void res_rele() { digitalWrite(screen_open, HIGH); digitalWrite(screen_close, HIGH); digitalWrite(blades, HIGH); digitalWrite(lamp, HIGH); digitalWrite(mp3, HIGH); digitalWrite(collar, HIGH); digitalWrite(door_chamber, HIGH); digitalWrite(door_out, LOW); digitalWrite(smoke, LOW); digitalWrite(fire, LOW); digitalWrite(beep, LOW); digitalWrite(GND, LOW); } void setup_in() { pinMode(keycell, INPUT_PULLUP); pinMode(keycollar, INPUT_PULLUP); pinMode(keychair, INPUT_PULLUP); pinMode(keyout, INPUT_PULLUP); pinMode(button, INPUT_PULLUP); } void setup_out() { pinMode(screen_open, OUTPUT); pinMode(screen_close, OUTPUT); pinMode(blades, OUTPUT); pinMode(lamp, OUTPUT); pinMode(mp3, OUTPUT); pinMode(collar, OUTPUT); pinMode(door_chamber, OUTPUT); pinMode(door_out, OUTPUT); pinMode(smoke, OUTPUT); pinMode(fire, OUTPUT); pinMode(beep, OUTPUT); pinMode(GND, OUTPUT); } void loop() { // listen for incoming clients EthernetClient client = server.available(); if (client) { // an http request ends with a blank line boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); if (req_index < (REQ_BUF_SZ - 1)) { HTTP_req[req_index] = c; // save HTTP request character req_index++; } if (c == '\n' && currentLineIsBlank) { if (StrContains(HTTP_req, "GET /")) { if (StrContains(HTTP_req, "/ ") || StrContains(HTTP_req, "/index.htm")) { sendHtmlFile(client, "index.htm"); } else if (StrContains(HTTP_req, "/my.css")) { sendFile(client, "my.css"); } else if (StrContains(HTTP_req, "ajax_inputs")) { sendBaseAnswer(client); char buff[64]; sprintf(buff, "%d:%d:%d:%d:%d:%d:%d:%d:", digitalRead(22), digitalRead(24), digitalRead(26), digitalRead(28),digitalRead(30), digitalRead(32), digitalRead(34), digitalRead(36),digitalRead(38), digitalRead(40), digitalRead(42), digitalRead(44),digitalRead(46), digitalRead(48), digitalRead(31), digitalRead(37), pd); client.println(buff); } else if (StrContains(HTTP_req, "inputs")) { if (StrContains(HTTP_req, "pin=01")) { Serial.print('1'); } else if (StrContains(HTTP_req, "pin=02")) { Serial.print('g'); } else if (StrContains(HTTP_req, "pin=03")) { p03 = !p03; digitalWrite(26, p03); } else if (StrContains(HTTP_req, "pin=04")) { p04 = !p04; digitalWrite(28, p04); } else if (StrContains(HTTP_req, "pin=05")) { p05 = !p05; digitalWrite(30, p05); } else if (StrContains(HTTP_req, "pin=06")) { p06 = !p06; digitalWrite(32, p06); } else if (StrContains(HTTP_req, "pin=07")) { p07 = !p07; digitalWrite(34, p07); } else if (StrContains(HTTP_req, "pin=08")) { p08 = !p08; digitalWrite(36, p08); } else if (StrContains(HTTP_req, "pin=09")) { p09 = !p09; digitalWrite(38, p09); } else if (StrContains(HTTP_req, "pin=10")) { p01 = !p01; digitalWrite(40, p01); } else if (StrContains(HTTP_req, "pin=11")) { p02 = !p02; digitalWrite(42, p02); } else if (StrContains(HTTP_req, "pin=12")) { p03 = !p03; digitalWrite(44, p03); } else if (StrContains(HTTP_req, "pin=13")) { p04 = !p04; digitalWrite(46, p04); } else if (StrContains(HTTP_req, "pin=14")) { p05 = !p05; digitalWrite(48, p05); } else if (StrContains(HTTP_req, "pin=15")) { p06 = !p06; digitalWrite(31, p06); } else if (StrContains(HTTP_req, "pin=16")) { p07 = !p07; digitalWrite(37, p07); } else if (StrContains(HTTP_req, "pin=17")) { String input = HTTP_req; int posStart = input.indexOf("value="); int posEnd = input.indexOf(' ', posStart); String param = input.substring(posStart + 6, posEnd + 1); pd = param.toInt(); } sendBaseAnswer(client); } } req_index = 0; StrClear(HTTP_req, REQ_BUF_SZ); 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; } } } // give the web browser time to receive the data delay(1); // close the connection: client.stop(); } if (Serial.available() > 0) ReadSerial(); if (game) { if (cell_lable) Cell(); if (collar_lable) Collar(); if (chair_lable) Chair(); if (chamber_lable) GasCam(); if (button_lable) Fire(); Keyout(); } if (beep_lable) BEEP(500); } bool sendHtmlFile(EthernetClient client, char *fileName) { webFile = SD.open(fileName); sendBaseAnswer(client); return sendFile(client, webFile); } bool sendFile(EthernetClient client, char *fileName) { webFile = SD.open(fileName); sendHttpOkAnswer(client); client.println(); return sendFile(client, webFile); } bool sendFile(EthernetClient client, File &webFile) { if (webFile) { while (webFile.available()) client.write(webFile.read()); // send web page to client webFile.close(); return 1; } return 0; } void sendBaseAnswer(EthernetClient client) { sendHttpOkAnswer(client); client.println(F("Content-Type: text/html")); client.println(F("Connection: close")); client.println(); } void sendHttpOkAnswer(EthernetClient client) { client.println(F("HTTP/1.1 200 OK")); } void StrClear(char *str, char length) { for (int i = 0; i < length; i++) { str[i] = 0; } } char StrContains(char *str, char *sfind) { char found = 0; char index = 0; char len; len = strlen(str); if (strlen(sfind) > len) { return 0; } while (index < len) { if (str[index] == sfind[found]) { found++; if (strlen(sfind) == found) { return 1; } } else { found = 0; } index++; } return 0; } void Cell() { int x = 0; while (digitalRead(keycell)) { x++; if (x > 10) { Screen_open(); Serial.println("cell"); cell_lable = false; break; } delay(10); } } void Collar() { int x = 0; while (!digitalRead(keycollar)) // Реле замыкает на минус 5В { x++; if (x > 10) { Screen_open(); Serial.println("collar"); collar_lable = false; break; } delay(10); } } void Chair() { int x = 0; while (digitalRead(keychair)) { x++; if (x > 10) { Screen_open(); Serial.println("chair"); chair_lable = false; break; } delay(10); } } void GasCam() { int x = 0; while (digitalRead(door_chamber)) { x++; if (x > 10) { Screen_open(); chamber_lable = false; digitalWrite(door_chamber, HIGH); delay(10); Smoke(); digitalWrite(fire, LOW); Screen_open(); Serial.println("gasCamera"); break; } delay(10); } } void Keyout() { int x = 0; while (digitalRead(keyout)) { x++; if (x > 10) { digitalWrite(door_out, LOW); Serial.println("win"); delay(50); Finish(); break; } delay(10); } } void Fire() { int x = 0; while (!digitalRead(button)) // Кнопка замыкает на минус 5В { x++; if (x > 10) { chamber_lable = true; button_lable = false; BEEP(0); Smoke(); BEEP(0); digitalWrite(fire, HIGH); Serial.println("fire"); break; } delay(50); } } void Smoke() { digitalWrite(smoke, HIGH); delay(500); digitalWrite(smoke, LOW); Serial.println("smoke"); } void Screen_open() { digitalWrite(screen_open, LOW); delay(timeScreen); digitalWrite(screen_open, HIGH); } void Screen_close() { digitalWrite(screen_close, LOW); delay(timeScreen); digitalWrite(screen_close, HIGH); } void Blades() { digitalWrite(blades, LOW); delay(500); digitalWrite(blades, HIGH); } void Finish() { Screen_close(); setup_out(); res_logic(); res_rele(); } void BEEP(int f) { if ((digitalRead(keyout)) or (!digitalRead(button)) or (chamber_lable)) { if (millis() > beepTime + f) { switch (fl) { case 0: digitalWrite(beep, HIGH); fl = 1; break; case 1: digitalWrite(beep, LOW); fl = 0; break; } beepTime = millis(); } } else { digitalWrite(beep, LOW); fl = 0; } } //void BEEP() //{ // if ((digitalRead(keyout)) or (!digitalRead(button))) // { // switch (u) { // case 0: if (p < 1024) p++; // else u = 1; // break; // case 1: if (p > 0) p--; // else u = 0; // break; // } // analogWrite(beep, p); // delay(1); // } // else digitalWrite(beep, LOW); //} //////////////////////////// Чтение порта ///////////////////////////////////// void ReadSerial() { switch (Serial.read()) { case '1': // Старт игры digitalWrite(beep, LOW); res_logic(); fl = 0; beep_lable = false; Screen_close(); Blades(); digitalWrite(door_chamber, LOW); digitalWrite(mp3, LOW); digitalWrite(lamp, HIGH); digitalWrite(collar, LOW); digitalWrite(door_out, HIGH); Serial.println("New game"); game = true; break; case '2': // Включить плеер digitalWrite(mp3, LOW); Serial.println("MP3 on"); break; case '3': // Выключить плеер digitalWrite(mp3, HIGH); Serial.println("MP3 off"); break; case '4': // Закрыть экран Screen_close(); if (!svet) { digitalWrite(lamp, LOW); svet = true; } Serial.println("close screen"); break; case '5': // Запустить лезвия Blades(); break; case '6': // Включить свет digitalWrite(lamp, LOW); Serial.println("Svet on"); break; case '7': // Выключить свет digitalWrite(lamp, HIGH); Serial.println("Svet off"); break; case '8': // Открыть экран Screen_open(); Serial.println("video"); break; case '9': // Конец игры Serial.println("Game over"); //Screen_close(); res_logic(); res_rele(); break; case 'a': // Включить ошейник digitalWrite(collar, LOW); Serial.println("close collar"); break; case 'b': // Выключить ошейник digitalWrite(collar, HIGH); Serial.println("open collar"); break; case 'c': // Включить ремни на стуле break; case 'd': // Выключить ремни на стуле break; case 'e': // Открыть выходную дверь digitalWrite(door_out, LOW); break; case 'f': // Закрыть выходную дверь digitalWrite(door_out, HIGH); break; case 'g': // Режим "Подготовка" digitalWrite(lamp, LOW); digitalWrite(collar, LOW); digitalWrite(door_chamber, LOW); digitalWrite(door_out, HIGH); beep_lable = true; break; case 'h': // Открыть газовую камеру digitalWrite(door_chamber, HIGH); digitalWrite(beep, LOW); break; case 'k': // Включить теплопушку case 'l': // Включить кнопку авария chamber_lable = true; button_lable = false; delay(20); Smoke(); digitalWrite(fire, HIGH); Serial.println("fire"); break; case 'm': // Включить дым.машину Smoke(); break; case 'n': // break; case 'o': // break; case 'p': // break; case 'r': // break; case 's': // break; case 't': // break; } }
P.S. Плата Arduino Mega R3 2560, Ethernet-Shield W5100.
как мне по запросу с браузера заставить работать определённый цикл в программе. По нажатию "Start" (HTTP_req, "pin=01") должен выполняться "case '1'", по нажатию "Stop"(HTTP_req, "pin=02" "case 'g'" из цикла void ReadSerial(){switch (Serial.read())......} (находится в конце скетча).
Никак. Так не делается.
И, да, про цикл return не забываем.
Ну, это ведь не вопрос - это утверждение. Оно принято к сведению. Вопросы у Вас есть? Чего Вы ждёте от сообщества, опубликовав Ваш пост? Вы ждёте, что Вам посочувствуют? Подскажут литературу? Поменяют Ваш код за Вас? Что Вам нужно-то?
Выходит, что я могу управлять лишь отдельными элементами кода и переменными?
Не, не можешь, это куклавуд может :)))
Спасибо Voodoo Doll. Долго ломал голову как оно работает, а по факту просто на каждое действие нужна отдельная кнопка со ссыкой, части которых будут отлавливаться кодом и менять значение переменных либо слать сигнал прямо в порт. Вот только пока не додумался что писать в сервисы.
Чем больше думаю тем больше понимаю - в сервис пишется переменная (как locks в примере). Получается, что в service_locks пишется переменная которая отвечает за отправку сигнала в тот или иной порт, а так же там можно указать часть программы которая будет выполняться при вызове переменной из сервиса.
Satanael
Исходник выложен мной в таком виде не потому что было лень чистить, а потому что я хочу, чтобы отложилось главное: любые сервисные функции должны быть неблокирующими. В эскейп-румах, да и вообще любых субклассах неглупого дома код типа while(!digitalRead(N)) является в недопустимым, особенно если после while стоят пустые скобки, NOP или точка с запятой - это всё равно что программе сказали: "Вась, покури тут пока кнопку нажмут, вот тебе 40-тонный контейнер Marlboro, как останется последняя пачка - ещё подвезу". И программа будет тупить и курить, потому что курево у неё не кончится - просто примите как данность, что с открытием последней пачки чудодейственным образом из ничего материализуется новый контейнер, битком набитый такими же пачками. Несмотря ни на какие доводы Лавуазье и Ломоносова о том, что ничто не появляется из ничего. Курение так и будет продолжаться, пока условие в while не станет ложно.
В каждой из service_xxxx(), locks(), setlight() - либо максимально короткое действие которое не замедлит опрос Ethernet, либо максимально нечувствительное к многократному повторению действие. Дверь закрылась? Чудно, подаём единицу на транзистор, коммутирующий замок. Или двигатель, у которого предусмотрены оба концевика. Следующий проход loop()? Дверь не открыли? Подаём единицу. Уже была? Плевать, подаём единицу. Пятьсот, тысячу, 2 млн. раз в секунду. Другая секунда? Ну, может надо что-то открыть - это предусматривается в функциях service_xxxx(). Переменная, которая помнит такие секунды - unsigned long time_current;. Как-то так.