Сопряжение 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 не забываем.
Ну, это ведь не вопрос - это утверждение. Оно принято к сведению. Вопросы у Вас есть? Чего Вы ждёте от сообщества, опубликовав Ваш пост? Вы ждёте, что Вам посочувствуют? Подскажут литературу? Поменяют Ваш код за Вас? Что Вам нужно-то?
void loop() { String req; char c; EthernetClient client = server.available(); if (client) { boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { char c = client.read(); req+=c; if (c == '\n' && currentLineIsBlank) { // if (req.indexOf("?")>-1) Serial.println(req.substring(6,req.indexOf(" HTTP"))); // DEBUG: Dump request // приём, получает поля GET запроса (то что есть в URI) if(req.indexOf("ovenunlock")>-1) locks(2); if(req.indexOf("secretunlock")>-1) locks(3); if(req.indexOf("door1unlock")>-1) locks(4); if(req.indexOf("door2unlock")>-1) locks(5); // .......... // поняли смысл? if(req.indexOf("room2l_on")>-1) setlight(2,1); if(req.indexOf("room2l_off")>-1) setlight(2,0); if(req.indexOf("room1l_on")>-1) setlight(1,1); if(req.indexOf("room1l_off")>-1) setlight(1,0); // и т д и т п // Serial.println(req); // DEBUG: Dump HTTP data client.println("HTTP/1.1 200 OK"); client.println("Content-Type: application/json"); client.println("Access-Control-Allow-Origin: *"); client.println("Connection: close"); client.println(); // передача client.print("{"); client.print("\"thr0\":\""); client.print(throne0); client.print("\",\"thr1\":\""); client.print(s_throne[0]); // .... client.print("\",\"sf\":\""); client.print(seq_fr); client.print("\",\"sn\":\""); client.print(seq_n); client.print("\""); client.println("}"); // end JSON req=""; break; } if (c == '\n') currentLineIsBlank = true; else if (c != '\r') currentLineIsBlank = false; } } delay(1); client.stop(); } time_current=millis(); // яж надеюсь ясно зачем это service_door(); // асинхронные (отвязанные от delay) службы service_jaws(); service_locks(); // ......... }Выходит, что я могу управлять лишь отдельными элементами кода и переменными?
Не, не можешь, это куклавуд может :)))
Спасибо 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;. Как-то так.